suite passes now with mcode->mach lowering
This commit is contained in:
@@ -1658,6 +1658,19 @@ JSValue JS_CallRegisterVM(JSContext *ctx, JSCodeRegister *code,
|
||||
case MACH_IS_NULL:
|
||||
frame->slots[a] = JS_NewBool(ctx, JS_IsNull(frame->slots[b]));
|
||||
break;
|
||||
case MACH_IS_FUNC:
|
||||
frame->slots[a] = JS_NewBool(ctx, JS_IsFunction(frame->slots[b]));
|
||||
break;
|
||||
case MACH_IS_PROXY: {
|
||||
JSValue v = frame->slots[b];
|
||||
int is_proxy = 0;
|
||||
if (JS_IsFunction(v)) {
|
||||
JSFunction *fn = JS_VALUE_GET_FUNCTION(v);
|
||||
is_proxy = (fn->length == 2);
|
||||
}
|
||||
frame->slots[a] = JS_NewBool(ctx, is_proxy);
|
||||
break;
|
||||
}
|
||||
case MACH_TYPEOF: {
|
||||
JSValue val = frame->slots[b];
|
||||
const char *tname = "unknown";
|
||||
@@ -1681,15 +1694,19 @@ JSValue JS_CallRegisterVM(JSContext *ctx, JSCodeRegister *code,
|
||||
break;
|
||||
}
|
||||
case MACH_AND: {
|
||||
int ba = JS_ToBool(ctx, frame->slots[b]);
|
||||
int bb = JS_ToBool(ctx, frame->slots[c]);
|
||||
frame->slots[a] = JS_NewBool(ctx, ba && bb);
|
||||
JSValue left = frame->slots[b];
|
||||
if (!JS_ToBool(ctx, left))
|
||||
frame->slots[a] = left;
|
||||
else
|
||||
frame->slots[a] = frame->slots[c];
|
||||
break;
|
||||
}
|
||||
case MACH_OR: {
|
||||
int ba = JS_ToBool(ctx, frame->slots[b]);
|
||||
int bb = JS_ToBool(ctx, frame->slots[c]);
|
||||
frame->slots[a] = JS_NewBool(ctx, ba || bb);
|
||||
JSValue left = frame->slots[b];
|
||||
if (JS_ToBool(ctx, left))
|
||||
frame->slots[a] = left;
|
||||
else
|
||||
frame->slots[a] = frame->slots[c];
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1717,12 +1734,9 @@ JSValue JS_CallRegisterVM(JSContext *ctx, JSCodeRegister *code,
|
||||
JSValue obj = frame->slots[b];
|
||||
JSValue key = code->cpool[c];
|
||||
if (JS_IsFunction(obj)) {
|
||||
JSFunction *fn_chk = JS_VALUE_GET_FUNCTION(obj);
|
||||
if (fn_chk->length != 2) {
|
||||
JS_ThrowTypeError(ctx, "cannot read property of non-proxy function");
|
||||
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
|
||||
goto disrupt;
|
||||
}
|
||||
JS_ThrowTypeError(ctx, "cannot read property of function");
|
||||
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
|
||||
goto disrupt;
|
||||
}
|
||||
JSValue val = JS_GetProperty(ctx, obj, key);
|
||||
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
|
||||
@@ -1790,6 +1804,9 @@ JSValue JS_CallRegisterVM(JSContext *ctx, JSCodeRegister *code,
|
||||
} else if (JS_IsArray(obj)) {
|
||||
JS_ThrowTypeError(ctx, "array index must be a number");
|
||||
ret = -1;
|
||||
} else if (JS_IsBool(key) || JS_IsNull(key) || JS_IsArray(key) || JS_IsFunction(key)) {
|
||||
JS_ThrowTypeError(ctx, "object key must be text");
|
||||
ret = -1;
|
||||
} else {
|
||||
ret = JS_SetProperty(ctx, obj, key, val);
|
||||
}
|
||||
@@ -2553,6 +2570,8 @@ static MachCode *mcode_lower_func(cJSON *fobj, const char *filename) {
|
||||
else if (strcmp(op, "is_text") == 0) { AB2(MACH_IS_TEXT); }
|
||||
else if (strcmp(op, "is_bool") == 0) { AB2(MACH_IS_BOOL); }
|
||||
else if (strcmp(op, "is_null") == 0) { AB2(MACH_IS_NULL); }
|
||||
else if (strcmp(op, "is_func") == 0) { AB2(MACH_IS_FUNC); }
|
||||
else if (strcmp(op, "is_proxy") == 0) { AB2(MACH_IS_PROXY); }
|
||||
else if (strcmp(op, "typeof") == 0) { AB2(MACH_TYPEOF); }
|
||||
/* Logical */
|
||||
else if (strcmp(op, "not") == 0) { AB2(MACH_NOT); }
|
||||
@@ -2571,7 +2590,15 @@ static MachCode *mcode_lower_func(cJSON *fobj, const char *filename) {
|
||||
int dest = A1, obj = A2;
|
||||
cJSON *key_item = cJSON_GetArrayItem(it, 3);
|
||||
if (cJSON_IsString(key_item)) {
|
||||
EM(MACH_ABC(MACH_LOAD_FIELD, dest, obj, ml_cpool_str(&s, key_item->valuestring)));
|
||||
int ki = ml_cpool_str(&s, key_item->valuestring);
|
||||
if (ki <= 255) {
|
||||
EM(MACH_ABC(MACH_LOAD_FIELD, dest, obj, ki));
|
||||
} else {
|
||||
/* cpool index > 255: load key via LOADK, then use dynamic access */
|
||||
int tmp = s.nr_slots++;
|
||||
EM(MACH_ABx(MACH_LOADK, tmp, ki));
|
||||
EM(MACH_ABC(MACH_LOAD_DYNAMIC, dest, obj, tmp));
|
||||
}
|
||||
} else {
|
||||
/* key is a register — fall back to dynamic access */
|
||||
int key_reg = (int)key_item->valuedouble;
|
||||
@@ -2582,7 +2609,15 @@ static MachCode *mcode_lower_func(cJSON *fobj, const char *filename) {
|
||||
int obj = A1, val = A2;
|
||||
cJSON *key_item = cJSON_GetArrayItem(it, 3);
|
||||
if (cJSON_IsString(key_item)) {
|
||||
EM(MACH_ABC(MACH_STORE_FIELD, obj, ml_cpool_str(&s, key_item->valuestring), val));
|
||||
int ki = ml_cpool_str(&s, key_item->valuestring);
|
||||
if (ki <= 255) {
|
||||
EM(MACH_ABC(MACH_STORE_FIELD, obj, ki, val));
|
||||
} else {
|
||||
/* cpool index > 255: load key via LOADK, then use dynamic access */
|
||||
int tmp = s.nr_slots++;
|
||||
EM(MACH_ABx(MACH_LOADK, tmp, ki));
|
||||
EM(MACH_ABC(MACH_STORE_DYNAMIC, obj, tmp, val));
|
||||
}
|
||||
} else {
|
||||
/* key is a register — fall back to dynamic access */
|
||||
int key_reg = (int)key_item->valuedouble;
|
||||
@@ -2601,7 +2636,21 @@ static MachCode *mcode_lower_func(cJSON *fobj, const char *filename) {
|
||||
}
|
||||
/* Delete */
|
||||
else if (strcmp(op, "delete") == 0) {
|
||||
ABC3(MACH_DELETEINDEX);
|
||||
int dest = A1, obj = A2;
|
||||
cJSON *key_item = cJSON_GetArrayItem(it, 3);
|
||||
if (cJSON_IsString(key_item)) {
|
||||
int ki = ml_cpool_str(&s, key_item->valuestring);
|
||||
if (ki <= 255) {
|
||||
EM(MACH_ABC(MACH_DELETE, dest, obj, ki));
|
||||
} else {
|
||||
int tmp = s.nr_slots++;
|
||||
EM(MACH_ABx(MACH_LOADK, tmp, ki));
|
||||
EM(MACH_ABC(MACH_DELETEINDEX, dest, obj, tmp));
|
||||
}
|
||||
} else {
|
||||
int key_reg = (int)key_item->valuedouble;
|
||||
EM(MACH_ABC(MACH_DELETEINDEX, dest, obj, key_reg));
|
||||
}
|
||||
}
|
||||
/* Array/Object creation */
|
||||
else if (strcmp(op, "array") == 0) {
|
||||
@@ -3271,3 +3320,21 @@ JSValue JS_RunMachBin(JSContext *ctx, const uint8_t *data, size_t size, JSValue
|
||||
return result;
|
||||
}
|
||||
|
||||
void JS_DumpMachBin(JSContext *ctx, const uint8_t *data, size_t size, JSValue env) {
|
||||
MachCode *mc = JS_DeserializeMachCode(data, size);
|
||||
if (!mc) {
|
||||
printf("Failed to deserialize MACH bytecode\n");
|
||||
return;
|
||||
}
|
||||
|
||||
JSGCRef env_ref;
|
||||
JS_PushGCRef(ctx, &env_ref);
|
||||
env_ref.val = env;
|
||||
|
||||
JSCodeRegister *code = JS_LoadMachCode(ctx, mc, env_ref.val);
|
||||
JS_FreeMachCode(mc);
|
||||
|
||||
dump_register_code(ctx, code, 0);
|
||||
JS_PopGCRef(ctx, &env_ref);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user