respsect array and object length requests
This commit is contained in:
@@ -1196,7 +1196,7 @@ JSValue JS_CallRegisterVM(JSContext *ctx, JSCodeRegister *code,
|
||||
}
|
||||
|
||||
case MACH_NEWARRAY: {
|
||||
JSValue arr = JS_NewArray(ctx);
|
||||
JSValue arr = JS_NewArrayCap(ctx, b);
|
||||
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
|
||||
if (JS_IsException(arr)) { goto disrupt; }
|
||||
frame->slots[a] = arr;
|
||||
@@ -1550,7 +1550,7 @@ JSValue JS_CallRegisterVM(JSContext *ctx, JSCodeRegister *code,
|
||||
|
||||
/* New record */
|
||||
case MACH_NEWRECORD: {
|
||||
JSValue obj = JS_NewObject(ctx);
|
||||
JSValue obj = b > 0 ? JS_NewObjectCap(ctx, b) : JS_NewObject(ctx);
|
||||
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
|
||||
if (JS_IsException(obj)) goto disrupt;
|
||||
frame->slots[a] = obj;
|
||||
@@ -2008,11 +2008,9 @@ static int mcode_reg_items(cJSON *it, cJSON **out) {
|
||||
/* record: [1]=dest, [2]=0(const) — no line/col suffix */
|
||||
if (!strcmp(op, "record")) { ADD(1); return c; }
|
||||
|
||||
/* array: [1]=dest, [2]=count(const), [3..]=elements (no line/col suffix) */
|
||||
/* array: [1]=dest, [2]=count(const) — elements added via separate push instrs */
|
||||
if (!strcmp(op, "array")) {
|
||||
ADD(1);
|
||||
int cnt = (int)cJSON_GetArrayItem(it, 2)->valuedouble;
|
||||
for (int j = 0; j < cnt; j++) ADD(3 + j);
|
||||
return c;
|
||||
}
|
||||
|
||||
@@ -2475,15 +2473,10 @@ static MachCode *mcode_lower_func(cJSON *fobj, const char *filename) {
|
||||
}
|
||||
/* Array/Object creation */
|
||||
else if (strcmp(op, "array") == 0) {
|
||||
int dest = A1, count = A2;
|
||||
EM(MACH_ABC(MACH_NEWARRAY, dest, 0, 0));
|
||||
for (int j = 0; j < count; j++) {
|
||||
int elem = ml_int(it, 3 + j);
|
||||
EM(MACH_ABC(MACH_PUSH, dest, elem, 0));
|
||||
}
|
||||
EM(MACH_ABC(MACH_NEWARRAY, A1, A2, 0));
|
||||
}
|
||||
else if (strcmp(op, "record") == 0) {
|
||||
EM(MACH_ABC(MACH_NEWRECORD, A1, 0, 0));
|
||||
EM(MACH_ABC(MACH_NEWRECORD, A1, A2, 0));
|
||||
}
|
||||
/* Push/Pop */
|
||||
else if (strcmp(op, "push") == 0) {
|
||||
|
||||
@@ -514,9 +514,11 @@ JSValue JS_NewObjectProtoClass (JSContext *ctx, JSValue proto, JSClassID class_i
|
||||
JSValue JS_NewObjectClass (JSContext *ctx, int class_id);
|
||||
JSValue JS_NewObjectProto (JSContext *ctx, JSValue proto);
|
||||
JSValue JS_NewObject (JSContext *ctx);
|
||||
JSValue JS_NewObjectCap (JSContext *ctx, uint32_t n);
|
||||
|
||||
JSValue JS_NewArray (JSContext *ctx);
|
||||
JSValue JS_NewArrayLen (JSContext *ctx, uint32_t len);
|
||||
JSValue JS_NewArrayCap (JSContext *ctx, uint32_t cap);
|
||||
JSValue JS_NewArrayFrom (JSContext *ctx, int count, JSValue *values);
|
||||
int JS_ArrayPush (JSContext *ctx, JSValue *arr_ptr, JSValue val);
|
||||
JSValue JS_ArrayPop (JSContext *ctx, JSValue obj);
|
||||
|
||||
@@ -2136,8 +2136,24 @@ static JSValue js_sub_string_val (JSContext *ctx, JSValue src, int start, int en
|
||||
return js_new_string8_len (ctx, buf, len);
|
||||
}
|
||||
|
||||
/* Heap string — fast path for short ASCII substrings (avoids heap alloc) */
|
||||
JSText *p = JS_VALUE_GET_STRING (src);
|
||||
if (len <= MIST_ASCII_MAX_LEN) {
|
||||
char buf[MIST_ASCII_MAX_LEN];
|
||||
int all_ascii = 1;
|
||||
for (int i = 0; i < len; i++) {
|
||||
uint32_t c = string_get (p, start + i);
|
||||
if (c >= 0x80) { all_ascii = 0; break; }
|
||||
buf[i] = (char)c;
|
||||
}
|
||||
if (all_ascii) {
|
||||
JSValue imm = MIST_TryNewImmediateASCII (buf, len);
|
||||
if (!JS_IsNull (imm)) return imm;
|
||||
}
|
||||
}
|
||||
|
||||
/* Heap string — delegate to existing js_sub_string */
|
||||
return js_sub_string (ctx, JS_VALUE_GET_STRING (src), start, end);
|
||||
return js_sub_string (ctx, p, start, end);
|
||||
}
|
||||
|
||||
/* Allocate a new pretext (mutable JSText) with initial capacity */
|
||||
@@ -2646,11 +2662,51 @@ JSValue JS_NewArrayLen (JSContext *ctx, uint32_t len) {
|
||||
|
||||
JSValue JS_NewArray (JSContext *ctx) { return JS_NewArrayLen (ctx, 0); }
|
||||
|
||||
/* Create array with pre-allocated capacity but len=0 (for push-fill patterns) */
|
||||
JSValue JS_NewArrayCap (JSContext *ctx, uint32_t cap) {
|
||||
if (cap == 0) cap = JS_ARRAY_INITIAL_SIZE;
|
||||
size_t values_size = sizeof (JSValue) * cap;
|
||||
size_t total_size = sizeof (JSArray) + values_size;
|
||||
JSArray *arr = js_malloc (ctx, total_size);
|
||||
if (!arr) return JS_EXCEPTION;
|
||||
arr->mist_hdr = objhdr_make (cap, OBJ_ARRAY, false, false, false, false);
|
||||
arr->len = 0;
|
||||
for (uint32_t i = 0; i < cap; i++)
|
||||
arr->values[i] = JS_NULL;
|
||||
return JS_MKPTR (arr);
|
||||
}
|
||||
|
||||
JSValue JS_NewObject (JSContext *ctx) {
|
||||
/* inline JS_NewObjectClass(ctx, JS_CLASS_OBJECT); */
|
||||
return JS_NewObjectProtoClass (ctx, ctx->class_proto[JS_CLASS_OBJECT], JS_CLASS_OBJECT);
|
||||
}
|
||||
|
||||
/* Create object with pre-allocated hash table for n properties */
|
||||
JSValue JS_NewObjectCap (JSContext *ctx, uint32_t n) {
|
||||
/* slot 0 is reserved, so need n+1 slots minimum.
|
||||
Hash table needs ~2x entries for good load factor.
|
||||
mask must be power-of-2 minus 1. */
|
||||
uint32_t need = (n + 1) * 2;
|
||||
uint32_t mask = JS_RECORD_INITIAL_MASK;
|
||||
while (mask + 1 < need) mask = (mask << 1) | 1;
|
||||
|
||||
JSGCRef proto_ref;
|
||||
JS_PushGCRef (ctx, &proto_ref);
|
||||
proto_ref.val = ctx->class_proto[JS_CLASS_OBJECT];
|
||||
|
||||
JSRecord *rec = js_new_record_class (ctx, mask, JS_CLASS_OBJECT);
|
||||
|
||||
JSValue proto_val = proto_ref.val;
|
||||
JS_PopGCRef (ctx, &proto_ref);
|
||||
|
||||
if (!rec) return JS_EXCEPTION;
|
||||
|
||||
if (JS_IsRecord (proto_val))
|
||||
rec->proto = proto_val;
|
||||
|
||||
return JS_MKPTR (rec);
|
||||
}
|
||||
|
||||
|
||||
/* Note: at least 'length' arguments will be readable in 'argv' */
|
||||
static JSValue JS_NewCFunction3 (JSContext *ctx, JSCFunction *func, const char *name, int length, JSCFunctionEnum cproto, int magic) {
|
||||
|
||||
Reference in New Issue
Block a user