Merge branch 'optimize_mcode'

This commit is contained in:
2026-02-21 03:38:34 -06:00
23 changed files with 51074 additions and 121790 deletions

View File

@@ -2910,6 +2910,84 @@ JSValue JS_ConcatString (JSContext *ctx, JSValue op1, JSValue op2) {
return ret_val;
}
/* Concat with over-allocated capacity and NO stoning.
Used by MACH_CONCAT self-assign (s = s + x) slow path so that
subsequent appends can reuse the excess capacity in-place. */
JSValue JS_ConcatStringGrow (JSContext *ctx, JSValue op1, JSValue op2) {
if (unlikely (!JS_IsText (op1))) {
JSGCRef op2_guard;
JS_PushGCRef (ctx, &op2_guard);
op2_guard.val = op2;
op1 = JS_ToString (ctx, op1);
op2 = op2_guard.val;
JS_PopGCRef (ctx, &op2_guard);
if (JS_IsException (op1)) return JS_EXCEPTION;
}
if (unlikely (!JS_IsText (op2))) {
JSGCRef op1_guard;
JS_PushGCRef (ctx, &op1_guard);
op1_guard.val = op1;
op2 = JS_ToString (ctx, op2);
op1 = op1_guard.val;
JS_PopGCRef (ctx, &op1_guard);
if (JS_IsException (op2)) return JS_EXCEPTION;
}
int len1 = js_string_value_len (op1);
int len2 = js_string_value_len (op2);
int new_len = len1 + len2;
/* Try immediate ASCII for short results */
if (new_len <= MIST_ASCII_MAX_LEN) {
char buf[8];
BOOL all_ascii = TRUE;
for (int i = 0; i < len1 && all_ascii; i++) {
uint32_t c = js_string_value_get (op1, i);
if (c >= 0x80) all_ascii = FALSE;
else buf[i] = (char)c;
}
for (int i = 0; i < len2 && all_ascii; i++) {
uint32_t c = js_string_value_get (op2, i);
if (c >= 0x80) all_ascii = FALSE;
else buf[len1 + i] = (char)c;
}
if (all_ascii) {
JSValue imm = MIST_TryNewImmediateASCII (buf, new_len);
if (!JS_IsNull (imm)) return imm;
}
}
/* Allocate with 2x growth factor, minimum 16 */
int capacity = new_len * 2;
if (capacity < 16) capacity = 16;
JSGCRef op1_ref, op2_ref;
JS_PushGCRef (ctx, &op1_ref);
op1_ref.val = op1;
JS_PushGCRef (ctx, &op2_ref);
op2_ref.val = op2;
JSText *p = js_alloc_string (ctx, capacity);
if (!p) {
JS_PopGCRef (ctx, &op2_ref);
JS_PopGCRef (ctx, &op1_ref);
return JS_EXCEPTION;
}
op1 = op1_ref.val;
op2 = op2_ref.val;
JS_PopGCRef (ctx, &op2_ref);
JS_PopGCRef (ctx, &op1_ref);
for (int i = 0; i < len1; i++)
string_put (p, i, js_string_value_get (op1, i));
for (int i = 0; i < len2; i++)
string_put (p, len1 + i, js_string_value_get (op2, i));
p->length = new_len;
/* Do NOT stone — leave mutable so in-place append can reuse capacity */
return JS_MKPTR (p);
}
/* WARNING: proto must be an object or JS_NULL */
JSValue JS_NewObjectProtoClass (JSContext *ctx, JSValue proto_val, JSClassID class_id) {
JSGCRef proto_ref;