lower ops directly
This commit is contained in:
181
source/mach.c
181
source/mach.c
@@ -547,7 +547,7 @@ static JSValue reg_vm_binop(JSContext *ctx, int op, JSValue a, JSValue b) {
|
||||
return JS_NewFloat64(ctx, (double)ia / (double)ib);
|
||||
case MACH_MOD:
|
||||
if (ib == 0) return JS_NULL;
|
||||
return JS_NewInt32(ctx, ia % ib);
|
||||
return JS_NewFloat64(ctx, (double)ia - ((double)ib * floor((double)ia / (double)ib)));
|
||||
case MACH_EQ:
|
||||
return JS_NewBool(ctx, ia == ib);
|
||||
case MACH_NEQ:
|
||||
@@ -673,8 +673,9 @@ static JSValue reg_vm_binop(JSContext *ctx, int op, JSValue a, JSValue b) {
|
||||
}
|
||||
case MACH_MOD: {
|
||||
if (db == 0.0) return JS_NULL;
|
||||
double r = fmod(da, db);
|
||||
if (!isfinite(r)) return JS_NULL;
|
||||
if (isnan(da) || isnan(db)) return JS_NULL;
|
||||
if (da == 0.0) return JS_NewFloat64(ctx, 0.0);
|
||||
double r = da - (db * floor(da / db));
|
||||
return JS_NewFloat64(ctx, r);
|
||||
}
|
||||
case MACH_POW: {
|
||||
@@ -704,6 +705,34 @@ static JSValue reg_vm_binop(JSContext *ctx, int op, JSValue a, JSValue b) {
|
||||
return JS_RaiseDisrupt(ctx, "type mismatch in binary operation");
|
||||
}
|
||||
|
||||
static inline int mach_get_number(JSValue v, double *out) {
|
||||
uint32_t tag = JS_VALUE_GET_TAG(v);
|
||||
if (tag == JS_TAG_INT) {
|
||||
*out = (double)JS_VALUE_GET_INT(v);
|
||||
return 0;
|
||||
}
|
||||
if (JS_TAG_IS_FLOAT64(tag)) {
|
||||
*out = JS_VALUE_GET_FLOAT64(v);
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int mach_get_place(JSContext *ctx, JSValue v, int32_t *out) {
|
||||
uint32_t tag = JS_VALUE_GET_NORM_TAG(v);
|
||||
if (tag == JS_TAG_INT || tag == JS_TAG_BOOL || tag == JS_TAG_NULL || tag == JS_TAG_FLOAT64) {
|
||||
return JS_ToInt32(ctx, out, v);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline double mach_apply_place(double d, int32_t place, double (*f)(double)) {
|
||||
if (place == 0)
|
||||
return f(d);
|
||||
double mult = pow(10.0, -(double)place);
|
||||
return f(d * mult) / mult;
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAVE_ASAN
|
||||
void __asan_on_error(void) {
|
||||
@@ -856,6 +885,12 @@ vm_dispatch:
|
||||
DT(MACH_MUL), DT(MACH_DIV),
|
||||
DT(MACH_MOD), DT(MACH_POW),
|
||||
DT(MACH_NEG),
|
||||
DT(MACH_REMAINDER), DT(MACH_MAX),
|
||||
DT(MACH_MIN), DT(MACH_ABS),
|
||||
DT(MACH_SIGN), DT(MACH_FRACTION),
|
||||
DT(MACH_INTEGER), DT(MACH_FLOOR),
|
||||
DT(MACH_CEILING), DT(MACH_ROUND),
|
||||
DT(MACH_TRUNC),
|
||||
DT(MACH_EQ), DT(MACH_NEQ),
|
||||
DT(MACH_LT), DT(MACH_LE),
|
||||
DT(MACH_GT), DT(MACH_GE),
|
||||
@@ -1043,17 +1078,15 @@ vm_dispatch:
|
||||
}
|
||||
VM_CASE(MACH_MOD): {
|
||||
JSValue left = frame->slots[b], right = frame->slots[c];
|
||||
if (JS_VALUE_IS_BOTH_INT(left, right)) {
|
||||
int32_t ib = JS_VALUE_GET_INT(right);
|
||||
frame->slots[a] = (ib != 0) ? JS_NewInt32(ctx, JS_VALUE_GET_INT(left) % ib) : JS_NULL;
|
||||
double da, db;
|
||||
if (mach_get_number(left, &da) != 0 || mach_get_number(right, &db) != 0 || db == 0.0 ||
|
||||
isnan(da) || isnan(db)) {
|
||||
frame->slots[a] = JS_NULL;
|
||||
} else {
|
||||
double da, db, r;
|
||||
JS_ToFloat64(ctx, &da, left);
|
||||
JS_ToFloat64(ctx, &db, right);
|
||||
if (db == 0.0) { frame->slots[a] = JS_NULL; }
|
||||
else {
|
||||
r = fmod(da, db);
|
||||
frame->slots[a] = !isfinite(r) ? JS_NULL : JS_NewFloat64(ctx, r);
|
||||
if (da == 0.0) {
|
||||
frame->slots[a] = JS_NewFloat64(ctx, 0.0);
|
||||
} else {
|
||||
frame->slots[a] = JS_NewFloat64(ctx, da - (db * floor(da / db)));
|
||||
}
|
||||
}
|
||||
VM_BREAK();
|
||||
@@ -1077,6 +1110,116 @@ vm_dispatch:
|
||||
VM_BREAK();
|
||||
}
|
||||
|
||||
VM_CASE(MACH_REMAINDER): {
|
||||
JSValue left = frame->slots[b], right = frame->slots[c];
|
||||
double da, db;
|
||||
if (mach_get_number(left, &da) != 0 || mach_get_number(right, &db) != 0 || db == 0.0) {
|
||||
frame->slots[a] = JS_NULL;
|
||||
} else {
|
||||
frame->slots[a] = JS_NewFloat64(ctx, da - (trunc(da / db) * db));
|
||||
}
|
||||
VM_BREAK();
|
||||
}
|
||||
|
||||
VM_CASE(MACH_MAX): {
|
||||
JSValue left = frame->slots[b], right = frame->slots[c];
|
||||
double da, db;
|
||||
if (mach_get_number(left, &da) != 0 || mach_get_number(right, &db) != 0) {
|
||||
frame->slots[a] = JS_NULL;
|
||||
} else {
|
||||
frame->slots[a] = JS_NewFloat64(ctx, da > db ? da : db);
|
||||
}
|
||||
VM_BREAK();
|
||||
}
|
||||
|
||||
VM_CASE(MACH_MIN): {
|
||||
JSValue left = frame->slots[b], right = frame->slots[c];
|
||||
double da, db;
|
||||
if (mach_get_number(left, &da) != 0 || mach_get_number(right, &db) != 0) {
|
||||
frame->slots[a] = JS_NULL;
|
||||
} else {
|
||||
frame->slots[a] = JS_NewFloat64(ctx, da < db ? da : db);
|
||||
}
|
||||
VM_BREAK();
|
||||
}
|
||||
|
||||
VM_CASE(MACH_ABS): {
|
||||
JSValue v = frame->slots[b];
|
||||
double d;
|
||||
if (mach_get_number(v, &d) != 0) {
|
||||
frame->slots[a] = JS_NULL;
|
||||
} else {
|
||||
frame->slots[a] = JS_NewFloat64(ctx, fabs(d));
|
||||
}
|
||||
VM_BREAK();
|
||||
}
|
||||
|
||||
VM_CASE(MACH_SIGN): {
|
||||
JSValue v = frame->slots[b];
|
||||
double d;
|
||||
if (mach_get_number(v, &d) != 0) {
|
||||
frame->slots[a] = JS_NULL;
|
||||
} else if (d < 0) {
|
||||
frame->slots[a] = JS_NewInt32(ctx, -1);
|
||||
} else if (d > 0) {
|
||||
frame->slots[a] = JS_NewInt32(ctx, 1);
|
||||
} else {
|
||||
frame->slots[a] = JS_NewInt32(ctx, 0);
|
||||
}
|
||||
VM_BREAK();
|
||||
}
|
||||
|
||||
VM_CASE(MACH_FRACTION): {
|
||||
JSValue v = frame->slots[b];
|
||||
double d;
|
||||
if (mach_get_number(v, &d) != 0) {
|
||||
frame->slots[a] = JS_NULL;
|
||||
} else {
|
||||
frame->slots[a] = JS_NewFloat64(ctx, d - trunc(d));
|
||||
}
|
||||
VM_BREAK();
|
||||
}
|
||||
|
||||
VM_CASE(MACH_INTEGER): {
|
||||
JSValue v = frame->slots[b];
|
||||
double d;
|
||||
if (mach_get_number(v, &d) != 0) {
|
||||
frame->slots[a] = JS_NULL;
|
||||
} else {
|
||||
frame->slots[a] = JS_NewFloat64(ctx, trunc(d));
|
||||
}
|
||||
VM_BREAK();
|
||||
}
|
||||
|
||||
VM_CASE(MACH_FLOOR):
|
||||
VM_CASE(MACH_CEILING):
|
||||
VM_CASE(MACH_ROUND):
|
||||
VM_CASE(MACH_TRUNC): {
|
||||
JSValue v = frame->slots[b];
|
||||
JSValue pval = frame->slots[c];
|
||||
double d, r;
|
||||
int32_t place = 0;
|
||||
if (mach_get_number(v, &d) != 0) {
|
||||
frame->slots[a] = JS_NULL;
|
||||
VM_BREAK();
|
||||
}
|
||||
if (!JS_IsNull(pval) && mach_get_place(ctx, pval, &place) != 0) {
|
||||
frame->slots[a] = JS_NULL;
|
||||
VM_BREAK();
|
||||
}
|
||||
if (op == MACH_FLOOR) {
|
||||
r = mach_apply_place(d, place, floor);
|
||||
} else if (op == MACH_CEILING) {
|
||||
r = mach_apply_place(d, place, ceil);
|
||||
} else if (op == MACH_ROUND) {
|
||||
r = mach_apply_place(d, place, round);
|
||||
} else {
|
||||
r = mach_apply_place(d, place, trunc);
|
||||
}
|
||||
frame->slots[a] = JS_NewFloat64(ctx, r);
|
||||
VM_BREAK();
|
||||
}
|
||||
|
||||
/* Comparison — inline integer fast paths */
|
||||
VM_CASE(MACH_EQ): {
|
||||
JSValue left = frame->slots[b], right = frame->slots[c];
|
||||
@@ -2403,6 +2546,17 @@ static MachCode *mcode_lower_func(cJSON *fobj, const char *filename) {
|
||||
else if (strcmp(op, "modulo") == 0) { ABC3(MACH_MOD); }
|
||||
else if (strcmp(op, "pow") == 0) { ABC3(MACH_POW); }
|
||||
else if (strcmp(op, "negate") == 0) { AB2(MACH_NEG); }
|
||||
else if (strcmp(op, "remainder") == 0) { ABC3(MACH_REMAINDER); }
|
||||
else if (strcmp(op, "max") == 0) { ABC3(MACH_MAX); }
|
||||
else if (strcmp(op, "min") == 0) { ABC3(MACH_MIN); }
|
||||
else if (strcmp(op, "abs") == 0) { AB2(MACH_ABS); }
|
||||
else if (strcmp(op, "sign") == 0) { AB2(MACH_SIGN); }
|
||||
else if (strcmp(op, "fraction") == 0) { AB2(MACH_FRACTION); }
|
||||
else if (strcmp(op, "integer") == 0) { AB2(MACH_INTEGER); }
|
||||
else if (strcmp(op, "floor") == 0) { ABC3(MACH_FLOOR); }
|
||||
else if (strcmp(op, "ceiling") == 0) { ABC3(MACH_CEILING); }
|
||||
else if (strcmp(op, "round") == 0) { ABC3(MACH_ROUND); }
|
||||
else if (strcmp(op, "trunc") == 0) { ABC3(MACH_TRUNC); }
|
||||
/* Typed integer comparisons */
|
||||
else if (strcmp(op, "eq_int") == 0) { ABC3(MACH_EQ_INT); }
|
||||
else if (strcmp(op, "ne_int") == 0) { ABC3(MACH_NE_INT); }
|
||||
@@ -3107,4 +3261,3 @@ void JS_DumpMachBin(JSContext *ctx, const uint8_t *data, size_t size, JSValue en
|
||||
dump_register_code(ctx, code, 0);
|
||||
JS_PopGCRef(ctx, &env_ref);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user