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