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