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 array->proto = proto; 1489 1490 return true; 1491 1492 case UC_OBJECT: 1493 object = (uc_object_t *)uv; 1494 object->proto = proto; 1495 1496 return true; 1497 1498 default: 1499 return false; 1500 } 1501 } 1502 1503 uc_value_t * 1504 ucv_property_get(uc_value_t *uv, const char *key) 1505 { 1506 uc_value_t *val; 1507 bool found; 1508 1509 for (; uv; uv = ucv_prototype_get(uv)) { 1510 val = ucv_object_get(uv, key, &found); 1511 1512 if (found) 1513 return val; 1514 } 1515 1516 return NULL; 1517 } 1518 1519 1520 uc_value_t * 1521 ucv_from_json(uc_vm_t *vm, json_object *jso) 1522 { 1523 //uc_array_t *arr; 1524 uc_value_t *uv, *item; 1525 int64_t n; 1526 size_t i; 1527 1528 switch (json_object_get_type(jso)) { 1529 case json_type_null: 1530 return NULL; 1531 1532 case json_type_boolean: 1533 return ucv_boolean_new(json_object_get_boolean(jso)); 1534 1535 case json_type_double: 1536 return ucv_double_new(json_object_get_double(jso)); 1537 1538 case json_type_int: 1539 n = json_object_get_int64(jso); 1540 1541 if (n == INT64_MAX) 1542 return ucv_uint64_new(json_object_get_uint64(jso)); 1543 1544 return ucv_int64_new(n); 1545 1546 case json_type_object: 1547 uv = ucv_object_new(vm); 1548 1549 json_object_object_foreach(jso, key, val) { 1550 item = ucv_from_json(vm, val); 1551 1552 if (!ucv_object_add(uv, key, item)) 1553 ucv_put(item); 1554 1555 #ifdef __clang_analyzer__ 1556 /* Clang static analyzer does not understand that the object retains 1557 * our item so pretend to free it here to suppress the false positive 1558 * memory leak warning. */ 1559 ucv_put(item); 1560 #endif 1561 } 1562 1563 return uv; 1564 1565 case json_type_array: 1566 /* XXX 1567 arr = (uc_array_t *)ucv_array_new_length(vm, json_object_array_length(jso)); 1568 1569 for (i = 0; i < arr->count; i++) 1570 arr->entries[i] = ucv_from_json(vm, json_object_array_get_idx(jso, i)); 1571 1572 return &arr->header; 1573 */ 1574 uv = ucv_array_new(vm); 1575 1576 for (i = 0; i < json_object_array_length(jso); i++) { 1577 item = ucv_from_json(vm, json_object_array_get_idx(jso, i)); 1578 1579 if (!ucv_array_push(uv, item)) 1580 ucv_put(item); 1581 1582 #ifdef __clang_analyzer__ 1583 /* Clang static analyzer does not understand that the array retains 1584 * our item so pretend to free it here to suppress the false positive 1585 * memory leak warning. */ 1586 ucv_put(item); 1587 #endif 1588 } 1589 1590 return uv; 1591 1592 case json_type_string: 1593 return ucv_string_new_length(json_object_get_string(jso), json_object_get_string_len(jso)); 1594 } 1595 1596 return NULL; 1597 } 1598 1599 json_object * 1600 ucv_to_json(uc_value_t *uv) 1601 { 1602 uc_regexp_t *regexp; 1603 uc_array_t *array; 1604 json_object *jso; 1605 size_t i; 1606 char *s; 1607 1608 switch (ucv_type(uv)) { 1609 case UC_BOOLEAN: 1610 return json_object_new_boolean(ucv_boolean_get(uv)); 1611 1612 case UC_INTEGER: 1613 if (ucv_is_u64(uv)) 1614 return json_object_new_uint64(ucv_uint64_get(uv)); 1615 1616 return json_object_new_int64(ucv_int64_get(uv)); 1617 1618 case UC_DOUBLE: 1619 return json_object_new_double(ucv_double_get(uv)); 1620 1621 case UC_STRING: 1622 return json_object_new_string_len(ucv_string_get(uv), ucv_string_length(uv)); 1623 1624 case UC_ARRAY: 1625 array = (uc_array_t *)uv; 1626 jso = json_object_new_array_ext(array->count); 1627 1628 for (i = 0; i < array->count; i++) 1629 json_object_array_put_idx(jso, i, ucv_to_json(array->entries[i])); 1630 1631 return jso; 1632 1633 case UC_OBJECT: 1634 jso = json_object_new_object(); 1635 1636 ucv_object_foreach(uv, key, val) 1637 json_object_object_add(jso, key, ucv_to_json(val)); 1638 1639 return jso; 1640 1641 case UC_REGEXP: 1642 regexp = (uc_regexp_t *)uv; 1643 i = asprintf(&s, "/%s/%s%s%s", 1644 regexp->source, 1645 regexp->global ? "g" : "", 1646 regexp->icase ? "i" : "", 1647 regexp->newline ? "s" : ""); 1648 1649 if (i <= 0) 1650 return NULL; 1651 1652 jso = json_object_new_string_len(s, i); 1653 1654 free(s); 1655 1656 return jso; 1657 1658 case UC_CLOSURE: 1659 case UC_CFUNCTION: 1660 case UC_RESOURCE: 1661 case UC_UPVALUE: 1662 case UC_PROGRAM: 1663 case UC_SOURCE: 1664 case UC_NULL: 1665 return NULL; 1666 } 1667 1668 return NULL; 1669 } 1670 1671 static void 1672 ucv_to_string_json_encoded(uc_stringbuf_t *pb, const char *s, size_t len, bool regexp) 1673 { 1674 size_t i; 1675 1676 if (!regexp) 1677 ucv_stringbuf_append(pb, "\""); 1678 1679 for (i = 0; s != NULL && i < len; i++, s++) { 1680 switch (*s) { 1681 case '"': 1682 ucv_stringbuf_append(pb, "\\\""); 1683 break; 1684 1685 case '\\': 1686 ucv_stringbuf_append(pb, "\\\\"); 1687 break; 1688 1689 case '\b': 1690 ucv_stringbuf_append(pb, "\\b"); 1691 break; 1692 1693 case '\f': 1694 ucv_stringbuf_append(pb, "\\f"); 1695 break; 1696 1697 case '\n': 1698 ucv_stringbuf_append(pb, "\\n"); 1699 break; 1700 1701 case '\r': 1702 ucv_stringbuf_append(pb, "\\r"); 1703 break; 1704 1705 case '\t': 1706 ucv_stringbuf_append(pb, "\\t"); 1707 break; 1708 1709 case '/': 1710 ucv_stringbuf_append(pb, "/"); 1711 break; 1712 1713 default: 1714 if ((unsigned char)*s < 0x20) 1715 ucv_stringbuf_printf(pb, "\\u%04x", (unsigned char)*s); 1716 else 1717 ucv_stringbuf_addstr(pb, s, 1); 1718 1719 break; 1720 } 1721 } 1722 1723 if (!regexp) 1724 ucv_stringbuf_append(pb, "\""); 1725 } 1726 1727 static bool 1728 ucv_call_tostring(uc_vm_t *vm, uc_stringbuf_t *pb, uc_value_t *uv, bool json) 1729 { 1730 uc_value_t *proto = ucv_prototype_get(uv); 1731 uc_value_t *tostr = ucv_object_get(proto, "tostring", NULL); 1732 uc_value_t *str; 1733 size_t l; 1734 char *s; 1735 1736 if (!ucv_is_callable(tostr)) 1737 return false; 1738 1739 uc_vm_stack_push(vm, ucv_get(uv)); 1740 uc_vm_stack_push(vm, ucv_get(tostr)); 1741 1742 if (uc_vm_call(vm, true, 0) != EXCEPTION_NONE) 1743 return false; 1744 1745 str = uc_vm_stack_pop(vm); 1746 1747 if (ucv_type(str) == UC_STRING) { 1748 s = ucv_string_get(str); 1749 l = ucv_string_length(str); 1750 1751 if (json) 1752 ucv_to_string_json_encoded(pb, s, l, false); 1753 else if (s) 1754 ucv_stringbuf_addstr(pb, s, l); 1755 } 1756 else if (json) { 1757 ucv_stringbuf_append(pb, "\"\""); 1758 } 1759 1760 ucv_put(str); 1761 1762 return true; 1763 } 1764 1765 void 1766 _ucv_stringbuf_append(uc_stringbuf_t *pb, const char *str, size_t len) 1767 { 1768 printbuf_memappend_fast(pb, str, (int)len); 1769 } 1770 1771 static void 1772 ucv_to_stringbuf_add_padding(uc_stringbuf_t *pb, char pad_char, size_t pad_size) 1773 { 1774 if (pad_char != '\0' && pad_char != '\1') { 1775 ucv_stringbuf_append(pb, "\n"); 1776 printbuf_memset(pb, -1, pad_char, pad_size); 1777 } 1778 else { 1779 ucv_stringbuf_append(pb, " "); 1780 } 1781 } 1782 1783 static void 1784 ucv_to_stringbuf_add_double(uc_stringbuf_t *pb, double val, bool json) 1785 { 1786 int len = ucv_stringbuf_printf(pb, "%.14g", val); 1787 1788 if (!json) 1789 return; 1790 1791 for (char *p = pb->buf + pb->bpos - len; len > 0; len--, p++) 1792 if (*p == '.' || *p == 'e') 1793 return; 1794 1795 ucv_stringbuf_append(pb, ".0"); 1796 } 1797 1798 void 1799 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) 1800 { 1801 bool json = (pad_char != '\0'); 1802 uc_resource_type_t *restype; 1803 uc_cfunction_t *cfunction; 1804 uc_function_t *function; 1805 uc_closure_t *closure; 1806 uc_regexp_t *regexp; 1807 uc_value_t *argname; 1808 uc_upvalref_t *ref; 1809 uc_array_t *array; 1810 size_t i, l; 1811 double d; 1812 char *s; 1813 1814 if (ucv_is_marked(uv)) { 1815 ucv_stringbuf_append(pb, "null"); 1816 1817 return; 1818 } 1819 1820 if (vm != NULL && ucv_call_tostring(vm, pb, uv, json)) 1821 return; 1822 1823 ucv_set_mark(uv); 1824 1825 switch (ucv_type(uv)) { 1826 case UC_NULL: 1827 ucv_stringbuf_append(pb, "null"); 1828 break; 1829 1830 case UC_BOOLEAN: 1831 if (ucv_boolean_get(uv)) 1832 ucv_stringbuf_append(pb, "true"); 1833 else 1834 ucv_stringbuf_append(pb, "false"); 1835 break; 1836 1837 case UC_INTEGER: 1838 if (ucv_is_u64(uv)) 1839 ucv_stringbuf_printf(pb, "%" PRIu64, ucv_uint64_get(uv)); 1840 else 1841 ucv_stringbuf_printf(pb, "%" PRId64, ucv_int64_get(uv)); 1842 break; 1843 1844 case UC_DOUBLE: 1845 d = ucv_double_get(uv); 1846 1847 if (json && isnan(d)) 1848 ucv_stringbuf_append(pb, "\"NaN\""); 1849 else if (json && d == INFINITY) 1850 ucv_stringbuf_append(pb, "1e309"); 1851 else if (json && d == -INFINITY) 1852 ucv_stringbuf_append(pb, "-1e309"); 1853 else if (isnan(d)) 1854 ucv_stringbuf_append(pb, "NaN"); 1855 else if (d == INFINITY) 1856 ucv_stringbuf_append(pb, "Infinity"); 1857 else if (d == -INFINITY) 1858 ucv_stringbuf_append(pb, "-Infinity"); 1859 else 1860 ucv_to_stringbuf_add_double(pb, d, json); 1861 1862 break; 1863 1864 case UC_STRING: 1865 s = ucv_string_get(uv); 1866 l = ucv_string_length(uv); 1867 1868 if (s) { 1869 if (json) 1870 ucv_to_string_json_encoded(pb, s, l, false); 1871 else 1872 ucv_stringbuf_addstr(pb, s, l); 1873 } 1874 1875 break; 1876 1877 case UC_ARRAY: 1878 array = (uc_array_t *)uv; 1879 1880 ucv_stringbuf_append(pb, "["); 1881 1882 for (i = 0; i < array->count; i++) { 1883 if (i) 1884 ucv_stringbuf_append(pb, ","); 1885 1886 ucv_to_stringbuf_add_padding(pb, pad_char, (depth + 1) * pad_size); 1887 ucv_to_stringbuf_formatted(vm, pb, array->entries[i], depth + 1, pad_char ? pad_char : '\1', pad_size); 1888 } 1889 1890 ucv_to_stringbuf_add_padding(pb, pad_char, depth * pad_size); 1891 ucv_stringbuf_append(pb, "]"); 1892 break; 1893 1894 case UC_OBJECT: 1895 ucv_stringbuf_append(pb, "{"); 1896 1897 i = 0; 1898 ucv_object_foreach(uv, key, val) { 1899 if (i++) 1900 ucv_stringbuf_append(pb, ","); 1901 1902 ucv_to_stringbuf_add_padding(pb, pad_char, (depth + 1) * pad_size); 1903 ucv_to_string_json_encoded(pb, key, strlen(key), false); 1904 ucv_stringbuf_append(pb, ": "); 1905 ucv_to_stringbuf_formatted(vm, pb, val, depth + 1, pad_char ? pad_char : '\1', pad_size); 1906 } 1907 1908 ucv_to_stringbuf_add_padding(pb, pad_char, depth * pad_size); 1909 ucv_stringbuf_append(pb, "}"); 1910 break; 1911 1912 case UC_REGEXP: 1913 regexp = (uc_regexp_t *)uv; 1914 1915 if (json) 1916 ucv_stringbuf_append(pb, "\""); 1917 1918 ucv_stringbuf_append(pb, "/"); 1919 ucv_to_string_json_encoded(pb, regexp->source, strlen(regexp->source), true); 1920 ucv_stringbuf_append(pb, "/"); 1921 1922 if (regexp->global) 1923 ucv_stringbuf_append(pb, "g"); 1924 1925 if (regexp->icase) 1926 ucv_stringbuf_append(pb, "i"); 1927 1928 if (regexp->newline) 1929 ucv_stringbuf_append(pb, "s"); 1930 1931 if (json) 1932 ucv_stringbuf_append(pb, "\""); 1933 1934 break; 1935 1936 case UC_CLOSURE: 1937 closure = (uc_closure_t *)uv; 1938 function = closure->function; 1939 1940 if (json) 1941 ucv_stringbuf_append(pb, "\""); 1942 1943 if (!closure->is_arrow) { 1944 ucv_stringbuf_append(pb, "function"); 1945 1946 if (function->name[0]) { 1947 ucv_stringbuf_append(pb, " "); 1948 ucv_stringbuf_addstr(pb, function->name, strlen(function->name)); 1949 } 1950 } 1951 1952 ucv_stringbuf_append(pb, "("); 1953 1954 for (i = 1; i <= function->nargs; i++) { 1955 argname = uc_chunk_debug_get_variable(&function->chunk, i - 1, i, false); 1956 1957 if (i > 1) 1958 ucv_stringbuf_append(pb, ", "); 1959 1960 if (i == function->nargs && function->vararg) 1961 ucv_stringbuf_append(pb, "..."); 1962 1963 if (argname) { 1964 s = ucv_string_get(argname); 1965 l = ucv_string_length(argname); 1966 1967 if (s) 1968 ucv_stringbuf_addstr(pb, s, l); 1969 1970 ucv_put(argname); 1971 1972 continue; 1973 } 1974 1975 ucv_stringbuf_printf(pb, "[arg%zu]", i); 1976 } 1977 1978 ucv_stringbuf_printf(pb, ")%s { ... }%s", 1979 closure->is_arrow ? " =>" : "", 1980 json ? "\"" : ""); 1981 1982 break; 1983 1984 case UC_CFUNCTION: 1985 cfunction = (uc_cfunction_t *)uv; 1986 1987 ucv_stringbuf_printf(pb, "%sfunction%s%s(...) { [native code] }%s", 1988 json ? "\"" : "", 1989 cfunction->name[0] ? " " : "", 1990 cfunction->name[0] ? cfunction->name : "", 1991 json ? "\"" : ""); 1992 1993 break; 1994 1995 case UC_RESOURCE: 1996 restype = ucv_resource_type(uv); 1997 1998 ucv_stringbuf_printf(pb, "%s<%s %p>%s", 1999 json ? "\"" : "", 2000 restype ? restype->name : "resource", 2001 ucv_resource_data(uv, NULL), 2002 json ? "\"" : ""); 2003 2004 break; 2005 2006 case UC_UPVALUE: 2007 ref = (uc_upvalref_t *)uv; 2008 2009 if (ref->closed) 2010 ucv_to_stringbuf_formatted(vm, pb, ref->value, depth, pad_char, pad_size); 2011 else if (vm != NULL && ref->slot < vm->stack.count) 2012 ucv_to_stringbuf_formatted(vm, pb, vm->stack.entries[ref->slot], depth, pad_char, pad_size); 2013 else 2014 ucv_stringbuf_printf(pb, "%s<upvalref %p>%s", 2015 json ? "\"" : "", 2016 uv, 2017 json ? "\"" : ""); 2018 2019 break; 2020 2021 case UC_PROGRAM: 2022 ucv_stringbuf_printf(pb, "%s<program %p>%s", 2023 json ? "\"" : "", 2024 uv, 2025 json ? "\"" : ""); 2026 2027 break; 2028 2029 case UC_SOURCE: 2030 ucv_stringbuf_printf(pb, "%s<source %p>%s", 2031 json ? "\"" : "", 2032 uv, 2033 json ? "\"" : ""); 2034 } 2035 2036 ucv_clear_mark(uv); 2037 } 2038 2039 static char * 2040 ucv_to_string_any(uc_vm_t *vm, uc_value_t *uv, char pad_char, size_t pad_size) 2041 { 2042 uc_stringbuf_t *pb = xprintbuf_new(); 2043 char *rv; 2044 2045 ucv_to_stringbuf_formatted(vm, pb, uv, 0, pad_char, pad_size); 2046 2047 rv = pb->buf; 2048 2049 free(pb); 2050 2051 return rv; 2052 } 2053 2054 char * 2055 ucv_to_string(uc_vm_t *vm, uc_value_t *uv) 2056 { 2057 return ucv_to_string_any(vm, uv, '\0', 0); 2058 } 2059 2060 char * 2061 ucv_to_jsonstring_formatted(uc_vm_t *vm, uc_value_t *uv, char pad_char, size_t pad_size) 2062 { 2063 return ucv_to_string_any(vm, uv, pad_char ? pad_char : '\1', pad_size); 2064 } 2065 2066 2067 bool 2068 ucv_is_equal(uc_value_t *uv1, uc_value_t *uv2) 2069 { 2070 uc_type_t t1 = ucv_type(uv1); 2071 uc_type_t t2 = ucv_type(uv2); 2072 const char *s1, *s2; 2073 uint64_t u1, u2; 2074 int64_t n1, n2; 2075 bool b1, b2; 2076 2077 if (t1 != t2) 2078 return false; 2079 2080 if (t1 != UC_DOUBLE && uv1 == uv2) 2081 return true; 2082 2083 switch (t1) { 2084 case UC_NULL: 2085 return true; 2086 2087 case UC_BOOLEAN: 2088 return ucv_boolean_get(uv1) == ucv_boolean_get(uv2); 2089 2090 case UC_DOUBLE: 2091 return ucv_double_get(uv1) == ucv_double_get(uv2); 2092 2093 case UC_INTEGER: 2094 n1 = ucv_int64_get(uv1); 2095 b1 = (errno == 0); 2096 2097 n2 = ucv_int64_get(uv2); 2098 b2 = (errno == 0); 2099 2100 if (b1 && b2) 2101 return (n1 == n2); 2102 2103 u1 = ucv_uint64_get(uv1); 2104 b1 = (errno == 0); 2105 2106 u2 = ucv_uint64_get(uv2); 2107 b2 = (errno == 0); 2108 2109 if (b1 && b2) 2110 return (u1 == u2); 2111 2112 return false; 2113 2114 case UC_STRING: 2115 s1 = ucv_string_get(uv1); 2116 s2 = ucv_string_get(uv2); 2117 u1 = ucv_string_length(uv1); 2118 u2 = ucv_string_length(uv2); 2119 2120 if (s1 == NULL || s2 == NULL || u1 != u2) 2121 return false; 2122 2123 return (memcmp(s1, s2, u1) == 0); 2124 2125 case UC_ARRAY: 2126 u1 = ucv_array_length(uv1); 2127 u2 = ucv_array_length(uv2); 2128 2129 if (u1 != u2) 2130 return false; 2131 2132 for (u1 = 0; u1 < u2; u1++) 2133 if (!ucv_is_equal(ucv_array_get(uv1, u1), ucv_array_get(uv2, u1))) 2134 return false; 2135 2136 return true; 2137 2138 case UC_OBJECT: 2139 u1 = ucv_object_length(uv1); 2140 u2 = ucv_object_length(uv2); 2141 2142 if (u1 != u2) 2143 return false; 2144 2145 ucv_object_foreach(uv1, key, val) { 2146 if (!ucv_is_equal(val, ucv_object_get(uv2, key, NULL))) 2147 return false; 2148 } 2149 2150 ucv_object_foreach(uv2, key2, val2) { 2151 (void)val2; 2152 ucv_object_get(uv1, key2, &b1); 2153 2154 if (!b1) 2155 return false; 2156 } 2157 2158 return true; 2159 2160 default: 2161 return false; 2162 } 2163 } 2164 2165 bool 2166 ucv_is_truish(uc_value_t *val) 2167 { 2168 double d; 2169 2170 switch (ucv_type(val)) { 2171 case UC_INTEGER: 2172 if (ucv_is_u64(val)) 2173 return (ucv_uint64_get(val) != 0); 2174 2175 return (ucv_int64_get(val) != 0); 2176 2177 case UC_DOUBLE: 2178 d = ucv_double_get(val); 2179 2180 return (d != 0 && !isnan(d)); 2181 2182 case UC_BOOLEAN: 2183 return ucv_boolean_get(val); 2184 2185 case UC_STRING: 2186 return (ucv_string_length(val) > 0); 2187 2188 case UC_NULL: 2189 return false; 2190 2191 default: 2192 return true; 2193 } 2194 } 2195 2196 uc_value_t * 2197 ucv_to_number(uc_value_t *v) 2198 { 2199 switch (ucv_type(v)) { 2200 case UC_NULL: 2201 return ucv_uint64_new(0); 2202 2203 case UC_BOOLEAN: 2204 return ucv_uint64_new(ucv_boolean_get(v)); 2205 2206 case UC_INTEGER: 2207 return ucv_get(v); 2208 2209 case UC_DOUBLE: 2210 if (isnan(ucv_double_get(v))) 2211 return NULL; 2212 2213 return ucv_get(v); 2214 2215 case UC_STRING: 2216 return uc_number_parse(ucv_string_get(v), NULL); 2217 2218 default: 2219 return NULL; 2220 } 2221 } 2222 2223 bool 2224 ucv_compare(int how, uc_value_t *v1, uc_value_t *v2, int *deltap) 2225 { 2226 uc_type_t t1 = ucv_type(v1); 2227 uc_type_t t2 = ucv_type(v2); 2228 uc_value_t *nv1, *nv2; 2229 uint64_t u1, u2; 2230 int64_t n1, n2; 2231 double d1, d2; 2232 int delta; 2233 2234 /* at least one operand is null and we compare for equality or inequality ... */ 2235 if ((!v1 || !v2) && (how == I_EQ || how == I_NE)) { 2236 delta = (v1 != v2); 2237 } 2238 2239 /* ... otherwise if both operands are strings, compare bytewise ... */ 2240 else if (t1 == UC_STRING && t2 == UC_STRING) { 2241 u1 = ucv_string_length(v1); 2242 u2 = ucv_string_length(v2); 2243 2244 delta = memcmp(ucv_string_get(v1), ucv_string_get(v2), 2245 (u1 < u2) ? u1 : u2); 2246 2247 if (delta == 0 && u1 < u2) 2248 delta = -1; 2249 else if (delta == 0 && u1 > u2) 2250 delta = 1; 2251 } 2252 2253 /* handle non-string cases... */ 2254 else { 2255 /* ... both operands are of the same, non-scalar type... */ 2256 if (t1 == t2 && !ucv_is_scalar(v1)) { 2257 /* ... compare memory addrs */ 2258 if ((uintptr_t)v1 == (uintptr_t)v2) 2259 delta = 0; 2260 else if ((uintptr_t)v1 < (uintptr_t)v2) 2261 delta = -1; 2262 else 2263 delta = 1; 2264 } 2265 2266 /* ... operands are of different type or at least one is scalar... */ 2267 else { 2268 nv1 = ucv_to_number(v1); 2269 nv2 = ucv_to_number(v2); 2270 2271 /* ... at least one of them is NaN (not convertible)... */ 2272 if (!nv1 || !nv2) { 2273 ucv_put(nv1); 2274 ucv_put(nv2); 2275 2276 if (deltap) 2277 *deltap = 2; 2278 2279 /* ... all comparison results except `!=` involving NaN are false */ 2280 return (how == I_NE); 2281 } 2282 2283 /* ... either of them is a double, compare both as double */ 2284 if (ucv_type(nv1) == UC_DOUBLE || ucv_type(nv2) == UC_DOUBLE) { 2285 d1 = ucv_double_get(nv1); 2286 d2 = ucv_double_get(nv2); 2287 2288 if (d1 == d2) 2289 delta = 0; 2290 else if (d1 < d2) 2291 delta = -1; 2292 else 2293 delta = 1; 2294 } 2295 2296 /* ... both are integers... */ 2297 else { 2298 n1 = ucv_int64_get(nv1); 2299 2300 /* ... left operand is large positive... */ 2301 if (errno == ERANGE) { 2302 ucv_int64_get(nv2); 2303 2304 /* ... right operand is large positive too... */ 2305 if (errno == ERANGE) { 2306 /* ... compare both as unsigned */ 2307 u1 = ucv_uint64_get(nv1); 2308 u2 = ucv_uint64_get(nv2); 2309 2310 if (u1 == u2) 2311 delta = 0; 2312 else if (u1 < u2) 2313 delta = -1; 2314 else 2315 delta = 1; 2316 } 2317 2318 /* ... right operand is within int64_t range... */ 2319 else { 2320 /* ... left > right by definition */ 2321 delta = 1; 2322 } 2323 } 2324 2325 /* ... left operand is within int64_t range... */ 2326 else { 2327 n2 = ucv_int64_get(nv2); 2328 2329 /* ... right operand is large positive... */ 2330 if (errno == ERANGE) { 2331 /* ... left < right by definition */ 2332 delta = -1; 2333 } 2334 2335 /* ... right operand is within int64_t range... */ 2336 else { 2337 /* ... compare both as signed */ 2338 if (n1 == n2) 2339 delta = 0; 2340 else if (n1 < n2) 2341 delta = -1; 2342 else 2343 delta = 1; 2344 } 2345 } 2346 } 2347 2348 ucv_put(nv1); 2349 ucv_put(nv2); 2350 } 2351 } 2352 2353 if (deltap) 2354 *deltap = delta; 2355 2356 switch (how) { 2357 case I_LT: 2358 return (delta < 0); 2359 2360 case I_LE: 2361 return (delta <= 0); 2362 2363 case I_GT: 2364 return (delta > 0); 2365 2366 case I_GE: 2367 return (delta >= 0); 2368 2369 case I_EQ: 2370 return (delta == 0); 2371 2372 case I_NE: 2373 return (delta != 0); 2374 2375 default: 2376 return false; 2377 } 2378 } 2379 2380 2381 static char * 2382 ucv_key_to_string(uc_vm_t *vm, uc_value_t *val) 2383 { 2384 if (ucv_type(val) != UC_STRING) 2385 return ucv_to_string(vm, val); 2386 2387 return NULL; 2388 } 2389 2390 static int64_t 2391 ucv_key_to_index(uc_value_t *val) 2392 { 2393 const char *k; 2394 int64_t idx; 2395 double d; 2396 char *e; 2397 2398 /* only consider doubles with integer values as array keys */ 2399 if (ucv_type(val) == UC_DOUBLE) { 2400 d = ucv_double_get(val); 2401 2402 if (trunc(d) != d) 2403 return INT64_MIN; 2404 2405 return (int64_t)d; 2406 } 2407 else if (ucv_type(val) == UC_INTEGER) { 2408 return ucv_int64_get(val); 2409 } 2410 else if (ucv_type(val) == UC_STRING) { 2411 errno = 0; 2412 k = ucv_string_get(val); 2413 idx = strtoll(k, &e, 0); 2414 2415 if (errno != 0 || e == k || *e != 0) 2416 return INT64_MIN; 2417 2418 return idx; 2419 } 2420 2421 return INT64_MIN; 2422 } 2423 2424 uc_value_t * 2425 ucv_key_get(uc_vm_t *vm, uc_value_t *scope, uc_value_t *key) 2426 { 2427 uc_value_t *o, *v = NULL; 2428 bool found = false; 2429 uc_upvalref_t *ref; 2430 int64_t idx; 2431 char *k; 2432 2433 if (ucv_type(scope) == UC_ARRAY) { 2434 idx = ucv_key_to_index(key); 2435 2436 if (idx < 0 && idx > INT64_MIN && (uint64_t)llabs(idx) <= ucv_array_length(scope)) 2437 idx += ucv_array_length(scope); 2438 2439 if (idx >= 0 && (uint64_t)idx < ucv_array_length(scope)) { 2440 v = ucv_array_get(scope, idx); 2441 found = true; 2442 } 2443 } 2444 2445 if (!found) { 2446 k = ucv_key_to_string(vm, key); 2447 2448 for (o = scope; o; o = ucv_prototype_get(o)) { 2449 if (ucv_type(o) != UC_OBJECT) 2450 continue; 2451 2452 v = ucv_object_get(o, k ? k : ucv_string_get(key), &found); 2453 2454 if (found) 2455 break; 2456 } 2457 2458 free(k); 2459 } 2460 2461 /* Handle upvalue values in objects; under some specific circumstances 2462 objects may contain upvalues, this primarily happens with wildcard module 2463 import namespace dictionaries. */ 2464 #ifdef __clang_analyzer__ 2465 /* Clang static analyzer does not understand that ucv_type(NULL) can't 2466 * possibly yield UC_UPVALUE. Nudge it. */ 2467 if (v != NULL && ucv_type(v) == UC_UPVALUE) 2468 #else 2469 if (ucv_type(v) == UC_UPVALUE) 2470 #endif 2471 { 2472 ref = (uc_upvalref_t *)v; 2473 2474 if (ref->closed) 2475 return ucv_get(ref->value); 2476 else if (vm) 2477 return ucv_get(vm->stack.entries[ref->slot]); 2478 else 2479 return NULL; 2480 } 2481 2482 return ucv_get(v); 2483 } 2484 2485 uc_value_t * 2486 ucv_key_set(uc_vm_t *vm, uc_value_t *scope, uc_value_t *key, uc_value_t *val) 2487 { 2488 int64_t idx; 2489 char *s; 2490 bool rv; 2491 2492 if (!key) 2493 return NULL; 2494 2495 if (ucv_type(scope) == UC_ARRAY) { 2496 idx = ucv_key_to_index(key); 2497 2498 if (idx < 0 && idx > INT64_MIN && (uint64_t)llabs(idx) <= ucv_array_length(scope)) 2499 idx += ucv_array_length(scope); 2500 2501 if (idx < 0 || !ucv_array_set(scope, idx, val)) 2502 return NULL; 2503 2504 return ucv_get(val); 2505 } 2506 2507 s = ucv_key_to_string(vm, key); 2508 rv = ucv_object_add(scope, s ? s : ucv_string_get(key), val); 2509 free(s); 2510 2511 return rv ? ucv_get(val) : NULL; 2512 } 2513 2514 bool 2515 ucv_key_delete(uc_vm_t *vm, uc_value_t *scope, uc_value_t *key) 2516 { 2517 char *s; 2518 bool rv; 2519 2520 if (!key) 2521 return NULL; 2522 2523 s = ucv_key_to_string(vm, key); 2524 rv = ucv_object_delete(scope, s ? s : ucv_string_get(key)); 2525 free(s); 2526 2527 return rv; 2528 } 2529 2530 2531 static void 2532 ucv_gc_common(uc_vm_t *vm, bool final) 2533 { 2534 uc_weakref_t *ref, *tmp; 2535 uc_value_t *val; 2536 size_t i; 2537 2538 vm->alloc_refs = 0; 2539 2540 /* back out early if value list is uninitialized */ 2541 if (!vm->values.prev || !vm->values.next) 2542 return; 2543 2544 if (!final) { 2545 /* mark reachable objects */ 2546 ucv_gc_mark(vm->globals); 2547 ucv_gc_mark(vm->registry); 2548 ucv_gc_mark(vm->signal.handler); 2549 ucv_gc_mark(vm->exception.stacktrace); 2550 2551 for (i = 0; i < vm->callframes.count; i++) { 2552 ucv_gc_mark(vm->callframes.entries[i].ctx); 2553 2554 if (vm->callframes.entries[i].closure) 2555 ucv_gc_mark(&vm->callframes.entries[i].closure->header); 2556 2557 if (vm->callframes.entries[i].cfunction) 2558 ucv_gc_mark(&vm->callframes.entries[i].cfunction->header); 2559 } 2560 2561 for (i = 0; i < vm->stack.count; i++) 2562 ucv_gc_mark(vm->stack.entries[i]); 2563 2564 for (i = 0; i < vm->restypes.count; i++) 2565 ucv_gc_mark(vm->restypes.entries[i]->proto); 2566 2567 /* mark no-gc resources with embedded values */ 2568 for (ref = vm->values.prev; ref != &vm->values; ref = ref->prev) { 2569 val = (uc_value_t *)((uintptr_t)ref - offsetof(uc_array_t, ref)); 2570 if (ucv_type(val) != UC_RESOURCE) 2571 break; 2572 2573 if (ucv_resource_is_persistent(val)) 2574 ucv_gc_mark(val); 2575 } 2576 } 2577 2578 /* unref unreachable objects */ 2579 for (ref = vm->values.next; ref != &vm->values; ref = ref->next) { 2580 val = (uc_value_t *)((uintptr_t)ref - offsetof(uc_array_t, ref)); 2581 2582 if (ucv_is_marked(val)) 2583 ucv_clear_mark(val); 2584 else 2585 ucv_free(val, true); 2586 } 2587 2588 /* free destroyed objects */ 2589 for (ref = vm->values.next, tmp = ref->next; ref != &vm->values; ref = tmp, tmp = tmp->next) { 2590 val = (uc_value_t *)((uintptr_t)ref - offsetof(uc_array_t, ref)); 2591 2592 if (val->type == UC_NULL) { 2593 ucv_unref(ref); 2594 free(val); 2595 } 2596 } 2597 } 2598 2599 void 2600 ucv_gc(uc_vm_t *vm) 2601 { 2602 ucv_gc_common(vm, false); 2603 } 2604 2605 void 2606 ucv_freeall(uc_vm_t *vm) 2607 { 2608 ucv_gc_common(vm, true); 2609 } 2610 2611 void 2612 uc_search_path_init(uc_search_path_t *search_path) 2613 { 2614 size_t i; 2615 2616 for (i = 0; i < ARRAY_SIZE(uc_default_search_path); i++) 2617 uc_vector_push(search_path, xstrdup(uc_default_search_path[i])); 2618 } 2619 2620 2621 static __thread uc_thread_context_t *tls_ctx; 2622 2623 uc_thread_context_t * 2624 uc_thread_context_get(void) 2625 { 2626 if (tls_ctx == NULL) { 2627 tls_ctx = xalloc(sizeof(*tls_ctx)); 2628 tls_ctx->object_iterators.prev = &tls_ctx->object_iterators; 2629 tls_ctx->object_iterators.next = &tls_ctx->object_iterators; 2630 } 2631 2632 return tls_ctx; 2633 } 2634
This page was automatically generated by LXR 0.3.1. • OpenWrt