Merge branch 'mach' into bytecode_cleanup
This commit is contained in:
@@ -406,6 +406,8 @@ typedef struct { uint16_t line; uint16_t col; } MachLineEntry;
|
||||
#define MACH_GET_sJ(i) ((int32_t)((i) & 0xFFFFFF00) >> 8)
|
||||
|
||||
typedef enum MachOpcode {
|
||||
/* === Legacy opcodes (used by existing .mach files) === */
|
||||
|
||||
/* Constants & Loading */
|
||||
MACH_LOADK, /* R(A) = K(Bx) — load from constant pool (ABx) */
|
||||
MACH_LOADI, /* R(A) = (int16_t)sBx — load small integer (AsBx) */
|
||||
@@ -416,7 +418,7 @@ typedef enum MachOpcode {
|
||||
/* Movement */
|
||||
MACH_MOVE, /* R(A) = R(B) */
|
||||
|
||||
/* Arithmetic (ABC) */
|
||||
/* Generic arithmetic (ABC) — used by legacy .mach */
|
||||
MACH_ADD, /* R(A) = R(B) + R(C) */
|
||||
MACH_SUB, /* R(A) = R(B) - R(C) */
|
||||
MACH_MUL, /* R(A) = R(B) * R(C) */
|
||||
@@ -427,7 +429,7 @@ typedef enum MachOpcode {
|
||||
MACH_INC, /* R(A) = R(B) + 1 */
|
||||
MACH_DEC, /* R(A) = R(B) - 1 */
|
||||
|
||||
/* Comparison (ABC) */
|
||||
/* Generic comparison (ABC) — used by legacy .mach */
|
||||
MACH_EQ, /* R(A) = (R(B) == R(C)) */
|
||||
MACH_NEQ, /* R(A) = (R(B) != R(C)) */
|
||||
MACH_LT, /* R(A) = (R(B) < R(C)) */
|
||||
@@ -435,7 +437,7 @@ typedef enum MachOpcode {
|
||||
MACH_GT, /* R(A) = (R(B) > R(C)) */
|
||||
MACH_GE, /* R(A) = (R(B) >= R(C)) */
|
||||
|
||||
/* Logical/Bitwise */
|
||||
/* Logical/Bitwise — used by legacy .mach */
|
||||
MACH_LNOT, /* R(A) = !R(B) */
|
||||
MACH_BNOT, /* R(A) = ~R(B) */
|
||||
MACH_BAND, /* R(A) = R(B) & R(C) */
|
||||
@@ -445,7 +447,7 @@ typedef enum MachOpcode {
|
||||
MACH_SHR, /* R(A) = R(B) >> R(C) */
|
||||
MACH_USHR, /* R(A) = R(B) >>> R(C) */
|
||||
|
||||
/* Property access */
|
||||
/* Property access — used by legacy .mach */
|
||||
MACH_GETFIELD, /* R(A) = R(B)[K(C)] — named property */
|
||||
MACH_SETFIELD, /* R(A)[K(B)] = R(C) — named property */
|
||||
MACH_GETINDEX, /* R(A) = R(B)[R(C)] — computed property */
|
||||
@@ -466,12 +468,12 @@ typedef enum MachOpcode {
|
||||
MACH_JMPFALSE, /* if !R(A): pc += sBx — (iAsBx format) */
|
||||
MACH_JMPNULL, /* if R(A)==null: pc += sBx */
|
||||
|
||||
/* Function calls — Lua-style consecutive registers */
|
||||
/* Function calls — Lua-style consecutive registers (legacy .mach) */
|
||||
MACH_CALL, /* Call R(A) with B args R(A+1)..R(A+B), C=0 discard, C=1 keep result in R(A) */
|
||||
MACH_RETURN, /* Return R(A) */
|
||||
MACH_RETNIL, /* Return null */
|
||||
|
||||
/* Object/array creation */
|
||||
/* Object/array creation — legacy .mach */
|
||||
MACH_NEWOBJECT, /* R(A) = {} */
|
||||
MACH_NEWARRAY, /* R(A) = new array, B = element count in R(A+1)..R(A+B) */
|
||||
MACH_CLOSURE, /* R(A) = closure(functions[Bx]) (ABx) */
|
||||
@@ -493,10 +495,112 @@ typedef enum MachOpcode {
|
||||
|
||||
MACH_NOP,
|
||||
|
||||
/* === New mcode-derived opcodes (1:1 mapping to mcode IR) === */
|
||||
|
||||
/* Typed integer arithmetic (ABC) */
|
||||
MACH_ADD_INT, /* R(A) = R(B) + R(C) — int, overflow → float */
|
||||
MACH_SUB_INT, /* R(A) = R(B) - R(C) — int */
|
||||
MACH_MUL_INT, /* R(A) = R(B) * R(C) — int */
|
||||
MACH_DIV_INT, /* R(A) = R(B) / R(C) — int */
|
||||
MACH_MOD_INT, /* R(A) = R(B) % R(C) — int */
|
||||
MACH_NEG_INT, /* R(A) = -R(B) — int (AB) */
|
||||
|
||||
/* Typed float arithmetic (ABC) */
|
||||
MACH_ADD_FLOAT, /* R(A) = R(B) + R(C) — float */
|
||||
MACH_SUB_FLOAT, /* R(A) = R(B) - R(C) — float */
|
||||
MACH_MUL_FLOAT, /* R(A) = R(B) * R(C) — float */
|
||||
MACH_DIV_FLOAT, /* R(A) = R(B) / R(C) — float */
|
||||
MACH_MOD_FLOAT, /* R(A) = R(B) % R(C) — float */
|
||||
MACH_NEG_FLOAT, /* R(A) = -R(B) — float (AB) */
|
||||
|
||||
/* Text */
|
||||
MACH_CONCAT, /* R(A) = R(B) ++ R(C) — string concatenation */
|
||||
|
||||
/* Typed integer comparisons (ABC) */
|
||||
MACH_EQ_INT, /* R(A) = (R(B) == R(C)) — int */
|
||||
MACH_NE_INT, /* R(A) = (R(B) != R(C)) — int */
|
||||
MACH_LT_INT, /* R(A) = (R(B) < R(C)) — int */
|
||||
MACH_LE_INT, /* R(A) = (R(B) <= R(C)) — int */
|
||||
MACH_GT_INT, /* R(A) = (R(B) > R(C)) — int */
|
||||
MACH_GE_INT, /* R(A) = (R(B) >= R(C)) — int */
|
||||
|
||||
/* Typed float comparisons (ABC) */
|
||||
MACH_EQ_FLOAT, /* R(A) = (R(B) == R(C)) — float */
|
||||
MACH_NE_FLOAT, /* R(A) = (R(B) != R(C)) — float */
|
||||
MACH_LT_FLOAT, /* R(A) = (R(B) < R(C)) — float */
|
||||
MACH_LE_FLOAT, /* R(A) = (R(B) <= R(C)) — float */
|
||||
MACH_GT_FLOAT, /* R(A) = (R(B) > R(C)) — float */
|
||||
MACH_GE_FLOAT, /* R(A) = (R(B) >= R(C)) — float */
|
||||
|
||||
/* Typed text comparisons (ABC) */
|
||||
MACH_EQ_TEXT, /* R(A) = (R(B) == R(C)) — text */
|
||||
MACH_NE_TEXT, /* R(A) = (R(B) != R(C)) — text */
|
||||
MACH_LT_TEXT, /* R(A) = (R(B) < R(C)) — text */
|
||||
MACH_LE_TEXT, /* R(A) = (R(B) <= R(C)) — text */
|
||||
MACH_GT_TEXT, /* R(A) = (R(B) > R(C)) — text */
|
||||
MACH_GE_TEXT, /* R(A) = (R(B) >= R(C)) — text */
|
||||
|
||||
/* Typed bool comparisons (ABC) */
|
||||
MACH_EQ_BOOL, /* R(A) = (R(B) == R(C)) — bool */
|
||||
MACH_NE_BOOL, /* R(A) = (R(B) != R(C)) — bool */
|
||||
|
||||
/* Special comparisons */
|
||||
MACH_IS_IDENTICAL, /* R(A) = (R(B) === R(C)) — identity check (ABC) */
|
||||
|
||||
/* Type checks (AB) */
|
||||
MACH_IS_INT, /* R(A) = is_int(R(B)) */
|
||||
MACH_IS_NUM, /* R(A) = is_num(R(B)) */
|
||||
MACH_IS_TEXT, /* R(A) = is_text(R(B)) */
|
||||
MACH_IS_BOOL, /* R(A) = is_bool(R(B)) */
|
||||
MACH_IS_NULL, /* R(A) = is_null(R(B)) */
|
||||
MACH_TYPEOF, /* R(A) = typeof(R(B)) */
|
||||
|
||||
/* Logical (mcode-style) */
|
||||
MACH_NOT, /* R(A) = !R(B) — boolean not (AB) */
|
||||
MACH_AND, /* R(A) = R(B) && R(C) (ABC) */
|
||||
MACH_OR, /* R(A) = R(B) || R(C) (ABC) */
|
||||
|
||||
/* Bitwise (mcode names) */
|
||||
MACH_BITNOT, /* R(A) = ~R(B) (AB) */
|
||||
MACH_BITAND, /* R(A) = R(B) & R(C) (ABC) */
|
||||
MACH_BITOR, /* R(A) = R(B) | R(C) (ABC) */
|
||||
MACH_BITXOR, /* R(A) = R(B) ^ R(C) (ABC) */
|
||||
|
||||
/* Property access (mcode names) */
|
||||
MACH_LOAD_FIELD, /* R(A) = R(B).K(C) — named property (ABC) */
|
||||
MACH_STORE_FIELD, /* R(A).K(B) = R(C) — named property (ABC) */
|
||||
MACH_LOAD_INDEX, /* R(A) = R(B)[R(C)] — integer index (ABC) */
|
||||
MACH_STORE_INDEX, /* R(A)[R(B)] = R(C) — integer index (ABC) */
|
||||
MACH_LOAD_DYNAMIC, /* R(A) = R(B)[R(C)] — dynamic key (ABC) */
|
||||
MACH_STORE_DYNAMIC, /* R(A)[R(B)] = R(C) — dynamic key (ABC) */
|
||||
|
||||
/* Object/Array creation (mcode names) */
|
||||
MACH_NEWRECORD, /* R(A) = {} — new empty record (A only) */
|
||||
|
||||
/* Decomposed function calls (mcode-style) */
|
||||
MACH_FRAME, /* R(A) = frame(R(B), C) — alloc call frame (ABC) */
|
||||
MACH_SETARG, /* frame R(A)[B] = R(C) — set arg in frame (ABC) */
|
||||
MACH_INVOKE, /* R(B) = invoke(R(A)) — call frame, result in R(B) (AB) */
|
||||
MACH_GOFRAME, /* R(A) = goframe(R(B), C) — async frame (ABC) */
|
||||
MACH_GOINVOKE, /* goinvoke(R(A)) — async invoke, no result (A only) */
|
||||
|
||||
/* Control flow */
|
||||
MACH_JMPNOTNULL, /* if R(A)!=null: pc += sBx (iAsBx) */
|
||||
|
||||
/* Error handling */
|
||||
MACH_DISRUPT, /* trigger disruption (A only) */
|
||||
|
||||
/* Variable storage */
|
||||
MACH_SET_VAR, /* env/global[K(Bx)] = R(A) — store to var (ABx) */
|
||||
|
||||
/* Misc */
|
||||
MACH_IN, /* R(A) = (R(B) in R(C)) — has property (ABC) */
|
||||
|
||||
MACH_OP_COUNT
|
||||
} MachOpcode;
|
||||
|
||||
static const char *mach_opcode_names[MACH_OP_COUNT] = {
|
||||
/* Legacy */
|
||||
[MACH_LOADK] = "loadk",
|
||||
[MACH_LOADI] = "loadi",
|
||||
[MACH_LOADNULL] = "loadnull",
|
||||
@@ -556,6 +660,70 @@ static const char *mach_opcode_names[MACH_OP_COUNT] = {
|
||||
[MACH_EQ_TOL] = "eq_tol",
|
||||
[MACH_NEQ_TOL] = "neq_tol",
|
||||
[MACH_NOP] = "nop",
|
||||
/* Mcode-derived */
|
||||
[MACH_ADD_INT] = "add_int",
|
||||
[MACH_SUB_INT] = "sub_int",
|
||||
[MACH_MUL_INT] = "mul_int",
|
||||
[MACH_DIV_INT] = "div_int",
|
||||
[MACH_MOD_INT] = "mod_int",
|
||||
[MACH_NEG_INT] = "neg_int",
|
||||
[MACH_ADD_FLOAT] = "add_float",
|
||||
[MACH_SUB_FLOAT] = "sub_float",
|
||||
[MACH_MUL_FLOAT] = "mul_float",
|
||||
[MACH_DIV_FLOAT] = "div_float",
|
||||
[MACH_MOD_FLOAT] = "mod_float",
|
||||
[MACH_NEG_FLOAT] = "neg_float",
|
||||
[MACH_CONCAT] = "concat",
|
||||
[MACH_EQ_INT] = "eq_int",
|
||||
[MACH_NE_INT] = "ne_int",
|
||||
[MACH_LT_INT] = "lt_int",
|
||||
[MACH_LE_INT] = "le_int",
|
||||
[MACH_GT_INT] = "gt_int",
|
||||
[MACH_GE_INT] = "ge_int",
|
||||
[MACH_EQ_FLOAT] = "eq_float",
|
||||
[MACH_NE_FLOAT] = "ne_float",
|
||||
[MACH_LT_FLOAT] = "lt_float",
|
||||
[MACH_LE_FLOAT] = "le_float",
|
||||
[MACH_GT_FLOAT] = "gt_float",
|
||||
[MACH_GE_FLOAT] = "ge_float",
|
||||
[MACH_EQ_TEXT] = "eq_text",
|
||||
[MACH_NE_TEXT] = "ne_text",
|
||||
[MACH_LT_TEXT] = "lt_text",
|
||||
[MACH_LE_TEXT] = "le_text",
|
||||
[MACH_GT_TEXT] = "gt_text",
|
||||
[MACH_GE_TEXT] = "ge_text",
|
||||
[MACH_EQ_BOOL] = "eq_bool",
|
||||
[MACH_NE_BOOL] = "ne_bool",
|
||||
[MACH_IS_IDENTICAL] = "is_identical",
|
||||
[MACH_IS_INT] = "is_int",
|
||||
[MACH_IS_NUM] = "is_num",
|
||||
[MACH_IS_TEXT] = "is_text",
|
||||
[MACH_IS_BOOL] = "is_bool",
|
||||
[MACH_IS_NULL] = "is_null",
|
||||
[MACH_TYPEOF] = "typeof",
|
||||
[MACH_NOT] = "not",
|
||||
[MACH_AND] = "and",
|
||||
[MACH_OR] = "or",
|
||||
[MACH_BITNOT] = "bitnot",
|
||||
[MACH_BITAND] = "bitand",
|
||||
[MACH_BITOR] = "bitor",
|
||||
[MACH_BITXOR] = "bitxor",
|
||||
[MACH_LOAD_FIELD] = "load_field",
|
||||
[MACH_STORE_FIELD] = "store_field",
|
||||
[MACH_LOAD_INDEX] = "load_index",
|
||||
[MACH_STORE_INDEX] = "store_index",
|
||||
[MACH_LOAD_DYNAMIC] = "load_dynamic",
|
||||
[MACH_STORE_DYNAMIC] = "store_dynamic",
|
||||
[MACH_NEWRECORD] = "newrecord",
|
||||
[MACH_FRAME] = "frame",
|
||||
[MACH_SETARG] = "setarg",
|
||||
[MACH_INVOKE] = "invoke",
|
||||
[MACH_GOFRAME] = "goframe",
|
||||
[MACH_GOINVOKE] = "goinvoke",
|
||||
[MACH_JMPNOTNULL] = "jmpnotnull",
|
||||
[MACH_DISRUPT] = "disrupt",
|
||||
[MACH_SET_VAR] = "set_var",
|
||||
[MACH_IN] = "in",
|
||||
};
|
||||
|
||||
/* Compiled register-based code (off-heap, never GC'd).
|
||||
@@ -586,28 +754,6 @@ typedef struct JSCodeRegister {
|
||||
uint16_t disruption_pc; /* start of disruption handler (0 = none) */
|
||||
} JSCodeRegister;
|
||||
|
||||
/* Pre-parsed MCODE for a single function (off-heap, never GC'd).
|
||||
Created by jsmcode_parse from cJSON MCODE output.
|
||||
Instructions remain as cJSON pointers for string-based dispatch. */
|
||||
typedef struct JSMCode {
|
||||
uint16_t nr_args;
|
||||
uint16_t nr_slots;
|
||||
/* Pre-flattened instruction array (cJSON array items → C array for O(1) access) */
|
||||
cJSON **instrs;
|
||||
uint32_t instr_count;
|
||||
/* Label map: label string → instruction index */
|
||||
struct { const char *name; uint32_t index; } *labels;
|
||||
uint32_t label_count;
|
||||
/* Nested function definitions (indexes into top-level functions array) */
|
||||
struct JSMCode **functions;
|
||||
uint32_t func_count;
|
||||
/* Keep root cJSON alive (owns all the cJSON nodes instrs[] point into) */
|
||||
cJSON *json_root;
|
||||
MachLineEntry *line_table; /* [instr_count], parallel to instrs[] */
|
||||
const char *name; /* function name (points into cJSON tree) */
|
||||
const char *filename; /* source filename (points into cJSON tree) */
|
||||
uint16_t disruption_pc; /* start of disruption handler (0 = none) */
|
||||
} JSMCode;
|
||||
|
||||
/* Frame for closures - used by link-time relocation model where closures
|
||||
reference outer frames via (depth, slot) addressing.
|
||||
@@ -1068,7 +1214,6 @@ typedef enum {
|
||||
JS_FUNC_KIND_BYTECODE,
|
||||
JS_FUNC_KIND_C_DATA,
|
||||
JS_FUNC_KIND_REGISTER, /* register-based VM function */
|
||||
JS_FUNC_KIND_MCODE, /* MCODE JSON interpreter */
|
||||
} JSFunctionKind;
|
||||
|
||||
typedef struct JSFunction {
|
||||
@@ -1092,11 +1237,6 @@ typedef struct JSFunction {
|
||||
JSValue env_record; /* stone record, module environment */
|
||||
JSValue outer_frame; /* JSFrame JSValue, for closures */
|
||||
} reg;
|
||||
struct {
|
||||
JSMCode *code; /* pre-parsed MCODE (off-heap) */
|
||||
JSValue outer_frame; /* lexical parent frame for closures */
|
||||
JSValue env_record; /* module env or JS_NULL */
|
||||
} mcode;
|
||||
} u;
|
||||
} JSFunction;
|
||||
|
||||
@@ -1259,8 +1399,6 @@ JSValue js_call_c_function (JSContext *ctx, JSValue func_obj, JSValue this_obj,
|
||||
JSValue js_call_bound_function (JSContext *ctx, JSValue func_obj, JSValue this_obj, int argc, JSValue *argv);
|
||||
JSValue JS_CallInternal (JSContext *ctx, JSValue func_obj, JSValue this_obj, int argc, JSValue *argv, int flags);
|
||||
JSValue JS_CallRegisterVM(JSContext *ctx, JSCodeRegister *code, JSValue this_obj, int argc, JSValue *argv, JSValue env, JSValue outer_frame);
|
||||
JSValue mcode_exec(JSContext *ctx, JSMCode *code, JSValue this_obj,
|
||||
int argc, JSValue *argv, JSValue outer_frame);
|
||||
int JS_DeleteProperty (JSContext *ctx, JSValue obj, JSValue prop);
|
||||
JSValue __attribute__ ((format (printf, 2, 3)))
|
||||
JS_ThrowInternalError (JSContext *ctx, const char *fmt, ...);
|
||||
@@ -1574,13 +1712,6 @@ typedef struct {
|
||||
} GetLineColCache;
|
||||
|
||||
|
||||
/* === MachVarInfo (shared by mach.c and mcode.c) === */
|
||||
typedef struct MachVarInfo {
|
||||
char *name;
|
||||
int slot;
|
||||
int is_const; /* 1 for def, function args; 0 for var */
|
||||
int is_closure; /* 1 if captured by a nested function */
|
||||
} MachVarInfo;
|
||||
|
||||
/* === PPretext (parser pretext, system-malloc, used by cell_js.c parser) === */
|
||||
typedef struct PPretext {
|
||||
@@ -1770,8 +1901,5 @@ JSFrameRegister *alloc_frame_register(JSContext *ctx, int slot_count);
|
||||
cJSON *mach_find_scope_record(cJSON *scopes, int function_nr);
|
||||
int reg_vm_check_interrupt(JSContext *ctx);
|
||||
|
||||
/* mcode.c exports */
|
||||
JSValue mcode_exec(JSContext *ctx, JSMCode *code, JSValue this_obj, int argc, JSValue *argv, JSValue outer_frame);
|
||||
|
||||
|
||||
#endif /* QUICKJS_INTERNAL_H */
|
||||
|
||||
Reference in New Issue
Block a user