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