diff --git a/source/quickjs.c b/source/quickjs.c index 507ae8d3..a70c1e47 100644 --- a/source/quickjs.c +++ b/source/quickjs.c @@ -30226,36 +30226,35 @@ static int mach_gen_expr (MachGenState *s, cJSON *expr) { /* Object literal */ if (strcmp (kind, "record") == 0) { cJSON *list = cJSON_GetObjectItem (expr, "list"); - int count = cJSON_GetArraySize (list); + /* Create empty record */ int dest = mach_alloc_slot (s); cJSON *instr = cJSON_CreateArray (); cJSON_AddItemToArray (instr, cJSON_CreateString ("mkrecord")); cJSON_AddItemToArray (instr, cJSON_CreateNumber (dest)); - cJSON_AddItemToArray (instr, cJSON_CreateNumber (count)); + cJSON_AddItemToArray (instr, cJSON_CreateNumber (0)); + cJSON_AddItemToArray (s->instructions, instr); + /* Add each property */ cJSON *pair; cJSON_ArrayForEach (pair, list) { cJSON *key = cJSON_GetObjectItem (pair, "left"); cJSON *val = cJSON_GetObjectItem (pair, "right"); + int val_slot = mach_gen_expr (s, val); const char *key_kind = cJSON_GetStringValue (cJSON_GetObjectItem (key, "kind")); if (key_kind && strcmp (key_kind, "name") == 0) { const char *name = cJSON_GetStringValue (cJSON_GetObjectItem (key, "name")); - cJSON_AddItemToArray (instr, cJSON_CreateString (name)); + mach_emit_set_prop (s, dest, name, val_slot); } else if (key_kind && strcmp (key_kind, "text") == 0) { const char *name = cJSON_GetStringValue (cJSON_GetObjectItem (key, "value")); - cJSON_AddItemToArray (instr, cJSON_CreateString (name ? name : "")); + mach_emit_set_prop (s, dest, name ? name : "", val_slot); } else { - /* Computed property - emit the key slot (negative to distinguish) */ + /* Computed property - use store_idx */ int key_slot = mach_gen_expr (s, key); - cJSON_AddItemToArray (instr, cJSON_CreateNumber (-1 - key_slot)); + mach_emit_set_elem (s, dest, key_slot, val_slot); } - - int val_slot = mach_gen_expr (s, val); - cJSON_AddItemToArray (instr, cJSON_CreateNumber (val_slot)); } - cJSON_AddItemToArray (s->instructions, instr); return dest; } @@ -30310,7 +30309,15 @@ static int mach_gen_expr (MachGenState *s, cJSON *expr) { } /* Assignment operators */ - if (strcmp (kind, "assign") == 0 || strstr (kind, "=") != NULL) { + if (strcmp (kind, "assign") == 0 || + strcmp (kind, "+=") == 0 || strcmp (kind, "-=") == 0 || + strcmp (kind, "*=") == 0 || strcmp (kind, "/=") == 0 || + strcmp (kind, "%=") == 0 || strcmp (kind, "**=") == 0 || + strcmp (kind, "&=") == 0 || strcmp (kind, "|=") == 0 || + strcmp (kind, "^=") == 0 || strcmp (kind, "<<=") == 0 || + strcmp (kind, ">>=") == 0 || strcmp (kind, ">>>=") == 0 || + strcmp (kind, "&&=") == 0 || strcmp (kind, "||=") == 0 || + strcmp (kind, "??=") == 0) { return mach_gen_assign (s, expr); } @@ -31468,6 +31475,15 @@ static JSCodeRegister *js_link_mach_unit(JSContext *ctx, cJSON *unit, JSValue en case MACH_OP_NOP: /* No operands */ break; + case MACH_OP_MKRECORD: + case MACH_OP_MKARRAY: { + /* mkrecord dest, count or mkarray dest, count */ + cJSON *dest = cJSON_GetArrayItem(item, 1); + cJSON *count = cJSON_GetArrayItem(item, 2); + instr->a = dest ? (int16_t)cJSON_GetNumberValue(dest) : 0; + instr->b = count ? (int16_t)cJSON_GetNumberValue(count) : 0; + break; + } default: /* Handle remaining cases */ break; @@ -31839,11 +31855,15 @@ static JSValue JS_CallRegisterVM(JSContext *ctx, JSCodeRegister *code, case MACH_OP_BITXOR: case MACH_OP_SHL: case MACH_OP_SHR: - case MACH_OP_USHR: - frame->slots[instr->a] = reg_vm_binop(ctx, instr->opcode, - frame->slots[instr->b], - frame->slots[instr->c]); + case MACH_OP_USHR: { + JSValue left = frame->slots[instr->b]; + JSValue right = frame->slots[instr->c]; + JSValue res = reg_vm_binop(ctx, instr->opcode, left, right); + /* GC may have moved frame - refresh from GC root */ + frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val); + frame->slots[instr->a] = res; break; + } case MACH_OP_NEG: { JSValue v = frame->slots[instr->b]; @@ -31909,7 +31929,10 @@ static JSValue JS_CallRegisterVM(JSContext *ctx, JSCodeRegister *code, case MACH_OP_LOAD_PROP: { JSValue obj = frame->slots[instr->b]; JSValue key = code->cpool[instr->c]; - frame->slots[instr->a] = JS_GetProperty(ctx, obj, key); + JSValue val = JS_GetProperty(ctx, obj, key); + /* GC may have moved frame - refresh from GC root */ + frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val); + frame->slots[instr->a] = val; break; } @@ -31918,17 +31941,23 @@ static JSValue JS_CallRegisterVM(JSContext *ctx, JSCodeRegister *code, JSValue val = frame->slots[instr->b]; JSValue key = code->cpool[instr->c]; JS_SetProperty(ctx, obj, key, val); + /* GC may have moved frame - refresh from GC root */ + frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val); break; } case MACH_OP_LOAD_IDX: { JSValue obj = frame->slots[instr->b]; JSValue idx = frame->slots[instr->c]; + JSValue val; if (JS_IsInt(idx)) { - frame->slots[instr->a] = JS_GetPropertyUint32(ctx, obj, JS_VALUE_GET_INT(idx)); + val = JS_GetPropertyUint32(ctx, obj, JS_VALUE_GET_INT(idx)); } else { - frame->slots[instr->a] = JS_GetProperty(ctx, obj, idx); + val = JS_GetProperty(ctx, obj, idx); } + /* GC may have moved frame - refresh from GC root */ + frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val); + frame->slots[instr->a] = val; break; } @@ -31941,6 +31970,8 @@ static JSValue JS_CallRegisterVM(JSContext *ctx, JSCodeRegister *code, } else { JS_SetProperty(ctx, obj, idx, val); } + /* GC may have moved frame - refresh from GC root */ + frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val); break; } @@ -32194,6 +32225,32 @@ static JSValue JS_CallRegisterVM(JSContext *ctx, JSCodeRegister *code, break; } + case MACH_OP_MKRECORD: { + /* Create empty record */ + JSValue rec = JS_NewObject(ctx); + /* GC may have moved frame - refresh from GC root */ + frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val); + if (JS_IsException(rec)) { + result = rec; + goto done; + } + frame->slots[instr->a] = rec; + break; + } + + case MACH_OP_MKARRAY: { + /* Create empty array */ + JSValue arr = JS_NewArray(ctx); + /* GC may have moved frame - refresh from GC root */ + frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val); + if (JS_IsException(arr)) { + result = arr; + goto done; + } + frame->slots[instr->a] = arr; + break; + } + case MACH_OP_RETURN: result = frame->slots[instr->a];