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