1 /* 2 * Copyright (C) 2021 Jo-Philipp Wich <jo@mein.io> 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 #include <stdarg.h> 18 #include <stdlib.h> 19 #include <assert.h> 20 #include <errno.h> 21 #include <math.h> 22 #include <ctype.h> 23 #include <float.h> 24 25 #include "json-c-compat.h" 26 27 #include "ucode/types.h" 28 #include "ucode/util.h" 29 #include "ucode/vm.h" 30 #include "ucode/program.h" 31 32 static char *uc_default_search_path[] = { LIB_SEARCH_PATH }; 33 34 uc_parse_config_t uc_default_parse_config = { 35 .module_search_path = { 36 .count = ARRAY_SIZE(uc_default_search_path), 37 .entries = uc_default_search_path 38 } 39 }; 40 41 uc_type_t 42 ucv_type(uc_value_t *uv) 43 { 44 uc_type_t type = ((uintptr_t)uv & 3); 45 46 if (type == UC_NULL && uv != NULL) 47 type = uv->type; 48 49 return type; 50 } 51 52 const char * 53 ucv_typename(uc_value_t *uv) 54 { 55 switch (ucv_type(uv)) { 56 case UC_NULL: return "null"; 57 case UC_INTEGER: return "integer"; 58 case UC_BOOLEAN: return "boolean"; 59 case UC_STRING: return "string"; 60 case UC_DOUBLE: return "double"; 61 case UC_ARRAY: return "array"; 62 case UC_OBJECT: return "object"; 63 case UC_REGEXP: return "regexp"; 64 case UC_CFUNCTION: return "cfunction"; 65 case UC_CLOSURE: return "closure"; 66 case UC_UPVALUE: return "upvalue"; 67 case UC_RESOURCE: return "resource"; 68 case UC_PROGRAM: return "program"; 69 case UC_SOURCE: return "source"; 70 } 71 72 return "unknown"; 73 } 74 75 void 76 ucv_unref(uc_weakref_t *ref) 77 { 78 ref->prev->next = ref->next; 79 ref->next->prev = ref->prev; 80 } 81 82 static void 83 ucv_ref_tail(uc_weakref_t *head, uc_weakref_t *item) 84 { 85 item->next = head; 86 item->prev = head->prev; 87 head->prev->next = item; 88 head->prev = item; 89 } 90 91 void 92 ucv_ref(uc_weakref_t *head, uc_weakref_t *item) 93 { 94 item->next = head->next; 95 item->prev = head; 96 head->next->prev = item; 97 head->next = item; 98 } 99 100 static uc_value_t ** 101 ucv_resource_values(uc_resource_ext_t *res) 102 { 103 void *data; 104 105 if (!ucv_resource_is_extended((uc_value_t *)res) || !res->uvcount) 106 return NULL; 107 108 data = res + 1; 109 data += res->datasize * 8; 110 111 return data; 112 } 113 114 #if 0 115 static uc_weakref_t * 116 ucv_get_weakref(uc_value_t *uv) 117 { 118 switch (ucv_type(uv)) { 119 case UC_ARRAY: 120 return &((uc_array_t *)uv)->ref; 121 122 case UC_OBJECT: 123 return &((uc_object_t *)uv)->ref; 124 125 case UC_CLOSURE: 126 return &((uc_closure_t *)uv)->ref; 127 128 default: 129 return NULL; 130 } 131 } 132 #endif 133 134 static void 135 ucv_put_value(uc_value_t *uv, bool retain) 136 { 137 if (uv == NULL || (uintptr_t)uv & 3) 138 return; 139 140 assert(uv->type == UC_NULL || uv->refcount > 0); 141 142 if (uv->refcount > 0) 143 uv->refcount--; 144 145 if (uv->refcount == 0) 146 ucv_free(uv, retain); 147 } 148 149 static void 150 ucv_gc_mark(uc_value_t *uv); 151 152 static void 153 ucv_gc_mark(uc_value_t *uv) 154 { 155 uc_function_t *function; 156 uc_closure_t *closure; 157 uc_upvalref_t *upval; 158 uc_object_t *object; 159 uc_array_t *array; 160 uc_resource_type_t *restype; 161 uc_program_t *program; 162 uc_value_t **values; 163 struct lh_entry *entry; 164 size_t i; 165 166 if (ucv_is_marked(uv)) 167 return; 168 169 switch (ucv_type(uv)) { 170 case UC_ARRAY: 171 array = (uc_array_t *)uv; 172 173 if (array->ref.next) 174 ucv_set_mark(uv); 175 176 ucv_gc_mark(array->proto); 177 178 for (i = 0; i < array->count; i++) 179 ucv_gc_mark(array->entries[i]); 180 181 break; 182 183 case UC_OBJECT: 184 object = (uc_object_t *)uv; 185 186 if (object->ref.next) 187 ucv_set_mark(uv); 188 189 ucv_gc_mark(object->proto); 190 191 lh_foreach(object->table, entry) 192 ucv_gc_mark((uc_value_t *)lh_entry_v(entry)); 193 194 break; 195 196 case UC_CLOSURE: 197 closure = (uc_closure_t *)uv; 198 function = closure->function; 199 200 if (closure->ref.next) 201 ucv_set_mark(uv); 202 203 for (i = 0; i < function->nupvals; i++) 204 ucv_gc_mark(&closure->upvals[i]->header); 205 206 ucv_gc_mark(&function->program->header); 207 208 break; 209 210 case UC_UPVALUE: 211 upval = (uc_upvalref_t *)uv; 212 ucv_gc_mark(upval->value); 213 break; 214 215 case UC_RESOURCE: 216 if (uv->ext_flag) { 217 uc_resource_ext_t *res = (uc_resource_ext_t *)uv; 218 219 if (res->ref.next) 220 ucv_set_mark(uv); 221 222 values = ucv_resource_values(res); 223 if (!values) 224 break; 225 226 for (i = 0; i < res->uvcount; i++) 227 ucv_gc_mark(values[i]); 228 } 229 230 restype = ucv_resource_type(uv); 231 if (restype) 232 ucv_gc_mark(restype->proto); 233 234 break; 235 236 case UC_PROGRAM: 237 program = (uc_program_t *)uv; 238 239 for (i = 0; i < program->sources.count; i++) 240 ucv_gc_mark(&program->sources.entries[i]->header); 241 242 for (i = 0; i < program->exports.count; i++) 243 ucv_gc_mark(&program->exports.entries[i]->header); 244 245 break; 246 247 default: 248 break; 249 } 250 } 251 252 void 253 ucv_free(uc_value_t *uv, bool retain) 254 { 255 uc_function_t *function; 256 uc_closure_t *closure; 257 uc_program_t *program; 258 uc_upvalref_t *upval; 259 uc_source_t *source; 260 uc_regexp_t *regexp; 261 uc_object_t *object; 262 uc_array_t *array; 263 uc_weakref_t *ref; 264 size_t i; 265 266 if (uv == NULL || (uintptr_t)uv & 3) 267 return; 268 269 if (uv->mark) 270 return; 271 272 uv->mark = true; 273 274 ref = NULL; 275 276 switch (uv->type) { 277 case UC_ARRAY: 278 array = (uc_array_t *)uv; 279 ref = &array->ref; 280 ucv_put_value(array->proto, retain); 281 282 for (i = 0; i < array->count; i++) 283 ucv_put_value(array->entries[i], retain); 284 285 uc_vector_clear(array); 286 break; 287 288 case UC_OBJECT: 289 object = (uc_object_t *)uv; 290 ref = &object->ref; 291 ucv_put_value(object->proto, retain); 292 lh_table_free(object->table); 293 break; 294 295 case UC_REGEXP: 296 regexp = (uc_regexp_t *)uv; 297 regfree(®exp->regexp); 298 break; 299 300 case UC_CLOSURE: 301 closure = (uc_closure_t *)uv; 302 function = closure->function; 303 ref = &closure->ref; 304 305 for (i = 0; i < function->nupvals; i++) 306 if (closure->upvals[i]) 307 ucv_put_value(&closure->upvals[i]->header, retain); 308 309 ucv_put_value(&function->program->header, retain); 310 break; 311 312 case UC_RESOURCE: 313 if (uv->ext_flag) { 314 uc_resource_ext_t *res = (uc_resource_ext_t *)uv; 315 uc_value_t **values; 316 317 values = ucv_resource_values(res); 318 if (values) { 319 for (i = 0; i < res->uvcount; i++) 320 ucv_put_value(values[i], retain); 321 } 322 323 if (res->type && res->type->free) { 324 void *data = res + 1; 325 326 res->type->free(data); 327 } 328 329 ref = &res->ref; 330 } 331 else { 332 uc_resource_t *res = (uc_resource_t *)uv; 333 334 if (res->type && res->type->free) 335 res->type->free(res->data); 336 } 337 break; 338 339 case UC_UPVALUE: 340 upval = (uc_upvalref_t *)uv; 341 ucv_put_value(upval->value, retain); 342 break; 343 344 case UC_PROGRAM: 345 program = (uc_program_t *)uv; 346 347 uc_program_function_foreach_safe(program, func) 348 uc_program_function_free(func); 349 350 uc_vallist_free(&program->constants); 351 352 for (i = 0; i < program->sources.count; i++) 353 ucv_put_value(&program->sources.entries[i]->header, retain); 354 355 for (i = 0; i < program->exports.count; i++) 356 ucv_put_value(&program->exports.entries[i]->header, retain); 357 358 uc_vector_clear(&program->sources); 359 uc_vector_clear(&program->exports); 360 break; 361 362 case UC_SOURCE: 363 source = (uc_source_t *)uv; 364 365 if (source->runpath != source->filename) 366 free(source->runpath); 367 368 for (i = 0; i < source->exports.count; i++) 369 ucv_put(source->exports.entries[i]); 370 371 uc_vector_clear(&source->lineinfo); 372 uc_vector_clear(&source->exports); 373 fclose(source->fp); 374 free(source->buffer); 375 break; 376 } 377 378 if (!ref || !retain) { 379 if (ref && ref->prev && ref->next) 380 ucv_unref(ref); 381 382 free(uv); 383 } 384 else { 385 uv->type = UC_NULL; 386 } 387 } 388 389 void 390 ucv_put(uc_value_t *uv) 391 { 392 ucv_put_value(uv, false); 393 } 394 395 uc_value_t * 396 ucv_get(uc_value_t *uv) 397 { 398 if (uv == NULL || (uintptr_t)uv & 3) 399 return uv; 400 401 assert(uv->refcount < 0x03ffffff); 402 403 uv->refcount++; 404 405 return uv; 406 } 407 408 uc_value_t * 409 ucv_boolean_new(bool val) 410 { 411 uintptr_t pv = UC_BOOLEAN | (val << 2); 412 413 return (uc_value_t *)pv; 414 } 415 416 bool 417 ucv_boolean_get(uc_value_t *uv) 418 { 419 uintptr_t pv = (uintptr_t)uv; 420 421 if ((pv & 3) == UC_BOOLEAN) 422 return (pv >> 2) & 1; 423 424 return false; 425 } 426 427 428 uc_value_t * 429 ucv_string_new(const char *str) 430 { 431 return ucv_string_new_length(str, strlen(str)); 432 } 433 434 uc_value_t * 435 ucv_string_alloc(char **str, size_t length) 436 { 437 uc_string_t *ustr; 438 439 ustr = xalloc(sizeof(*ustr) + length + 1); 440 ustr->header.type = UC_STRING; 441 ustr->header.refcount = 1; 442 ustr->length = length; 443 *str = (char *)ustr->str; 444 445 return &ustr->header; 446 } 447 448 uc_value_t * 449 ucv_string_new_length(const char *str, size_t length) 450 { 451 uc_value_t *ustr; 452 char *buf; 453 454 if ((length + 1) < sizeof(void *)) { 455 uintptr_t pv = UC_STRING | (length << 2); 456 size_t i; 457 char *s; 458 459 #if __BYTE_ORDER == __LITTLE_ENDIAN 460 s = (char *)&pv + 1; 461 #else 462 s = (char *)&pv; 463 #endif 464 465 for (i = 0; i < length; i++) 466 s[i] = str[i]; 467 468 return (uc_value_t *)pv; 469 } 470 471 ustr = ucv_string_alloc(&buf, length); 472 memcpy(buf, str, length); 473 474 return ustr; 475 } 476 477 uc_stringbuf_t * 478 ucv_stringbuf_new(void) 479 { 480 uc_stringbuf_t *sb = xprintbuf_new(); 481 uc_string_t ustr = { 482 .header = { 483 .type = UC_STRING, 484 .refcount = 1 485 } 486 }; 487 488 printbuf_memappend_fast(sb, (char *)&ustr, (int)sizeof(ustr)); 489 490 return sb; 491 } 492 493 uc_value_t * 494 ucv_stringbuf_finish(uc_stringbuf_t *sb) 495 { 496 uc_string_t *ustr = (uc_string_t *)sb->buf; 497 498 ustr->length = printbuf_length(sb) - offsetof(uc_string_t, str); 499 500 free(sb); 501 502 return &ustr->header; 503 } 504 505 char * 506 _ucv_string_get(uc_value_t **uv) 507 { 508 uc_string_t *str; 509 510 switch ((uintptr_t)*uv & 3) { 511 case UC_STRING: 512 #if __BYTE_ORDER == __LITTLE_ENDIAN 513 return (char *)uv + 1; 514 #else 515 return (char *)uv; 516 #endif 517 518 case UC_NULL: 519 if (*uv != NULL && (*uv)->type == UC_STRING) { 520 str = (uc_string_t *)*uv; 521 522 return str->str; 523 } 524 } 525 526 return NULL; 527 } 528 529 size_t 530 ucv_string_length(uc_value_t *uv) 531 { 532 uc_string_t *str = (uc_string_t *)uv; 533 uintptr_t pv = (uintptr_t)uv; 534 535 if ((pv & 3) == UC_STRING) 536 return (pv & 0xff) >> 2; 537 else if (uv != NULL && uv->type == UC_STRING) 538 return str->length; 539 540 return 0; 541 } 542 543 544 uc_value_t * 545 ucv_int64_new(int64_t n) 546 { 547 uint64_t uval = (n < 0) ? ((n > INT64_MIN) ? (~n + 1) : INT64_MAX) : n; 548 uint64_t max = (1ULL << ((sizeof(void *) * 8) - 3)) - 1; 549 uc_integer_t *integer; 550 uintptr_t pv; 551 552 if (uval <= max) { 553 pv = UC_INTEGER | ((n < 0) << 2) | (uval << 3); 554 555 return (uc_value_t *)pv; 556 } 557 558 integer = xalloc(sizeof(*integer)); 559 integer->header.type = UC_INTEGER; 560 integer->header.refcount = 1; 561 integer->header.ext_flag = 0; 562 integer->i.s64 = n; 563 564 return &integer->header; 565 } 566 567 uc_value_t * 568 ucv_uint64_new(uint64_t n) 569 { 570 uint64_t max = (1ULL << ((sizeof(void *) * 8) - 3)) - 1; 571 uc_integer_t *integer; 572 uintptr_t pv; 573 574 if (n <= max) { 575 pv = UC_INTEGER | (n << 3); 576 577 return (uc_value_t *)pv; 578 } 579 580 integer = xalloc(sizeof(*integer)); 581 integer->header.type = UC_INTEGER; 582 integer->header.refcount = 1; 583 integer->header.ext_flag = 1; 584 integer->i.u64 = n; 585 586 return &integer->header; 587 } 588 589 uint64_t 590 ucv_uint64_get(uc_value_t *uv) 591 { 592 uintptr_t pv = (uintptr_t)uv; 593 uc_integer_t *integer; 594 double d; 595 596 errno = 0; 597 598 if ((pv & 3) == UC_INTEGER) { 599 if (((pv >> 2) & 1) == 0) 600 return (uint64_t)(pv >> 3); 601 602 errno = ERANGE; 603 604 return 0; 605 } 606 607 switch (ucv_type(uv)) { 608 case UC_INTEGER: 609 integer = (uc_integer_t *)uv; 610 611 if (integer->header.ext_flag) 612 return integer->i.u64; 613 614 if (integer->i.s64 >= 0) 615 return (uint64_t)integer->i.s64; 616 617 errno = ERANGE; 618 619 return 0; 620 621 case UC_DOUBLE: 622 d = ucv_double_get(uv); 623 624 if (d < 0.0) { 625 errno = ERANGE; 626 627 return 0; 628 } 629 630 if (d >= ldexp(1.0, 64)) { 631 errno = ERANGE; 632 633 return UINT64_MAX; 634 } 635 636 return (uint64_t)d; 637 638 default: 639 errno = EINVAL; 640 641 return 0; 642 } 643 } 644 645 int64_t 646 ucv_int64_get(uc_value_t *uv) 647 { 648 uintptr_t pv = (uintptr_t)uv; 649 uc_integer_t *integer; 650 double d; 651 652 errno = 0; 653 654 if ((pv & 3) == UC_INTEGER) { 655 if (((pv >> 2) & 1) == 0) 656 return (int64_t)(pv >> 3); 657 658 return -(int64_t)(pv >> 3); 659 } 660 661 switch (ucv_type(uv)) { 662 case UC_INTEGER: 663 integer = (uc_integer_t *)uv; 664 665 if (integer->header.ext_flag && integer->i.u64 <= (uint64_t)INT64_MAX) 666 return (int64_t)integer->i.u64; 667 668 if (!integer->header.ext_flag) 669 return integer->i.s64; 670 671 errno = ERANGE; 672 673 return INT64_MAX; 674 675 case UC_DOUBLE: 676 d = ucv_double_get(uv); 677 678 if (d < ldexp(-1.0, 63)) { 679 errno = ERANGE; 680 681 return INT64_MIN; 682 } 683 684 if (d >= ldexp(1.0, 63)) { 685 errno = ERANGE; 686 687 return INT64_MAX; 688 } 689 690 return (int64_t)d; 691 692 default: 693 errno = EINVAL; 694 695 return 0; 696 } 697 } 698 699 700 uc_value_t * 701 ucv_double_new(double d) 702 { 703 uc_double_t *dbl; 704 705 dbl = xalloc(sizeof(*dbl)); 706 dbl->header.type = UC_DOUBLE; 707 dbl->header.refcount = 1; 708 dbl->dbl = d; 709 710 return &dbl->header; 711 } 712 713 double 714 ucv_double_get(uc_value_t *uv) 715 { 716 uint64_t max_int = (2ULL << (DBL_MANT_DIG - 1)); 717 uc_double_t *dbl; 718 uint64_t u; 719 int64_t n; 720 721 errno = 0; 722 723 switch (ucv_type(uv)) { 724 case UC_DOUBLE: 725 dbl = (uc_double_t *)uv; 726 727 return dbl->dbl; 728 729 case UC_INTEGER: 730 n = ucv_int64_get(uv); 731 732 if (errno == ERANGE) { 733 u = ucv_uint64_get(uv); 734 735 /* signal precision loss for integral values >2^53 */ 736 if (u > max_int) 737 errno = ERANGE; 738 739 return (double)u; 740 } 741 742 /* signal precision loss for integral values <-2^53 or >2^53 */ 743 if (n < -(int64_t)max_int || n > (int64_t)max_int) 744 errno = ERANGE; 745 746 return (double)n; 747 748 default: 749 errno = EINVAL; 750 751 return NAN; 752 } 753 } 754 755 756 uc_value_t * 757 ucv_array_new(uc_vm_t *vm) 758 { 759 return ucv_array_new_length(vm, 0); 760 } 761 762 uc_value_t * 763 ucv_array_new_length(uc_vm_t *vm, size_t length) 764 { 765 uc_array_t *array; 766 767 array = xalloc(sizeof(*array)); 768 array->header.type = UC_ARRAY; 769 array->header.refcount = 1; 770 771 /* preallocate memory */ 772 if (length) 773 uc_vector_extend(array, length); 774 775 if (vm) { 776 ucv_ref(&vm->values, &array->ref); 777 vm->alloc_refs++; 778 } 779 780 return &array->header; 781 } 782 783 uc_value_t * 784 ucv_array_pop(uc_value_t *uv) 785 { 786 uc_array_t *array = (uc_array_t *)uv; 787 uc_value_t *item; 788 789 if (ucv_type(uv) != UC_ARRAY || array->count == 0) 790 return NULL; 791 792 item = ucv_get(array->entries[array->count - 1]); 793 794 ucv_array_delete(uv, array->count - 1, 1); 795 796 return item; 797 } 798 799 uc_value_t * 800 ucv_array_push(uc_value_t *uv, uc_value_t *item) 801 { 802 uc_array_t *array = (uc_array_t *)uv; 803 804 if (ucv_type(uv) != UC_ARRAY || uv->ext_flag) 805 return NULL; 806 807 ucv_array_set(uv, array->count, item); 808 809 return item; 810 } 811 812 uc_value_t * 813 ucv_array_shift(uc_value_t *uv) 814 { 815 uc_array_t *array = (uc_array_t *)uv; 816 uc_value_t *item; 817 818 if (ucv_type(uv) != UC_ARRAY || array->count == 0) 819 return NULL; 820 821 item = ucv_get(array->entries[0]); 822 823 ucv_array_delete(uv, 0, 1); 824 825 return item; 826 } 827 828 uc_value_t * 829 ucv_array_unshift(uc_value_t *uv, uc_value_t *item) 830 { 831 uc_array_t *array = (uc_array_t *)uv; 832 size_t i; 833 834 if (ucv_type(uv) != UC_ARRAY) 835 return NULL; 836 837 uc_vector_extend(array, 1); 838 839 for (i = ++array->count; i > 1; i--) 840 array->entries[i - 1] = array->entries[i - 2]; 841 842 array->entries[0] = item; 843 844 return item; 845 } 846 847 typedef struct { 848 int (*cmp)(uc_value_t *, uc_value_t *, void *); 849 void *ud; 850 } array_sort_ctx_t; 851 852 static uc_vector_sort_cb(ucv_array_sort_r_cb, uc_value_t *, array_sort_ctx_t *, { 853 return ctx->cmp(v1, v2, ctx->ud); 854 }); 855 856 void 857 ucv_array_sort_r(uc_value_t *uv, 858 int (*cmp)(uc_value_t *, uc_value_t *, void *), void *ud) 859 { 860 array_sort_ctx_t ctx = { .cmp = cmp, .ud = ud }; 861 uc_array_t *array = (uc_array_t *)uv; 862 863 if (ucv_type(uv) != UC_ARRAY || array->count <= 1) 864 return; 865 866 uc_vector_sort(array, ucv_array_sort_r_cb, &ctx); 867 } 868 869 void 870 ucv_array_sort(uc_value_t *uv, int (*cmp)(const void *, const void *)) 871 { 872 uc_array_t *array = (uc_array_t *)uv; 873 874 if (ucv_type(uv) != UC_ARRAY || array->count <= 1) 875 return; 876 877 qsort(array->entries, array->count, sizeof(array->entries[0]), cmp); 878 } 879 880 bool 881 ucv_array_delete(uc_value_t *uv, size_t offset, size_t count) 882 { 883 uc_array_t *array = (uc_array_t *)uv; 884 size_t i; 885 886 if (ucv_type(uv) != UC_ARRAY || array->count == 0) 887 return false; 888 889 if (offset >= array->count) 890 return false; 891 892 if ((offset + count) < offset) 893 return false; 894 895 if ((offset + count) > array->count) 896 count = array->count - offset; 897 898 for (i = 0; i < count; i++) 899 ucv_put(array->entries[offset + i]); 900 901 memmove(&array->entries[offset], 902 &array->entries[offset + count], 903 (array->count - (offset + count)) * sizeof(array->entries[0])); 904 905 uc_vector_reduce(array, count); 906 array->count -= count; 907 908 return true; 909 } 910 911 bool 912 ucv_array_set(uc_value_t *uv, size_t index, uc_value_t *item) 913 { 914 uc_array_t *array = (uc_array_t *)uv; 915 916 if (ucv_type(uv) != UC_ARRAY) 917 return false; 918 919 if (index >= array->count) { 920 uc_vector_extend(array, index + 1 - array->count); 921 array->count = index + 1; 922 } 923 else { 924 ucv_put(array->entries[index]); 925 } 926 927 array->entries[index] = item; 928 929 return true; 930 } 931 932 uc_value_t * 933 ucv_array_get(uc_value_t *uv, size_t index) 934 { 935 uc_array_t *array = (uc_array_t *)uv; 936 937 if (ucv_type(uv) != UC_ARRAY) 938 return NULL; 939 940 if (index >= array->count) 941 return NULL; 942 943 return array->entries[index]; 944 } 945 size_t 946 ucv_array_length(uc_value_t *uv) 947 { 948 uc_array_t *array = (uc_array_t *)uv; 949 950 if (ucv_type(uv) != UC_ARRAY) 951 return 0; 952 953 return array->count; 954 } 955 956 957 static void 958 ucv_free_object_entry(struct lh_entry *entry) 959 { 960 uc_list_foreach(item, &uc_thread_context_get()->object_iterators) { 961 uc_object_iterator_t *iter = (uc_object_iterator_t *)item; 962 963 if (iter->u.pos == entry) 964 iter->u.pos = entry->next; 965 } 966 967 free(lh_entry_k(entry)); 968 ucv_put(lh_entry_v(entry)); 969 } 970 971 uc_value_t * 972 ucv_object_new(uc_vm_t *vm) 973 { 974 struct lh_table *table; 975 uc_object_t *object; 976 977 table = lh_kchar_table_new(16, ucv_free_object_entry); 978 979 if (!table) { 980 fprintf(stderr, "Out of memory\n"); 981 abort(); 982 } 983 984 object = xalloc(sizeof(*object)); 985 object->header.type = UC_OBJECT; 986 object->header.refcount = 1; 987 object->table = table; 988 989 if (vm) { 990 ucv_ref(&vm->values, &object->ref); 991 vm->alloc_refs++; 992 } 993 994 return &object->header; 995 } 996 997 bool 998 ucv_object_add(uc_value_t *uv, const char *key, uc_value_t *val) 999 { 1000 uc_object_t *object = (uc_object_t *)uv; 1001 struct lh_entry *existing_entry; 1002 uc_value_t *existing_value; 1003 unsigned long hash; 1004 void *k; 1005 1006 if (ucv_type(uv) != UC_OBJECT || uv->ext_flag) 1007 return false; 1008 1009 hash = lh_get_hash(object->table, (const void *)key); 1010 existing_entry = lh_table_lookup_entry_w_hash(object->table, (const void *)key, hash); 1011 1012 if (existing_entry == NULL) { 1013 bool rehash = (object->table->count >= object->table->size * LH_LOAD_FACTOR); 1014 1015 /* insert will rehash table, backup affected iterator states */ 1016 if (rehash) { 1017 uc_list_foreach(item, &uc_thread_context_get()->object_iterators) { 1018 uc_object_iterator_t *iter = (uc_object_iterator_t *)item; 1019 1020 if (iter->table != object->table) 1021 continue; 1022 1023 if (iter->u.pos == NULL) 1024 continue; 1025 1026 iter->u.kh.k = iter->u.pos->k; 1027 iter->u.kh.hash = lh_get_hash(iter->table, iter->u.kh.k); 1028 } 1029 } 1030 1031 k = xstrdup(key); 1032 1033 if (lh_table_insert_w_hash(object->table, k, val, hash, 0) != 0) { 1034 free(k); 1035 1036 return false; 1037 } 1038 1039 /* restore affected iterator state pointer after rehash */ 1040 if (rehash) { 1041 uc_list_foreach(item, &uc_thread_context_get()->object_iterators) { 1042 uc_object_iterator_t *iter = (uc_object_iterator_t *)item; 1043 1044 if (iter->table != object->table) 1045 continue; 1046 1047 if (iter->u.kh.k == NULL) 1048 continue; 1049 1050 iter->u.pos = lh_table_lookup_entry_w_hash(iter->table, 1051 iter->u.kh.k, 1052 iter->u.kh.hash); 1053 } 1054 } 1055 1056 return true; 1057 } 1058 1059 existing_value = (uc_value_t *)lh_entry_v(existing_entry); 1060 1061 if (existing_value) 1062 ucv_put(existing_value); 1063 1064 existing_entry->v = val; 1065 1066 return true; 1067 } 1068 1069 1070 typedef struct { 1071 int (*cmp)(const void *, const void *); 1072 int (*cmpr)(const char *, uc_value_t *, const char *, uc_value_t *, void *); 1073 void *ud; 1074 } object_sort_ctx_t; 1075 1076 static uc_vector_sort_cb(ucv_object_sort_cb, const void *, object_sort_ctx_t *, { 1077 (void)v1; 1078 (void)v2; 1079 1080 return ctx->cmp(k1, k2); 1081 }); 1082 1083 static uc_vector_sort_cb(ucv_object_sort_r_cb, const struct lh_entry *, object_sort_ctx_t *, { 1084 return ctx->cmpr( 1085 v1 ? lh_entry_k(v1) : NULL, v1 ? lh_entry_v(v1) : NULL, 1086 v2 ? lh_entry_k(v2) : NULL, v2 ? lh_entry_v(v2) : NULL, 1087 ctx->ud); 1088 }); 1089 1090 static void 1091 ucv_object_sort_common(uc_value_t *uv, object_sort_ctx_t *ctx) 1092 { 1093 uc_object_t *object = (uc_object_t *)uv; 1094 struct lh_table *t; 1095 struct lh_entry *e; 1096 size_t i; 1097 1098 struct { 1099 struct lh_entry **entries; 1100 size_t count; 1101 } keys = { 0 }; 1102 1103 if (ucv_type(uv) != UC_OBJECT || lh_table_length(object->table) <= 1) 1104 return; 1105 1106 for (t = object->table, e = t->head; e; e = e->next) 1107 uc_vector_push(&keys, e); 1108 1109 if (!keys.entries) 1110 return; 1111 1112 uc_vector_sort(&keys, 1113 ctx->cmpr ? ucv_object_sort_r_cb : ucv_object_sort_cb, ctx); 1114 1115 for (i = 0; i < keys.count; i++) { 1116 e = keys.entries[i]; 1117 1118 if (i == 0) { 1119 t->head = t->tail = e; 1120 e->next = e->prev = NULL; 1121 } 1122 else { 1123 t->tail->next = e; 1124 e->prev = t->tail; 1125 e->next = NULL; 1126 t->tail = e; 1127 } 1128 } 1129 1130 uc_vector_clear(&keys); 1131 } 1132 1133 void 1134 ucv_object_sort_r(uc_value_t *uv, 1135 int (*cmp)(const char *, uc_value_t *, 1136 const char *, uc_value_t *, void *), 1137 void *ud) 1138 { 1139 object_sort_ctx_t ctx = { .cmp = NULL, .cmpr = cmp, .ud = ud }; 1140 1141 ucv_object_sort_common(uv, &ctx); 1142 } 1143 1144 void 1145 ucv_object_sort(uc_value_t *uv, int (*cmp)(const void *, const void *)) 1146 { 1147 object_sort_ctx_t ctx = { .cmp = cmp, .cmpr = NULL, .ud = NULL }; 1148 1149 ucv_object_sort_common(uv, &ctx); 1150 } 1151 1152 bool 1153 ucv_object_delete(uc_value_t *uv, const char *key) 1154 { 1155 uc_object_t *object = (uc_object_t *)uv; 1156 1157 if (ucv_type(uv) != UC_OBJECT || uv->ext_flag) 1158 return false; 1159 1160 return (lh_table_delete(object->table, key) == 0); 1161 } 1162 1163 uc_value_t * 1164 ucv_object_get(uc_value_t *uv, const char *key, bool *found) 1165 { 1166 uc_object_t *object = (uc_object_t *)uv; 1167 uc_value_t *val = NULL; 1168 bool rv; 1169 1170 if (found != NULL) 1171 *found = false; 1172 1173 if (ucv_type(uv) != UC_OBJECT) 1174 return NULL; 1175 1176 rv = lh_table_lookup_ex(object->table, (const void *)key, (void **)&val); 1177 1178 if (found != NULL) 1179 *found = rv; 1180 1181 return val; 1182 } 1183 1184 size_t 1185 ucv_object_length(uc_value_t *uv) 1186 { 1187 uc_object_t *object = (uc_object_t *)uv; 1188 1189 if (ucv_type(uv) != UC_OBJECT) 1190 return 0; 1191 1192 return lh_table_length(object->table); 1193 } 1194 1195 1196 uc_value_t * 1197 ucv_cfunction_new(const char *name, uc_cfn_ptr_t fptr) 1198 { 1199 uc_cfunction_t *cfn; 1200 size_t namelen = 0; 1201 1202 if (name) 1203 namelen = strlen(name); 1204 1205 cfn = xalloc(sizeof(*cfn) + namelen + 1); 1206 cfn->header.type = UC_CFUNCTION; 1207 cfn->header.refcount = 1; 1208 1209 if (name) 1210 strcpy(cfn->name, name); 1211 1212 cfn->cfn = fptr; 1213 1214 return &cfn->header; 1215 } 1216 1217 1218 uc_value_t * 1219 ucv_closure_new(uc_vm_t *vm, uc_function_t *function, bool arrow_fn) 1220 { 1221 uc_closure_t *closure; 1222 1223 closure = xalloc(sizeof(*closure) + (sizeof(uc_upvalref_t *) * function->nupvals)); 1224 closure->header.type = UC_CLOSURE; 1225 closure->header.refcount = 1; 1226 closure->function = function; 1227 closure->is_arrow = arrow_fn; 1228 closure->upvals = function->nupvals ? (uc_upvalref_t **)((uintptr_t)closure + ALIGN(sizeof(*closure))) : NULL; 1229 1230 if (vm) { 1231 ucv_ref(&vm->values, &closure->ref); 1232 vm->alloc_refs++; 1233 } 1234 1235 uc_program_get(function->program); 1236 1237 return &closure->header; 1238 } 1239 1240 1241 uc_resource_type_t * 1242 ucv_resource_type_add(uc_vm_t *vm, const char *name, uc_value_t *proto, void (*freefn)(void *)) 1243 { 1244 uc_resource_type_t *type; 1245 1246 type = ucv_resource_type_lookup(vm, name); 1247 1248 if (type) { 1249 ucv_put(proto); 1250 1251 return type; 1252 } 1253 1254 type = xalloc(sizeof(*type)); 1255 type->name = name; 1256 type->proto = proto; 1257 type->free = freefn; 1258 1259 uc_vector_push(&vm->restypes, type); 1260 1261 return type; 1262 } 1263 1264 uc_resource_type_t * 1265 ucv_resource_type_lookup(uc_vm_t *vm, const char *name) 1266 { 1267 size_t i; 1268 1269 for (i = 0; i < vm->restypes.count; i++) 1270 if (!strcmp(vm->restypes.entries[i]->name, name)) 1271 return vm->restypes.entries[i]; 1272 1273 return NULL; 1274 } 1275 1276 1277 uc_value_t * 1278 ucv_resource_new(uc_resource_type_t *type, void *data) 1279 { 1280 uc_resource_t *res; 1281 1282 res = xalloc(sizeof(*res)); 1283 res->header.type = UC_RESOURCE; 1284 res->header.refcount = 1; 1285 res->type = type; 1286 res->data = data; 1287 1288 return &res->header; 1289 } 1290 1291 uc_value_t * 1292 ucv_resource_new_ex(uc_vm_t *vm, uc_resource_type_t *type, void **data, size_t uvcount, size_t datasize) 1293 { 1294 uc_resource_ext_t *res; 1295 size_t size; 1296 1297 assert(uvcount < (1 << 8)); 1298 assert(datasize < (8 << 20)); 1299 1300 size = sizeof(*res); 1301 size += uvcount * sizeof(uc_value_t *); 1302 size += datasize = (datasize + 7) & ~7; 1303 1304 res = xalloc(size); 1305 res->header.type = UC_RESOURCE; 1306 res->header.refcount = 1; 1307 res->header.ext_flag = 1; 1308 res->type = type; 1309 res->uvcount = uvcount; 1310 res->datasize = datasize / 8; 1311 if (data) 1312 *data = res + 1; 1313 1314 if (vm && uvcount) { 1315 ucv_ref_tail(&vm->values, &res->ref); 1316 vm->alloc_refs++; 1317 } 1318 1319 return &res->header; 1320 } 1321 1322 static bool 1323 ucv_resource_check(uc_value_t *uv, const char *name) 1324 { 1325 uc_resource_type_t *restype; 1326 1327 if (ucv_type(uv) != UC_RESOURCE) 1328 return false; 1329 1330 if (!name) 1331 return true; 1332 1333 restype = ucv_resource_type(uv); 1334 1335 return restype && !strcmp(restype->name, name); 1336 } 1337 1338 void * 1339 ucv_resource_data(uc_value_t *uv, const char *name) 1340 { 1341 if (!ucv_resource_check(uv, name)) 1342 return NULL; 1343 1344 if (uv->ext_flag) { 1345 uc_resource_ext_t *res = (uc_resource_ext_t *)uv; 1346 1347 return res + 1; 1348 } 1349 else { 1350 uc_resource_t *res = (uc_resource_t *)uv; 1351 1352 return res->data; 1353 } 1354 } 1355 1356 void ** 1357 ucv_resource_dataptr(uc_value_t *uv, const char *name) 1358 { 1359 uc_resource_t *res = (uc_resource_t *)uv; 1360 1361 if (!ucv_resource_check(uv, name) || res->header.ext_flag) 1362 return NULL; 1363 1364 return &res->data; 1365 } 1366 1367 uc_value_t * 1368 ucv_resource_value_get(uc_value_t *uv, size_t idx) 1369 { 1370 uc_resource_ext_t *res = (uc_resource_ext_t *)uv; 1371 uc_value_t **uvdata = ucv_resource_values(res); 1372 1373 if (!uvdata || idx >= res->uvcount) 1374 return NULL; 1375 1376 return uvdata[idx]; 1377 } 1378 1379 bool 1380 ucv_resource_value_set(uc_value_t *uv, size_t idx, uc_value_t *val) 1381 { 1382 uc_resource_ext_t *res = (uc_resource_ext_t *)uv; 1383 uc_value_t **uvdata = ucv_resource_values(res); 1384 1385 if (!uvdata || idx >= res->uvcount) 1386 return NULL; 1387 1388 ucv_put(uvdata[idx]); 1389 uvdata[idx] = val; 1390 1391 return true; 1392 } 1393 1394 uc_value_t * 1395 ucv_regexp_new(const char *pattern, bool icase, bool newline, bool global, char **error) 1396 { 1397 int cflags = REG_EXTENDED, res; 1398 uc_regexp_t *re; 1399 size_t len; 1400 1401 re = xalloc(sizeof(*re) + strlen(pattern) + 1); 1402 re->header.type = UC_REGEXP; 1403 re->header.refcount = 1; 1404 re->icase = icase; 1405 re->global = global; 1406 re->newline = newline; 1407 strcpy(re->source, pattern); 1408 1409 if (icase) 1410 cflags |= REG_ICASE; 1411 1412 if (!newline) 1413 cflags |= REG_NEWLINE; 1414 1415 res = regcomp(&re->regexp, pattern, cflags); 1416 1417 if (res != 0) { 1418 if (error) { 1419 len = regerror(res, &re->regexp, NULL, 0); 1420 *error = xalloc(len); 1421 1422 regerror(res, &re->regexp, *error, len); 1423 } 1424 1425 free(re); 1426 1427 return NULL; 1428 } 1429 1430 return &re->header; 1431 } 1432 1433 1434 uc_value_t * 1435 ucv_upvalref_new(size_t slot) 1436 { 1437 uc_upvalref_t *up; 1438 1439 up = xalloc(sizeof(*up)); 1440 up->header.type = UC_UPVALUE; 1441 up->header.refcount = 1; 1442 up->slot = slot; 1443 1444 return &up->header; 1445 } 1446 1447 1448 uc_value_t * 1449 ucv_prototype_get(uc_value_t *uv) 1450 { 1451 uc_resource_type_t *restype; 1452 uc_object_t *object; 1453 uc_array_t *array; 1454 1455 switch (ucv_type(uv)) { 1456 case UC_ARRAY: 1457 array = (uc_array_t *)uv; 1458 1459 return array->proto; 1460 1461 case UC_OBJECT: 1462 object = (uc_object_t *)uv; 1463 1464 return object->proto; 1465 1466 case UC_RESOURCE: 1467 restype = ucv_resource_type(uv); 1468 1469 return restype ? restype->proto : NULL; 1470 1471 default: 1472 return NULL; 1473 } 1474 } 1475 1476 bool 1477 ucv_prototype_set(uc_value_t *uv, uc_value_t *proto) 1478 { 1479 uc_object_t *object; 1480 uc_array_t *array; 1481 1482 if (ucv_type(proto) != UC_OBJECT) 1483 return false; 1484 1485 switch (ucv_type(uv)) { 1486 case UC_ARRAY: 1487 array = (uc_array_t *)uv; 1488 ucv_put(array->proto); 1489 array->proto = proto; 1490 1491 return true; 1492 1493 case UC_OBJECT: 1494 object = (uc_object_t *)uv; 1495 ucv_put(object->proto); 1496 object->proto = proto; 1497 1498 return true; 1499 1500 default: 1501 return false; 1502 } 1503 } 1504 1505 uc_value_t * 1506 ucv_property_get(uc_value_t *uv, const char *key) 1507 { 1508 uc_value_t *val; 1509 bool found; 1510 1511 for (; uv; uv = ucv_prototype_get(uv)) { 1512 val = ucv_object_get(uv, key, &found); 1513 1514 if (found) 1515 return val; 1516 } 1517 1518 return NULL; 1519 } 1520 1521 1522 uc_value_t * 1523 ucv_from_json(uc_vm_t *vm, json_object *jso) 1524 { 1525 //uc_array_t *arr; 1526 uc_value_t *uv, *item; 1527 int64_t n; 1528 size_t i; 1529 1530 switch (json_object_get_type(jso)) { 1531 case json_type_null: 1532 return NULL; 1533 1534 case json_type_boolean: 1535 return ucv_boolean_new(json_object_get_boolean(jso)); 1536 1537 case json_type_double: 1538 return ucv_double_new(json_object_get_double(jso)); 1539 1540 case json_type_int: 1541 n = json_object_get_int64(jso); 1542 1543 if (n == INT64_MAX) 1544 return ucv_uint64_new(json_object_get_uint64(jso)); 1545 1546 return ucv_int64_new(n); 1547 1548 case json_type_object: 1549 uv = ucv_object_new(vm); 1550 1551 json_object_object_foreach(jso, key, val) { 1552 item = ucv_from_json(vm, val); 1553 1554 if (!ucv_object_add(uv, key, item)) 1555 ucv_put(item); 1556 1557 #ifdef __clang_analyzer__ 1558 /* Clang static analyzer does not understand that the object retains 1559 * our item so pretend to free it here to suppress the false positive 1560 * memory leak warning. */ 1561 ucv_put(item); 1562 #endif 1563 } 1564 1565 return uv; 1566 1567 case json_type_array: 1568 /* XXX 1569 arr = (uc_array_t *)ucv_array_new_length(vm, json_object_array_length(jso)); 1570 1571 for (i = 0; i < arr->count; i++) 1572 arr->entries[i] = ucv_from_json(vm, json_object_array_get_idx(jso, i)); 1573 1574 return &arr->header; 1575 */ 1576 uv = ucv_array_new(vm); 1577 1578 for (i = 0; i < json_object_array_length(jso); i++) { 1579 item = ucv_from_json(vm, json_object_array_get_idx(jso, i)); 1580 1581 if (!ucv_array_push(uv, item)) 1582 ucv_put(item); 1583 1584 #ifdef __clang_analyzer__ 1585 /* Clang static analyzer does not understand that the array retains 1586 * our item so pretend to free it here to suppress the false positive 1587 * memory leak warning. */ 1588 ucv_put(item); 1589 #endif 1590 } 1591 1592 return uv; 1593 1594 case json_type_string: 1595 return ucv_string_new_length(json_object_get_string(jso), json_object_get_string_len(jso)); 1596 } 1597 1598 return NULL; 1599 } 1600 1601 json_object * 1602 ucv_to_json(uc_value_t *uv) 1603 { 1604 uc_regexp_t *regexp; 1605 uc_array_t *array; 1606 json_object *jso; 1607 size_t i; 1608 char *s; 1609 1610 switch (ucv_type(uv)) { 1611 case UC_BOOLEAN: 1612 return json_object_new_boolean(ucv_boolean_get(uv)); 1613 1614 case UC_INTEGER: 1615 if (ucv_is_u64(uv)) 1616 return json_object_new_uint64(ucv_uint64_get(uv)); 1617 1618 return json_object_new_int64(ucv_int64_get(uv)); 1619 1620 case UC_DOUBLE: 1621 return json_object_new_double(ucv_double_get(uv)); 1622 1623 case UC_STRING: 1624 return json_object_new_string_len(ucv_string_get(uv), ucv_string_length(uv)); 1625 1626 case UC_ARRAY: 1627 array = (uc_array_t *)uv; 1628 jso = json_object_new_array_ext(array->count); 1629 1630 for (i = 0; i < array->count; i++) 1631 json_object_array_put_idx(jso, i, ucv_to_json(array->entries[i])); 1632 1633 return jso; 1634 1635 case UC_OBJECT: 1636 jso = json_object_new_object(); 1637 1638 ucv_object_foreach(uv, key, val) 1639 json_object_object_add(jso, key, ucv_to_json(val)); 1640 1641 return jso; 1642 1643 case UC_REGEXP: 1644 regexp = (uc_regexp_t *)uv; 1645 i = asprintf(&s, "/%s/%s%s%s", 1646 regexp->source, 1647 regexp->global ? "g" : "", 1648 regexp->icase ? "i" : "", 1649 regexp->newline ? "s" : ""); 1650 1651 if (i <= 0) 1652 return NULL; 1653 1654 jso = json_object_new_string_len(s, i); 1655 1656 free(s); 1657 1658 return jso; 1659 1660 case UC_CLOSURE: 1661 case UC_CFUNCTION: 1662 case UC_RESOURCE: 1663 case UC_UPVALUE: 1664 case UC_PROGRAM: 1665 case UC_SOURCE: 1666 case UC_NULL: 1667 return NULL; 1668 } 1669 1670 return NULL; 1671 } 1672 1673 static void 1674 ucv_to_string_json_encoded(uc_stringbuf_t *pb, const char *s, size_t len, bool regexp) 1675 { 1676 size_t i; 1677 1678 if (!regexp) 1679 ucv_stringbuf_append(pb, "\""); 1680 1681 for (i = 0; s != NULL && i < len; i++, s++) { 1682 switch (*s) { 1683 case '"': 1684 ucv_stringbuf_append(pb, "\\\""); 1685 break; 1686 1687 case '\\': 1688 ucv_stringbuf_append(pb, "\\\\"); 1689 break; 1690 1691 case '\b': 1692 ucv_stringbuf_append(pb, "\\b"); 1693 break; 1694 1695 case '\f': 1696 ucv_stringbuf_append(pb, "\\f"); 1697 break; 1698 1699 case '\n': 1700 ucv_stringbuf_append(pb, "\\n"); 1701 break; 1702 1703 case '\r': 1704 ucv_stringbuf_append(pb, "\\r"); 1705 break; 1706 1707 case '\t': 1708 ucv_stringbuf_append(pb, "\\t"); 1709 break; 1710 1711 case '/': 1712 ucv_stringbuf_append(pb, "/"); 1713 break; 1714 1715 default: 1716 if ((unsigned char)*s < 0x20) 1717 ucv_stringbuf_printf(pb, "\\u%04x", (unsigned char)*s); 1718 else 1719 ucv_stringbuf_addstr(pb, s, 1); 1720 1721 break; 1722 } 1723 } 1724 1725 if (!regexp) 1726 ucv_stringbuf_append(pb, "\""); 1727 } 1728 1729 static bool 1730 ucv_call_tostring(uc_vm_t *vm, uc_stringbuf_t *pb, uc_value_t *uv, bool json) 1731 { 1732 uc_value_t *proto = ucv_prototype_get(uv); 1733 uc_value_t *tostr = ucv_object_get(proto, "tostring", NULL); 1734 uc_value_t *str; 1735 size_t l; 1736 char *s; 1737 1738 if (!ucv_is_callable(tostr)) 1739 return false; 1740 1741 uc_vm_stack_push(vm, ucv_get(uv)); 1742 uc_vm_stack_push(vm, ucv_get(tostr)); 1743 1744 if (uc_vm_call(vm, true, 0) != EXCEPTION_NONE) 1745 return false; 1746 1747 str = uc_vm_stack_pop(vm); 1748 1749 if (ucv_type(str) == UC_STRING) { 1750 s = ucv_string_get(str); 1751 l = ucv_string_length(str); 1752 1753 if (json) 1754 ucv_to_string_json_encoded(pb, s, l, false); 1755 else if (s) 1756 ucv_stringbuf_addstr(pb, s, l); 1757 } 1758 else if (json) { 1759 ucv_stringbuf_append(pb, "\"\""); 1760 } 1761 1762 ucv_put(str); 1763 1764 return true; 1765 } 1766 1767 void 1768 _ucv_stringbuf_append(uc_stringbuf_t *pb, const char *str, size_t len) 1769 { 1770 printbuf_memappend_fast(pb, str, (int)len); 1771 } 1772 1773 static void 1774 ucv_to_stringbuf_add_padding(uc_stringbuf_t *pb, char pad_char, size_t pad_size) 1775 { 1776 if (pad_char != '\0' && pad_char != '\1') { 1777 ucv_stringbuf_append(pb, "\n"); 1778 printbuf_memset(pb, -1, pad_char, pad_size); 1779 } 1780 else { 1781 ucv_stringbuf_append(pb, " "); 1782 } 1783 } 1784 1785 static void 1786 ucv_to_stringbuf_add_double(uc_stringbuf_t *pb, double val, bool json) 1787 { 1788 int len = ucv_stringbuf_printf(pb, "%.14g", val); 1789 1790 if (!json) 1791 return; 1792 1793 for (char *p = pb->buf + pb->bpos - len; len > 0; len--, p++) 1794 if (*p == '.' || *p == 'e') 1795 return; 1796 1797 ucv_stringbuf_append(pb, ".0"); 1798 } 1799 1800 void 1801 ucv_to_stringbuf_formatted(uc_vm_t *vm, uc_stringbuf_t *pb, uc_value_t *uv, size_t depth, char pad_char, size_t pad_size) 1802 { 1803 bool json = (pad_char != '\0'); 1804 uc_resource_type_t *restype; 1805 uc_cfunction_t *cfunction; 1806 uc_function_t *function; 1807 uc_closure_t *closure; 1808 uc_regexp_t *regexp; 1809 uc_value_t *argname; 1810 uc_upvalref_t *ref; 1811 uc_array_t *array; 1812 size_t i, l; 1813 double d; 1814 char *s; 1815 1816 if (ucv_is_marked(uv)) { 1817 ucv_stringbuf_append(pb, "null"); 1818 1819 return; 1820 } 1821 1822 if (vm != NULL && ucv_call_tostring(vm, pb, uv, json)) 1823 return; 1824 1825 ucv_set_mark(uv); 1826 1827 switch (ucv_type(uv)) { 1828 case UC_NULL: 1829 ucv_stringbuf_append(pb, "null"); 1830 break; 1831 1832 case UC_BOOLEAN: 1833 if (ucv_boolean_get(uv)) 1834 ucv_stringbuf_append(pb, "true"); 1835 else 1836 ucv_stringbuf_append(pb, "false"); 1837 break; 1838 1839 case UC_INTEGER: 1840 if (ucv_is_u64(uv)) 1841 ucv_stringbuf_printf(pb, "%" PRIu64, ucv_uint64_get(uv)); 1842 else 1843 ucv_stringbuf_printf(pb, "%" PRId64, ucv_int64_get(uv)); 1844 break; 1845 1846 case UC_DOUBLE: 1847 d = ucv_double_get(uv); 1848 1849 if (json && isnan(d)) 1850 ucv_stringbuf_append(pb, "\"NaN\""); 1851 else if (json && d == INFINITY) 1852 ucv_stringbuf_append(pb, "1e309"); 1853 else if (json && d == -INFINITY) 1854 ucv_stringbuf_append(pb, "-1e309"); 1855 else if (isnan(d)) 1856 ucv_stringbuf_append(pb, "NaN"); 1857 else if (d == INFINITY) 1858 ucv_stringbuf_append(pb, "Infinity"); 1859 else if (d == -INFINITY) 1860 ucv_stringbuf_append(pb, "-Infinity"); 1861 else 1862 ucv_to_stringbuf_add_double(pb, d, json); 1863 1864 break; 1865 1866 case UC_STRING: 1867 s = ucv_string_get(uv); 1868 l = ucv_string_length(uv); 1869 1870 if (s) { 1871 if (json) 1872 ucv_to_string_json_encoded(pb, s, l, false); 1873 else 1874 ucv_stringbuf_addstr(pb, s, l); 1875 } 1876 1877 break; 1878 1879 case UC_ARRAY: 1880 array = (uc_array_t *)uv; 1881 1882 ucv_stringbuf_append(pb, "["); 1883 1884 for (i = 0; i < array->count; i++) { 1885 if (i) 1886 ucv_stringbuf_append(pb, ","); 1887 1888 ucv_to_stringbuf_add_padding(pb, pad_char, (depth + 1) * pad_size); 1889 ucv_to_stringbuf_formatted(vm, pb, array->entries[i], depth + 1, pad_char ? pad_char : '\1', pad_size); 1890 } 1891 1892 ucv_to_stringbuf_add_padding(pb, pad_char, depth * pad_size); 1893 ucv_stringbuf_append(pb, "]"); 1894 break; 1895 1896 case UC_OBJECT: 1897 ucv_stringbuf_append(pb, "{"); 1898 1899 i = 0; 1900 ucv_object_foreach(uv, key, val) { 1901 if (i++) 1902 ucv_stringbuf_append(pb, ","); 1903 1904 ucv_to_stringbuf_add_padding(pb, pad_char, (depth + 1) * pad_size); 1905 ucv_to_string_json_encoded(pb, key, strlen(key), false); 1906 ucv_stringbuf_append(pb, ": "); 1907 ucv_to_stringbuf_formatted(vm, pb, val, depth + 1, pad_char ? pad_char : '\1', pad_size); 1908 } 1909 1910 ucv_to_stringbuf_add_padding(pb, pad_char, depth * pad_size); 1911 ucv_stringbuf_append(pb, "}"); 1912 break; 1913 1914 case UC_REGEXP: 1915 regexp = (uc_regexp_t *)uv; 1916 1917 if (json) 1918 ucv_stringbuf_append(pb, "\""); 1919 1920 ucv_stringbuf_append(pb, "/"); 1921 ucv_to_string_json_encoded(pb, regexp->source, strlen(regexp->source), true); 1922 ucv_stringbuf_append(pb, "/"); 1923 1924 if (regexp->global) 1925 ucv_stringbuf_append(pb, "g"); 1926 1927 if (regexp->icase) 1928 ucv_stringbuf_append(pb, "i"); 1929 1930 if (regexp->newline) 1931 ucv_stringbuf_append(pb, "s"); 1932 1933 if (json) 1934 ucv_stringbuf_append(pb, "\""); 1935 1936 break; 1937 1938 case UC_CLOSURE: 1939 closure = (uc_closure_t *)uv; 1940 function = closure->function; 1941 1942 if (json) 1943 ucv_stringbuf_append(pb, "\""); 1944 1945 if (!closure->is_arrow) { 1946 ucv_stringbuf_append(pb, "function"); 1947 1948 if (function->name[0]) { 1949 ucv_stringbuf_append(pb, " "); 1950 ucv_stringbuf_addstr(pb, function->name, strlen(function->name)); 1951 } 1952 } 1953 1954 ucv_stringbuf_append(pb, "("); 1955 1956 for (i = 1; i <= function->nargs; i++) { 1957 argname = uc_chunk_debug_get_variable(&function->chunk, i - 1, i, false); 1958 1959 if (i > 1) 1960 ucv_stringbuf_append(pb, ", "); 1961 1962 if (i == function->nargs && function->vararg) 1963 ucv_stringbuf_append(pb, "..."); 1964 1965 if (argname) { 1966 s = ucv_string_get(argname); 1967 l = ucv_string_length(argname); 1968 1969 if (s) 1970 ucv_stringbuf_addstr(pb, s, l); 1971 1972 ucv_put(argname); 1973 1974 continue; 1975 } 1976 1977 ucv_stringbuf_printf(pb, "[arg%zu]", i); 1978 } 1979 1980 ucv_stringbuf_printf(pb, ")%s { ... }%s", 1981 closure->is_arrow ? " =>" : "", 1982 json ? "\"" : ""); 1983 1984 break; 1985 1986 case UC_CFUNCTION: 1987 cfunction = (uc_cfunction_t *)uv; 1988 1989 ucv_stringbuf_printf(pb, "%sfunction%s%s(...) { [native code] }%s", 1990 json ? "\"" : "", 1991 cfunction->name[0] ? " " : "", 1992 cfunction->name[0] ? cfunction->name : "", 1993 json ? "\"" : ""); 1994 1995 break; 1996 1997 case UC_RESOURCE: 1998 restype = ucv_resource_type(uv); 1999 2000 ucv_stringbuf_printf(pb, "%s<%s %p>%s", 2001 json ? "\"" : "", 2002 restype ? restype->name : "resource", 2003 ucv_resource_data(uv, NULL), 2004 json ? "\"" : ""); 2005 2006 break; 2007 2008 case UC_UPVALUE: 2009 ref = (uc_upvalref_t *)uv; 2010 2011 if (ref->closed) 2012 ucv_to_stringbuf_formatted(vm, pb, ref->value, depth, pad_char, pad_size); 2013 else if (vm != NULL && ref->slot < vm->stack.count) 2014 ucv_to_stringbuf_formatted(vm, pb, vm->stack.entries[ref->slot], depth, pad_char, pad_size); 2015 else 2016 ucv_stringbuf_printf(pb, "%s<upvalref %p>%s", 2017 json ? "\"" : "", 2018 uv, 2019 json ? "\"" : ""); 2020 2021 break; 2022 2023 case UC_PROGRAM: 2024 ucv_stringbuf_printf(pb, "%s<program %p>%s", 2025 json ? "\"" : "", 2026 uv, 2027 json ? "\"" : ""); 2028 2029 break; 2030 2031 case UC_SOURCE: 2032 ucv_stringbuf_printf(pb, "%s<source %p>%s", 2033 json ? "\"" : "", 2034 uv, 2035 json ? "\"" : ""); 2036 } 2037 2038 ucv_clear_mark(uv); 2039 } 2040 2041 static char * 2042 ucv_to_string_any(uc_vm_t *vm, uc_value_t *uv, char pad_char, size_t pad_size) 2043 { 2044 uc_stringbuf_t *pb = xprintbuf_new(); 2045 char *rv; 2046 2047 ucv_to_stringbuf_formatted(vm, pb, uv, 0, pad_char, pad_size); 2048 2049 rv = pb->buf; 2050 2051 free(pb); 2052 2053 return rv; 2054 } 2055 2056 char * 2057 ucv_to_string(uc_vm_t *vm, uc_value_t *uv) 2058 { 2059 return ucv_to_string_any(vm, uv, '\0', 0); 2060 } 2061 2062 char * 2063 ucv_to_jsonstring_formatted(uc_vm_t *vm, uc_value_t *uv, char pad_char, size_t pad_size) 2064 { 2065 return ucv_to_string_any(vm, uv, pad_char ? pad_char : '\1', pad_size); 2066 } 2067 2068 2069 bool 2070 ucv_is_equal(uc_value_t *uv1, uc_value_t *uv2) 2071 { 2072 uc_type_t t1 = ucv_type(uv1); 2073 uc_type_t t2 = ucv_type(uv2); 2074 const char *s1, *s2; 2075 uint64_t u1, u2; 2076 int64_t n1, n2; 2077 bool b1, b2; 2078 2079 if (t1 != t2) 2080 return false; 2081 2082 if (t1 != UC_DOUBLE && uv1 == uv2) 2083 return true; 2084 2085 switch (t1) { 2086 case UC_NULL: 2087 return true; 2088 2089 case UC_BOOLEAN: 2090 return ucv_boolean_get(uv1) == ucv_boolean_get(uv2); 2091 2092 case UC_DOUBLE: 2093 return ucv_double_get(uv1) == ucv_double_get(uv2); 2094 2095 case UC_INTEGER: 2096 n1 = ucv_int64_get(uv1); 2097 b1 = (errno == 0); 2098 2099 n2 = ucv_int64_get(uv2); 2100 b2 = (errno == 0); 2101 2102 if (b1 && b2) 2103 return (n1 == n2); 2104 2105 u1 = ucv_uint64_get(uv1); 2106 b1 = (errno == 0); 2107 2108 u2 = ucv_uint64_get(uv2); 2109 b2 = (errno == 0); 2110 2111 if (b1 && b2) 2112 return (u1 == u2); 2113 2114 return false; 2115 2116 case UC_STRING: 2117 s1 = ucv_string_get(uv1); 2118 s2 = ucv_string_get(uv2); 2119 u1 = ucv_string_length(uv1); 2120 u2 = ucv_string_length(uv2); 2121 2122 if (s1 == NULL || s2 == NULL || u1 != u2) 2123 return false; 2124 2125 return (memcmp(s1, s2, u1) == 0); 2126 2127 case UC_ARRAY: 2128 u1 = ucv_array_length(uv1); 2129 u2 = ucv_array_length(uv2); 2130 2131 if (u1 != u2) 2132 return false; 2133 2134 for (u1 = 0; u1 < u2; u1++) 2135 if (!ucv_is_equal(ucv_array_get(uv1, u1), ucv_array_get(uv2, u1))) 2136 return false; 2137 2138 return true; 2139 2140 case UC_OBJECT: 2141 u1 = ucv_object_length(uv1); 2142 u2 = ucv_object_length(uv2); 2143 2144 if (u1 != u2) 2145 return false; 2146 2147 ucv_object_foreach(uv1, key, val) { 2148 if (!ucv_is_equal(val, ucv_object_get(uv2, key, NULL))) 2149 return false; 2150 } 2151 2152 ucv_object_foreach(uv2, key2, val2) { 2153 (void)val2; 2154 ucv_object_get(uv1, key2, &b1); 2155 2156 if (!b1) 2157 return false; 2158 } 2159 2160 return true; 2161 2162 default: 2163 return false; 2164 } 2165 } 2166 2167 bool 2168 ucv_is_truish(uc_value_t *val) 2169 { 2170 double d; 2171 2172 switch (ucv_type(val)) { 2173 case UC_INTEGER: 2174 if (ucv_is_u64(val)) 2175 return (ucv_uint64_get(val) != 0); 2176 2177 return (ucv_int64_get(val) != 0); 2178 2179 case UC_DOUBLE: 2180 d = ucv_double_get(val); 2181 2182 return (d != 0 && !isnan(d)); 2183 2184 case UC_BOOLEAN: 2185 return ucv_boolean_get(val); 2186 2187 case UC_STRING: 2188 return (ucv_string_length(val) > 0); 2189 2190 case UC_NULL: 2191 return false; 2192 2193 default: 2194 return true; 2195 } 2196 } 2197 2198 uc_value_t * 2199 ucv_to_number(uc_value_t *v) 2200 { 2201 switch (ucv_type(v)) { 2202 case UC_NULL: 2203 return ucv_uint64_new(0); 2204 2205 case UC_BOOLEAN: 2206 return ucv_uint64_new(ucv_boolean_get(v)); 2207 2208 case UC_INTEGER: 2209 return ucv_get(v); 2210 2211 case UC_DOUBLE: 2212 if (isnan(ucv_double_get(v))) 2213 return NULL; 2214 2215 return ucv_get(v); 2216 2217 case UC_STRING: 2218 return uc_number_parse(ucv_string_get(v), NULL); 2219 2220 default: 2221 return NULL; 2222 } 2223 } 2224 2225 bool 2226 ucv_compare(int how, uc_value_t *v1, uc_value_t *v2, int *deltap) 2227 { 2228 uc_type_t t1 = ucv_type(v1); 2229 uc_type_t t2 = ucv_type(v2); 2230 uc_value_t *nv1, *nv2; 2231 uint64_t u1, u2; 2232 int64_t n1, n2; 2233 double d1, d2; 2234 int delta; 2235 2236 /* at least one operand is null and we compare for equality or inequality ... */ 2237 if ((!v1 || !v2) && (how == I_EQ || how == I_NE)) { 2238 delta = (v1 != v2); 2239 } 2240 2241 /* ... otherwise if both operands are strings, compare bytewise ... */ 2242 else if (t1 == UC_STRING && t2 == UC_STRING) { 2243 u1 = ucv_string_length(v1); 2244 u2 = ucv_string_length(v2); 2245 2246 delta = memcmp(ucv_string_get(v1), ucv_string_get(v2), 2247 (u1 < u2) ? u1 : u2); 2248 2249 if (delta == 0 && u1 < u2) 2250 delta = -1; 2251 else if (delta == 0 && u1 > u2) 2252 delta = 1; 2253 } 2254 2255 /* handle non-string cases... */ 2256 else { 2257 /* ... both operands are of the same, non-scalar type... */ 2258 if (t1 == t2 && !ucv_is_scalar(v1)) { 2259 /* ... compare memory addrs */ 2260 if ((uintptr_t)v1 == (uintptr_t)v2) 2261 delta = 0; 2262 else if ((uintptr_t)v1 < (uintptr_t)v2) 2263 delta = -1; 2264 else 2265 delta = 1; 2266 } 2267 2268 /* ... operands are of different type or at least one is scalar... */ 2269 else { 2270 nv1 = ucv_to_number(v1); 2271 nv2 = ucv_to_number(v2); 2272 2273 /* ... at least one of them is NaN (not convertible)... */ 2274 if (!nv1 || !nv2) { 2275 ucv_put(nv1); 2276 ucv_put(nv2); 2277 2278 if (deltap) 2279 *deltap = 2; 2280 2281 /* ... all comparison results except `!=` involving NaN are false */ 2282 return (how == I_NE); 2283 } 2284 2285 /* ... either of them is a double, compare both as double */ 2286 if (ucv_type(nv1) == UC_DOUBLE || ucv_type(nv2) == UC_DOUBLE) { 2287 d1 = ucv_double_get(nv1); 2288 d2 = ucv_double_get(nv2); 2289 2290 if (d1 == d2) 2291 delta = 0; 2292 else if (d1 < d2) 2293 delta = -1; 2294 else 2295 delta = 1; 2296 } 2297 2298 /* ... both are integers... */ 2299 else { 2300 n1 = ucv_int64_get(nv1); 2301 2302 /* ... left operand is large positive... */ 2303 if (errno == ERANGE) { 2304 ucv_int64_get(nv2); 2305 2306 /* ... right operand is large positive too... */ 2307 if (errno == ERANGE) { 2308 /* ... compare both as unsigned */ 2309 u1 = ucv_uint64_get(nv1); 2310 u2 = ucv_uint64_get(nv2); 2311 2312 if (u1 == u2) 2313 delta = 0; 2314 else if (u1 < u2) 2315 delta = -1; 2316 else 2317 delta = 1; 2318 } 2319 2320 /* ... right operand is within int64_t range... */ 2321 else { 2322 /* ... left > right by definition */ 2323 delta = 1; 2324 } 2325 } 2326 2327 /* ... left operand is within int64_t range... */ 2328 else { 2329 n2 = ucv_int64_get(nv2); 2330 2331 /* ... right operand is large positive... */ 2332 if (errno == ERANGE) { 2333 /* ... left < right by definition */ 2334 delta = -1; 2335 } 2336 2337 /* ... right operand is within int64_t range... */ 2338 else { 2339 /* ... compare both as signed */ 2340 if (n1 == n2) 2341 delta = 0; 2342 else if (n1 < n2) 2343 delta = -1; 2344 else 2345 delta = 1; 2346 } 2347 } 2348 } 2349 2350 ucv_put(nv1); 2351 ucv_put(nv2); 2352 } 2353 } 2354 2355 if (deltap) 2356 *deltap = delta; 2357 2358 switch (how) { 2359 case I_LT: 2360 return (delta < 0); 2361 2362 case I_LE: 2363 return (delta <= 0); 2364 2365 case I_GT: 2366 return (delta > 0); 2367 2368 case I_GE: 2369 return (delta >= 0); 2370 2371 case I_EQ: 2372 return (delta == 0); 2373 2374 case I_NE: 2375 return (delta != 0); 2376 2377 default: 2378 return false; 2379 } 2380 } 2381 2382 2383 static char * 2384 ucv_key_to_string(uc_vm_t *vm, uc_value_t *val) 2385 { 2386 if (ucv_type(val) != UC_STRING) 2387 return ucv_to_string(vm, val); 2388 2389 return NULL; 2390 } 2391 2392 static int64_t 2393 ucv_key_to_index(uc_value_t *val) 2394 { 2395 const char *k; 2396 int64_t idx; 2397 double d; 2398 char *e; 2399 2400 /* only consider doubles with integer values as array keys */ 2401 if (ucv_type(val) == UC_DOUBLE) { 2402 d = ucv_double_get(val); 2403 2404 if (trunc(d) != d) 2405 return INT64_MIN; 2406 2407 return (int64_t)d; 2408 } 2409 else if (ucv_type(val) == UC_INTEGER) { 2410 return ucv_int64_get(val); 2411 } 2412 else if (ucv_type(val) == UC_STRING) { 2413 errno = 0; 2414 k = ucv_string_get(val); 2415 idx = strtoll(k, &e, 0); 2416 2417 if (errno != 0 || e == k || *e != 0) 2418 return INT64_MIN; 2419 2420 return idx; 2421 } 2422 2423 return INT64_MIN; 2424 } 2425 2426 uc_value_t * 2427 ucv_key_get(uc_vm_t *vm, uc_value_t *scope, uc_value_t *key) 2428 { 2429 uc_value_t *o, *v = NULL; 2430 bool found = false; 2431 uc_upvalref_t *ref; 2432 int64_t idx; 2433 char *k; 2434 2435 if (ucv_type(scope) == UC_ARRAY) { 2436 idx = ucv_key_to_index(key); 2437 2438 if (idx < 0 && idx > INT64_MIN && (uint64_t)llabs(idx) <= ucv_array_length(scope)) 2439 idx += ucv_array_length(scope); 2440 2441 if (idx >= 0 && (uint64_t)idx < ucv_array_length(scope)) { 2442 v = ucv_array_get(scope, idx); 2443 found = true; 2444 } 2445 } 2446 2447 if (!found) { 2448 k = ucv_key_to_string(vm, key); 2449 2450 for (o = scope; o; o = ucv_prototype_get(o)) { 2451 if (ucv_type(o) != UC_OBJECT) 2452 continue; 2453 2454 v = ucv_object_get(o, k ? k : ucv_string_get(key), &found); 2455 2456 if (found) 2457 break; 2458 } 2459 2460 free(k); 2461 } 2462 2463 /* Handle upvalue values in objects; under some specific circumstances 2464 objects may contain upvalues, this primarily happens with wildcard module 2465 import namespace dictionaries. */ 2466 #ifdef __clang_analyzer__ 2467 /* Clang static analyzer does not understand that ucv_type(NULL) can't 2468 * possibly yield UC_UPVALUE. Nudge it. */ 2469 if (v != NULL && ucv_type(v) == UC_UPVALUE) 2470 #else 2471 if (ucv_type(v) == UC_UPVALUE) 2472 #endif 2473 { 2474 ref = (uc_upvalref_t *)v; 2475 2476 if (ref->closed) 2477 return ucv_get(ref->value); 2478 else if (vm) 2479 return ucv_get(vm->stack.entries[ref->slot]); 2480 else 2481 return NULL; 2482 } 2483 2484 return ucv_get(v); 2485 } 2486 2487 uc_value_t * 2488 ucv_key_set(uc_vm_t *vm, uc_value_t *scope, uc_value_t *key, uc_value_t *val) 2489 { 2490 int64_t idx; 2491 char *s; 2492 bool rv; 2493 2494 if (!key) 2495 return NULL; 2496 2497 if (ucv_type(scope) == UC_ARRAY) { 2498 idx = ucv_key_to_index(key); 2499 2500 if (idx < 0 && idx > INT64_MIN && (uint64_t)llabs(idx) <= ucv_array_length(scope)) 2501 idx += ucv_array_length(scope); 2502 2503 if (idx < 0 || !ucv_array_set(scope, idx, val)) 2504 return NULL; 2505 2506 return ucv_get(val); 2507 } 2508 2509 s = ucv_key_to_string(vm, key); 2510 rv = ucv_object_add(scope, s ? s : ucv_string_get(key), val); 2511 free(s); 2512 2513 return rv ? ucv_get(val) : NULL; 2514 } 2515 2516 bool 2517 ucv_key_delete(uc_vm_t *vm, uc_value_t *scope, uc_value_t *key) 2518 { 2519 char *s; 2520 bool rv; 2521 2522 if (!key) 2523 return NULL; 2524 2525 s = ucv_key_to_string(vm, key); 2526 rv = ucv_object_delete(scope, s ? s : ucv_string_get(key)); 2527 free(s); 2528 2529 return rv; 2530 } 2531 2532 2533 static void 2534 ucv_gc_common(uc_vm_t *vm, bool final) 2535 { 2536 uc_weakref_t *ref, *tmp; 2537 uc_value_t *val; 2538 size_t i; 2539 2540 vm->alloc_refs = 0; 2541 2542 /* back out early if value list is uninitialized */ 2543 if (!vm->values.prev || !vm->values.next) 2544 return; 2545 2546 if (!final) { 2547 /* mark reachable objects */ 2548 ucv_gc_mark(vm->globals); 2549 ucv_gc_mark(vm->registry); 2550 ucv_gc_mark(vm->signal.handler); 2551 ucv_gc_mark(vm->exception.stacktrace); 2552 2553 for (i = 0; i < vm->callframes.count; i++) { 2554 ucv_gc_mark(vm->callframes.entries[i].ctx); 2555 2556 if (vm->callframes.entries[i].closure) 2557 ucv_gc_mark(&vm->callframes.entries[i].closure->header); 2558 2559 if (vm->callframes.entries[i].cfunction) 2560 ucv_gc_mark(&vm->callframes.entries[i].cfunction->header); 2561 } 2562 2563 for (i = 0; i < vm->stack.count; i++) 2564 ucv_gc_mark(vm->stack.entries[i]); 2565 2566 for (i = 0; i < vm->restypes.count; i++) 2567 ucv_gc_mark(vm->restypes.entries[i]->proto); 2568 2569 /* mark no-gc resources with embedded values */ 2570 for (ref = vm->values.prev; ref != &vm->values; ref = ref->prev) { 2571 val = (uc_value_t *)((uintptr_t)ref - offsetof(uc_array_t, ref)); 2572 if (ucv_type(val) != UC_RESOURCE) 2573 break; 2574 2575 if (ucv_resource_is_persistent(val)) 2576 ucv_gc_mark(val); 2577 } 2578 } 2579 2580 /* unref unreachable objects */ 2581 for (ref = vm->values.next; ref != &vm->values; ref = ref->next) { 2582 val = (uc_value_t *)((uintptr_t)ref - offsetof(uc_array_t, ref)); 2583 2584 if (ucv_is_marked(val)) 2585 ucv_clear_mark(val); 2586 else 2587 ucv_free(val, true); 2588 } 2589 2590 /* free destroyed objects */ 2591 for (ref = vm->values.next, tmp = ref->next; ref != &vm->values; ref = tmp, tmp = tmp->next) { 2592 val = (uc_value_t *)((uintptr_t)ref - offsetof(uc_array_t, ref)); 2593 2594 if (val->type == UC_NULL) { 2595 ucv_unref(ref); 2596 free(val); 2597 } 2598 } 2599 } 2600 2601 void 2602 ucv_gc(uc_vm_t *vm) 2603 { 2604 ucv_gc_common(vm, false); 2605 } 2606 2607 void 2608 ucv_freeall(uc_vm_t *vm) 2609 { 2610 ucv_gc_common(vm, true); 2611 } 2612 2613 void 2614 uc_search_path_init(uc_search_path_t *search_path) 2615 { 2616 size_t i; 2617 2618 for (i = 0; i < ARRAY_SIZE(uc_default_search_path); i++) 2619 uc_vector_push(search_path, xstrdup(uc_default_search_path[i])); 2620 } 2621 2622 2623 static __thread uc_thread_context_t *tls_ctx; 2624 2625 uc_thread_context_t * 2626 uc_thread_context_get(void) 2627 { 2628 if (tls_ctx == NULL) { 2629 tls_ctx = xalloc(sizeof(*tls_ctx)); 2630 tls_ctx->object_iterators.prev = &tls_ctx->object_iterators; 2631 tls_ctx->object_iterators.next = &tls_ctx->object_iterators; 2632 } 2633 2634 return tls_ctx; 2635 } 2636 2637 void 2638 uc_thread_context_free(void) 2639 { 2640 free(tls_ctx); 2641 tls_ctx = NULL; 2642 } 2643
This page was automatically generated by LXR 0.3.1. • OpenWrt