1 /* 2 * Copyright (C) 2020-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 <string.h> 19 #include <assert.h> 20 #include <ctype.h> 21 #include <math.h> 22 #include <errno.h> 23 #include <limits.h> 24 #include <fcntl.h> 25 #include <unistd.h> 26 27 #include "ucode/vm.h" 28 #include "ucode/compiler.h" 29 #include "ucode/program.h" 30 #include "ucode/lib.h" /* uc_error_context_format() */ 31 #include "ucode/platform.h" 32 33 #undef __insn 34 #define __insn(_name) #_name, 35 36 static const char *insn_names[__I_MAX] = { 37 __insns 38 }; 39 40 static const int8_t insn_operand_bytes[__I_MAX] = { 41 [I_LOAD] = 4, 42 [I_LOAD8] = 1, 43 [I_LOAD16] = 2, 44 [I_LOAD32] = 4, 45 46 [I_LREXP] = 4, 47 48 [I_LLOC] = 4, 49 [I_LVAR] = 4, 50 [I_LUPV] = 4, 51 52 [I_CLFN] = 4, 53 [I_ARFN] = 4, 54 55 [I_SLOC] = 4, 56 [I_SUPV] = 4, 57 [I_SVAR] = 4, 58 59 [I_ULOC] = 4, 60 [I_UUPV] = 4, 61 [I_UVAR] = 4, 62 [I_UVAL] = 1, 63 64 [I_NARR] = 4, 65 [I_PARR] = 4, 66 67 [I_NOBJ] = 4, 68 [I_SOBJ] = 4, 69 70 [I_JMP] = -4, 71 [I_JMPZ] = -4, 72 73 [I_COPY] = 1, 74 75 [I_CALL] = 4, 76 [I_MCALL] = 4, 77 [I_QCALL] = 4, 78 [I_QMCALL] = 4, 79 80 [I_IMPORT] = 4, 81 [I_EXPORT] = 4, 82 [I_DYNLOAD] = 4 83 }; 84 85 static const char *exception_type_strings[] = { 86 [EXCEPTION_SYNTAX] = "Syntax error", 87 [EXCEPTION_RUNTIME] = "Runtime error", 88 [EXCEPTION_TYPE] = "Type error", 89 [EXCEPTION_REFERENCE] = "Reference error", 90 [EXCEPTION_USER] = "Error", 91 [EXCEPTION_EXIT] = "Exit" 92 }; 93 94 95 static void 96 uc_vm_reset_stack(uc_vm_t *vm) 97 { 98 while (vm->stack.count > 0) { 99 vm->stack.count--; 100 ucv_put(vm->stack.entries[vm->stack.count]); 101 vm->stack.entries[vm->stack.count] = NULL; 102 } 103 } 104 105 static uc_value_t * 106 uc_vm_callframe_pop(uc_vm_t *vm); 107 108 static void 109 uc_vm_reset_callframes(uc_vm_t *vm) 110 { 111 while (vm->callframes.count > 0) 112 ucv_put(uc_vm_callframe_pop(vm)); 113 } 114 115 static uc_value_t * 116 uc_vm_alloc_global_scope(uc_vm_t *vm) 117 { 118 uc_value_t *scope, *arr; 119 size_t i; 120 121 scope = ucv_object_new(vm); 122 123 /* build default require() search path */ 124 arr = ucv_array_new(vm); 125 126 for (i = 0; i < vm->config->module_search_path.count; i++) 127 ucv_array_push(arr, ucv_string_new(vm->config->module_search_path.entries[i])); 128 129 /* register module related constants */ 130 ucv_object_add(scope, "REQUIRE_SEARCH_PATH", arr); 131 ucv_object_add(scope, "modules", ucv_object_new(vm)); 132 133 /* register scope math constants */ 134 ucv_object_add(scope, "NaN", ucv_double_new(NAN)); 135 ucv_object_add(scope, "Infinity", ucv_double_new(INFINITY)); 136 137 /* register global property */ 138 ucv_object_add(scope, "global", ucv_get(scope)); 139 140 uc_vm_scope_set(vm, scope); 141 142 return scope; 143 } 144 145 static void 146 uc_vm_output_exception(uc_vm_t *vm, uc_exception_t *ex); 147 148 static uc_vm_t *signal_handler_vm; 149 150 static void 151 uc_vm_signal_handler(int sig) 152 { 153 assert(signal_handler_vm); 154 155 uc_vm_signal_raise(signal_handler_vm, sig); 156 } 157 158 static void 159 uc_vm_signal_handlers_setup(uc_vm_t *vm) 160 { 161 memset(&vm->signal, 0, sizeof(vm->signal)); 162 163 vm->signal.sigpipe[0] = -1; 164 vm->signal.sigpipe[1] = -1; 165 166 if (!vm->config->setup_signal_handlers) 167 return; 168 169 if (pipe2(vm->signal.sigpipe, O_CLOEXEC | O_NONBLOCK) != 0) 170 return; 171 172 signal_handler_vm = vm; 173 174 vm->signal.handler = ucv_array_new_length(vm, UC_SYSTEM_SIGNAL_COUNT); 175 176 vm->signal.sa.sa_handler = uc_vm_signal_handler; 177 vm->signal.sa.sa_flags = SA_RESTART | SA_ONSTACK; 178 sigemptyset(&vm->signal.sa.sa_mask); 179 } 180 181 void uc_vm_init(uc_vm_t *vm, uc_parse_config_t *config) 182 { 183 vm->exception.type = EXCEPTION_NONE; 184 vm->exception.message = NULL; 185 186 vm->config = config ? config : &uc_default_parse_config; 187 188 vm->open_upvals = NULL; 189 190 vm->values.prev = &vm->values; 191 vm->values.next = &vm->values; 192 193 vm->strbuf = NULL; 194 195 vm->output = stdout; 196 197 uc_vm_reset_stack(vm); 198 199 uc_vm_alloc_global_scope(vm); 200 201 uc_vm_exception_handler_set(vm, uc_vm_output_exception); 202 203 uc_vm_trace_set(vm, 0); 204 205 uc_vm_signal_handlers_setup(vm); 206 } 207 208 void uc_vm_free(uc_vm_t *vm) 209 { 210 uc_upvalref_t *ref; 211 size_t i; 212 213 ucv_put(vm->exception.stacktrace); 214 free(vm->exception.message); 215 216 while (vm->open_upvals) { 217 ref = vm->open_upvals->next; 218 ucv_put(&vm->open_upvals->header); 219 vm->open_upvals = ref; 220 } 221 222 for (i = 0; i < vm->restypes.count; i++) 223 ucv_put(vm->restypes.entries[i]->proto); 224 225 uc_vm_reset_callframes(vm); 226 uc_vm_reset_stack(vm); 227 uc_vector_clear(&vm->stack); 228 uc_vector_clear(&vm->callframes); 229 230 printbuf_free(vm->strbuf); 231 232 ucv_freeall(vm); 233 234 for (i = 0; i < vm->restypes.count; i++) 235 free(vm->restypes.entries[i]); 236 237 uc_vector_clear(&vm->restypes); 238 } 239 240 static uc_chunk_t * 241 uc_vm_frame_chunk(uc_callframe_t *frame) 242 { 243 return frame->closure ? &frame->closure->function->chunk : NULL; 244 } 245 246 static uc_program_t * 247 uc_vm_frame_program(uc_callframe_t *frame) 248 { 249 return frame->closure ? frame->closure->function->program : NULL; 250 } 251 252 static uc_source_t * 253 uc_vm_frame_source(uc_callframe_t *frame) 254 { 255 return frame->closure ? uc_program_function_source(frame->closure->function) : NULL; 256 } 257 258 static uc_callframe_t * 259 uc_vm_current_frame(uc_vm_t *vm) 260 { 261 return uc_vector_last(&vm->callframes); 262 } 263 264 static uc_program_t * 265 uc_vm_current_program(uc_vm_t *vm) 266 { 267 return uc_vm_frame_program(uc_vm_current_frame(vm)); 268 } 269 270 static bool 271 uc_vm_is_strict(uc_vm_t *vm) 272 { 273 return uc_vm_current_frame(vm)->strict; 274 } 275 276 static uc_vm_insn_t 277 uc_vm_decode_insn(uc_vm_t *vm, uc_callframe_t *frame, uc_chunk_t *chunk) 278 { 279 uc_vm_insn_t insn; 280 281 #ifndef NDEBUG 282 uint8_t *end = chunk->entries + chunk->count; 283 #endif 284 285 assert(frame->ip < end); 286 287 insn = frame->ip[0]; 288 frame->ip++; 289 290 assert(frame->ip + abs(insn_operand_bytes[insn]) <= end); 291 292 switch (insn_operand_bytes[insn]) { 293 case 0: 294 break; 295 296 case -4: 297 vm->arg.s32 = ( 298 frame->ip[0] * 0x1000000UL + 299 frame->ip[1] * 0x10000UL + 300 frame->ip[2] * 0x100UL + 301 frame->ip[3] 302 ) - 0x7fffffff; 303 frame->ip += 4; 304 break; 305 306 case 1: 307 vm->arg.u8 = frame->ip[0]; 308 frame->ip++; 309 break; 310 311 case 2: 312 vm->arg.u16 = ( 313 frame->ip[0] * 0x100 + 314 frame->ip[1] 315 ); 316 frame->ip += 2; 317 break; 318 319 case 4: 320 vm->arg.u32 = ( 321 frame->ip[0] * 0x1000000UL + 322 frame->ip[1] * 0x10000UL + 323 frame->ip[2] * 0x100UL + 324 frame->ip[3] 325 ); 326 frame->ip += 4; 327 break; 328 329 default: 330 fprintf(stderr, "Unhandled operand format: %" PRId8 "\n", insn_operand_bytes[insn]); 331 abort(); 332 } 333 334 return insn; 335 } 336 337 338 static char * 339 uc_vm_format_val(uc_vm_t *vm, uc_value_t *val) 340 { 341 if (!vm->strbuf) 342 vm->strbuf = xprintbuf_new(); 343 else 344 printbuf_reset(vm->strbuf); 345 346 ucv_to_stringbuf(NULL, vm->strbuf, val, true); 347 348 if (printbuf_length(vm->strbuf) >= 64) { 349 printbuf_memset(vm->strbuf, 60, '.', 3); 350 printbuf_memset(vm->strbuf, 63, 0, 1); 351 } 352 353 return vm->strbuf->buf; 354 } 355 356 static void 357 uc_vm_frame_dump(uc_vm_t *vm, uc_callframe_t *frame) 358 { 359 uc_chunk_t *chunk = uc_vm_frame_chunk(frame); 360 uc_function_t *function; 361 uc_closure_t *closure; 362 uc_upvalref_t *ref; 363 uc_value_t *v; 364 size_t i; 365 366 fprintf(stderr, " [*] CALLFRAME[%zx]\n", 367 frame - vm->callframes.entries); 368 369 fprintf(stderr, " |- stackframe %zu/%zu\n", 370 frame->stackframe, vm->stack.count); 371 372 fprintf(stderr, " |- ctx %s\n", 373 uc_vm_format_val(vm, frame->ctx)); 374 375 if (chunk) { 376 closure = frame->closure; 377 function = closure->function; 378 379 fprintf(stderr, " `- %zu upvalues\n", 380 function->nupvals); 381 382 for (i = 0; i < function->nupvals; i++) { 383 ref = closure->upvals[i]; 384 v = uc_chunk_debug_get_variable(chunk, 0, i, true); 385 386 fprintf(stderr, " [%zu] <%p> %s ", 387 i, (void *)ref, uc_vm_format_val(vm, v)); 388 389 if (!ref) { 390 fprintf(stderr, "{unresolved}\n"); 391 } 392 else if (ref->closed) { 393 fprintf(stderr, "{closed} %s\n", 394 uc_vm_format_val(vm, ref->value)); 395 } 396 else { 397 fprintf(stderr, "{open[%zu]} %s\n", 398 ref->slot, 399 uc_vm_format_val(vm, vm->stack.entries[ref->slot])); 400 } 401 402 ucv_put(v); 403 } 404 } 405 } 406 407 static uc_value_t * 408 uc_vm_resolve_upval(uc_vm_t *vm, uc_value_t *value) 409 { 410 uc_upvalref_t *ref; 411 412 #ifdef __clang_analyzer__ 413 /* Clang static analyzer does not understand that ucv_type(NULL) can't 414 * possibly yield UC_UPVALUE. Nudge it. */ 415 if (value != NULL && ucv_type(value) == UC_UPVALUE) 416 #else 417 if (ucv_type(value) == UC_UPVALUE) 418 #endif 419 { 420 ref = (uc_upvalref_t *)value; 421 422 if (ref->closed) 423 return ucv_get(ref->value); 424 else 425 return ucv_get(vm->stack.entries[ref->slot]); 426 } 427 428 return value; 429 } 430 431 void 432 uc_vm_stack_push(uc_vm_t *vm, uc_value_t *value) 433 { 434 uc_vector_grow(&vm->stack); 435 436 ucv_put(vm->stack.entries[vm->stack.count]); 437 vm->stack.entries[vm->stack.count] = uc_vm_resolve_upval(vm, value); 438 vm->stack.count++; 439 440 if (vm->trace) { 441 fprintf(stderr, " [+%zd] %s\n", 442 vm->stack.count - 1, 443 uc_vm_format_val(vm, vm->stack.entries[vm->stack.count - 1])); 444 } 445 } 446 447 uc_value_t * 448 uc_vm_stack_pop(uc_vm_t *vm) 449 { 450 uc_value_t *rv; 451 452 vm->stack.count--; 453 rv = vm->stack.entries[vm->stack.count]; 454 vm->stack.entries[vm->stack.count] = NULL; 455 456 if (vm->trace) { 457 fprintf(stderr, " [-%zd] %s\n", 458 vm->stack.count, 459 uc_vm_format_val(vm, rv)); 460 } 461 462 return rv; 463 } 464 465 uc_value_t * 466 uc_vm_stack_peek(uc_vm_t *vm, size_t offset) 467 { 468 return vm->stack.entries[vm->stack.count + (-1 - offset)]; 469 } 470 471 static void 472 uc_vm_stack_set(uc_vm_t *vm, size_t offset, uc_value_t *value) 473 { 474 if (vm->trace) { 475 fprintf(stderr, " [!%zu] %s\n", 476 offset, 477 uc_vm_format_val(vm, value)); 478 } 479 480 ucv_put(vm->stack.entries[offset]); 481 vm->stack.entries[offset] = value; 482 } 483 484 static void 485 uc_vm_call_native(uc_vm_t *vm, uc_value_t *ctx, uc_cfunction_t *fptr, bool mcall, size_t nargs) 486 { 487 uc_value_t *res = NULL; 488 uc_callframe_t *frame; 489 490 /* add new callframe */ 491 uc_vector_grow(&vm->callframes); 492 493 frame = &vm->callframes.entries[vm->callframes.count++]; 494 frame->stackframe = vm->stack.count - nargs - 1; 495 frame->cfunction = fptr; 496 frame->closure = NULL; 497 frame->ctx = ctx; 498 frame->mcall = mcall; 499 500 if (vm->trace) 501 uc_vm_frame_dump(vm, frame); 502 503 res = fptr->cfn(vm, nargs); 504 505 /* Reset stack, check for callframe depth since an uncatched exception in managed 506 * code executed by fptr->cfn() could've reset the callframe stack already. */ 507 if (vm->callframes.count > 0) 508 ucv_put(uc_vm_callframe_pop(vm)); 509 510 /* push return value */ 511 if (!vm->exception.type) 512 uc_vm_stack_push(vm, res); 513 else 514 ucv_put(res); 515 } 516 517 static bool 518 uc_vm_call_function(uc_vm_t *vm, uc_value_t *ctx, uc_value_t *fno, bool mcall, size_t argspec) 519 { 520 size_t i, j, stackoff, nargs = argspec & 0xffff, nspreads = argspec >> 16; 521 uc_callframe_t *frame = NULL; 522 uc_value_t *ellip, *arg; 523 uc_function_t *function; 524 uc_closure_t *closure; 525 uint16_t slot, tmp; 526 char *s; 527 528 /* XXX: make dependent on stack size */ 529 if (vm->callframes.count >= 1000) { 530 uc_vm_raise_exception(vm, EXCEPTION_RUNTIME, "Too much recursion"); 531 ucv_put(ctx); 532 ucv_put(fno); 533 534 return false; 535 } 536 537 stackoff = vm->stack.count - nargs - 1; 538 539 /* argument list contains spread operations, we need to reshuffle the stack */ 540 if (nspreads > 0) { 541 frame = uc_vm_current_frame(vm); 542 543 /* create temporary array */ 544 ellip = ucv_array_new_length(vm, nargs); 545 546 /* pop original stack values and push to temp array in reverse order */ 547 for (i = 0; i < nargs; i++) 548 ucv_array_push(ellip, uc_vm_stack_pop(vm)); 549 550 /* for each spread value index ... */ 551 for (i = 0, slot = nargs; i < nspreads; i++) { 552 /* decode stack depth value */ 553 tmp = frame->ip[0] * 0x100 + frame->ip[1]; 554 frame->ip += 2; 555 556 /* push each preceeding non-spread value to the stack */ 557 for (j = slot; j > tmp + 1UL; j--) 558 uc_vm_stack_push(vm, ucv_get(ucv_array_get(ellip, j - 1))); 559 560 /* read spread value at index... */ 561 slot = tmp; 562 arg = ucv_get(ucv_array_get(ellip, slot)); 563 564 /* ... ensure that it is an array type ... */ 565 if (ucv_type(arg) != UC_ARRAY) { 566 s = ucv_to_string(vm, arg); 567 uc_vm_raise_exception(vm, EXCEPTION_TYPE, "(%s) is not iterable", s); 568 free(s); 569 ucv_put(ctx); 570 ucv_put(fno); 571 ucv_put(ellip); 572 573 return false; 574 } 575 576 /* ... and push each spread array value as argument to the stack */ 577 for (j = 0; j < ucv_array_length(arg); j++) 578 uc_vm_stack_push(vm, ucv_get(ucv_array_get(arg, j))); 579 580 ucv_put(arg); 581 } 582 583 /* push remaining non-spread arguments to the stack */ 584 for (i = slot; i > 0; i--) 585 uc_vm_stack_push(vm, ucv_get(ucv_array_get(ellip, i - 1))); 586 587 /* free temp array */ 588 ucv_put(ellip); 589 590 /* update arg count */ 591 nargs = vm->stack.count - stackoff - 1; 592 } 593 594 /* is a native function */ 595 if (ucv_type(fno) == UC_CFUNCTION) { 596 uc_vm_call_native(vm, ctx, (uc_cfunction_t *)fno, mcall, nargs); 597 598 return true; 599 } 600 601 if (ucv_type(fno) != UC_CLOSURE) { 602 uc_vm_raise_exception(vm, EXCEPTION_TYPE, "left-hand side is not a function"); 603 ucv_put(ctx); 604 ucv_put(fno); 605 606 return false; 607 } 608 609 closure = (uc_closure_t *)fno; 610 function = closure->function; 611 612 /* fewer arguments on stack than function expects => pad */ 613 if (nargs < function->nargs) { 614 for (i = nargs; i < function->nargs; i++) { 615 if (function->vararg && (i + 1) == function->nargs) 616 uc_vm_stack_push(vm, ucv_array_new_length(vm, 0)); 617 else 618 uc_vm_stack_push(vm, NULL); 619 } 620 } 621 622 /* more arguments on stack than function expects... */ 623 else if (nargs > function->nargs - function->vararg) { 624 /* is a vararg function => pass excess args as array */ 625 if (function->vararg) { 626 ellip = ucv_array_new_length(vm, nargs - (function->nargs - 1)); 627 628 for (i = function->nargs; i <= nargs; i++) 629 ucv_array_push(ellip, uc_vm_stack_peek(vm, nargs - i)); 630 631 for (i = function->nargs; i <= nargs; i++) 632 uc_vm_stack_pop(vm); 633 634 uc_vm_stack_push(vm, ellip); 635 } 636 637 /* static amount of args => drop excess values */ 638 else { 639 for (i = function->nargs; i < nargs; i++) 640 ucv_put(uc_vm_stack_pop(vm)); 641 } 642 } 643 644 uc_vector_grow(&vm->callframes); 645 646 frame = &vm->callframes.entries[vm->callframes.count++]; 647 frame->stackframe = stackoff; 648 frame->cfunction = NULL; 649 frame->closure = closure; 650 frame->ctx = ctx; 651 frame->ip = function->chunk.entries; 652 frame->mcall = mcall; 653 frame->strict = function->strict; 654 655 if (vm->trace) 656 uc_vm_frame_dump(vm, frame); 657 658 return true; 659 } 660 661 static uc_source_t *last_source = NULL; 662 static size_t last_srcpos = 0; 663 664 static void 665 uc_dump_insn(uc_vm_t *vm, uint8_t *pos, uc_vm_insn_t insn) 666 { 667 uc_callframe_t *frame = uc_vm_current_frame(vm); 668 uc_chunk_t *chunk = uc_vm_frame_chunk(frame); 669 uc_stringbuf_t *buf = NULL; 670 uc_value_t *cnst = NULL; 671 uc_source_t *source; 672 size_t srcpos; 673 674 srcpos = uc_program_function_srcpos(frame->closure->function, pos - chunk->entries); 675 source = uc_vm_frame_source(frame); 676 677 if (last_srcpos == 0 || last_source != source || srcpos != last_srcpos) { 678 buf = xprintbuf_new(); 679 680 uc_source_context_format(buf, source, srcpos, true); 681 fwrite(buf->buf, 1, printbuf_length(buf), stderr); 682 printbuf_free(buf); 683 684 last_source = source; 685 last_srcpos = srcpos; 686 } 687 688 fprintf(stderr, "%08zx %s", pos - chunk->entries, insn_names[insn]); 689 690 switch (insn_operand_bytes[insn]) { 691 case 0: 692 break; 693 694 case -1: 695 fprintf(stderr, " {%s%hhd}", vm->arg.s8 < 0 ? "" : "+", vm->arg.s8); 696 break; 697 698 case -2: 699 fprintf(stderr, " {%c0x%hx}", 700 vm->arg.s16 < 0 ? '-' : '+', 701 (uint16_t)(vm->arg.s16 < 0 ? -vm->arg.s16 : vm->arg.s16)); 702 break; 703 704 case -4: 705 fprintf(stderr, " {%c0x%x}", 706 vm->arg.s32 < 0 ? '-' : '+', 707 (uint32_t)(vm->arg.s32 < 0 ? -vm->arg.s32 : vm->arg.s32)); 708 break; 709 710 case 1: 711 fprintf(stderr, " {%hhu}", vm->arg.u8); 712 break; 713 714 case 2: 715 fprintf(stderr, " {0x%hx}", vm->arg.u16); 716 break; 717 718 case 4: 719 fprintf(stderr, " {0x%x}", vm->arg.u32); 720 break; 721 722 default: 723 fprintf(stderr, " (unknown operand format: %" PRId8 ")", insn_operand_bytes[insn]); 724 break; 725 } 726 727 switch (insn) { 728 case I_LOAD: 729 case I_LVAR: 730 case I_SVAR: 731 cnst = uc_program_get_constant(uc_vm_frame_program(uc_vector_last(&vm->callframes)), vm->arg.u32); 732 733 fprintf(stderr, "\t; %s", 734 cnst ? uc_vm_format_val(vm, cnst) : "(?)"); 735 736 ucv_put(cnst); 737 break; 738 739 case I_LLOC: 740 case I_LUPV: 741 case I_SLOC: 742 case I_SUPV: 743 cnst = uc_chunk_debug_get_variable(chunk, pos - chunk->entries, vm->arg.u32, (insn == I_LUPV || insn == I_SUPV)); 744 745 fprintf(stderr, "\t; %s", 746 cnst ? uc_vm_format_val(vm, cnst) : "(?)"); 747 748 ucv_put(cnst); 749 break; 750 751 case I_ULOC: 752 case I_UUPV: 753 cnst = uc_chunk_debug_get_variable(chunk, pos - chunk->entries, vm->arg.u32 & 0x00ffffff, (insn == I_UUPV)); 754 /* fall through */ 755 756 case I_UVAR: 757 if (!cnst) 758 cnst = uc_program_get_constant(uc_vm_frame_program(uc_vector_last(&vm->callframes)), vm->arg.u32 & 0x00ffffff); 759 760 fprintf(stderr, "\t; %s (%s)", 761 cnst ? uc_vm_format_val(vm, cnst) : "(?)", 762 insn_names[vm->arg.u32 >> 24]); 763 764 ucv_put(cnst); 765 break; 766 767 case I_UVAL: 768 fprintf(stderr, "\t; (%s)", insn_names[vm->arg.u32]); 769 break; 770 771 default: 772 break; 773 } 774 775 fprintf(stderr, "\n"); 776 } 777 778 static uc_value_t * 779 uc_vm_exception_tostring(uc_vm_t *vm, size_t nargs) 780 { 781 uc_callframe_t *frame = uc_vm_current_frame(vm); 782 uc_value_t *message = ucv_object_get(frame->ctx, "message", NULL); 783 784 return message ? ucv_get(message) : ucv_string_new("Exception"); 785 } 786 787 static uc_value_t *exception_prototype = NULL; 788 789 static uc_value_t * 790 uc_vm_exception_new(uc_vm_t *vm, uc_exception_type_t type, const char *message, uc_value_t *stacktrace) 791 { 792 uc_value_t *exo; 793 794 if (exception_prototype == NULL) { 795 exception_prototype = ucv_object_new(vm); 796 797 ucv_object_add(exception_prototype, "tostring", 798 ucv_cfunction_new("tostring", uc_vm_exception_tostring)); 799 } 800 801 exo = ucv_object_new(vm); 802 803 ucv_object_add(exo, "type", ucv_string_new(exception_type_strings[type])); 804 ucv_object_add(exo, "message", ucv_string_new(message)); 805 ucv_object_add(exo, "stacktrace", ucv_get(stacktrace)); 806 807 ucv_prototype_set(exo, ucv_get(exception_prototype)); 808 809 return exo; 810 } 811 812 static void 813 uc_vm_clear_exception(uc_vm_t *vm) 814 { 815 vm->exception.type = EXCEPTION_NONE; 816 817 ucv_put(vm->exception.stacktrace); 818 vm->exception.stacktrace = NULL; 819 820 free(vm->exception.message); 821 vm->exception.message = NULL; 822 } 823 824 static bool 825 uc_vm_handle_exception(uc_vm_t *vm) 826 { 827 uc_callframe_t *frame = NULL; 828 uc_chunk_t *chunk = NULL; 829 uc_value_t *exo; 830 size_t i, pos; 831 832 if (vm->callframes.count) 833 frame = uc_vm_current_frame(vm); 834 835 if (!frame || !frame->closure) 836 return false; 837 838 chunk = uc_vm_frame_chunk(frame); 839 pos = frame->ip - chunk->entries; 840 841 /* iterate the known exception ranges, see if the current ip falls into any of them */ 842 for (i = 0; i < chunk->ehranges.count; i++) { 843 /* skip nonmatching ranges */ 844 if (pos < chunk->ehranges.entries[i].from || 845 pos >= chunk->ehranges.entries[i].to) 846 continue; 847 848 /* we found a matching range... first unwind stack */ 849 while (vm->stack.count > frame->stackframe + chunk->ehranges.entries[i].slot) 850 ucv_put(uc_vm_stack_pop(vm)); 851 852 /* prepare exception object and expose it to user handler code */ 853 exo = uc_vm_exception_new(vm, vm->exception.type, vm->exception.message, vm->exception.stacktrace); 854 855 uc_vm_stack_push(vm, exo); 856 857 /* reset exception information */ 858 uc_vm_clear_exception(vm); 859 860 /* jump to exception handler */ 861 if (chunk->ehranges.entries[i].target >= chunk->count) { 862 uc_vm_raise_exception(vm, EXCEPTION_RUNTIME, "jump target out of range"); 863 return false; 864 } 865 866 #if 0 867 if (vm->trace && chunk->entries + chunk->ehranges.entries[i].target > frame->ip) { 868 while (frame->ip < chunk->entries + chunk->ehranges.entries[i].target) { 869 fprintf(stderr, "(eh:skip) [%p:%zu] ", chunk, frame->ip - chunk->entries); 870 uc_dump_insn(vm, frame->ip, uc_vm_decode_insn(vm, frame, chunk)); 871 } 872 } 873 #endif 874 875 frame->ip = chunk->entries + chunk->ehranges.entries[i].target; 876 877 return true; 878 } 879 880 return false; 881 } 882 883 static uc_value_t * 884 uc_vm_capture_stacktrace(uc_vm_t *vm, size_t i) 885 { 886 uc_value_t *stacktrace, *entry, *last = NULL; 887 uc_function_t *function; 888 uc_callframe_t *frame; 889 uc_source_t *source; 890 size_t off, srcpos; 891 char *name; 892 893 stacktrace = ucv_array_new(vm); 894 895 for (; i > 0; i--) { 896 frame = &vm->callframes.entries[i - 1]; 897 entry = ucv_object_new(vm); 898 899 if (frame->closure) { 900 function = frame->closure->function; 901 source = uc_program_function_source(function); 902 903 off = (frame->ip - uc_vm_frame_chunk(frame)->entries) - 1; 904 srcpos = uc_program_function_srcpos(function, off); 905 906 ucv_object_add(entry, "filename", ucv_string_new(source->filename)); 907 ucv_object_add(entry, "line", ucv_int64_new(uc_source_get_line(source, &srcpos))); 908 ucv_object_add(entry, "byte", ucv_int64_new(srcpos)); 909 } 910 911 if (i > 1) { 912 if (frame->closure) { 913 if (frame->closure->function->name[0]) 914 name = frame->closure->function->name; 915 else if (frame->closure->is_arrow) 916 name = "[arrow function]"; 917 else 918 name = "[anonymous function]"; 919 } 920 else { 921 name = frame->cfunction->name; 922 } 923 924 ucv_object_add(entry, "function", ucv_string_new(name)); 925 } 926 927 if (!ucv_is_equal(last, entry)) { 928 ucv_array_push(stacktrace, entry); 929 last = entry; 930 } 931 else { 932 ucv_put(entry); 933 } 934 } 935 936 return stacktrace; 937 } 938 939 static uc_value_t * 940 uc_vm_get_error_context(uc_vm_t *vm) 941 { 942 size_t offset, i, byte, line; 943 uc_value_t *stacktrace; 944 uc_callframe_t *frame; 945 uc_stringbuf_t *buf; 946 uc_chunk_t *chunk; 947 948 /* skip to first non-native function call frame */ 949 for (i = vm->callframes.count; i > 1; i--) 950 if (vm->callframes.entries[i - 1].closure) 951 break; 952 953 frame = &vm->callframes.entries[i - 1]; 954 955 if (!frame->closure) 956 return NULL; 957 958 chunk = uc_vm_frame_chunk(frame); 959 offset = uc_program_function_srcpos(frame->closure->function, (frame->ip - chunk->entries) - 1); 960 stacktrace = uc_vm_capture_stacktrace(vm, i); 961 962 buf = ucv_stringbuf_new(); 963 964 byte = offset; 965 line = uc_source_get_line(uc_program_function_source(frame->closure->function), &byte); 966 967 if (line) 968 uc_error_context_format(buf, uc_vm_frame_source(frame), stacktrace, offset); 969 else if (frame->ip != chunk->entries) 970 ucv_stringbuf_printf(buf, "At instruction %zu", (frame->ip - chunk->entries) - 1); 971 else 972 ucv_stringbuf_append(buf, "At start of program"); 973 974 ucv_object_add(ucv_array_get(stacktrace, 0), "context", ucv_stringbuf_finish(buf)); 975 976 return stacktrace; 977 } 978 979 void __attribute__((format(printf, 3, 0))) 980 uc_vm_raise_exception(uc_vm_t *vm, uc_exception_type_t type, const char *fmt, ...) 981 { 982 va_list ap; 983 984 vm->exception.type = type; 985 986 free(vm->exception.message); 987 988 va_start(ap, fmt); 989 xvasprintf(&vm->exception.message, fmt, ap); 990 va_end(ap); 991 992 ucv_put(vm->exception.stacktrace); 993 vm->exception.stacktrace = uc_vm_get_error_context(vm); 994 } 995 996 997 static void 998 uc_vm_insn_load(uc_vm_t *vm, uc_vm_insn_t insn) 999 { 1000 switch (insn) { 1001 case I_LOAD: 1002 uc_vm_stack_push(vm, uc_program_get_constant(uc_vm_current_program(vm), vm->arg.u32)); 1003 break; 1004 1005 case I_LOAD8: 1006 uc_vm_stack_push(vm, ucv_uint64_new(vm->arg.u8)); 1007 break; 1008 1009 case I_LOAD16: 1010 uc_vm_stack_push(vm, ucv_uint64_new(vm->arg.u16)); 1011 break; 1012 1013 case I_LOAD32: 1014 uc_vm_stack_push(vm, ucv_uint64_new(vm->arg.u32)); 1015 break; 1016 1017 default: 1018 break; 1019 } 1020 } 1021 1022 static void 1023 uc_vm_insn_load_regexp(uc_vm_t *vm, uc_vm_insn_t insn) 1024 { 1025 uc_value_t *re, *jstr = uc_program_get_constant(uc_vm_current_program(vm), vm->arg.u32); 1026 bool icase = false, newline = false, global = false; 1027 char *str, *err = NULL; 1028 1029 if (ucv_type(jstr) != UC_STRING || ucv_string_length(jstr) < 2) { 1030 uc_vm_stack_push(vm, NULL); 1031 ucv_put(jstr); 1032 1033 return; 1034 } 1035 1036 str = ucv_string_get(jstr); 1037 1038 global = (*str & (1 << 0)); 1039 icase = (*str & (1 << 1)); 1040 newline = (*str & (1 << 2)); 1041 1042 re = ucv_regexp_new(++str, icase, newline, global, &err); 1043 1044 ucv_put(jstr); 1045 1046 if (re) 1047 uc_vm_stack_push(vm, re); 1048 else 1049 uc_vm_raise_exception(vm, EXCEPTION_SYNTAX, "%s", err); 1050 1051 free(err); 1052 } 1053 1054 static void 1055 uc_vm_insn_load_null(uc_vm_t *vm, uc_vm_insn_t insn) 1056 { 1057 uc_vm_stack_push(vm, NULL); 1058 } 1059 1060 static void 1061 uc_vm_insn_load_bool(uc_vm_t *vm, uc_vm_insn_t insn) 1062 { 1063 uc_vm_stack_push(vm, ucv_boolean_new(insn == I_LTRUE)); 1064 } 1065 1066 static void 1067 uc_vm_insn_load_var(uc_vm_t *vm, uc_vm_insn_t insn) 1068 { 1069 uc_value_t *name, *val = NULL; 1070 uc_value_t *scope, *next; 1071 bool found; 1072 1073 scope = vm->globals; 1074 name = uc_program_get_constant(uc_vm_current_program(vm), vm->arg.u32); 1075 1076 while (ucv_type(name) == UC_STRING) { 1077 val = ucv_object_get(scope, ucv_string_get(name), &found); 1078 1079 if (found) 1080 break; 1081 1082 next = ucv_prototype_get(scope); 1083 1084 if (!next) { 1085 if (uc_vm_is_strict(vm)) { 1086 uc_vm_raise_exception(vm, EXCEPTION_REFERENCE, 1087 "access to undeclared variable %s", 1088 ucv_string_get(name)); 1089 } 1090 1091 break; 1092 } 1093 1094 scope = next; 1095 } 1096 1097 ucv_put(name); 1098 1099 uc_vm_stack_push(vm, ucv_get(val)); 1100 } 1101 1102 static void 1103 uc_vm_insn_load_val(uc_vm_t *vm, uc_vm_insn_t insn) 1104 { 1105 uc_value_t *k = uc_vm_stack_pop(vm); 1106 uc_value_t *v = uc_vm_stack_pop(vm); 1107 1108 switch (ucv_type(v)) { 1109 case UC_RESOURCE: 1110 case UC_OBJECT: 1111 case UC_ARRAY: 1112 uc_vm_stack_push(vm, ucv_key_get(vm, v, k)); 1113 break; 1114 1115 default: 1116 if (insn == I_QLVAL) 1117 uc_vm_stack_push(vm, NULL); 1118 else 1119 uc_vm_raise_exception(vm, EXCEPTION_REFERENCE, 1120 "left-hand side expression is %s", 1121 v ? "not an array or object" : "null"); 1122 1123 break; 1124 } 1125 1126 ucv_put(k); 1127 ucv_put(v); 1128 } 1129 1130 static void 1131 uc_vm_insn_load_upval(uc_vm_t *vm, uc_vm_insn_t insn) 1132 { 1133 uc_callframe_t *frame = uc_vm_current_frame(vm); 1134 uc_upvalref_t *ref = frame->closure->upvals[vm->arg.u32]; 1135 1136 if (ref->closed) 1137 uc_vm_stack_push(vm, ucv_get(ref->value)); 1138 else 1139 uc_vm_stack_push(vm, ucv_get(vm->stack.entries[ref->slot])); 1140 } 1141 1142 static void 1143 uc_vm_insn_load_local(uc_vm_t *vm, uc_vm_insn_t insn) 1144 { 1145 uc_callframe_t *frame = uc_vm_current_frame(vm); 1146 1147 uc_vm_stack_push(vm, ucv_get(vm->stack.entries[frame->stackframe + vm->arg.u32])); 1148 } 1149 1150 static uc_upvalref_t * 1151 uc_vm_capture_upval(uc_vm_t *vm, size_t slot) 1152 { 1153 uc_upvalref_t *curr = vm->open_upvals; 1154 uc_upvalref_t *prev = NULL; 1155 uc_upvalref_t *created; 1156 char *s; 1157 1158 while (curr && curr->slot > slot) { 1159 prev = curr; 1160 curr = curr->next; 1161 } 1162 1163 if (curr && curr->slot == slot) { 1164 if (vm->trace) { 1165 s = ucv_to_string(NULL, vm->stack.entries[slot]); 1166 fprintf(stderr, " {+%zu} <%p> %s\n", slot, (void *)curr, s); 1167 free(s); 1168 } 1169 1170 return curr; 1171 } 1172 1173 created = (uc_upvalref_t *)ucv_upvalref_new(slot); 1174 created->next = curr; 1175 1176 if (vm->trace) { 1177 s = ucv_to_string(NULL, vm->stack.entries[slot]); 1178 fprintf(stderr, " {*%zu} <%p> %s\n", slot, (void *)created, s); 1179 free(s); 1180 } 1181 1182 if (prev) 1183 prev->next = created; 1184 else 1185 vm->open_upvals = created; 1186 1187 return created; 1188 } 1189 1190 static void 1191 uc_vm_close_upvals(uc_vm_t *vm, size_t slot) 1192 { 1193 uc_upvalref_t *ref; 1194 1195 while (vm->open_upvals && vm->open_upvals->slot >= slot) { 1196 ref = vm->open_upvals; 1197 ref->value = ucv_get(vm->stack.entries[ref->slot]); 1198 ref->closed = true; 1199 1200 if (vm->trace) { 1201 fprintf(stderr, " {!%zu} <%p> %s\n", ref->slot, 1202 (void *)ref, 1203 uc_vm_format_val(vm, ref->value)); 1204 } 1205 1206 vm->open_upvals = ref->next; 1207 ucv_put(&ref->header); 1208 } 1209 } 1210 1211 static void 1212 uc_vm_insn_load_closure(uc_vm_t *vm, uc_vm_insn_t insn) 1213 { 1214 uc_callframe_t *frame = uc_vm_current_frame(vm); 1215 uc_function_t *function = uc_program_function_load(uc_vm_current_program(vm), vm->arg.u32); 1216 uc_closure_t *closure = (uc_closure_t *)ucv_closure_new(vm, function, insn == I_ARFN); 1217 volatile int32_t uv; 1218 size_t i; 1219 1220 uc_vm_stack_push(vm, &closure->header); 1221 1222 if (function->module) 1223 return; 1224 1225 for (i = 0; i < function->nupvals; i++) { 1226 uv = ( 1227 frame->ip[0] * 0x1000000 + 1228 frame->ip[1] * 0x10000 + 1229 frame->ip[2] * 0x100 + 1230 frame->ip[3] 1231 ) - 0x7fffffff; 1232 1233 if (uv < 0) 1234 closure->upvals[i] = uc_vm_capture_upval(vm, frame->stackframe - (uv + 1)); 1235 else 1236 closure->upvals[i] = frame->closure->upvals[uv]; 1237 1238 ucv_get(&closure->upvals[i]->header); 1239 1240 frame->ip += 4; 1241 } 1242 } 1243 1244 static void 1245 uc_vm_insn_store_var(uc_vm_t *vm, uc_vm_insn_t insn) 1246 { 1247 uc_value_t *name, *v = uc_vm_stack_pop(vm); 1248 uc_value_t *scope, *next; 1249 bool found; 1250 1251 scope = vm->globals; 1252 name = uc_program_get_constant(uc_vm_current_program(vm), vm->arg.u32); 1253 1254 while (ucv_type(name) == UC_STRING) { 1255 ucv_object_get(scope, ucv_string_get(name), &found); 1256 1257 if (found) 1258 break; 1259 1260 next = ucv_prototype_get(scope); 1261 1262 if (!next) { 1263 if (uc_vm_is_strict(vm)) { 1264 uc_vm_raise_exception(vm, EXCEPTION_REFERENCE, 1265 "access to undeclared variable %s", 1266 ucv_string_get(name)); 1267 } 1268 1269 break; 1270 } 1271 1272 scope = next; 1273 } 1274 1275 if (scope && ucv_type(name) == UC_STRING) 1276 ucv_object_add(scope, ucv_string_get(name), ucv_get(v)); 1277 1278 ucv_put(name); 1279 uc_vm_stack_push(vm, v); 1280 } 1281 1282 static bool 1283 assert_mutable_value(uc_vm_t *vm, uc_value_t *val) 1284 { 1285 if (ucv_is_constant(val)) { 1286 uc_vm_stack_push(vm, NULL); 1287 uc_vm_raise_exception(vm, EXCEPTION_TYPE, 1288 "%s value is immutable", 1289 ucv_typename(val)); 1290 1291 return false; 1292 } 1293 1294 return true; 1295 } 1296 1297 static void 1298 uc_vm_insn_store_val(uc_vm_t *vm, uc_vm_insn_t insn) 1299 { 1300 uc_value_t *v = uc_vm_stack_pop(vm); 1301 uc_value_t *k = uc_vm_stack_pop(vm); 1302 uc_value_t *o = uc_vm_stack_pop(vm); 1303 1304 switch (ucv_type(o)) { 1305 case UC_OBJECT: 1306 case UC_ARRAY: 1307 if (assert_mutable_value(vm, o)) 1308 uc_vm_stack_push(vm, ucv_key_set(vm, o, k, v)); 1309 1310 break; 1311 1312 default: 1313 uc_vm_raise_exception(vm, EXCEPTION_TYPE, 1314 "attempt to set property on %s value", 1315 ucv_typename(o)); 1316 } 1317 1318 ucv_put(o); 1319 ucv_put(k); 1320 } 1321 1322 static void 1323 uc_vm_insn_store_upval(uc_vm_t *vm, uc_vm_insn_t insn) 1324 { 1325 uc_callframe_t *frame = uc_vm_current_frame(vm); 1326 uc_upvalref_t *ref = frame->closure->upvals[vm->arg.u32]; 1327 uc_value_t *val = ucv_get(uc_vm_stack_peek(vm, 0)); 1328 1329 if (ref->closed) { 1330 ucv_put(ref->value); 1331 ref->value = val; 1332 } 1333 else { 1334 uc_vm_stack_set(vm, ref->slot, val); 1335 } 1336 } 1337 1338 static void 1339 uc_vm_insn_store_local(uc_vm_t *vm, uc_vm_insn_t insn) 1340 { 1341 uc_callframe_t *frame = uc_vm_current_frame(vm); 1342 uc_value_t *val = ucv_get(uc_vm_stack_peek(vm, 0)); 1343 1344 uc_vm_stack_set(vm, frame->stackframe + vm->arg.u32, val); 1345 } 1346 1347 static int64_t 1348 int64(uc_value_t *nv, uint64_t *u64) 1349 { 1350 int64_t n; 1351 1352 n = ucv_int64_get(nv); 1353 *u64 = 0; 1354 1355 if (errno == ERANGE) { 1356 n = INT64_MAX; 1357 *u64 = ucv_uint64_get(nv); 1358 } 1359 1360 return n; 1361 } 1362 1363 static uint64_t 1364 abs64(int64_t n) 1365 { 1366 if (n == INT64_MIN) 1367 return 0x8000000000000000ULL; 1368 1369 if (n < 0) 1370 return -n; 1371 1372 return n; 1373 } 1374 1375 1376 static uc_value_t * 1377 uc_vm_value_bitop(uc_vm_t *vm, uc_vm_insn_t operation, uc_value_t *value, uc_value_t *operand) 1378 { 1379 uc_value_t *nv1, *nv2, *rv = NULL; 1380 uint64_t u1, u2; 1381 int64_t n1, n2; 1382 1383 nv1 = ucv_to_number(value); 1384 nv2 = ucv_to_number(operand); 1385 1386 n1 = int64(nv1, &u1); 1387 n2 = int64(nv2, &u2); 1388 1389 if (n1 < 0 || n2 < 0) { 1390 switch (operation) { 1391 case I_LSHIFT: 1392 rv = ucv_int64_new(n1 << n2); 1393 break; 1394 1395 case I_RSHIFT: 1396 rv = ucv_int64_new(n1 >> n2); 1397 break; 1398 1399 case I_BAND: 1400 rv = ucv_int64_new(n1 & n2); 1401 break; 1402 1403 case I_BXOR: 1404 rv = ucv_int64_new(n1 ^ n2); 1405 break; 1406 1407 case I_BOR: 1408 rv = ucv_int64_new(n1 | n2); 1409 break; 1410 1411 default: 1412 break; 1413 } 1414 } 1415 else { 1416 if (!u1) u1 = (uint64_t)n1; 1417 if (!u2) u2 = (uint64_t)n2; 1418 1419 switch (operation) { 1420 case I_LSHIFT: 1421 rv = ucv_uint64_new(u1 << (u2 % (sizeof(uint64_t) * CHAR_BIT))); 1422 break; 1423 1424 case I_RSHIFT: 1425 rv = ucv_uint64_new(u1 >> (u2 % (sizeof(uint64_t) * CHAR_BIT))); 1426 break; 1427 1428 case I_BAND: 1429 rv = ucv_uint64_new(u1 & u2); 1430 break; 1431 1432 case I_BXOR: 1433 rv = ucv_uint64_new(u1 ^ u2); 1434 break; 1435 1436 case I_BOR: 1437 rv = ucv_uint64_new(u1 | u2); 1438 break; 1439 1440 default: 1441 break; 1442 } 1443 } 1444 1445 ucv_put(nv1); 1446 ucv_put(nv2); 1447 1448 return rv; 1449 } 1450 1451 static uc_value_t * 1452 uc_vm_string_concat(uc_vm_t *vm, uc_value_t *v1, uc_value_t *v2) 1453 { 1454 char buf[sizeof(void *)], *s1, *s2; 1455 uc_stringbuf_t *sbuf; 1456 size_t l1, l2; 1457 1458 /* optimize cases for string+string concat... */ 1459 if (ucv_type(v1) == UC_STRING && ucv_type(v2) == UC_STRING) { 1460 s1 = ucv_string_get(v1); 1461 s2 = ucv_string_get(v2); 1462 l1 = ucv_string_length(v1); 1463 l2 = ucv_string_length(v2); 1464 1465 /* ... result fits into a tagged pointer */ 1466 if (l1 + l2 + 1 < sizeof(buf)) { 1467 memcpy(&buf[0], s1, l1); 1468 memcpy(&buf[l1], s2, l2); 1469 1470 return ucv_string_new_length(buf, l1 + l2); 1471 } 1472 } 1473 1474 sbuf = ucv_stringbuf_new(); 1475 1476 ucv_to_stringbuf(vm, sbuf, v1, false); 1477 ucv_to_stringbuf(vm, sbuf, v2, false); 1478 1479 return ucv_stringbuf_finish(sbuf); 1480 } 1481 1482 static uint64_t 1483 upow64(uint64_t base, uint64_t exponent) 1484 { 1485 uint64_t result = 1; 1486 1487 while (exponent) { 1488 if (exponent & 1) 1489 result *= base; 1490 1491 exponent >>= 1; 1492 base *= base; 1493 } 1494 1495 return result; 1496 } 1497 1498 static uc_value_t * 1499 uc_vm_value_arith(uc_vm_t *vm, uc_vm_insn_t operation, uc_value_t *value, uc_value_t *operand) 1500 { 1501 uc_value_t *nv1, *nv2, *rv = NULL; 1502 uint64_t u1, u2; 1503 int64_t n1, n2; 1504 double d1, d2; 1505 1506 if (operation == I_LSHIFT || operation == I_RSHIFT || 1507 operation == I_BAND || operation == I_BXOR || operation == I_BOR) 1508 return uc_vm_value_bitop(vm, operation, value, operand); 1509 1510 if (operation == I_ADD && (ucv_type(value) == UC_STRING || ucv_type(operand) == UC_STRING)) 1511 return uc_vm_string_concat(vm, value, operand); 1512 1513 nv1 = ucv_to_number(value); 1514 nv2 = ucv_to_number(operand); 1515 1516 /* any operation involving NaN results in NaN */ 1517 if (!nv1 || !nv2) { 1518 ucv_put(nv1); 1519 ucv_put(nv2); 1520 1521 return ucv_double_new(NAN); 1522 } 1523 if (ucv_type(nv1) == UC_DOUBLE || ucv_type(nv2) == UC_DOUBLE) { 1524 d1 = ucv_double_get(nv1); 1525 d2 = ucv_double_get(nv2); 1526 1527 switch (operation) { 1528 case I_ADD: 1529 case I_PLUS: 1530 rv = ucv_double_new(d1 + d2); 1531 break; 1532 1533 case I_SUB: 1534 case I_MINUS: 1535 rv = ucv_double_new(d1 - d2); 1536 break; 1537 1538 case I_MUL: 1539 rv = ucv_double_new(d1 * d2); 1540 break; 1541 1542 case I_DIV: 1543 if (d2 == 0.0) 1544 rv = ucv_double_new(INFINITY); 1545 else if (isnan(d2)) 1546 rv = ucv_double_new(NAN); 1547 else if (!isfinite(d2)) 1548 rv = ucv_double_new(isfinite(d1) ? 0.0 : NAN); 1549 else 1550 rv = ucv_double_new(d1 / d2); 1551 1552 break; 1553 1554 case I_MOD: 1555 rv = ucv_double_new(fmod(d1, d2)); 1556 break; 1557 1558 case I_EXP: 1559 rv = ucv_double_new(pow(d1, d2)); 1560 break; 1561 1562 default: 1563 uc_vm_raise_exception(vm, EXCEPTION_RUNTIME, 1564 "undefined arithmetic operation %d", 1565 operation); 1566 break; 1567 } 1568 } 1569 else { 1570 n1 = int64(nv1, &u1); 1571 n2 = int64(nv2, &u2); 1572 1573 switch (operation) { 1574 case I_ADD: 1575 case I_PLUS: 1576 if (n1 < 0 || n2 < 0) { 1577 if (u1) 1578 rv = ucv_uint64_new(u1 - abs64(n2)); 1579 else if (u2) 1580 rv = ucv_uint64_new(u2 - abs64(n1)); 1581 else 1582 rv = ucv_int64_new(n1 + n2); 1583 } 1584 else { 1585 if (!u1) u1 = (uint64_t)n1; 1586 if (!u2) u2 = (uint64_t)n2; 1587 1588 rv = ucv_uint64_new(u1 + u2); 1589 } 1590 1591 break; 1592 1593 case I_SUB: 1594 case I_MINUS: 1595 if (n1 < 0 && n2 < 0) { 1596 if (n1 > n2) 1597 rv = ucv_uint64_new(abs64(n2) - abs64(n1)); 1598 else 1599 rv = ucv_int64_new(n1 - n2); 1600 } 1601 else if (n1 >= 0 && n2 >= 0) { 1602 if (!u1) u1 = (uint64_t)n1; 1603 if (!u2) u2 = (uint64_t)n2; 1604 1605 if (u2 > u1) 1606 rv = ucv_int64_new(-(u2 - u1)); 1607 else 1608 rv = ucv_uint64_new(u1 - u2); 1609 } 1610 else if (n1 >= 0) { 1611 if (!u1) u1 = (uint64_t)n1; 1612 1613 rv = ucv_uint64_new(u1 + abs64(n2)); 1614 } 1615 else { 1616 rv = ucv_int64_new(n1 - n2); 1617 } 1618 1619 break; 1620 1621 case I_MUL: 1622 if (n1 < 0 && n2 < 0) { 1623 rv = ucv_uint64_new(abs64(n1) * abs64(n2)); 1624 } 1625 else if (n1 >= 0 && n2 >= 0) { 1626 if (!u1) u1 = (uint64_t)n1; 1627 if (!u2) u2 = (uint64_t)n2; 1628 1629 rv = ucv_uint64_new(u1 * u2); 1630 } 1631 else { 1632 rv = ucv_int64_new(n1 * n2); 1633 } 1634 1635 break; 1636 1637 case I_DIV: 1638 if (n2 == 0) { 1639 rv = ucv_double_new(INFINITY); 1640 } 1641 else if (n1 < 0 || n2 < 0) { 1642 rv = ucv_int64_new(n1 / n2); 1643 } 1644 else { 1645 if (!u1) u1 = (uint64_t)n1; 1646 if (!u2) u2 = (uint64_t)n2; 1647 1648 rv = ucv_uint64_new(u1 / u2); 1649 } 1650 1651 break; 1652 1653 case I_MOD: 1654 if (n1 < 0 || n2 < 0) { 1655 rv = ucv_int64_new(n1 % n2); 1656 } 1657 else { 1658 if (!u1) u1 = (uint64_t)n1; 1659 if (!u2) u2 = (uint64_t)n2; 1660 1661 rv = ucv_uint64_new(u1 % u2); 1662 } 1663 1664 break; 1665 1666 case I_EXP: 1667 if (n1 < 0 || n2 < 0) { 1668 if (n1 < 0 && n2 < 0) 1669 rv = ucv_double_new(-(1.0 / (double)upow64(abs64(n1), abs64(n2)))); 1670 else if (n2 < 0) 1671 rv = ucv_double_new(1.0 / (double)upow64(abs64(n1), abs64(n2))); 1672 else 1673 rv = ucv_int64_new(-upow64(abs64(n1), abs64(n2))); 1674 } 1675 else { 1676 if (!u1) u1 = (uint64_t)n1; 1677 if (!u2) u2 = (uint64_t)n2; 1678 1679 rv = ucv_uint64_new(upow64(u1, u2)); 1680 } 1681 1682 break; 1683 1684 default: 1685 uc_vm_raise_exception(vm, EXCEPTION_RUNTIME, 1686 "undefined arithmetic operation %d", 1687 operation); 1688 break; 1689 } 1690 } 1691 1692 ucv_put(nv1); 1693 ucv_put(nv2); 1694 1695 return rv; 1696 } 1697 1698 static void 1699 uc_vm_insn_update_var(uc_vm_t *vm, uc_vm_insn_t insn) 1700 { 1701 uc_value_t *name, *val = NULL, *inc = uc_vm_stack_pop(vm); 1702 uc_value_t *scope, *next; 1703 bool found; 1704 1705 scope = vm->globals; 1706 name = uc_program_get_constant(uc_vm_current_program(vm), vm->arg.u32 & 0x00FFFFFF); 1707 1708 assert(ucv_type(name) == UC_STRING); 1709 1710 while (true) { 1711 val = ucv_object_get(scope, ucv_string_get(name), &found); 1712 1713 if (found) 1714 break; 1715 1716 next = ucv_prototype_get(scope); 1717 1718 if (!next) { 1719 if (uc_vm_is_strict(vm)) { 1720 uc_vm_raise_exception(vm, EXCEPTION_REFERENCE, 1721 "access to undeclared variable %s", 1722 ucv_string_get(name)); 1723 } 1724 1725 break; 1726 } 1727 1728 scope = next; 1729 } 1730 1731 val = uc_vm_value_arith(vm, vm->arg.u32 >> 24, val, inc); 1732 1733 ucv_object_add(scope, ucv_string_get(name), ucv_get(val)); 1734 uc_vm_stack_push(vm, val); 1735 1736 ucv_put(name); 1737 ucv_put(inc); 1738 } 1739 1740 static void 1741 uc_vm_insn_update_val(uc_vm_t *vm, uc_vm_insn_t insn) 1742 { 1743 uc_value_t *inc = uc_vm_stack_pop(vm); 1744 uc_value_t *k = uc_vm_stack_pop(vm); 1745 uc_value_t *v = uc_vm_stack_pop(vm); 1746 uc_value_t *val = NULL; 1747 1748 switch (ucv_type(v)) { 1749 case UC_OBJECT: 1750 case UC_ARRAY: 1751 if (assert_mutable_value(vm, v)) { 1752 val = ucv_key_get(vm, v, k); 1753 uc_vm_stack_push(vm, ucv_key_set(vm, v, k, uc_vm_value_arith(vm, vm->arg.u8, val, inc))); 1754 } 1755 1756 break; 1757 1758 default: 1759 uc_vm_raise_exception(vm, EXCEPTION_REFERENCE, 1760 "left-hand side expression is %s", 1761 v ? "not an array or object" : "null"); 1762 1763 break; 1764 } 1765 1766 ucv_put(val); 1767 ucv_put(inc); 1768 ucv_put(v); 1769 ucv_put(k); 1770 } 1771 1772 static void 1773 uc_vm_insn_update_upval(uc_vm_t *vm, uc_vm_insn_t insn) 1774 { 1775 uc_callframe_t *frame = uc_vm_current_frame(vm); 1776 size_t slot = vm->arg.u32 & 0x00FFFFFF; 1777 uc_upvalref_t *ref = frame->closure->upvals[slot]; 1778 uc_value_t *inc = uc_vm_stack_pop(vm); 1779 uc_value_t *val; 1780 1781 if (ref->closed) 1782 val = ref->value; 1783 else 1784 val = vm->stack.entries[ref->slot]; 1785 1786 val = uc_vm_value_arith(vm, vm->arg.u32 >> 24, val, inc); 1787 1788 uc_vm_stack_push(vm, val); 1789 1790 ucv_put(inc); 1791 1792 if (ref->closed) { 1793 ucv_put(ref->value); 1794 ref->value = ucv_get(uc_vm_stack_peek(vm, 0)); 1795 } 1796 else { 1797 uc_vm_stack_set(vm, ref->slot, ucv_get(uc_vm_stack_peek(vm, 0))); 1798 } 1799 } 1800 1801 static void 1802 uc_vm_insn_update_local(uc_vm_t *vm, uc_vm_insn_t insn) 1803 { 1804 uc_callframe_t *frame = uc_vm_current_frame(vm); 1805 size_t slot = vm->arg.u32 & 0x00FFFFFF; 1806 uc_value_t *inc = uc_vm_stack_pop(vm); 1807 uc_value_t *val; 1808 1809 val = uc_vm_value_arith(vm, vm->arg.u32 >> 24, 1810 vm->stack.entries[frame->stackframe + slot], inc); 1811 1812 uc_vm_stack_push(vm, val); 1813 1814 ucv_put(inc); 1815 uc_vm_stack_set(vm, frame->stackframe + slot, ucv_get(uc_vm_stack_peek(vm, 0))); 1816 } 1817 1818 static void 1819 uc_vm_insn_narr(uc_vm_t *vm, uc_vm_insn_t insn) 1820 { 1821 uc_value_t *arr = ucv_array_new_length(vm, vm->arg.u32); 1822 1823 uc_vm_stack_push(vm, arr); 1824 } 1825 1826 static void 1827 uc_vm_insn_parr(uc_vm_t *vm, uc_vm_insn_t insn) 1828 { 1829 uc_value_t *arr = uc_vm_stack_peek(vm, vm->arg.u32); 1830 size_t idx; 1831 1832 for (idx = 0; idx < vm->arg.u32; idx++) 1833 ucv_array_push(arr, uc_vm_stack_peek(vm, vm->arg.u32 - idx - 1)); 1834 1835 for (idx = 0; idx < vm->arg.u32; idx++) 1836 uc_vm_stack_pop(vm); 1837 1838 //uc_vm_shrink(state, vm->arg.u32); 1839 } 1840 1841 static void 1842 uc_vm_insn_marr(uc_vm_t *vm, uc_vm_insn_t insn) 1843 { 1844 uc_value_t *src = uc_vm_stack_pop(vm); 1845 uc_value_t *dst = uc_vm_stack_peek(vm, 0); 1846 size_t i; 1847 char *s; 1848 1849 if (ucv_type(src) != UC_ARRAY) { 1850 s = ucv_to_string(vm, src); 1851 uc_vm_raise_exception(vm, EXCEPTION_TYPE, "(%s) is not iterable", s); 1852 ucv_put(src); 1853 free(s); 1854 1855 return; 1856 } 1857 1858 for (i = 0; i < ucv_array_length(src); i++) 1859 ucv_array_push(dst, ucv_get(ucv_array_get(src, i))); 1860 1861 ucv_put(src); 1862 } 1863 1864 static void 1865 uc_vm_insn_nobj(uc_vm_t *vm, uc_vm_insn_t insn) 1866 { 1867 uc_value_t *obj = ucv_object_new(vm); 1868 1869 uc_vm_stack_push(vm, obj); 1870 } 1871 1872 static void 1873 uc_vm_insn_sobj(uc_vm_t *vm, uc_vm_insn_t insn) 1874 { 1875 uc_value_t *obj = uc_vm_stack_peek(vm, vm->arg.u32); 1876 size_t idx; 1877 1878 for (idx = 0; idx < vm->arg.u32; idx += 2) 1879 ucv_key_set(vm, obj, 1880 uc_vm_stack_peek(vm, vm->arg.u32 - idx - 1), 1881 uc_vm_stack_peek(vm, vm->arg.u32 - idx - 2)); 1882 1883 for (idx = 0; idx < vm->arg.u32; idx++) 1884 ucv_put(uc_vm_stack_pop(vm)); 1885 } 1886 1887 static void 1888 uc_vm_insn_mobj(uc_vm_t *vm, uc_vm_insn_t insn) 1889 { 1890 uc_value_t *src = uc_vm_stack_pop(vm); 1891 uc_value_t *dst = uc_vm_stack_peek(vm, 0); 1892 size_t i; 1893 char *s; 1894 1895 switch (ucv_type(src)) { 1896 case UC_OBJECT: 1897 ; /* a label can only be part of a statement and a declaration is not a statement */ 1898 ucv_object_foreach(src, k, v) 1899 ucv_object_add(dst, k, ucv_get(v)); 1900 1901 ucv_put(src); 1902 break; 1903 1904 case json_type_array: 1905 for (i = 0; i < ucv_array_length(src); i++) { 1906 xasprintf(&s, "%zu", i); 1907 ucv_object_add(dst, s, ucv_get(ucv_array_get(src, i))); 1908 free(s); 1909 } 1910 1911 ucv_put(src); 1912 break; 1913 1914 default: 1915 s = ucv_to_string(vm, src); 1916 uc_vm_raise_exception(vm, EXCEPTION_TYPE, "Value (%s) is not iterable", s); 1917 free(s); 1918 1919 break; 1920 } 1921 } 1922 1923 static void 1924 uc_vm_insn_arith(uc_vm_t *vm, uc_vm_insn_t insn) 1925 { 1926 uc_value_t *r2 = uc_vm_stack_pop(vm); 1927 uc_value_t *r1 = uc_vm_stack_pop(vm); 1928 uc_value_t *rv; 1929 1930 rv = uc_vm_value_arith(vm, insn, r1, r2); 1931 1932 ucv_put(r1); 1933 ucv_put(r2); 1934 1935 uc_vm_stack_push(vm, rv); 1936 } 1937 1938 static void 1939 uc_vm_insn_plus_minus(uc_vm_t *vm, uc_vm_insn_t insn) 1940 { 1941 uc_value_t *v = uc_vm_stack_pop(vm), *nv; 1942 bool is_sub = (insn == I_MINUS); 1943 int64_t n; 1944 double d; 1945 1946 if (ucv_type(v) == UC_STRING) { 1947 nv = uc_number_parse(ucv_string_get(v), NULL); 1948 1949 if (nv) { 1950 ucv_put(v); 1951 v = nv; 1952 } 1953 } 1954 1955 switch (ucv_type(v)) { 1956 case UC_INTEGER: 1957 n = ucv_int64_get(v); 1958 1959 /* numeric value is in range 9223372036854775808..18446744073709551615 */ 1960 if (errno == ERANGE) { 1961 if (is_sub) 1962 /* make negation of large numeric value result in smallest negative value */ 1963 uc_vm_stack_push(vm, ucv_int64_new(INT64_MIN)); 1964 else 1965 /* for positive number coercion return value as-is */ 1966 uc_vm_stack_push(vm, ucv_get(v)); 1967 } 1968 1969 /* numeric value is in range -9223372036854775808..9223372036854775807 */ 1970 else { 1971 if (is_sub) { 1972 if (n == INT64_MIN) 1973 /* make negation of minimum value result in maximum signed positive value */ 1974 uc_vm_stack_push(vm, ucv_int64_new(INT64_MAX)); 1975 else 1976 /* for all other values flip the sign */ 1977 uc_vm_stack_push(vm, ucv_int64_new(-n)); 1978 } 1979 else { 1980 /* for positive number coercion return value as-is */ 1981 uc_vm_stack_push(vm, ucv_get(v)); 1982 } 1983 } 1984 1985 break; 1986 1987 case UC_DOUBLE: 1988 d = ucv_double_get(v); 1989 uc_vm_stack_push(vm, ucv_double_new(is_sub ? -d : d)); 1990 break; 1991 1992 case UC_BOOLEAN: 1993 n = (int64_t)ucv_boolean_get(v); 1994 uc_vm_stack_push(vm, ucv_int64_new(is_sub ? -n : n)); 1995 break; 1996 1997 case UC_NULL: 1998 uc_vm_stack_push(vm, ucv_int64_new(0)); 1999 break; 2000 2001 default: 2002 uc_vm_stack_push(vm, ucv_double_new(NAN)); 2003 } 2004 2005 ucv_put(v); 2006 } 2007 2008 static void 2009 uc_vm_insn_bitop(uc_vm_t *vm, uc_vm_insn_t insn) 2010 { 2011 uc_value_t *r2 = uc_vm_stack_pop(vm); 2012 uc_value_t *r1 = uc_vm_stack_pop(vm); 2013 uc_value_t *rv; 2014 2015 rv = uc_vm_value_bitop(vm, insn, r1, r2); 2016 2017 ucv_put(r1); 2018 ucv_put(r2); 2019 2020 uc_vm_stack_push(vm, rv); 2021 } 2022 2023 static void 2024 uc_vm_insn_complement(uc_vm_t *vm, uc_vm_insn_t insn) 2025 { 2026 uc_value_t *v = uc_vm_stack_pop(vm); 2027 uc_value_t *nv; 2028 uint64_t u; 2029 int64_t n; 2030 2031 nv = ucv_to_number(v); 2032 n = int64(nv, &u); 2033 2034 if (n < 0) { 2035 uc_vm_stack_push(vm, ucv_int64_new(~n)); 2036 } 2037 else { 2038 if (!u) u = (uint64_t)n; 2039 2040 uc_vm_stack_push(vm, ucv_uint64_new(~u)); 2041 } 2042 2043 ucv_put(nv); 2044 ucv_put(v); 2045 } 2046 2047 static void 2048 uc_vm_insn_rel(uc_vm_t *vm, uc_vm_insn_t insn) 2049 { 2050 uc_value_t *r2 = uc_vm_stack_pop(vm); 2051 uc_value_t *r1 = uc_vm_stack_pop(vm); 2052 2053 bool res = ucv_compare(insn, r1, r2, NULL); 2054 2055 ucv_put(r1); 2056 ucv_put(r2); 2057 2058 uc_vm_stack_push(vm, ucv_boolean_new(res)); 2059 } 2060 2061 static void 2062 uc_vm_insn_in(uc_vm_t *vm, uc_vm_insn_t insn) 2063 { 2064 uc_value_t *r2 = uc_vm_stack_pop(vm); 2065 uc_value_t *r1 = uc_vm_stack_pop(vm); 2066 uc_value_t *item; 2067 size_t arrlen, arridx; 2068 bool found = false; 2069 char *key; 2070 2071 switch (ucv_type(r2)) { 2072 case UC_ARRAY: 2073 for (arridx = 0, arrlen = ucv_array_length(r2); 2074 arridx < arrlen; arridx++) { 2075 item = ucv_array_get(r2, arridx); 2076 2077 if (ucv_compare(I_EQ, r1, item, NULL)) { 2078 found = true; 2079 break; 2080 } 2081 } 2082 2083 break; 2084 2085 case UC_OBJECT: 2086 if (ucv_type(r1) == UC_STRING) { 2087 ucv_object_get(r2, ucv_string_get(r1), &found); 2088 } 2089 else { 2090 key = ucv_to_string(vm, r1); 2091 ucv_object_get(r2, key, &found); 2092 free(key); 2093 } 2094 2095 break; 2096 2097 default: 2098 found = false; 2099 } 2100 2101 ucv_put(r1); 2102 ucv_put(r2); 2103 2104 uc_vm_stack_push(vm, ucv_boolean_new(found)); 2105 } 2106 2107 static void 2108 uc_vm_insn_equality(uc_vm_t *vm, uc_vm_insn_t insn) 2109 { 2110 uc_value_t *r2 = uc_vm_stack_pop(vm); 2111 uc_value_t *r1 = uc_vm_stack_pop(vm); 2112 bool equal; 2113 2114 if (ucv_is_scalar(r1) && ucv_is_scalar(r2)) 2115 equal = ucv_is_equal(r1, r2); 2116 else 2117 equal = (r1 == r2); 2118 2119 ucv_put(r1); 2120 ucv_put(r2); 2121 2122 uc_vm_stack_push(vm, ucv_boolean_new((insn == I_EQS) ? equal : !equal)); 2123 } 2124 2125 static void 2126 uc_vm_insn_not(uc_vm_t *vm, uc_vm_insn_t insn) 2127 { 2128 uc_value_t *r1 = uc_vm_stack_pop(vm); 2129 2130 uc_vm_stack_push(vm, ucv_boolean_new(!ucv_is_truish(r1))); 2131 ucv_put(r1); 2132 } 2133 2134 static void 2135 uc_vm_insn_jmp(uc_vm_t *vm, uc_vm_insn_t insn) 2136 { 2137 uc_callframe_t *frame = uc_vm_current_frame(vm); 2138 uc_chunk_t *chunk = uc_vm_frame_chunk(frame); 2139 int32_t addr = vm->arg.s32; 2140 2141 /* ip already has been incremented */ 2142 addr -= 5; 2143 2144 if (frame->ip + addr < chunk->entries || 2145 frame->ip + addr >= chunk->entries + chunk->count) { 2146 uc_vm_raise_exception(vm, EXCEPTION_RUNTIME, "jump target out of range"); 2147 return; 2148 } 2149 2150 frame->ip += addr; 2151 } 2152 2153 static void 2154 uc_vm_insn_jmpz(uc_vm_t *vm, uc_vm_insn_t insn) 2155 { 2156 uc_callframe_t *frame = uc_vm_current_frame(vm); 2157 uc_chunk_t *chunk = uc_vm_frame_chunk(frame); 2158 uc_value_t *v = uc_vm_stack_pop(vm); 2159 int32_t addr = vm->arg.s32; 2160 2161 /* ip already has been incremented */ 2162 addr -= 5; 2163 2164 if (frame->ip + addr < chunk->entries || 2165 frame->ip + addr >= chunk->entries + chunk->count) { 2166 uc_vm_raise_exception(vm, EXCEPTION_RUNTIME, "jump target out of range"); 2167 return; 2168 } 2169 2170 if (!ucv_is_truish(v)) 2171 frame->ip += addr; 2172 2173 ucv_put(v); 2174 } 2175 2176 static void 2177 uc_vm_insn_next(uc_vm_t *vm, uc_vm_insn_t insn) 2178 { 2179 uc_value_t *k = uc_vm_stack_pop(vm); 2180 uc_value_t *v = uc_vm_stack_pop(vm); 2181 void *end = (void *)~(uintptr_t)0; 2182 uc_resource_t *iterk; 2183 struct lh_entry *curr; 2184 uint64_t n; 2185 2186 if (k != NULL && ucv_type(k) != UC_RESOURCE) { 2187 fprintf(stderr, "Invalid iterator value\n"); 2188 abort(); 2189 } 2190 2191 if (k == NULL) 2192 k = ucv_resource_new(NULL, NULL); 2193 2194 iterk = (uc_resource_t *)k; 2195 2196 switch (ucv_type(v)) { 2197 case UC_OBJECT: 2198 curr = iterk->data ? iterk->data : ((uc_object_t *)v)->table->head; 2199 2200 if (curr != NULL && curr != end) { 2201 iterk->data = curr->next ? curr->next : end; 2202 2203 uc_vm_stack_push(vm, ucv_string_new(curr->k)); 2204 2205 if (insn == I_NEXTKV) 2206 uc_vm_stack_push(vm, ucv_get((uc_value_t *)curr->v)); 2207 2208 uc_vm_stack_push(vm, k); 2209 ucv_put(v); 2210 2211 return; 2212 } 2213 2214 break; 2215 2216 case UC_ARRAY: 2217 n = (uintptr_t)iterk->data; 2218 2219 if (n < ucv_array_length(v)) { 2220 iterk->data = (void *)(uintptr_t)(n + 1); 2221 2222 if (insn == I_NEXTKV) 2223 uc_vm_stack_push(vm, ucv_uint64_new(n)); 2224 2225 uc_vm_stack_push(vm, ucv_get(ucv_array_get(v, n))); 2226 2227 uc_vm_stack_push(vm, k); 2228 ucv_put(v); 2229 2230 return; 2231 } 2232 2233 break; 2234 2235 default: 2236 break; 2237 } 2238 2239 uc_vm_stack_push(vm, NULL); 2240 uc_vm_stack_push(vm, NULL); 2241 2242 if (insn == I_NEXTKV) 2243 uc_vm_stack_push(vm, NULL); 2244 2245 ucv_put(k); 2246 ucv_put(v); 2247 } 2248 2249 static void 2250 uc_vm_insn_close_upval(uc_vm_t *vm, uc_vm_insn_t insn) 2251 { 2252 uc_vm_close_upvals(vm, vm->stack.count - 1); 2253 ucv_put(uc_vm_stack_pop(vm)); 2254 } 2255 2256 static void 2257 uc_vm_skip_call(uc_vm_t *vm, bool mcall) 2258 { 2259 uc_callframe_t *frame = uc_vm_current_frame(vm); 2260 size_t i; 2261 2262 /* pop all function arguments, the function itself and the associated 2263 * function context off the stack */ 2264 for (i = 0; i < 1 + mcall + (vm->arg.u32 & 0xffff); i++) 2265 ucv_put(uc_vm_stack_pop(vm)); 2266 2267 /* skip all encoded spread value indexes */ 2268 for (i = 0; i < (vm->arg.u32 >> 16); i++) 2269 frame->ip += 2; 2270 2271 uc_vm_stack_push(vm, NULL); 2272 } 2273 2274 static void 2275 uc_vm_insn_call(uc_vm_t *vm, uc_vm_insn_t insn) 2276 { 2277 uc_value_t *fno = ucv_get(uc_vm_stack_peek(vm, vm->arg.u32 & 0xffff)); 2278 uc_value_t *ctx = NULL; 2279 2280 if (!ucv_is_callable(fno) && insn == I_QCALL) 2281 return uc_vm_skip_call(vm, false); 2282 2283 if (!ucv_is_arrowfn(fno)) 2284 ctx = NULL; 2285 else if (vm->callframes.count > 0) 2286 ctx = uc_vm_current_frame(vm)->ctx; 2287 2288 uc_vm_call_function(vm, ucv_get(ctx), fno, false, vm->arg.u32); 2289 } 2290 2291 static void 2292 uc_vm_insn_mcall(uc_vm_t *vm, uc_vm_insn_t insn) 2293 { 2294 size_t key_slot = vm->stack.count - (vm->arg.u32 & 0xffff) - 1; 2295 uc_value_t *ctx = vm->stack.entries[key_slot - 1]; 2296 uc_value_t *key = vm->stack.entries[key_slot]; 2297 uc_value_t *fno = uc_vm_resolve_upval(vm, ucv_key_get(vm, ctx, key)); 2298 2299 if (!ucv_is_callable(fno) && insn == I_QMCALL) 2300 return uc_vm_skip_call(vm, true); 2301 2302 uc_vm_stack_set(vm, key_slot, fno); 2303 2304 /* arrow functions as method calls inherit the parent ctx */ 2305 if (ucv_is_arrowfn(fno)) 2306 ctx = uc_vm_current_frame(vm)->ctx; 2307 2308 uc_vm_call_function(vm, ucv_get(ctx), ucv_get(fno), true, vm->arg.u32); 2309 } 2310 2311 static void 2312 uc_vm_insn_print(uc_vm_t *vm, uc_vm_insn_t insn) 2313 { 2314 uc_value_t *v = uc_vm_stack_pop(vm); 2315 char *p; 2316 2317 switch (ucv_type(v)) { 2318 case UC_OBJECT: 2319 case UC_ARRAY: 2320 p = ucv_to_jsonstring(vm, v); 2321 fwrite(p, 1, strlen(p), vm->output); 2322 free(p); 2323 break; 2324 2325 case UC_STRING: 2326 fwrite(ucv_string_get(v), 1, ucv_string_length(v), vm->output); 2327 break; 2328 2329 case UC_NULL: 2330 break; 2331 2332 default: 2333 p = ucv_to_string(vm, v); 2334 fwrite(p, 1, strlen(p), vm->output); 2335 free(p); 2336 } 2337 2338 ucv_put(v); 2339 } 2340 2341 static void 2342 uc_vm_insn_delete(uc_vm_t *vm, uc_vm_insn_t insn) 2343 { 2344 uc_value_t *k = uc_vm_stack_pop(vm); 2345 uc_value_t *v = uc_vm_stack_pop(vm); 2346 bool rv; 2347 2348 switch (ucv_type(v)) { 2349 case UC_OBJECT: 2350 if (assert_mutable_value(vm, v)) { 2351 rv = ucv_key_delete(vm, v, k); 2352 uc_vm_stack_push(vm, ucv_boolean_new(rv)); 2353 } 2354 2355 break; 2356 2357 default: 2358 uc_vm_raise_exception(vm, EXCEPTION_REFERENCE, 2359 "left-hand side expression is %s", 2360 v ? "not an object" : "null"); 2361 2362 break; 2363 } 2364 2365 ucv_put(k); 2366 ucv_put(v); 2367 } 2368 2369 static void 2370 uc_vm_insn_import(uc_vm_t *vm, uc_vm_insn_t insn) 2371 { 2372 uc_callframe_t *frame = uc_vm_current_frame(vm); 2373 uc_program_t *prog = uc_vm_current_program(vm); 2374 uint16_t from = vm->arg.u32 & 0xffff; 2375 uint16_t to = vm->arg.u32 >> 16; 2376 uc_value_t *name, *modobj; 2377 uint32_t cidx; 2378 2379 /* is a wildcard import * from ... */ 2380 if (to == 0xffff) { 2381 to = from; 2382 modobj = ucv_object_new(vm); 2383 2384 /* instruction is followed by u16 containing the offset of the 2385 * first module export and `from` times u32 values containing 2386 * the constant indexes of the names */ 2387 for (from = frame->ip[0] * 0x100 + frame->ip[1], frame->ip += 2; 2388 from < prog->exports.count && to > 0; 2389 from++, to--) { 2390 2391 cidx = ( 2392 frame->ip[0] * 0x1000000UL + 2393 frame->ip[1] * 0x10000UL + 2394 frame->ip[2] * 0x100UL + 2395 frame->ip[3] 2396 ); 2397 2398 frame->ip += 4; 2399 2400 name = uc_program_get_constant(uc_vm_current_program(vm), cidx); 2401 2402 if (ucv_type(name) == UC_STRING && prog->exports.entries[from]) 2403 ucv_object_add(modobj, ucv_string_get(name), 2404 ucv_get(&prog->exports.entries[from]->header)); 2405 2406 ucv_put(name); 2407 } 2408 2409 ucv_set_constant(modobj, true); 2410 2411 uc_vm_stack_push(vm, modobj); 2412 } 2413 2414 /* module export available, patch into upvalue */ 2415 else if (from <= prog->exports.count && prog->exports.entries[from]) { 2416 frame->closure->upvals[to] = prog->exports.entries[from]; 2417 ucv_get(&prog->exports.entries[from]->header); 2418 } 2419 2420 /* module export missing, e.g. due to premature return in module, 2421 * patch up dummy upvalue ref with `null` value */ 2422 else { 2423 frame->closure->upvals[to] = (uc_upvalref_t *)ucv_upvalref_new(0); 2424 frame->closure->upvals[to]->closed = true; 2425 } 2426 } 2427 2428 static void 2429 uc_vm_insn_export(uc_vm_t *vm, uc_vm_insn_t insn) 2430 { 2431 uc_callframe_t *frame = uc_vm_current_frame(vm); 2432 uc_program_t *prog = uc_vm_current_program(vm); 2433 uc_upvalref_t *ref = uc_vm_capture_upval(vm, frame->stackframe + vm->arg.u32); 2434 2435 uc_vector_push(&prog->exports, ref); 2436 ucv_get(&ref->header); 2437 } 2438 2439 static void 2440 uc_vm_insn_dynload(uc_vm_t *vm, uc_vm_insn_t insn) 2441 { 2442 uc_callframe_t *frame = uc_vm_current_frame(vm); 2443 uc_value_t *name, *export, *modscope, *modobj; 2444 uint16_t count = vm->arg.u32 & 0xffff; 2445 uint16_t to = vm->arg.u32 >> 16; 2446 uint32_t cidx; 2447 bool found; 2448 2449 /* instruction is followed by u32 containing the constant index of the 2450 * module name string to import and `count` times u32 values containing 2451 * the import name constant indexes */ 2452 2453 cidx = ( 2454 frame->ip[0] * 0x1000000UL + 2455 frame->ip[1] * 0x10000UL + 2456 frame->ip[2] * 0x100UL + 2457 frame->ip[3] 2458 ); 2459 2460 frame->ip += 4; 2461 2462 /* push module name onto stack, then attempt to load module and pop 2463 * name value again. Will raise exception on error */ 2464 name = uc_program_get_constant(uc_vm_current_program(vm), cidx); 2465 modscope = uc_require_library(vm, name, true); 2466 ucv_put(name); 2467 2468 if (!modscope) 2469 return; 2470 2471 /* If count is zero, we're doing a wildcard import. Shallow copy module 2472 * object, mark it constant and patch into the target upvalue. */ 2473 if (count == 0) { 2474 modobj = ucv_object_new(vm); 2475 2476 ucv_object_foreach(modscope, k, v) 2477 ucv_object_add(modobj, k, ucv_get(v)); 2478 2479 ucv_set_constant(modobj, true); 2480 2481 uc_vm_stack_push(vm, modobj); 2482 } 2483 2484 /* ... otherwise we're importing a specific list of names */ 2485 else { 2486 while (count > 0) { 2487 cidx = ( 2488 frame->ip[0] * 0x1000000UL + 2489 frame->ip[1] * 0x10000UL + 2490 frame->ip[2] * 0x100UL + 2491 frame->ip[3] 2492 ); 2493 2494 frame->ip += 4; 2495 2496 name = uc_program_get_constant(uc_vm_current_program(vm), cidx); 2497 export = ucv_object_get(modscope, ucv_string_get(name), &found); 2498 2499 if (!found) { 2500 uc_vm_raise_exception(vm, EXCEPTION_REFERENCE, 2501 "Module does not export %s", 2502 ucv_string_get(name)); 2503 2504 ucv_put(name); 2505 2506 return; 2507 } 2508 2509 ucv_put(name); 2510 2511 frame->closure->upvals[to] = (uc_upvalref_t *)ucv_upvalref_new(0); 2512 frame->closure->upvals[to]->closed = true; 2513 frame->closure->upvals[to]->value = ucv_get(export); 2514 2515 count--; 2516 to++; 2517 } 2518 } 2519 } 2520 2521 static void 2522 uc_vm_gc_step(uc_vm_t *vm) 2523 { 2524 size_t curr_count = 0, prev_count = 0; 2525 uc_weakref_t *ref; 2526 2527 if (!(vm->gc_flags & GC_ENABLED)) 2528 return; 2529 2530 if (vm->alloc_refs >= vm->gc_interval) { 2531 if (vm->trace) { 2532 for (ref = vm->values.next; ref != &vm->values; ref = ref->next) 2533 prev_count++; 2534 2535 ucv_gc(vm); 2536 2537 for (ref = vm->values.next; ref != &vm->values; ref = ref->next) 2538 curr_count++; 2539 2540 fprintf(stderr, "! GC reclaimed %zu object(s)\n", prev_count - curr_count); 2541 } 2542 else { 2543 ucv_gc(vm); 2544 } 2545 } 2546 } 2547 2548 static uc_value_t * 2549 uc_vm_callframe_pop(uc_vm_t *vm) 2550 { 2551 uc_callframe_t *frame = uc_vm_current_frame(vm); 2552 uc_value_t *retval; 2553 2554 /* close upvalues */ 2555 uc_vm_close_upvals(vm, frame->stackframe); 2556 2557 if (vm->stack.count > frame->stackframe) 2558 retval = uc_vm_stack_pop(vm); 2559 else 2560 retval = NULL; 2561 2562 /* reset function stack frame */ 2563 while (vm->stack.count > frame->stackframe) 2564 ucv_put(uc_vm_stack_pop(vm)); 2565 2566 /* for method calls, release context as well */ 2567 if (frame->mcall) 2568 ucv_put(uc_vm_stack_pop(vm)); 2569 2570 /* release function */ 2571 if (frame->closure) 2572 ucv_put(&frame->closure->header); 2573 2574 if (frame->cfunction) 2575 ucv_put(&frame->cfunction->header); 2576 2577 /* release context */ 2578 ucv_put(frame->ctx); 2579 2580 vm->callframes.count--; 2581 2582 return retval; 2583 } 2584 2585 static void 2586 uc_vm_output_exception(uc_vm_t *vm, uc_exception_t *ex) 2587 { 2588 uc_value_t *ctx; 2589 2590 if (ex->type == EXCEPTION_USER) 2591 fprintf(stderr, "%s\n", ex->message); 2592 else 2593 fprintf(stderr, "%s: %s\n", 2594 exception_type_strings[ex->type] ? exception_type_strings[ex->type] : "Error", 2595 ex->message); 2596 2597 ctx = ucv_object_get(ucv_array_get(ex->stacktrace, 0), "context", NULL); 2598 2599 if (ctx) 2600 fprintf(stderr, "%s\n", ucv_string_get(ctx)); 2601 2602 fprintf(stderr, "\n"); 2603 } 2604 2605 uc_exception_type_t 2606 uc_vm_signal_dispatch(uc_vm_t *vm) 2607 { 2608 uc_exception_type_t ex; 2609 uc_value_t *handler; 2610 uint64_t mask; 2611 size_t i, j; 2612 int sig, rv; 2613 2614 if (!vm->config->setup_signal_handlers) 2615 return EXCEPTION_NONE; 2616 2617 for (i = 0; i < ARRAY_SIZE(vm->signal.raised); i++) { 2618 if (!vm->signal.raised[i]) 2619 continue; 2620 2621 do { 2622 rv = read(vm->signal.sigpipe[0], &sig, sizeof(sig)); 2623 } while (rv > 0 || (rv == -1 && errno == EINTR)); 2624 2625 for (j = 0; j < 64; j++) { 2626 mask = 1ull << j; 2627 2628 if (vm->signal.raised[i] & mask) { 2629 vm->signal.raised[i] &= ~mask; 2630 2631 sig = i * 64 + j; 2632 handler = ucv_array_get(vm->signal.handler, sig); 2633 2634 if (ucv_is_callable(handler)) { 2635 uc_vm_stack_push(vm, ucv_get(handler)); 2636 uc_vm_stack_push(vm, ucv_int64_new(sig)); 2637 2638 ex = uc_vm_call(vm, false, 1); 2639 2640 if (ex != EXCEPTION_NONE) 2641 return ex; 2642 2643 ucv_put(uc_vm_stack_pop(vm)); 2644 } 2645 } 2646 } 2647 } 2648 2649 return EXCEPTION_NONE; 2650 } 2651 2652 static uc_vm_status_t 2653 uc_vm_execute_chunk(uc_vm_t *vm) 2654 { 2655 uc_callframe_t *frame = uc_vm_current_frame(vm); 2656 uc_chunk_t *chunk = uc_vm_frame_chunk(frame); 2657 size_t caller = vm->callframes.count - 1; 2658 uc_value_t *retval; 2659 uc_vm_insn_t insn; 2660 uint8_t *ip; 2661 2662 while (chunk && vm->callframes.count > caller) { 2663 if (vm->trace) { 2664 ip = frame->ip; 2665 insn = uc_vm_decode_insn(vm, frame, chunk); 2666 uc_dump_insn(vm, ip, insn); 2667 } 2668 else { 2669 insn = uc_vm_decode_insn(vm, frame, chunk); 2670 } 2671 2672 switch (insn) { 2673 case I_LOAD: 2674 case I_LOAD8: 2675 case I_LOAD16: 2676 case I_LOAD32: 2677 uc_vm_insn_load(vm, insn); 2678 break; 2679 2680 case I_LREXP: 2681 uc_vm_insn_load_regexp(vm, insn); 2682 break; 2683 2684 case I_LNULL: 2685 uc_vm_insn_load_null(vm, insn); 2686 break; 2687 2688 case I_LTRUE: 2689 case I_LFALSE: 2690 uc_vm_insn_load_bool(vm, insn); 2691 break; 2692 2693 case I_LTHIS: 2694 uc_vm_stack_push(vm, ucv_get(frame->ctx)); 2695 break; 2696 2697 case I_LVAR: 2698 uc_vm_insn_load_var(vm, insn); 2699 break; 2700 2701 case I_LVAL: 2702 case I_QLVAL: 2703 uc_vm_insn_load_val(vm, insn); 2704 break; 2705 2706 case I_LUPV: 2707 uc_vm_insn_load_upval(vm, insn); 2708 break; 2709 2710 case I_LLOC: 2711 uc_vm_insn_load_local(vm, insn); 2712 break; 2713 2714 case I_CLFN: 2715 case I_ARFN: 2716 uc_vm_insn_load_closure(vm, insn); 2717 break; 2718 2719 case I_NARR: 2720 uc_vm_insn_narr(vm, insn); 2721 break; 2722 2723 case I_PARR: 2724 uc_vm_insn_parr(vm, insn); 2725 break; 2726 2727 case I_MARR: 2728 uc_vm_insn_marr(vm, insn); 2729 break; 2730 2731 case I_NOBJ: 2732 uc_vm_insn_nobj(vm, insn); 2733 break; 2734 2735 case I_SOBJ: 2736 uc_vm_insn_sobj(vm, insn); 2737 break; 2738 2739 case I_MOBJ: 2740 uc_vm_insn_mobj(vm, insn); 2741 break; 2742 2743 case I_SVAR: 2744 uc_vm_insn_store_var(vm, insn); 2745 break; 2746 2747 case I_SVAL: 2748 uc_vm_insn_store_val(vm, insn); 2749 break; 2750 2751 case I_SUPV: 2752 uc_vm_insn_store_upval(vm, insn); 2753 break; 2754 2755 case I_SLOC: 2756 uc_vm_insn_store_local(vm, insn); 2757 break; 2758 2759 case I_UVAR: 2760 uc_vm_insn_update_var(vm, insn); 2761 break; 2762 2763 case I_UVAL: 2764 uc_vm_insn_update_val(vm, insn); 2765 break; 2766 2767 case I_UUPV: 2768 uc_vm_insn_update_upval(vm, insn); 2769 break; 2770 2771 case I_ULOC: 2772 uc_vm_insn_update_local(vm, insn); 2773 break; 2774 2775 case I_ADD: 2776 case I_SUB: 2777 case I_MUL: 2778 case I_DIV: 2779 case I_MOD: 2780 case I_EXP: 2781 uc_vm_insn_arith(vm, insn); 2782 break; 2783 2784 case I_PLUS: 2785 case I_MINUS: 2786 uc_vm_insn_plus_minus(vm, insn); 2787 break; 2788 2789 case I_LSHIFT: 2790 case I_RSHIFT: 2791 case I_BAND: 2792 case I_BXOR: 2793 case I_BOR: 2794 uc_vm_insn_bitop(vm, insn); 2795 break; 2796 2797 case I_COMPL: 2798 uc_vm_insn_complement(vm, insn); 2799 break; 2800 2801 case I_EQS: 2802 case I_NES: 2803 uc_vm_insn_equality(vm, insn); 2804 break; 2805 2806 case I_EQ: 2807 case I_NE: 2808 case I_LT: 2809 case I_LE: 2810 case I_GT: 2811 case I_GE: 2812 uc_vm_insn_rel(vm, insn); 2813 break; 2814 2815 case I_IN: 2816 uc_vm_insn_in(vm, insn); 2817 break; 2818 2819 case I_NOT: 2820 uc_vm_insn_not(vm, insn); 2821 break; 2822 2823 case I_JMP: 2824 uc_vm_insn_jmp(vm, insn); 2825 break; 2826 2827 case I_JMPZ: 2828 uc_vm_insn_jmpz(vm, insn); 2829 break; 2830 2831 case I_NEXTK: 2832 case I_NEXTKV: 2833 uc_vm_insn_next(vm, insn); 2834 break; 2835 2836 case I_COPY: 2837 uc_vm_stack_push(vm, ucv_get(uc_vm_stack_peek(vm, vm->arg.u8))); 2838 break; 2839 2840 case I_POP: 2841 ucv_put(uc_vm_stack_pop(vm)); 2842 uc_vm_gc_step(vm); 2843 break; 2844 2845 case I_CUPV: 2846 uc_vm_insn_close_upval(vm, insn); 2847 break; 2848 2849 case I_CALL: 2850 case I_QCALL: 2851 uc_vm_insn_call(vm, insn); 2852 frame = uc_vm_current_frame(vm); 2853 chunk = frame->closure ? uc_vm_frame_chunk(frame) : NULL; 2854 break; 2855 2856 case I_MCALL: 2857 case I_QMCALL: 2858 uc_vm_insn_mcall(vm, insn); 2859 frame = uc_vm_current_frame(vm); 2860 chunk = frame->closure ? uc_vm_frame_chunk(frame) : NULL; 2861 break; 2862 2863 case I_RETURN: 2864 retval = uc_vm_callframe_pop(vm); 2865 2866 uc_vm_stack_push(vm, retval); 2867 2868 if (vm->callframes.count == 0) 2869 return STATUS_OK; 2870 2871 frame = uc_vector_last(&vm->callframes); 2872 chunk = uc_vm_frame_chunk(frame); 2873 break; 2874 2875 case I_PRINT: 2876 uc_vm_insn_print(vm, insn); 2877 break; 2878 2879 case I_DELETE: 2880 uc_vm_insn_delete(vm, insn); 2881 break; 2882 2883 case I_IMPORT: 2884 uc_vm_insn_import(vm, insn); 2885 break; 2886 2887 case I_EXPORT: 2888 uc_vm_insn_export(vm, insn); 2889 break; 2890 2891 case I_DYNLOAD: 2892 uc_vm_insn_dynload(vm, insn); 2893 break; 2894 2895 default: 2896 uc_vm_raise_exception(vm, EXCEPTION_RUNTIME, "unknown opcode %d", insn); 2897 break; 2898 } 2899 2900 exception: 2901 /* previous instruction raised exception */ 2902 if (vm->exception.type != EXCEPTION_NONE) { 2903 /* VM termination was requested */ 2904 if (vm->exception.type == EXCEPTION_EXIT) { 2905 uc_vm_reset_callframes(vm); 2906 2907 return STATUS_EXIT; 2908 } 2909 2910 /* walk up callframes until something handles the exception or the original caller is reached */ 2911 while (!uc_vm_handle_exception(vm)) { 2912 /* if VM returned into native function, don't bubble up */ 2913 if (!chunk) 2914 return ERROR_RUNTIME; 2915 2916 /* no exception handler in current function, pop callframe */ 2917 if (vm->callframes.count > 0) 2918 ucv_put(uc_vm_callframe_pop(vm)); 2919 2920 /* no further callframe, report unhandled exception and terminate */ 2921 if (vm->callframes.count == 0 || vm->callframes.count <= caller) 2922 return ERROR_RUNTIME; 2923 2924 /* resume execution in next remaining callframe */ 2925 frame = uc_vector_last(&vm->callframes); 2926 chunk = uc_vm_frame_chunk(frame); 2927 } 2928 } 2929 2930 /* run handler for signal(s) delivered during previous instruction */ 2931 if (uc_vm_signal_dispatch(vm) != EXCEPTION_NONE) 2932 goto exception; 2933 } 2934 2935 return STATUS_OK; 2936 } 2937 2938 uc_vm_status_t 2939 uc_vm_execute(uc_vm_t *vm, uc_program_t *program, uc_value_t **retval) 2940 { 2941 uc_function_t *fn = uc_program_entry(program); 2942 uc_closure_t *closure = (uc_closure_t *)ucv_closure_new(vm, fn, false); 2943 uc_vm_status_t status; 2944 uc_callframe_t *frame; 2945 uc_stringbuf_t *buf; 2946 uc_value_t *val; 2947 2948 uc_vector_grow(&vm->callframes); 2949 2950 frame = &vm->callframes.entries[vm->callframes.count++]; 2951 frame->closure = closure; 2952 frame->stackframe = 0; 2953 frame->ip = uc_vm_frame_chunk(frame)->entries; 2954 frame->strict = fn->strict; 2955 2956 if (vm->trace) { 2957 buf = xprintbuf_new(); 2958 2959 uc_source_context_format(buf, uc_vm_frame_source(frame), 0, true); 2960 2961 fwrite(buf->buf, 1, printbuf_length(buf), stderr); 2962 printbuf_free(buf); 2963 2964 uc_vm_frame_dump(vm, frame); 2965 } 2966 2967 //uc_vm_stack_push(vm, closure->header.jso); 2968 uc_vm_stack_push(vm, NULL); 2969 2970 status = uc_vm_execute_chunk(vm); 2971 2972 switch (status) { 2973 case STATUS_OK: 2974 val = uc_vm_stack_pop(vm); 2975 2976 if (retval) 2977 *retval = val; 2978 else 2979 ucv_put(val); 2980 2981 break; 2982 2983 case STATUS_EXIT: 2984 if (retval) 2985 *retval = ucv_int64_new(vm->arg.s32); 2986 2987 break; 2988 2989 default: 2990 if (vm->exhandler) 2991 vm->exhandler(vm, &vm->exception); 2992 2993 if (retval) 2994 *retval = NULL; 2995 2996 break; 2997 } 2998 2999 return status; 3000 } 3001 3002 uc_exception_type_t 3003 uc_vm_call(uc_vm_t *vm, bool mcall, size_t nargs) 3004 { 3005 uc_value_t *ctx = mcall ? ucv_get(uc_vm_stack_peek(vm, nargs + 1)) : NULL; 3006 uc_value_t *fno = ucv_get(uc_vm_stack_peek(vm, nargs)); 3007 3008 uc_vm_clear_exception(vm); 3009 3010 if (uc_vm_call_function(vm, ctx, fno, mcall, nargs & 0xffff)) { 3011 if (ucv_type(fno) != UC_CFUNCTION) 3012 uc_vm_execute_chunk(vm); 3013 } 3014 3015 return vm->exception.type; 3016 } 3017 3018 uc_value_t * 3019 uc_vm_scope_get(uc_vm_t *vm) 3020 { 3021 return vm->globals; 3022 } 3023 3024 void 3025 uc_vm_scope_set(uc_vm_t *vm, uc_value_t *ctx) 3026 { 3027 ucv_put(vm->globals); 3028 vm->globals = ctx; 3029 } 3030 3031 uc_value_t * 3032 uc_vm_invoke(uc_vm_t *vm, const char *fname, size_t nargs, ...) 3033 { 3034 uc_exception_type_t ex; 3035 uc_value_t *fno, *arg; 3036 va_list ap; 3037 size_t i; 3038 3039 fno = ucv_property_get(vm->globals, fname); 3040 3041 if (!ucv_is_callable(fno)) 3042 return NULL; 3043 3044 uc_vm_stack_push(vm, ucv_get(fno)); 3045 3046 va_start(ap, nargs); 3047 3048 for (i = 0; i < nargs; i++) { 3049 arg = va_arg(ap, uc_value_t *); 3050 uc_vm_stack_push(vm, ucv_get(arg)); 3051 } 3052 3053 va_end(ap); 3054 3055 ex = uc_vm_call(vm, false, nargs); 3056 3057 if (ex) { 3058 if (vm->exhandler) 3059 vm->exhandler(vm, &vm->exception); 3060 3061 return NULL; 3062 } 3063 3064 return uc_vm_stack_pop(vm); 3065 } 3066 3067 uc_exception_handler_t * 3068 uc_vm_exception_handler_get(uc_vm_t *vm) 3069 { 3070 return vm->exhandler; 3071 } 3072 3073 void 3074 uc_vm_exception_handler_set(uc_vm_t *vm, uc_exception_handler_t *exhandler) 3075 { 3076 vm->exhandler = exhandler; 3077 } 3078 3079 uint32_t 3080 uc_vm_trace_get(uc_vm_t *vm) 3081 { 3082 return vm->trace; 3083 } 3084 3085 void 3086 uc_vm_trace_set(uc_vm_t *vm, uint32_t level) 3087 { 3088 vm->trace = level; 3089 } 3090 3091 bool 3092 uc_vm_registry_exists(uc_vm_t *vm, const char *key) 3093 { 3094 bool exists; 3095 3096 ucv_object_get(vm->registry, key, &exists); 3097 3098 return exists; 3099 } 3100 3101 uc_value_t * 3102 uc_vm_registry_get(uc_vm_t *vm, const char *key) 3103 { 3104 return ucv_object_get(vm->registry, key, NULL); 3105 } 3106 3107 void 3108 uc_vm_registry_set(uc_vm_t *vm, const char *key, uc_value_t *value) 3109 { 3110 if (!vm->registry) 3111 vm->registry = ucv_object_new(vm); 3112 3113 ucv_object_add(vm->registry, key, value); 3114 } 3115 3116 bool 3117 uc_vm_registry_delete(uc_vm_t *vm, const char *key) 3118 { 3119 return ucv_object_delete(vm->registry, key); 3120 } 3121 3122 bool 3123 uc_vm_gc_start(uc_vm_t *vm, uint16_t interval) 3124 { 3125 bool changed = false; 3126 3127 if (vm->gc_interval != interval) { 3128 vm->gc_interval = interval; 3129 changed = true; 3130 } 3131 3132 if (!(vm->gc_flags & GC_ENABLED)) { 3133 vm->gc_flags |= GC_ENABLED; 3134 changed = true; 3135 } 3136 3137 return changed; 3138 } 3139 3140 bool 3141 uc_vm_gc_stop(uc_vm_t *vm) 3142 { 3143 if (!(vm->gc_flags & GC_ENABLED)) 3144 return false; 3145 3146 vm->gc_flags &= ~GC_ENABLED; 3147 3148 return true; 3149 } 3150 3151 void 3152 uc_vm_signal_raise(uc_vm_t *vm, int signo) 3153 { 3154 uint8_t signum = signo; 3155 3156 if (signo <= 0 || signo >= UC_SYSTEM_SIGNAL_COUNT) 3157 return; 3158 3159 vm->signal.raised[signo / 64] |= (1ull << (signo % 64)); 3160 3161 if (write(vm->signal.sigpipe[1], &signum, sizeof(signum)) == -1) {} 3162 } 3163 3164 int 3165 uc_vm_signal_notifyfd(uc_vm_t *vm) 3166 { 3167 return vm->signal.sigpipe[0]; 3168 } 3169
This page was automatically generated by LXR 0.3.1. • OpenWrt