diff options
Diffstat (limited to 'vm.c')
-rw-r--r-- | vm.c | 1039 |
1 files changed, 549 insertions, 490 deletions
@@ -51,8 +51,8 @@ static const uc_insn_definition insn_defs[__I_MAX] = { [I_LUPV] = { 0, 1, 4 }, [I_LVAL] = { 2, 1, 0 }, - [I_CLFN] = { 0, 1, 4, true }, - [I_ARFN] = { 0, 1, 4, true }, + [I_CLFN] = { 0, 1, 4 }, + [I_ARFN] = { 0, 1, 4 }, [I_SLOC] = { 0, 0, 4 }, [I_SUPV] = { 0, 0, 4 }, @@ -90,8 +90,8 @@ static const uc_insn_definition insn_defs[__I_MAX] = { [I_GT] = { 2, 1, 0 }, [I_IN] = { 2, 1, 0 }, - [I_JMP] = { 0, 0, -4, true }, - [I_JMPZ] = { 1, 0, -4, true }, + [I_JMP] = { 0, 0, -4 }, + [I_JMPZ] = { 1, 0, -4 }, [I_COPY] = { 0, 1, 1 }, [I_POP] = { 1, 0, 0 }, @@ -124,19 +124,19 @@ uc_vm_reset_stack(uc_vm *vm) { while (vm->stack.count > 0) { vm->stack.count--; - uc_value_put(vm->stack.entries[vm->stack.count]); + ucv_put(vm->stack.entries[vm->stack.count]); vm->stack.entries[vm->stack.count] = NULL; } } -static json_object * +static uc_value_t * uc_vm_callframe_pop(uc_vm *vm); static void uc_vm_reset_callframes(uc_vm *vm) { while (vm->callframes.count > 0) - uc_value_put(uc_vm_callframe_pop(vm)); + ucv_put(uc_vm_callframe_pop(vm)); } void uc_vm_init(uc_vm *vm, uc_parse_config *config) @@ -152,19 +152,22 @@ void uc_vm_init(uc_vm *vm, uc_parse_config *config) vm->open_upvals = NULL; + vm->values.prev = &vm->values; + vm->values.next = &vm->values; + uc_vm_reset_stack(vm); } void uc_vm_free(uc_vm *vm) { - uc_upvalref *ref; + uc_upvalref_t *ref; - uc_value_put(vm->exception.stacktrace); + ucv_put(vm->exception.stacktrace); free(vm->exception.message); while (vm->open_upvals) { ref = vm->open_upvals->next; - uc_value_put(vm->open_upvals->header.jso); + ucv_put(&vm->open_upvals->header); vm->open_upvals = ref; } @@ -172,6 +175,8 @@ void uc_vm_free(uc_vm *vm) uc_vm_reset_stack(vm); uc_vector_clear(&vm->stack); uc_vector_clear(&vm->callframes); + + ucv_gc(vm, true); } static uc_chunk * @@ -263,11 +268,12 @@ static void uc_vm_frame_dump(uc_vm *vm, uc_callframe *frame) { uc_chunk *chunk = uc_vm_frame_chunk(frame); - uc_function *function; - uc_closure *closure; - uc_upvalref *ref; - json_object *v; + uc_function_t *function; + uc_closure_t *closure; + uc_upvalref_t *ref; + uc_value_t *v; size_t i; + char *s; fprintf(stderr, " [*] CALLFRAME[%zx]\n", frame - vm->callframes.entries); @@ -275,8 +281,9 @@ uc_vm_frame_dump(uc_vm *vm, uc_callframe *frame) fprintf(stderr, " |- stackframe %zu/%zu\n", frame->stackframe, vm->stack.count); - fprintf(stderr, " |- ctx %s\n", - json_object_to_json_string(frame->ctx)); + s = ucv_to_string(NULL, frame->ctx); + fprintf(stderr, " |- ctx %s\n", s); + free(s); if (chunk) { fprintf(stderr, " |- %zu constants\n", @@ -284,12 +291,10 @@ uc_vm_frame_dump(uc_vm *vm, uc_callframe *frame) for (i = 0; i < chunk->constants.isize; i++) { v = uc_chunk_get_constant(chunk, i); - - fprintf(stderr, " | [%zu] %s\n", - i, - json_object_to_json_string(v)); - - uc_value_put(v); + s = ucv_to_jsonstring(NULL, v); + fprintf(stderr, " | [%zu] %s\n", i, s); + free(s); + ucv_put(v); } closure = frame->closure; @@ -301,80 +306,88 @@ uc_vm_frame_dump(uc_vm *vm, uc_callframe *frame) for (i = 0; i < function->nupvals; i++) { ref = closure->upvals[i]; v = uc_chunk_debug_get_variable(chunk, 0, i, true); + s = ucv_to_string(NULL, v); + fprintf(stderr, " [%zu] <%p> %s ", i, ref, s); + free(s); - if (ref->closed) - fprintf(stderr, " [%zu] <%p> %s {closed} %s\n", - i, - ref, - json_object_to_json_string(v), - json_object_to_json_string(ref->value)); - else - fprintf(stderr, " [%zu] <%p> %s {open[%zu]} %s\n", - i, - ref, - json_object_to_json_string(v), - ref->slot, - json_object_to_json_string(vm->stack.entries[ref->slot])); - - uc_value_put(v); + if (ref->closed) { + s = ucv_to_jsonstring(NULL, ref->value); + fprintf(stderr, "{closed} %s\n", s); + } + else { + s = ucv_to_jsonstring(NULL, vm->stack.entries[ref->slot]); + fprintf(stderr, "{open[%zu]} %s\n", ref->slot, s); + } + + ucv_put(v); + free(s); } } } void -uc_vm_stack_push(uc_vm *vm, json_object *value) +uc_vm_stack_push(uc_vm *vm, uc_value_t *value) { + char *s; + uc_vector_grow(&vm->stack); - uc_value_put(vm->stack.entries[vm->stack.count]); + ucv_put(vm->stack.entries[vm->stack.count]); vm->stack.entries[vm->stack.count] = value; vm->stack.count++; - if (vm->trace) - fprintf(stderr, " [+%zd] %s\n", - vm->stack.count - 1, - json_object_to_json_string(value)); + if (vm->trace) { + s = ucv_to_jsonstring(NULL, value); + fprintf(stderr, " [+%zd] %s\n", vm->stack.count - 1, s); + free(s); + } } -json_object * +uc_value_t * uc_vm_stack_pop(uc_vm *vm) { - json_object *rv; + uc_value_t *rv; + char *s; vm->stack.count--; rv = vm->stack.entries[vm->stack.count]; vm->stack.entries[vm->stack.count] = NULL; - if (vm->trace) - fprintf(stderr, " [-%zd] %s\n", - vm->stack.count, - json_object_to_json_string(rv)); + if (vm->trace) { + s = ucv_to_jsonstring(NULL, rv); + fprintf(stderr, " [-%zd] %s\n", vm->stack.count, s); + free(s); + } return rv; } -json_object * +uc_value_t * uc_vm_stack_peek(uc_vm *vm, size_t offset) { return vm->stack.entries[vm->stack.count + (-1 - offset)]; } static void -uc_vm_stack_set(uc_vm *vm, size_t offset, json_object *value) +uc_vm_stack_set(uc_vm *vm, size_t offset, uc_value_t *value) { - if (vm->trace) - fprintf(stderr, " [!%zu] %s\n", - offset, json_object_to_json_string(value)); + char *s; - uc_value_put(vm->stack.entries[offset]); + if (vm->trace) { + s = ucv_to_jsonstring(NULL, value); + fprintf(stderr, " [!%zu] %s\n", offset, s); + free(s); + } + + ucv_put(vm->stack.entries[offset]); vm->stack.entries[offset] = value; } static void -uc_vm_call_native(uc_vm *vm, json_object *ctx, uc_cfunction *fptr, bool mcall, size_t nargs) +uc_vm_call_native(uc_vm *vm, uc_value_t *ctx, uc_cfunction_t *fptr, bool mcall, size_t nargs) { - json_object *res = NULL; + uc_value_t *res = NULL; uc_callframe *frame; /* add new callframe */ @@ -393,24 +406,25 @@ uc_vm_call_native(uc_vm *vm, json_object *ctx, uc_cfunction *fptr, bool mcall, s res = fptr->cfn(vm, nargs); /* reset stack */ - uc_value_put(uc_vm_callframe_pop(vm)); + ucv_put(uc_vm_callframe_pop(vm)); /* push return value */ if (!vm->exception.type) uc_vm_stack_push(vm, res); else - uc_value_put(res); + ucv_put(res); } static bool -uc_vm_call_function(uc_vm *vm, json_object *ctx, json_object *fno, bool mcall, size_t argspec) +uc_vm_call_function(uc_vm *vm, uc_value_t *ctx, uc_value_t *fno, bool mcall, size_t argspec) { size_t i, j, stackoff, nargs = argspec & 0xffff, nspreads = argspec >> 16; uc_callframe *frame = uc_vm_current_frame(vm); - json_object *ellip, *arg; - uc_function *function; - uc_closure *closure; + uc_value_t *ellip, *arg; + uc_function_t *function; + uc_closure_t *closure; uint16_t slot, tmp; + char *s; /* XXX: make dependent on stack size */ if (vm->callframes.count >= 1000) { @@ -424,11 +438,11 @@ uc_vm_call_function(uc_vm *vm, json_object *ctx, json_object *fno, bool mcall, s /* argument list contains spread operations, we need to reshuffle the stack */ if (nspreads > 0) { /* create temporary array */ - ellip = xjs_new_array_size(nargs); + ellip = ucv_array_new_length(vm, nargs); /* pop original stack values and push to temp array in reverse order */ for (i = 0; i < nargs; i++) - json_object_array_add(ellip, uc_vm_stack_pop(vm)); + ucv_array_push(ellip, uc_vm_stack_pop(vm)); /* for each spread value index ... */ for (i = 0, slot = nargs; i < nspreads; i++) { @@ -437,61 +451,61 @@ uc_vm_call_function(uc_vm *vm, json_object *ctx, json_object *fno, bool mcall, s frame->ip += 2; /* push each preceeding non-spread value to the stack */ - for (j = slot; j > tmp + 1; j--) - uc_vm_stack_push(vm, uc_value_get(json_object_array_get_idx(ellip, j - 1))); + for (j = slot; j > tmp + 1UL; j--) + uc_vm_stack_push(vm, ucv_get(ucv_array_get(ellip, j - 1))); /* read spread value at index... */ slot = tmp; - arg = uc_value_get(json_object_array_get_idx(ellip, slot)); + arg = ucv_get(ucv_array_get(ellip, slot)); /* ... ensure that it is an array type ... */ - if (!json_object_is_type(arg, json_type_array)) { - uc_vm_raise_exception(vm, EXCEPTION_TYPE, - "(%s) is not iterable", - json_object_to_json_string(arg)); + if (ucv_type(arg) != UC_ARRAY) { + s = ucv_to_string(vm, arg); + uc_vm_raise_exception(vm, EXCEPTION_TYPE, "(%s) is not iterable", s); + free(s); return false; } /* ... and push each spread array value as argument to the stack */ - for (j = 0; j < json_object_array_length(arg); j++) - uc_vm_stack_push(vm, uc_value_get(json_object_array_get_idx(arg, j))); + for (j = 0; j < ucv_array_length(arg); j++) + uc_vm_stack_push(vm, ucv_get(ucv_array_get(arg, j))); - uc_value_put(arg); + ucv_put(arg); } /* push remaining non-spread arguments to the stack */ for (i = slot; i > 0; i--) - uc_vm_stack_push(vm, uc_value_get(json_object_array_get_idx(ellip, i - 1))); + uc_vm_stack_push(vm, ucv_get(ucv_array_get(ellip, i - 1))); /* free temp array */ - uc_value_put(ellip); + ucv_put(ellip); /* update arg count */ nargs = vm->stack.count - stackoff - 1; } /* is a native function */ - if (uc_object_is_type(fno, UC_OBJ_CFUNCTION)) { - uc_vm_call_native(vm, ctx, uc_object_as_cfunction(fno), mcall, nargs); + if (ucv_type(fno) == UC_CFUNCTION) { + uc_vm_call_native(vm, ctx, (uc_cfunction_t *)fno, mcall, nargs); return true; } - if (!uc_object_is_type(fno, UC_OBJ_CLOSURE)) { + if (ucv_type(fno) != UC_CLOSURE) { uc_vm_raise_exception(vm, EXCEPTION_TYPE, "left-hand side is not a function"); return false; } - closure = uc_object_as_closure(fno); + closure = (uc_closure_t *)fno; function = closure->function; /* fewer arguments on stack than function expects => pad */ if (nargs < function->nargs) { for (i = nargs; i < function->nargs; i++) { if (function->vararg && (i + 1) == function->nargs) - uc_vm_stack_push(vm, xjs_new_array_size(0)); + uc_vm_stack_push(vm, ucv_array_new_length(vm, 0)); else uc_vm_stack_push(vm, NULL); } @@ -501,10 +515,10 @@ uc_vm_call_function(uc_vm *vm, json_object *ctx, json_object *fno, bool mcall, s else if (nargs > function->nargs - function->vararg) { /* is a vararg function => pass excess args as array */ if (function->vararg) { - ellip = xjs_new_array_size(nargs - (function->nargs - 1)); + ellip = ucv_array_new_length(vm, nargs - (function->nargs - 1)); for (i = function->nargs; i <= nargs; i++) - json_object_array_add(ellip, uc_vm_stack_peek(vm, nargs - i)); + ucv_array_push(ellip, uc_vm_stack_peek(vm, nargs - i)); for (i = function->nargs; i <= nargs; i++) uc_vm_stack_pop(vm); @@ -515,7 +529,7 @@ uc_vm_call_function(uc_vm *vm, json_object *ctx, json_object *fno, bool mcall, s /* static amount of args => drop excess values */ else { for (i = function->nargs; i < nargs; i++) - uc_value_put(uc_vm_stack_pop(vm)); + ucv_put(uc_vm_stack_pop(vm)); } } @@ -543,19 +557,19 @@ uc_dump_insn(uc_vm *vm, uint8_t *pos, enum insn_type insn) { uc_callframe *frame = uc_vm_current_frame(vm); uc_chunk *chunk = uc_vm_frame_chunk(frame); - size_t msglen = 0, srcpos; - json_object *cnst = NULL; - char *msg = NULL; + uc_stringbuf_t *buf = NULL; + uc_value_t *cnst = NULL; + size_t srcpos; + char *s; - srcpos = uc_function_get_srcpos(frame->closure->function, pos - chunk->entries); + srcpos = ucv_function_srcpos((uc_value_t *)frame->closure->function, pos - chunk->entries); if (last_srcpos == 0 || last_source != frame->closure->function->source || srcpos != last_srcpos) { - format_source_context(&msg, &msglen, - frame->closure->function->source, - srcpos, true); + buf = xprintbuf_new(); - fprintf(stderr, "%s", msg); - free(msg); + format_source_context(buf, frame->closure->function->source, srcpos, true); + fwrite(buf->buf, 1, printbuf_length(buf), stderr); + printbuf_free(buf); last_source = frame->closure->function->source; last_srcpos = srcpos; @@ -574,13 +588,13 @@ uc_dump_insn(uc_vm *vm, uint8_t *pos, enum insn_type insn) case -2: fprintf(stderr, " {%c0x%hx}", vm->arg.s16 < 0 ? '-' : '+', - vm->arg.s16 < 0 ? -(unsigned)vm->arg.s16 : vm->arg.s16); + vm->arg.s16 < 0 ? -(unsigned)vm->arg.s16 : (unsigned)vm->arg.s16); break; case -4: fprintf(stderr, " {%c0x%x}", vm->arg.s32 < 0 ? '-' : '+', - vm->arg.s32 < 0 ? -(unsigned)vm->arg.s32 : vm->arg.s32); + vm->arg.s32 < 0 ? -(unsigned)vm->arg.s32 : (unsigned)vm->arg.s32); break; case 1: @@ -605,9 +619,11 @@ uc_dump_insn(uc_vm *vm, uint8_t *pos, enum insn_type insn) case I_LVAR: case I_SVAR: cnst = uc_chunk_get_constant(uc_vm_frame_chunk(uc_vector_last(&vm->callframes)), vm->arg.u32); + s = cnst ? ucv_to_jsonstring(NULL, cnst) : NULL; - fprintf(stderr, "\t; %s", cnst ? json_object_to_json_string(cnst) : "null"); - uc_value_put(cnst); + fprintf(stderr, "\t; %s", s ? s : "(?)"); + ucv_put(cnst); + free(s); break; case I_LLOC: @@ -615,9 +631,11 @@ uc_dump_insn(uc_vm *vm, uint8_t *pos, enum insn_type insn) case I_SLOC: case I_SUPV: cnst = uc_chunk_debug_get_variable(chunk, pos - chunk->entries, vm->arg.u32, (insn == I_LUPV || insn == I_SUPV)); + s = cnst ? ucv_to_jsonstring(NULL, cnst) : NULL; - fprintf(stderr, "\t; %s", cnst ? json_object_to_json_string(cnst) : "(?)"); - uc_value_put(cnst); + fprintf(stderr, "\t; %s", s ? s : "(?)"); + ucv_put(cnst); + free(s); break; case I_ULOC: @@ -629,11 +647,14 @@ uc_dump_insn(uc_vm *vm, uint8_t *pos, enum insn_type insn) if (!cnst) cnst = uc_chunk_get_constant(uc_vm_frame_chunk(uc_vector_last(&vm->callframes)), vm->arg.u32 & 0x00ffffff); + s = cnst ? ucv_to_jsonstring(NULL, cnst) : NULL; + fprintf(stderr, "\t; %s (%s)", - cnst ? json_object_to_json_string(cnst) : "(?)", + s ? s : "(?)", insn_names[vm->arg.u32 >> 24]); - uc_value_put(cnst); + ucv_put(cnst); + free(s); break; case I_UVAL: @@ -647,14 +668,38 @@ uc_dump_insn(uc_vm *vm, uint8_t *pos, enum insn_type insn) fprintf(stderr, "\n"); } -static int -uc_vm_exception_tostring(json_object *jso, struct printbuf *pb, int level, int flags) +static uc_value_t * +uc_vm_exception_tostring(uc_vm *vm, size_t nargs) { - bool strict = (level > 0) || (flags & JSON_C_TO_STRING_STRICT); - json_object *message = json_object_object_get(jso, "message"); + uc_callframe *frame = uc_vm_current_frame(vm); + uc_value_t *message = ucv_object_get(frame->ctx, "message", NULL); - return sprintbuf(pb, "%s", - strict ? json_object_to_json_string(message) : json_object_get_string(message)); + return message ? ucv_get(message) : ucv_string_new("Exception"); +} + +static uc_value_t *exception_prototype = NULL; + +static uc_value_t * +uc_vm_exception_new(uc_vm *vm, uc_exception_type_t type, const char *message, uc_value_t *stacktrace) +{ + uc_value_t *exo; + + if (exception_prototype == NULL) { + exception_prototype = ucv_object_new(vm); + + ucv_object_add(exception_prototype, "tostring", + ucv_cfunction_new("tostring", uc_vm_exception_tostring)); + } + + exo = ucv_object_new(vm); + + ucv_object_add(exo, "type", ucv_string_new(exception_type_strings[type])); + ucv_object_add(exo, "message", ucv_string_new(message)); + ucv_object_add(exo, "stacktrace", ucv_get(stacktrace)); + + ucv_prototype_set(exo, ucv_get(exception_prototype)); + + return exo; } static bool @@ -662,7 +707,7 @@ uc_vm_handle_exception(uc_vm *vm) { uc_callframe *frame = uc_vm_current_frame(vm); uc_chunk *chunk = NULL; - json_object *exo; + uc_value_t *exo; size_t i, pos; if (!frame->closure) @@ -680,16 +725,11 @@ uc_vm_handle_exception(uc_vm *vm) /* we found a matching range... first unwind stack */ while (vm->stack.count > frame->stackframe + chunk->ehranges.entries[i].slot) - uc_value_put(uc_vm_stack_pop(vm)); + ucv_put(uc_vm_stack_pop(vm)); /* prepare exception object and expose it to user handler code */ - exo = xjs_new_object(); + exo = uc_vm_exception_new(vm, vm->exception.type, vm->exception.message, vm->exception.stacktrace); - json_object_object_add(exo, "type", xjs_new_string(exception_type_strings[vm->exception.type])); - json_object_object_add(exo, "message", xjs_new_string(vm->exception.message)); - json_object_object_add(exo, "stacktrace", uc_value_get(vm->exception.stacktrace)); - - json_object_set_serializer(exo, uc_vm_exception_tostring, NULL, NULL); uc_vm_stack_push(vm, exo); /* reset exception information */ @@ -721,35 +761,35 @@ uc_vm_handle_exception(uc_vm *vm) return false; } -static json_object * +static uc_value_t * uc_vm_capture_stacktrace(uc_vm *vm, size_t i) { - json_object *stacktrace, *entry, *last = NULL; - uc_function *function; + uc_value_t *stacktrace, *entry, *last = NULL; + uc_function_t *function; uc_callframe *frame; size_t off, srcpos; char *name; - stacktrace = xjs_new_array(); + stacktrace = ucv_array_new(vm); for (; i > 0; i--) { frame = &vm->callframes.entries[i - 1]; - entry = xjs_new_object(); + entry = ucv_object_new(vm); if (frame->closure) { function = frame->closure->function; off = (frame->ip - uc_vm_frame_chunk(frame)->entries) - 1; - srcpos = uc_function_get_srcpos(function, off); + srcpos = ucv_function_srcpos((uc_value_t *)function, off); - json_object_object_add(entry, "filename", xjs_new_string(function->source->filename)); - json_object_object_add(entry, "line", xjs_new_int64(uc_source_get_line(function->source, &srcpos))); - json_object_object_add(entry, "byte", xjs_new_int64(srcpos)); + ucv_object_add(entry, "filename", ucv_string_new(function->source->filename)); + ucv_object_add(entry, "line", ucv_int64_new(uc_source_get_line(function->source, &srcpos))); + ucv_object_add(entry, "byte", ucv_int64_new(srcpos)); } if (i > 1) { if (frame->closure) { - if (frame->closure->function->name) + if (frame->closure->function->name[0]) name = frame->closure->function->name; else if (frame->closure->is_arrow) name = "[arrow function]"; @@ -760,29 +800,29 @@ uc_vm_capture_stacktrace(uc_vm *vm, size_t i) name = frame->cfunction->name; } - json_object_object_add(entry, "function", xjs_new_string(name)); + ucv_object_add(entry, "function", ucv_string_new(name)); } - if (!json_object_equal(last, entry)) { - json_object_array_add(stacktrace, entry); + if (!ucv_equal(last, entry)) { + ucv_array_push(stacktrace, entry); last = entry; } else { - uc_value_put(entry); + ucv_put(entry); } } return stacktrace; } -static json_object * +static uc_value_t * uc_vm_get_error_context(uc_vm *vm) { - json_object *stacktrace; + uc_value_t *stacktrace; uc_callframe *frame; + uc_stringbuf_t *buf; uc_chunk *chunk; - size_t offset, len = 0, i; - char *msg = NULL; + size_t offset, i; /* skip to first non-native function call frame */ for (i = vm->callframes.count; i > 0; i--) @@ -795,17 +835,17 @@ uc_vm_get_error_context(uc_vm *vm) return NULL; chunk = uc_vm_frame_chunk(frame); - offset = uc_function_get_srcpos(frame->closure->function, (frame->ip - chunk->entries) - 1); + offset = ucv_function_srcpos((uc_value_t *)frame->closure->function, (frame->ip - chunk->entries) - 1); stacktrace = uc_vm_capture_stacktrace(vm, i); + buf = ucv_stringbuf_new(); + if (offset) - format_error_context(&msg, &len, frame->closure->function->source, stacktrace, offset); + format_error_context(buf, frame->closure->function->source, stacktrace, offset); else - xasprintf(&msg, "At offset %zu", (frame->ip - chunk->entries) - 1); + ucv_stringbuf_printf(buf, "At offset %zu", (frame->ip - chunk->entries) - 1); - json_object_object_add(json_object_array_get_idx(stacktrace, 0), "context", xjs_new_string(msg)); - - free(msg); + ucv_object_add(ucv_array_get(stacktrace, 0), "context", ucv_stringbuf_finish(buf)); return stacktrace; } @@ -823,7 +863,7 @@ uc_vm_raise_exception(uc_vm *vm, uc_exception_type_t type, const char *fmt, ...) xvasprintf(&vm->exception.message, fmt, ap); va_end(ap); - uc_value_put(vm->exception.stacktrace); + ucv_put(vm->exception.stacktrace); vm->exception.stacktrace = uc_vm_get_error_context(vm); } @@ -837,15 +877,15 @@ uc_vm_insn_load(uc_vm *vm, enum insn_type insn) break; case I_LOAD8: - uc_vm_stack_push(vm, xjs_new_int64(vm->arg.s8)); + uc_vm_stack_push(vm, ucv_int64_new(vm->arg.s8)); break; case I_LOAD16: - uc_vm_stack_push(vm, xjs_new_int64(vm->arg.s16)); + uc_vm_stack_push(vm, ucv_int64_new(vm->arg.s16)); break; case I_LOAD32: - uc_vm_stack_push(vm, xjs_new_int64(vm->arg.s32)); + uc_vm_stack_push(vm, ucv_int64_new(vm->arg.s32)); break; default: @@ -856,33 +896,33 @@ uc_vm_insn_load(uc_vm *vm, enum insn_type insn) static void uc_vm_insn_load_regexp(uc_vm *vm, enum insn_type insn) { + uc_value_t *re, *jstr = uc_chunk_get_constant(uc_vm_current_chunk(vm), vm->arg.u32); bool icase = false, newline = false, global = false; - json_object *jstr = uc_chunk_get_constant(uc_vm_current_chunk(vm), vm->arg.u32); - const char *str; - uc_regexp *re; - char *err; + char *str, *err = NULL; - if (!json_object_is_type(jstr, json_type_string) || json_object_get_string_len(jstr) < 2) { + if (ucv_type(jstr) != UC_STRING || ucv_string_length(jstr) < 2) { uc_vm_stack_push(vm, NULL); - uc_value_put(jstr); + ucv_put(jstr); return; } - str = json_object_get_string(jstr); + str = ucv_string_get(jstr); global = (*str & (1 << 0)); icase = (*str & (1 << 1)); newline = (*str & (1 << 2)); - re = uc_regexp_new(++str, icase, newline, global, &err); + re = ucv_regexp_new(++str, icase, newline, global, &err); - uc_value_put(jstr); + ucv_put(jstr); if (re) - uc_vm_stack_push(vm, re->header.jso); + uc_vm_stack_push(vm, re); else uc_vm_raise_exception(vm, EXCEPTION_SYNTAX, "%s", err); + + free(err); } static void @@ -894,29 +934,32 @@ uc_vm_insn_load_null(uc_vm *vm, enum insn_type insn) static void uc_vm_insn_load_bool(uc_vm *vm, enum insn_type insn) { - uc_vm_stack_push(vm, xjs_new_boolean(insn == I_LTRUE)); + uc_vm_stack_push(vm, ucv_boolean_new(insn == I_LTRUE)); } static void uc_vm_insn_load_var(uc_vm *vm, enum insn_type insn) { - json_object *name, *val = NULL; - uc_prototype *scope, *next; + uc_value_t *name, *val = NULL; + uc_value_t *scope, *next; + bool found; scope = vm->globals; name = uc_chunk_get_constant(uc_vm_current_chunk(vm), vm->arg.u32); - while (json_object_get_type(name) == json_type_string) { - if (json_object_object_get_ex(scope->header.jso, json_object_get_string(name), &val)) + while (ucv_type(name) == UC_STRING) { + val = ucv_object_get(scope, ucv_string_get(name), &found); + + if (found) break; - next = scope->parent; + next = ucv_prototype_get(scope); if (!next) { if (vm->config->strict_declarations) { uc_vm_raise_exception(vm, EXCEPTION_REFERENCE, "access to undeclared variable %s", - json_object_get_string(name)); + ucv_string_get(name)); } break; @@ -925,21 +968,21 @@ uc_vm_insn_load_var(uc_vm *vm, enum insn_type insn) scope = next; } - uc_value_put(name); + ucv_put(name); - uc_vm_stack_push(vm, uc_value_get(val)); + uc_vm_stack_push(vm, ucv_get(val)); } static void uc_vm_insn_load_val(uc_vm *vm, enum insn_type insn) { - json_object *k = uc_vm_stack_pop(vm); - json_object *v = uc_vm_stack_pop(vm); + uc_value_t *k = uc_vm_stack_pop(vm); + uc_value_t *v = uc_vm_stack_pop(vm); - switch (json_object_get_type(v)) { - case json_type_object: - case json_type_array: - uc_vm_stack_push(vm, uc_getval(v, k)); + switch (ucv_type(v)) { + case UC_OBJECT: + case UC_ARRAY: + uc_vm_stack_push(vm, uc_getval(vm, v, k)); break; default: @@ -950,21 +993,20 @@ uc_vm_insn_load_val(uc_vm *vm, enum insn_type insn) break; } - - uc_value_put(k); - uc_value_put(v); + ucv_put(k); + ucv_put(v); } static void uc_vm_insn_load_upval(uc_vm *vm, enum insn_type insn) { uc_callframe *frame = uc_vm_current_frame(vm); - uc_upvalref *ref = frame->closure->upvals[vm->arg.u32]; + uc_upvalref_t *ref = frame->closure->upvals[vm->arg.u32]; if (ref->closed) - uc_vm_stack_push(vm, uc_value_get(ref->value)); + uc_vm_stack_push(vm, ucv_get(ref->value)); else - uc_vm_stack_push(vm, uc_value_get(vm->stack.entries[ref->slot])); + uc_vm_stack_push(vm, ucv_get(vm->stack.entries[ref->slot])); } static void @@ -972,15 +1014,16 @@ uc_vm_insn_load_local(uc_vm *vm, enum insn_type insn) { uc_callframe *frame = uc_vm_current_frame(vm); - uc_vm_stack_push(vm, uc_value_get(vm->stack.entries[frame->stackframe + vm->arg.u32])); + uc_vm_stack_push(vm, ucv_get(vm->stack.entries[frame->stackframe + vm->arg.u32])); } -static uc_upvalref * +static uc_upvalref_t * uc_vm_capture_upval(uc_vm *vm, size_t slot) { - uc_upvalref *curr = vm->open_upvals; - uc_upvalref *prev = NULL; - uc_upvalref *created; + uc_upvalref_t *curr = vm->open_upvals; + uc_upvalref_t *prev = NULL; + uc_upvalref_t *created; + char *s; while (curr && curr->slot > slot) { prev = curr; @@ -988,23 +1031,23 @@ uc_vm_capture_upval(uc_vm *vm, size_t slot) } if (curr && curr->slot == slot) { - if (vm->trace) - fprintf(stderr, " {+%zu} <%p> %s\n", - slot, - curr, - json_object_to_json_string(vm->stack.entries[slot])); + if (vm->trace) { + s = ucv_to_string(NULL, vm->stack.entries[slot]); + fprintf(stderr, " {+%zu} <%p> %s\n", slot, curr, s); + free(s); + } return curr; } - created = uc_upvalref_new(slot); + created = (uc_upvalref_t *)ucv_upvalref_new(slot); created->next = curr; - if (vm->trace) - fprintf(stderr, " {*%zu} <%p> %s\n", - slot, - created, - json_object_to_json_string(vm->stack.entries[slot])); + if (vm->trace) { + s = ucv_to_string(NULL, vm->stack.entries[slot]); + fprintf(stderr, " {*%zu} <%p> %s\n", slot, created, s); + free(s); + } if (prev) prev->next = created; @@ -1017,21 +1060,22 @@ uc_vm_capture_upval(uc_vm *vm, size_t slot) static void uc_vm_close_upvals(uc_vm *vm, size_t slot) { - uc_upvalref *ref; + uc_upvalref_t *ref; + char *s; while (vm->open_upvals && vm->open_upvals->slot >= slot) { ref = vm->open_upvals; - ref->value = uc_value_get(vm->stack.entries[ref->slot]); + ref->value = ucv_get(vm->stack.entries[ref->slot]); ref->closed = true; - if (vm->trace) - fprintf(stderr, " {!%zu} <%p> %s\n", - ref->slot, - ref, - json_object_to_json_string(ref->value)); + if (vm->trace) { + s = ucv_to_string(NULL, ref->value); + fprintf(stderr, " {!%zu} <%p> %s\n", ref->slot, ref, s); + free(s); + } vm->open_upvals = ref->next; - json_object_put(ref->header.jso); + ucv_put(&ref->header); } } @@ -1039,13 +1083,13 @@ static void uc_vm_insn_load_closure(uc_vm *vm, enum insn_type insn) { uc_callframe *frame = uc_vm_current_frame(vm); - json_object *fno = uc_chunk_get_constant(uc_vm_current_chunk(vm), vm->arg.u32); - uc_function *function = uc_object_as_function(fno); - uc_closure *closure = uc_closure_new(function, insn == I_ARFN); + uc_value_t *fno = uc_chunk_get_constant(uc_vm_current_chunk(vm), vm->arg.u32); + uc_function_t *function = (uc_function_t *)fno; + uc_closure_t *closure = (uc_closure_t *)ucv_closure_new(vm, function, insn == I_ARFN); volatile int32_t uv; size_t i; - uc_vm_stack_push(vm, closure->header.jso); + uc_vm_stack_push(vm, &closure->header); for (i = 0; i < function->nupvals; i++) { uv = ( @@ -1060,7 +1104,7 @@ uc_vm_insn_load_closure(uc_vm *vm, enum insn_type insn) else closure->upvals[i] = frame->closure->upvals[uv]; - uc_value_get(closure->upvals[i]->header.jso); + ucv_get(&closure->upvals[i]->header); frame->ip += 4; } @@ -1069,23 +1113,26 @@ uc_vm_insn_load_closure(uc_vm *vm, enum insn_type insn) static void uc_vm_insn_store_var(uc_vm *vm, enum insn_type insn) { - json_object *name, *v = uc_vm_stack_pop(vm); - uc_prototype *scope, *next; + uc_value_t *name, *v = uc_vm_stack_pop(vm); + uc_value_t *scope, *next; + bool found; scope = vm->globals; name = uc_chunk_get_constant(uc_vm_current_chunk(vm), vm->arg.u32); - while (json_object_get_type(name) == json_type_string) { - if (json_object_object_get_ex(scope->header.jso, json_object_get_string(name), NULL)) + while (ucv_type(name) == UC_STRING) { + ucv_object_get(scope, ucv_string_get(name), &found); + + if (found) break; - next = scope->parent; + next = ucv_prototype_get(scope); if (!next) { if (vm->config->strict_declarations) { uc_vm_raise_exception(vm, EXCEPTION_REFERENCE, "access to undeclared variable %s", - json_object_get_string(name)); + ucv_string_get(name)); } break; @@ -1094,53 +1141,45 @@ uc_vm_insn_store_var(uc_vm *vm, enum insn_type insn) scope = next; } - if (scope && json_object_get_type(name) == json_type_string) - json_object_object_add(scope->header.jso, json_object_get_string(name), uc_value_get(v)); + if (scope && ucv_type(name) == UC_STRING) + ucv_object_add(scope, ucv_string_get(name), ucv_get(v)); - uc_value_put(name); + ucv_put(name); uc_vm_stack_push(vm, v); } static void uc_vm_insn_store_val(uc_vm *vm, enum insn_type insn) { - json_object *v = uc_vm_stack_pop(vm); - json_object *k = uc_vm_stack_pop(vm); - json_object *o = uc_vm_stack_pop(vm); - - const char *typenames[] = { - [json_type_string] = "string", - [json_type_int] = "integer", - [json_type_double] = "double", - [json_type_boolean] = "boolean", - [json_type_null] = "null" - }; + uc_value_t *v = uc_vm_stack_pop(vm); + uc_value_t *k = uc_vm_stack_pop(vm); + uc_value_t *o = uc_vm_stack_pop(vm); - switch (json_object_get_type(o)) { - case json_type_object: - case json_type_array: - uc_vm_stack_push(vm, uc_setval(o, k, v)); + switch (ucv_type(o)) { + case UC_OBJECT: + case UC_ARRAY: + uc_vm_stack_push(vm, uc_setval(vm, o, k, v)); break; default: uc_vm_raise_exception(vm, EXCEPTION_TYPE, "attempt to set property on %s value", - typenames[json_object_get_type(o)]); + ucv_typename(o)); } - uc_value_put(o); - uc_value_put(k); + ucv_put(o); + ucv_put(k); } static void uc_vm_insn_store_upval(uc_vm *vm, enum insn_type insn) { uc_callframe *frame = uc_vm_current_frame(vm); - uc_upvalref *ref = frame->closure->upvals[vm->arg.u32]; - json_object *val = uc_value_get(uc_vm_stack_peek(vm, 0)); + uc_upvalref_t *ref = frame->closure->upvals[vm->arg.u32]; + uc_value_t *val = ucv_get(uc_vm_stack_peek(vm, 0)); if (ref->closed) { - uc_value_put(ref->value); + ucv_put(ref->value); ref->value = val; } else { @@ -1152,43 +1191,43 @@ static void uc_vm_insn_store_local(uc_vm *vm, enum insn_type insn) { uc_callframe *frame = uc_vm_current_frame(vm); - json_object *val = uc_value_get(uc_vm_stack_peek(vm, 0)); + uc_value_t *val = ucv_get(uc_vm_stack_peek(vm, 0)); uc_vm_stack_set(vm, frame->stackframe + vm->arg.u32, val); } -static json_object * -uc_vm_value_bitop(uc_vm *vm, enum insn_type operation, json_object *value, json_object *operand) +static uc_value_t * +uc_vm_value_bitop(uc_vm *vm, enum insn_type operation, uc_value_t *value, uc_value_t *operand) { - json_object *rv = NULL; + uc_value_t *rv = NULL; int64_t n1, n2; double d; - if (uc_cast_number(value, &n1, &d) == json_type_double) + if (uc_cast_number(value, &n1, &d) == UC_DOUBLE) n1 = isnan(d) ? 0 : (int64_t)d; - if (uc_cast_number(operand, &n2, &d) == json_type_double) + if (uc_cast_number(operand, &n2, &d) == UC_DOUBLE) n2 = isnan(d) ? 0 : (int64_t)d; switch (operation) { case I_LSHIFT: - rv = xjs_new_int64(n1 << n2); + rv = ucv_int64_new(n1 << n2); break; case I_RSHIFT: - rv = xjs_new_int64(n1 >> n2); + rv = ucv_int64_new(n1 >> n2); break; case I_BAND: - rv = xjs_new_int64(n1 & n2); + rv = ucv_int64_new(n1 & n2); break; case I_BXOR: - rv = xjs_new_int64(n1 ^ n2); + rv = ucv_int64_new(n1 ^ n2); break; case I_BOR: - rv = xjs_new_int64(n1 | n2); + rv = ucv_int64_new(n1 | n2); break; default: @@ -1198,32 +1237,32 @@ uc_vm_value_bitop(uc_vm *vm, enum insn_type operation, json_object *value, json_ return rv; } -static json_object * -uc_vm_value_arith(uc_vm *vm, enum insn_type operation, json_object *value, json_object *operand) +static uc_value_t * +uc_vm_value_arith(uc_vm *vm, enum insn_type operation, uc_value_t *value, uc_value_t *operand) { - json_object *rv = NULL; - enum json_type t1, t2; - const char *s1, *s2; + uc_value_t *rv = NULL; + uc_type_t t1, t2; + char *s, *s1, *s2; size_t len1, len2; int64_t n1, n2; double d1, d2; - char *s; if (operation > I_MOD) return uc_vm_value_bitop(vm, operation, value, operand); - if (operation == I_ADD && - (json_object_is_type(value, json_type_string) || - json_object_is_type(operand, json_type_string))) { - s1 = value ? json_object_get_string(value) : "null"; - s2 = operand ? json_object_get_string(operand) : "null"; - len1 = strlen(s1); - len2 = strlen(s2); + if (operation == I_ADD && (ucv_type(value) == UC_STRING || ucv_type(operand) == UC_STRING)) { + s1 = (ucv_type(value) != UC_STRING) ? ucv_to_string(vm, value) : NULL; + s2 = (ucv_type(operand) != UC_STRING) ? ucv_to_string(vm, operand) : NULL; + len1 = s1 ? strlen(s1) : ucv_string_length(value); + len2 = s2 ? strlen(s2) : ucv_string_length(operand); s = xalloc(len1 + len2 + 1); - snprintf(s, len1 + len2 + 1, "%s%s", s1, s2); + memcpy(s, s1 ? s1 : ucv_string_get(value), len1); + memcpy(s + len1, s2 ? s2 : ucv_string_get(operand), len2); + free(s1); + free(s2); - rv = xjs_new_string(s); + rv = ucv_string_new_length(s, len1 + len2); free(s); @@ -1233,38 +1272,38 @@ uc_vm_value_arith(uc_vm *vm, enum insn_type operation, json_object *value, json_ t1 = uc_cast_number(value, &n1, &d1); t2 = uc_cast_number(operand, &n2, &d2); - if (t1 == json_type_double || t2 == json_type_double) { - d1 = (t1 == json_type_double) ? d1 : (double)n1; - d2 = (t2 == json_type_double) ? d2 : (double)n2; + if (t1 == UC_DOUBLE || t2 == UC_DOUBLE) { + d1 = (t1 == UC_DOUBLE) ? d1 : (double)n1; + d2 = (t2 == UC_DOUBLE) ? d2 : (double)n2; switch (operation) { case I_ADD: case I_PLUS: - rv = uc_double_new(d1 + d2); + rv = ucv_double_new(d1 + d2); break; case I_SUB: - rv = uc_double_new(d1 - d2); + rv = ucv_double_new(d1 - d2); break; case I_MUL: - rv = uc_double_new(d1 * d2); + rv = ucv_double_new(d1 * d2); break; case I_DIV: if (d2 == 0.0) - rv = uc_double_new(INFINITY); + rv = ucv_double_new(INFINITY); else if (isnan(d2)) - rv = uc_double_new(NAN); + rv = ucv_double_new(NAN); else if (!isfinite(d2)) - rv = uc_double_new(isfinite(d1) ? 0.0 : NAN); + rv = ucv_double_new(isfinite(d1) ? 0.0 : NAN); else - rv = uc_double_new(d1 / d2); + rv = ucv_double_new(d1 / d2); break; case I_MOD: - rv = uc_double_new(NAN); + rv = ucv_double_new(NAN); break; default: @@ -1278,27 +1317,27 @@ uc_vm_value_arith(uc_vm *vm, enum insn_type operation, json_object *value, json_ switch (operation) { case I_ADD: case I_PLUS: - rv = xjs_new_int64(n1 + n2); + rv = ucv_int64_new(n1 + n2); break; case I_SUB: - rv = xjs_new_int64(n1 - n2); + rv = ucv_int64_new(n1 - n2); break; case I_MUL: - rv = xjs_new_int64(n1 * n2); + rv = ucv_int64_new(n1 * n2); break; case I_DIV: if (n2 == 0) - rv = uc_double_new(INFINITY); + rv = ucv_double_new(INFINITY); else - rv = xjs_new_int64(n1 / n2); + rv = ucv_int64_new(n1 / n2); break; case I_MOD: - rv = xjs_new_int64(n1 % n2); + rv = ucv_int64_new(n1 % n2); break; default: @@ -1315,25 +1354,28 @@ uc_vm_value_arith(uc_vm *vm, enum insn_type operation, json_object *value, json_ static void uc_vm_insn_update_var(uc_vm *vm, enum insn_type insn) { - json_object *name, *val, *inc = uc_vm_stack_pop(vm); - uc_prototype *scope, *next; + uc_value_t *name, *val, *inc = uc_vm_stack_pop(vm); + uc_value_t *scope, *next; + bool found; scope = vm->globals; name = uc_chunk_get_constant(uc_vm_current_chunk(vm), vm->arg.u32 & 0x00FFFFFF); - assert(json_object_is_type(name, json_type_string)); + assert(ucv_type(name) == UC_STRING); + + while (true) { + val = ucv_object_get(scope, ucv_string_get(name), &found); - while (true) { - if (json_object_object_get_ex(scope->header.jso, json_object_get_string(name), &val)) + if (found) break; - next = scope->parent; + next = ucv_prototype_get(scope); if (!next) { if (vm->config->strict_declarations) { uc_vm_raise_exception(vm, EXCEPTION_REFERENCE, "access to undeclared variable %s", - json_object_get_string(name)); + ucv_string_get(name)); } break; @@ -1344,26 +1386,26 @@ uc_vm_insn_update_var(uc_vm *vm, enum insn_type insn) val = uc_vm_value_arith(vm, vm->arg.u32 >> 24, val, inc); - json_object_object_add(scope->header.jso, json_object_get_string(name), uc_value_get(val)); + ucv_object_add(scope, ucv_string_get(name), ucv_get(val)); uc_vm_stack_push(vm, val); - uc_value_put(name); - uc_value_put(inc); + ucv_put(name); + ucv_put(inc); } static void uc_vm_insn_update_val(uc_vm *vm, enum insn_type insn) { - json_object *inc = uc_vm_stack_pop(vm); - json_object *k = uc_vm_stack_pop(vm); - json_object *v = uc_vm_stack_pop(vm); - json_object *val = NULL; + uc_value_t *inc = uc_vm_stack_pop(vm); + uc_value_t *k = uc_vm_stack_pop(vm); + uc_value_t *v = uc_vm_stack_pop(vm); + uc_value_t *val = NULL; - switch (json_object_get_type(v)) { - case json_type_object: - case json_type_array: - val = uc_getval(v, k); - uc_vm_stack_push(vm, uc_setval(v, k, uc_vm_value_arith(vm, vm->arg.u8, val, inc))); + switch (ucv_type(v)) { + case UC_OBJECT: + case UC_ARRAY: + val = uc_getval(vm, v, k); + uc_vm_stack_push(vm, uc_setval(vm, v, k, uc_vm_value_arith(vm, vm->arg.u8, val, inc))); break; default: @@ -1374,10 +1416,10 @@ uc_vm_insn_update_val(uc_vm *vm, enum insn_type insn) break; } - uc_value_put(val); - uc_value_put(inc); - uc_value_put(v); - uc_value_put(k); + ucv_put(val); + ucv_put(inc); + ucv_put(v); + ucv_put(k); } static void @@ -1385,9 +1427,9 @@ uc_vm_insn_update_upval(uc_vm *vm, enum insn_type insn) { uc_callframe *frame = uc_vm_current_frame(vm); size_t slot = vm->arg.u32 & 0x00FFFFFF; - uc_upvalref *ref = frame->closure->upvals[slot]; - json_object *inc = uc_vm_stack_pop(vm); - json_object *val; + uc_upvalref_t *ref = frame->closure->upvals[slot]; + uc_value_t *inc = uc_vm_stack_pop(vm); + uc_value_t *val; if (ref->closed) val = ref->value; @@ -1398,14 +1440,14 @@ uc_vm_insn_update_upval(uc_vm *vm, enum insn_type insn) uc_vm_stack_push(vm, val); - uc_value_put(inc); + ucv_put(inc); if (ref->closed) { - uc_value_put(ref->value); - ref->value = uc_value_get(uc_vm_stack_peek(vm, 0)); + ucv_put(ref->value); + ref->value = ucv_get(uc_vm_stack_peek(vm, 0)); } else { - uc_vm_stack_set(vm, ref->slot, uc_value_get(uc_vm_stack_peek(vm, 0))); + uc_vm_stack_set(vm, ref->slot, ucv_get(uc_vm_stack_peek(vm, 0))); } } @@ -1414,22 +1456,22 @@ uc_vm_insn_update_local(uc_vm *vm, enum insn_type insn) { uc_callframe *frame = uc_vm_current_frame(vm); size_t slot = vm->arg.u32 & 0x00FFFFFF; - json_object *inc = uc_vm_stack_pop(vm); - json_object *val; + uc_value_t *inc = uc_vm_stack_pop(vm); + uc_value_t *val; val = uc_vm_value_arith(vm, vm->arg.u32 >> 24, vm->stack.entries[frame->stackframe + slot], inc); uc_vm_stack_push(vm, val); - uc_value_put(inc); - uc_vm_stack_set(vm, frame->stackframe + slot, uc_value_get(uc_vm_stack_peek(vm, 0))); + ucv_put(inc); + uc_vm_stack_set(vm, frame->stackframe + slot, ucv_get(uc_vm_stack_peek(vm, 0))); } static void uc_vm_insn_narr(uc_vm *vm, enum insn_type insn) { - json_object *arr = xjs_new_array_size(vm->arg.u32); + uc_value_t *arr = ucv_array_new_length(vm, vm->arg.u32); uc_vm_stack_push(vm, arr); } @@ -1437,11 +1479,11 @@ uc_vm_insn_narr(uc_vm *vm, enum insn_type insn) static void uc_vm_insn_parr(uc_vm *vm, enum insn_type insn) { - json_object *arr = uc_vm_stack_peek(vm, vm->arg.u32); + uc_value_t *arr = uc_vm_stack_peek(vm, vm->arg.u32); size_t idx; for (idx = 0; idx < vm->arg.u32; idx++) - json_object_array_add(arr, uc_vm_stack_peek(vm, vm->arg.u32 - idx - 1)); + ucv_array_push(arr, uc_vm_stack_peek(vm, vm->arg.u32 - idx - 1)); for (idx = 0; idx < vm->arg.u32; idx++) uc_vm_stack_pop(vm); @@ -1452,79 +1494,81 @@ uc_vm_insn_parr(uc_vm *vm, enum insn_type insn) static void uc_vm_insn_marr(uc_vm *vm, enum insn_type insn) { - json_object *src = uc_vm_stack_pop(vm); - json_object *dst = uc_vm_stack_peek(vm, 0); + uc_value_t *src = uc_vm_stack_pop(vm); + uc_value_t *dst = uc_vm_stack_peek(vm, 0); size_t i; + char *s; - if (!json_object_is_type(src, json_type_array)) { - uc_vm_raise_exception(vm, EXCEPTION_TYPE, - "(%s) is not iterable", - json_object_to_json_string(src)); + if (ucv_type(src) != UC_ARRAY) { + s = ucv_to_string(vm, src); + uc_vm_raise_exception(vm, EXCEPTION_TYPE, "(%s) is not iterable", s); + ucv_put(src); + free(s); return; } - for (i = 0; i < json_object_array_length(src); i++) - json_object_array_add(dst, uc_value_get(json_object_array_get_idx(src, i))); + for (i = 0; i < ucv_array_length(src); i++) + ucv_array_push(dst, ucv_get(ucv_array_get(src, i))); - uc_value_put(src); + ucv_put(src); } static void uc_vm_insn_nobj(uc_vm *vm, enum insn_type insn) { - json_object *arr = xjs_new_object(); + uc_value_t *obj = ucv_object_new(vm); - uc_vm_stack_push(vm, arr); + uc_vm_stack_push(vm, obj); } static void uc_vm_insn_sobj(uc_vm *vm, enum insn_type insn) { - json_object *obj = uc_vm_stack_peek(vm, vm->arg.u32); + uc_value_t *obj = uc_vm_stack_peek(vm, vm->arg.u32); size_t idx; for (idx = 0; idx < vm->arg.u32; idx += 2) { - json_object_object_add(obj, - json_object_get_string(uc_vm_stack_peek(vm, vm->arg.u32 - idx - 1)), - uc_value_get(uc_vm_stack_peek(vm, vm->arg.u32 - idx - 2))); + ucv_object_add(obj, + ucv_string_get(uc_vm_stack_peek(vm, vm->arg.u32 - idx - 1)), + ucv_get(uc_vm_stack_peek(vm, vm->arg.u32 - idx - 2))); } for (idx = 0; idx < vm->arg.u32; idx++) - uc_value_put(uc_vm_stack_pop(vm)); + ucv_put(uc_vm_stack_pop(vm)); } static void uc_vm_insn_mobj(uc_vm *vm, enum insn_type insn) { - json_object *src = uc_vm_stack_pop(vm); - json_object *dst = uc_vm_stack_peek(vm, 0); - char *istr; + uc_value_t *src = uc_vm_stack_pop(vm); + uc_value_t *dst = uc_vm_stack_peek(vm, 0); size_t i; + char *s; - switch (json_object_get_type(src)) { - case json_type_object: + switch (ucv_type(src)) { + case UC_OBJECT: ; /* a label can only be part of a statement and a declaration is not a statement */ - json_object_object_foreach(src, k, v) - json_object_object_add(dst, k, uc_value_get(v)); + ucv_object_foreach(src, k, v) + ucv_object_add(dst, k, ucv_get(v)); - uc_value_put(src); + ucv_put(src); break; case json_type_array: - for (i = 0; i < json_object_array_length(src); i++) { - xasprintf(&istr, "%zu", i); - json_object_object_add(dst, istr, uc_value_get(json_object_array_get_idx(src, i))); - free(istr); + for (i = 0; i < ucv_array_length(src); i++) { + xasprintf(&s, "%zu", i); + ucv_object_add(dst, s, ucv_get(ucv_array_get(src, i))); + free(s); } - uc_value_put(src); + ucv_put(src); break; default: - uc_vm_raise_exception(vm, EXCEPTION_TYPE, - "Value (%s) is not iterable", - json_object_to_json_string(src)); + s = ucv_to_string(vm, src); + uc_vm_raise_exception(vm, EXCEPTION_TYPE, "Value (%s) is not iterable", s); + free(s); break; } @@ -1533,14 +1577,14 @@ uc_vm_insn_mobj(uc_vm *vm, enum insn_type insn) static void uc_vm_insn_arith(uc_vm *vm, enum insn_type insn) { - json_object *r2 = uc_vm_stack_pop(vm); - json_object *r1 = uc_vm_stack_pop(vm); - json_object *rv; + uc_value_t *r2 = uc_vm_stack_pop(vm); + uc_value_t *r1 = uc_vm_stack_pop(vm); + uc_value_t *rv; rv = uc_vm_value_arith(vm, insn, r1, r2); - uc_value_put(r1); - uc_value_put(r2); + ucv_put(r1); + ucv_put(r2); uc_vm_stack_push(vm, rv); } @@ -1548,23 +1592,23 @@ uc_vm_insn_arith(uc_vm *vm, enum insn_type insn) static void uc_vm_insn_plus_minus(uc_vm *vm, enum insn_type insn) { - struct json_object *v = uc_vm_stack_pop(vm); + uc_value_t *v = uc_vm_stack_pop(vm); bool is_sub = (insn == I_MINUS); - enum json_type t; + uc_type_t t; int64_t n; double d; t = uc_cast_number(v, &n, &d); - json_object_put(v); + ucv_put(v); switch (t) { - case json_type_int: - uc_vm_stack_push(vm, xjs_new_int64(is_sub ? -n : n)); + case UC_INTEGER: + uc_vm_stack_push(vm, ucv_int64_new(is_sub ? -n : n)); break; default: - uc_vm_stack_push(vm, uc_double_new(is_sub ? -d : d)); + uc_vm_stack_push(vm, ucv_double_new(is_sub ? -d : d)); break; } } @@ -1572,14 +1616,14 @@ uc_vm_insn_plus_minus(uc_vm *vm, enum insn_type insn) static void uc_vm_insn_bitop(uc_vm *vm, enum insn_type insn) { - json_object *r2 = uc_vm_stack_pop(vm); - json_object *r1 = uc_vm_stack_pop(vm); - json_object *rv; + uc_value_t *r2 = uc_vm_stack_pop(vm); + uc_value_t *r1 = uc_vm_stack_pop(vm); + uc_value_t *rv; rv = uc_vm_value_bitop(vm, insn, r1, r2); - uc_value_put(r1); - uc_value_put(r2); + ucv_put(r1); + ucv_put(r2); uc_vm_stack_push(vm, rv); } @@ -1587,23 +1631,23 @@ uc_vm_insn_bitop(uc_vm *vm, enum insn_type insn) static void uc_vm_insn_complement(uc_vm *vm, enum insn_type insn) { - struct json_object *v = uc_vm_stack_pop(vm); + uc_value_t *v = uc_vm_stack_pop(vm); int64_t n; double d; - if (uc_cast_number(v, &n, &d) == json_type_double) + if (uc_cast_number(v, &n, &d) == UC_DOUBLE) n = isnan(d) ? 0 : (int64_t)d; - json_object_put(v); + ucv_put(v); - uc_vm_stack_push(vm, xjs_new_int64(~n)); + uc_vm_stack_push(vm, ucv_int64_new(~n)); } static void uc_vm_insn_rel(uc_vm *vm, enum insn_type insn) { - json_object *r2 = uc_vm_stack_pop(vm); - json_object *r1 = uc_vm_stack_pop(vm); + uc_value_t *r2 = uc_vm_stack_pop(vm); + uc_value_t *r1 = uc_vm_stack_pop(vm); bool res = false; switch (insn) { @@ -1627,27 +1671,27 @@ uc_vm_insn_rel(uc_vm *vm, enum insn_type insn) break; } - uc_value_put(r1); - uc_value_put(r2); + ucv_put(r1); + ucv_put(r2); - uc_vm_stack_push(vm, xjs_new_boolean(res)); + uc_vm_stack_push(vm, ucv_boolean_new(res)); } static void uc_vm_insn_in(uc_vm *vm, enum insn_type insn) { - json_object *r2 = uc_vm_stack_pop(vm); - json_object *r1 = uc_vm_stack_pop(vm); - json_object *item; + uc_value_t *r2 = uc_vm_stack_pop(vm); + uc_value_t *r1 = uc_vm_stack_pop(vm); + uc_value_t *item; size_t arrlen, arridx; bool found = false; - const char *key; + char *key; - switch (json_object_get_type(r2)) { - case json_type_array: - for (arridx = 0, arrlen = json_object_array_length(r2); + switch (ucv_type(r2)) { + case UC_ARRAY: + for (arridx = 0, arrlen = ucv_array_length(r2); arridx < arrlen; arridx++) { - item = json_object_array_get_idx(r2, arridx); + item = ucv_array_get(r2, arridx); if (uc_cmp(TK_EQ, r1, item)) { found = true; @@ -1657,41 +1701,53 @@ uc_vm_insn_in(uc_vm *vm, enum insn_type insn) break; - case json_type_object: - key = r1 ? json_object_get_string(r1) : "null"; - found = json_object_object_get_ex(r2, key, NULL); + case UC_OBJECT: + if (ucv_type(r1) == UC_STRING) { + ucv_object_get(r2, ucv_string_get(r1), &found); + } + else { + key = ucv_to_string(vm, r1); + ucv_object_get(r2, key, &found); + free(key); + } + break; default: found = false; } - uc_value_put(r1); - uc_value_put(r2); + ucv_put(r1); + ucv_put(r2); - uc_vm_stack_push(vm, xjs_new_boolean(found)); + uc_vm_stack_push(vm, ucv_boolean_new(found)); } static void uc_vm_insn_equality(uc_vm *vm, enum insn_type insn) { - json_object *r2 = uc_vm_stack_pop(vm); - json_object *r1 = uc_vm_stack_pop(vm); - bool equal = uc_eq(r1, r2); + uc_value_t *r2 = uc_vm_stack_pop(vm); + uc_value_t *r1 = uc_vm_stack_pop(vm); + bool equal; + + if (ucv_is_scalar(r1) && ucv_is_scalar(r2)) + equal = ucv_equal(r1, r2); + else + equal = (r1 == r2); - uc_value_put(r1); - uc_value_put(r2); + ucv_put(r1); + ucv_put(r2); - uc_vm_stack_push(vm, xjs_new_boolean((insn == I_EQS) ? equal : !equal)); + uc_vm_stack_push(vm, ucv_boolean_new((insn == I_EQS) ? equal : !equal)); } static void uc_vm_insn_not(uc_vm *vm, enum insn_type insn) { - json_object *r1 = uc_vm_stack_pop(vm); + uc_value_t *r1 = uc_vm_stack_pop(vm); - uc_vm_stack_push(vm, xjs_new_boolean(!uc_val_is_truish(r1))); - uc_value_put(r1); + uc_vm_stack_push(vm, ucv_boolean_new(!uc_val_is_truish(r1))); + ucv_put(r1); } static void @@ -1718,7 +1774,7 @@ uc_vm_insn_jmpz(uc_vm *vm, enum insn_type insn) { uc_callframe *frame = uc_vm_current_frame(vm); uc_chunk *chunk = uc_vm_frame_chunk(frame); - json_object *v = uc_vm_stack_pop(vm); + uc_value_t *v = uc_vm_stack_pop(vm); int32_t addr = vm->arg.s32; /* ip already has been incremented */ @@ -1733,56 +1789,64 @@ uc_vm_insn_jmpz(uc_vm *vm, enum insn_type insn) if (!uc_val_is_truish(v)) frame->ip += addr; - uc_value_put(v); + ucv_put(v); } static void uc_vm_insn_next(uc_vm *vm, enum insn_type insn) { - json_object *k = uc_vm_stack_pop(vm); - json_object *v = uc_vm_stack_pop(vm); + uc_value_t *k = uc_vm_stack_pop(vm); + uc_value_t *v = uc_vm_stack_pop(vm); + void *end = (void *)~(uintptr_t)0; + uc_ressource_t *iterk; struct lh_entry *curr; - int64_t n; + uint64_t n; + + if (k != NULL && ucv_type(k) != UC_RESSOURCE) { + fprintf(stderr, "Invalid iterator value\n"); + abort(); + } + + if (k == NULL) { + k = ucv_ressource_new(NULL, NULL); + ((uc_ressource_t *)k)->type = UINT64_MAX; + } - switch (json_object_get_type(v)) { - case json_type_object: - curr = k ? json_object_get_userdata(k) : json_object_get_object(v)->head; + iterk = (uc_ressource_t *)k; - if (curr) { - if (!k) - k = xjs_new_string("[key]"); + switch (ucv_type(v)) { + case UC_OBJECT: + curr = iterk->data ? iterk->data : ((uc_object_t *)v)->table->head; - json_object_set_userdata(k, curr->next, NULL); + if (curr != NULL && curr != end) { + iterk->data = curr->next ? curr->next : end; - uc_vm_stack_push(vm, xjs_new_string(curr->k)); + uc_vm_stack_push(vm, ucv_string_new(curr->k)); if (insn == I_NEXTKV) - uc_vm_stack_push(vm, uc_value_get((json_object *)curr->v)); + uc_vm_stack_push(vm, ucv_get((uc_value_t *)curr->v)); uc_vm_stack_push(vm, k); - uc_value_put(v); + ucv_put(v); return; } break; - case json_type_array: - if (!k) - k = xjs_new_int64(0); - - n = json_object_get_int64(k); + case UC_ARRAY: + n = (uintptr_t)iterk->data; - if (json_object_is_type(k, json_type_int) && n < json_object_array_length(v)) { - json_object_int_inc(k, 1); + if (n < ucv_array_length(v)) { + iterk->data = (void *)(n + 1); if (insn == I_NEXTKV) - uc_vm_stack_push(vm, xjs_new_int64(n)); + uc_vm_stack_push(vm, ucv_uint64_new(n)); - uc_vm_stack_push(vm, uc_value_get(json_object_array_get_idx(v, n))); + uc_vm_stack_push(vm, ucv_get(ucv_array_get(v, n))); uc_vm_stack_push(vm, k); - uc_value_put(v); + ucv_put(v); return; } @@ -1799,87 +1863,83 @@ uc_vm_insn_next(uc_vm *vm, enum insn_type insn) if (insn == I_NEXTKV) uc_vm_stack_push(vm, NULL); - uc_value_put(k); - uc_value_put(v); + ucv_put(k); + ucv_put(v); } static void uc_vm_insn_close_upval(uc_vm *vm, enum insn_type insn) { uc_vm_close_upvals(vm, vm->stack.count - 1); - uc_value_put(uc_vm_stack_pop(vm)); + ucv_put(uc_vm_stack_pop(vm)); } static void uc_vm_insn_call(uc_vm *vm, enum insn_type insn) { - json_object *fno = uc_value_get(uc_vm_stack_peek(vm, vm->arg.u32 & 0xffff)); - json_object *ctx = NULL; + uc_value_t *fno = ucv_get(uc_vm_stack_peek(vm, vm->arg.u32 & 0xffff)); + uc_value_t *ctx = NULL; - if (!uc_object_is_type(fno, UC_OBJ_CLOSURE) || !uc_object_as_closure(fno)->is_arrow) + if (!ucv_is_arrowfn(fno)) ctx = NULL; else if (vm->callframes.count > 0) - ctx = uc_value_get(uc_vm_current_frame(vm)->ctx); + ctx = uc_vm_current_frame(vm)->ctx; - uc_vm_call_function(vm, ctx, fno, false, vm->arg.u32); + uc_vm_call_function(vm, ucv_get(ctx), fno, false, vm->arg.u32); } static void uc_vm_insn_mcall(uc_vm *vm, enum insn_type insn) { size_t key_slot = vm->stack.count - (vm->arg.u32 & 0xffff) - 1; - json_object *ctx = vm->stack.entries[key_slot - 1]; - json_object *key = vm->stack.entries[key_slot]; - json_object *fno = uc_getval(ctx, key); + uc_value_t *ctx = vm->stack.entries[key_slot - 1]; + uc_value_t *key = vm->stack.entries[key_slot]; + uc_value_t *fno = uc_getval(vm, ctx, key); uc_vm_stack_set(vm, key_slot, fno); /* arrow functions as method calls inherit the parent ctx */ - if (uc_object_is_type(fno, UC_OBJ_CLOSURE) && uc_object_as_closure(fno)->is_arrow) + if (ucv_is_arrowfn(fno)) ctx = uc_vm_current_frame(vm)->ctx; - uc_vm_call_function(vm, uc_value_get(ctx), uc_value_get(fno), true, vm->arg.u32); + uc_vm_call_function(vm, ucv_get(ctx), ucv_get(fno), true, vm->arg.u32); } static void uc_vm_insn_print(uc_vm *vm, enum insn_type insn) { - json_object *v = uc_vm_stack_pop(vm); - const char *p; - size_t len; + uc_value_t *v = uc_vm_stack_pop(vm); + char *p; - switch (json_object_get_type(v)) { - case json_type_object: - case json_type_array: - p = json_object_to_json_string_ext(v, JSON_C_TO_STRING_NOSLASHESCAPE|JSON_C_TO_STRING_SPACED); - len = strlen(p); + switch (ucv_type(v)) { + case UC_OBJECT: + case UC_ARRAY: + p = ucv_to_jsonstring(vm, v); + fwrite(p, 1, strlen(p), stdout); + free(p); break; - case json_type_string: - p = json_object_get_string(v); - len = json_object_get_string_len(v); + case UC_STRING: + fwrite(ucv_string_get(v), 1, ucv_string_length(v), stdout); break; - case json_type_null: - p = ""; - len = 0; + case UC_NULL: break; default: - p = json_object_get_string(v); - len = strlen(p); + p = ucv_to_string(vm, v); + fwrite(p, 1, strlen(p), stdout); + free(p); } - fwrite(p, 1, len, stdout); - - uc_value_put(v); + ucv_put(v); } -static json_object * +static uc_value_t * uc_vm_callframe_pop(uc_vm *vm) { uc_callframe *frame = uc_vm_current_frame(vm); - json_object *retval; + uc_value_t *retval; /* close upvalues */ uc_vm_close_upvals(vm, frame->stackframe); @@ -1891,18 +1951,18 @@ uc_vm_callframe_pop(uc_vm *vm) /* reset function stack frame */ while (vm->stack.count > frame->stackframe) - uc_value_put(uc_vm_stack_pop(vm)); + ucv_put(uc_vm_stack_pop(vm)); /* for method calls, release context as well */ if (frame->mcall) - uc_value_put(uc_vm_stack_pop(vm)); + ucv_put(uc_vm_stack_pop(vm)); /* release function */ - uc_value_put(frame->closure ? frame->closure->header.jso : NULL); - uc_value_put(frame->cfunction ? frame->cfunction->header.jso : NULL); + ucv_put((uc_value_t *)frame->closure); + ucv_put((uc_value_t *)frame->cfunction); /* release context */ - uc_value_put(frame->ctx); + ucv_put(frame->ctx); vm->callframes.count--; @@ -1920,9 +1980,9 @@ uc_vm_output_exception(uc_vm *vm) vm->exception.message); fprintf(stderr, "%s\n\n", - json_object_get_string( - json_object_object_get( - json_object_array_get_idx(vm->exception.stacktrace, 0), "context"))); + ucv_string_get( + ucv_object_get( + ucv_array_get(vm->exception.stacktrace, 0), "context", NULL))); } static uc_vm_status_t @@ -1930,7 +1990,7 @@ uc_vm_execute_chunk(uc_vm *vm) { uc_callframe *frame = uc_vm_current_frame(vm); uc_chunk *chunk = uc_vm_frame_chunk(frame); - json_object *retval; + uc_value_t *retval; enum insn_type insn; while (chunk) { @@ -1961,7 +2021,7 @@ uc_vm_execute_chunk(uc_vm *vm) break; case I_LTHIS: - uc_vm_stack_push(vm, uc_value_get(frame->ctx)); + uc_vm_stack_push(vm, ucv_get(frame->ctx)); break; case I_LVAR: @@ -2100,11 +2160,11 @@ uc_vm_execute_chunk(uc_vm *vm) break; case I_COPY: - uc_vm_stack_push(vm, uc_value_get(uc_vm_stack_peek(vm, vm->arg.u8))); + uc_vm_stack_push(vm, ucv_get(uc_vm_stack_peek(vm, vm->arg.u8))); break; case I_POP: - uc_value_put(uc_vm_stack_pop(vm)); + ucv_put(uc_vm_stack_pop(vm)); break; case I_CUPV: @@ -2127,7 +2187,7 @@ uc_vm_execute_chunk(uc_vm *vm) retval = uc_vm_callframe_pop(vm); if (vm->callframes.count == 0) { - uc_value_put(retval); + ucv_put(retval); return STATUS_OK; } @@ -2163,7 +2223,7 @@ uc_vm_execute_chunk(uc_vm *vm) return ERROR_RUNTIME; /* no exception handler in current function, pop callframe */ - uc_value_put(uc_vm_callframe_pop(vm)); + ucv_put(uc_vm_callframe_pop(vm)); /* resume execution at topmost remaining callframe */ frame = uc_vector_last(&vm->callframes); @@ -2176,25 +2236,25 @@ uc_vm_execute_chunk(uc_vm *vm) } static uc_vm_status_t -uc_vm_preload(uc_vm *vm, json_object *modules) +uc_vm_preload(uc_vm *vm, uc_value_t *modules) { - json_object *requirefn, *module, *name; + uc_value_t *requirefn, *module, *name; uc_exception_type_t ex; size_t i; - if (!json_object_is_type(modules, json_type_array)) + if (ucv_type(modules) != UC_ARRAY) return STATUS_OK; - requirefn = uc_prototype_lookup(vm->globals, "require"); + requirefn = ucv_property_get(vm->globals, "require"); - if (!uc_object_is_type(requirefn, UC_OBJ_CFUNCTION)) + if (ucv_type(requirefn) != UC_CFUNCTION) return STATUS_OK; - for (i = 0; i < json_object_array_length(modules); i++) { - name = json_object_array_get_idx(modules, i); + for (i = 0; i < ucv_array_length(modules); i++) { + name = ucv_array_get(modules, i); - uc_vm_stack_push(vm, uc_value_get(requirefn)); - uc_vm_stack_push(vm, uc_value_get(name)); + uc_vm_stack_push(vm, ucv_get(requirefn)); + uc_vm_stack_push(vm, ucv_get(name)); ex = uc_vm_call(vm, false, 1); @@ -2203,21 +2263,22 @@ uc_vm_preload(uc_vm *vm, json_object *modules) module = uc_vm_stack_pop(vm); - uc_value_put(uc_setval(vm->globals->header.jso, name, module)); + ucv_put(uc_setval(vm, vm->globals, name, module)); } return STATUS_OK; } uc_vm_status_t -uc_vm_execute(uc_vm *vm, uc_function *fn, uc_prototype *globals, json_object *modules) +uc_vm_execute(uc_vm *vm, uc_function_t *fn, uc_value_t *globals, uc_value_t *modules) { - uc_closure *closure = uc_closure_new(fn, false); + uc_closure_t *closure = (uc_closure_t *)ucv_closure_new(vm, fn, false); uc_callframe *frame; + uc_stringbuf_t *buf; uc_vm_status_t rv; vm->globals = globals; - uc_value_get(globals ? globals->header.jso : NULL); + ucv_get(globals); uc_vector_grow(&vm->callframes); @@ -2227,14 +2288,12 @@ uc_vm_execute(uc_vm *vm, uc_function *fn, uc_prototype *globals, json_object *mo frame->ip = uc_vm_frame_chunk(frame)->entries; if (vm->trace) { - size_t msglen = 0; - char *msg = NULL; + buf = xprintbuf_new(); - format_source_context(&msg, &msglen, - fn->source, 0, true); + format_source_context(buf, fn->source, 0, true); - fprintf(stderr, "%s", msg); - free(msg); + fwrite(buf->buf, 1, printbuf_length(buf), stderr); + printbuf_free(buf); uc_vm_frame_dump(vm, frame); } @@ -2249,7 +2308,7 @@ uc_vm_execute(uc_vm *vm, uc_function *fn, uc_prototype *globals, json_object *mo else rv = uc_vm_execute_chunk(vm); - uc_value_put(vm->globals->header.jso); + ucv_put(vm->globals); vm->globals = NULL; return rv; @@ -2258,11 +2317,11 @@ uc_vm_execute(uc_vm *vm, uc_function *fn, uc_prototype *globals, json_object *mo uc_exception_type_t uc_vm_call(uc_vm *vm, bool mcall, size_t nargs) { - json_object *ctx = mcall ? uc_value_get(uc_vm_stack_peek(vm, nargs - 1)) : NULL; - json_object *fno = uc_value_get(uc_vm_stack_peek(vm, nargs)); + uc_value_t *ctx = mcall ? ucv_get(uc_vm_stack_peek(vm, nargs + 1)) : NULL; + uc_value_t *fno = ucv_get(uc_vm_stack_peek(vm, nargs)); if (uc_vm_call_function(vm, ctx, fno, mcall, nargs & 0xffff)) { - if (!uc_object_is_type(fno, UC_OBJ_CFUNCTION)) + if (ucv_type(fno) != UC_CFUNCTION) uc_vm_execute_chunk(vm); } |