1 Commits

Author SHA1 Message Date
John Alanbrook
dafcbaa4d4 add specific opcodes for number types 2025-06-24 10:10:08 -05:00
4 changed files with 120 additions and 31 deletions

View File

@@ -86,7 +86,7 @@ function offsetMomentum() {
} }
function advance(dt) { function advance(dt) {
var size = bodies.length; def size = bodies.length;
for (var i = 0; i < size; i++) { for (var i = 0; i < size; i++) {
var bodyi = bodies[i]; var bodyi = bodies[i];
@@ -148,7 +148,7 @@ function energy() {
return e; return e;
} }
var n = arg[0] || 100000 var n = arg[0] || 1000000
offsetMomentum(); offsetMomentum();
@@ -158,7 +158,10 @@ for (var i = 0; i < n; i++)
advance(0.01); advance(0.01);
log.console(energy().toFixed(9)) log.console(energy().toFixed(9))
var js = use('js') //var js = use('js')
//log.console(js.disassemble(advance))
/*
// Get function metadata // Get function metadata
var fn_info = js.fn_info(advance) var fn_info = js.fn_info(advance)
@@ -179,10 +182,11 @@ if (fn_info.locals && fn_info.locals.length > 0) {
} }
// Display stack size // Display stack size
log.console(` stack_size: ${fn_info.stack_size}`) //log.console(` stack_size: ${fn_info.stack_size}`)
// Display disassembly // Display disassembly
log.console(json.encode(js.disassemble(advance))) //log.console(json.encode(js.disassemble(advance)))
log.console(js.disassemble(advance).length) //log.console(js.disassemble(advance).length)
*/
$_.stop() $_.stop()

View File

@@ -207,10 +207,14 @@ DEF( delete, 1, 2, 1, none)
DEF( delete_var, 5, 0, 1, atom) DEF( delete_var, 5, 0, 1, atom)
DEF( mul, 1, 2, 1, none) DEF( mul, 1, 2, 1, none)
DEF( mul_float, 1, 2, 1, none)
DEF( div, 1, 2, 1, none) DEF( div, 1, 2, 1, none)
DEF( div_float, 1, 2, 1, none)
DEF( mod, 1, 2, 1, none) DEF( mod, 1, 2, 1, none)
DEF( add, 1, 2, 1, none) DEF( add, 1, 2, 1, none)
DEF( add_float, 1, 2, 1, none)
DEF( sub, 1, 2, 1, none) DEF( sub, 1, 2, 1, none)
DEF( sub_float, 1, 2, 1, none)
DEF( pow, 1, 2, 1, none) DEF( pow, 1, 2, 1, none)
DEF( shl, 1, 2, 1, none) DEF( shl, 1, 2, 1, none)
DEF( sar, 1, 2, 1, none) DEF( sar, 1, 2, 1, none)

View File

@@ -12401,6 +12401,13 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
#define CASE(op) case op #define CASE(op) case op
#define DEFAULT default #define DEFAULT default
#define BREAK break #define BREAK break
#define SWITCH_OPCODE(new_op, target_label) do { \
const uint8_t *instr_ptr = pc-1; \
uint8_t *bc = (uint8_t *)b->byte_code_buf; \
size_t instr_idx = instr_ptr - b->byte_code_buf; \
bc[instr_idx] = new_op; \
goto target_label; \
} while(0)
#else #else
static const void * const dispatch_table[256] = { static const void * const dispatch_table[256] = {
#define DEF(id, size, n_pop, n_push, f) && case_OP_ ## id, #define DEF(id, size, n_pop, n_push, f) && case_OP_ ## id,
@@ -12416,6 +12423,13 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
#define CASE(op) case_ ## op #define CASE(op) case_ ## op
#define DEFAULT case_default #define DEFAULT case_default
#define BREAK SWITCH(pc) #define BREAK SWITCH(pc)
#define SWITCH_OPCODE(new_op, target_label) do { \
const uint8_t *instr_ptr = pc-1; \
uint8_t *bc = (uint8_t *)b->byte_code_buf; \
size_t instr_idx = instr_ptr - b->byte_code_buf; \
bc[instr_idx] = new_op; \
goto target_label; \
} while(0)
#endif #endif
if (js_poll_interrupts(caller_ctx)) if (js_poll_interrupts(caller_ctx))
@@ -13971,36 +13985,29 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
CASE(OP_add): CASE(OP_add):
{ {
OPADD:
JSValue op1 = sp[-2], op2 = sp[-1], res; JSValue op1 = sp[-2], op2 = sp[-1], res;
int tag1 = JS_VALUE_GET_NORM_TAG(op1); int tag1 = JS_VALUE_GET_TAG(op1);
int tag2 = JS_VALUE_GET_NORM_TAG(op2); int tag2 = JS_VALUE_GET_TAG(op2);
/* 1) both ints? keep fast int path with overflow check */ if (likely((tag1 | tag2) == 0)) {
if (likely(JS_VALUE_IS_BOTH_INT(op1, op2))) { int64_t tmp1 = (int64_t)JS_VALUE_GET_INT(op1);
int64_t tmp = (int64_t)JS_VALUE_GET_INT(op1) int64_t tmp2 = (int64_t)JS_VALUE_GET_INT(op2);
+ JS_VALUE_GET_INT(op2); int64_t tmp = tmp1+tmp2;
if (likely((int)tmp == tmp)) { if (likely((int)tmp == tmp))
res = JS_NewInt32(ctx, (int)tmp); res = JS_NewInt32(ctx, (int)tmp);
} else { else
res = __JS_NewFloat64(ctx, (double)JS_VALUE_GET_INT(op1) + (double)JS_VALUE_GET_INT(op2)); res = __JS_NewFloat64(ctx, tmp1 + tmp2);
}
} }
/* 2) both floats? */ else if (JS_TAG_IS_FLOAT64(tag1) && JS_TAG_IS_FLOAT64(tag2)) {
else if (JS_VALUE_IS_BOTH_FLOAT(op1, op2)) { SWITCH_OPCODE(OP_add_float, CASE_OP_add_float_entry);
res = __JS_NewFloat64(ctx,
JS_VALUE_GET_FLOAT64(op1)
+ JS_VALUE_GET_FLOAT64(op2));
} }
/* 3) both strings? */ else if (JS_TAG_IS_STRING(tag1) && JS_TAG_IS_STRING(tag2)) {
else if (JS_IsString(op1) && JS_IsString(op2)) {
res = JS_ConcatString(ctx, op1, op2); res = JS_ConcatString(ctx, op1, op2);
if (JS_IsException(res)) if (JS_IsException(res))
goto exception; goto exception;
} }
/* 4) mixed int/float? promote to float */ else if (JS_TAG_IS_NUMBER(tag1) && JS_TAG_IS_NUMBER(tag2)) {
// TODO: Seems slow
else if ((tag1 == JS_TAG_INT && tag2 == JS_TAG_FLOAT64) ||
(tag1 == JS_TAG_FLOAT64 && tag2 == JS_TAG_INT)) {
double a, b; double a, b;
if(tag1 == JS_TAG_INT) if(tag1 == JS_TAG_INT)
a = (double)JS_VALUE_GET_INT(op1); a = (double)JS_VALUE_GET_INT(op1);
@@ -14021,6 +14028,20 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
sp--; sp--;
} }
BREAK; BREAK;
CASE(OP_add_float):
{
CASE_OP_add_float_entry:
JSValue op1 = sp[-2], op2 = sp[-1], res;
if (likely(JS_VALUE_IS_BOTH_FLOAT(op1,op2)))
res = __JS_NewFloat64(ctx, JS_VALUE_GET_FLOAT64(op1) + JS_VALUE_GET_FLOAT64(op2));
else {
SWITCH_OPCODE(OP_add, OPADD);
}
sp[-2] = res;
sp--;
}
BREAK;
CASE(OP_add_loc): CASE(OP_add_loc):
{ {
int idx = *pc++; int idx = *pc++;
@@ -14074,6 +14095,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
BREAK; BREAK;
CASE(OP_sub): CASE(OP_sub):
{ {
OPSUB:
JSValue op1, op2; JSValue op1, op2;
op1 = sp[-2]; op1 = sp[-2];
op2 = sp[-1]; op2 = sp[-1];
@@ -14085,9 +14107,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
sp[-2] = JS_NewInt32(ctx, r); sp[-2] = JS_NewInt32(ctx, r);
sp--; sp--;
} else if (JS_VALUE_IS_BOTH_FLOAT(op1, op2)) { } else if (JS_VALUE_IS_BOTH_FLOAT(op1, op2)) {
sp[-2] = __JS_NewFloat64(ctx, JS_VALUE_GET_FLOAT64(op1) - SWITCH_OPCODE(OP_sub_float, CASE_OP_sub_float_entry);
JS_VALUE_GET_FLOAT64(op2));
sp--;
} else { } else {
goto binary_arith_slow; goto binary_arith_slow;
} }
@@ -14095,6 +14115,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
BREAK; BREAK;
CASE(OP_mul): CASE(OP_mul):
{ {
OPMUL:
JSValue op1, op2; JSValue op1, op2;
double d; double d;
op1 = sp[-2]; op1 = sp[-2];
@@ -14117,7 +14138,21 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
sp[-2] = JS_NewInt32(ctx, r); sp[-2] = JS_NewInt32(ctx, r);
sp--; sp--;
} else if (JS_VALUE_IS_BOTH_FLOAT(op1, op2)) { } else if (JS_VALUE_IS_BOTH_FLOAT(op1, op2)) {
d = JS_VALUE_GET_FLOAT64(op1) * JS_VALUE_GET_FLOAT64(op2); SWITCH_OPCODE(OP_mul_float, CASE_OP_mul_float_entry);
} else if (JS_TAG_IS_FLOAT64(JS_VALUE_GET_TAG(op1)) ||
JS_TAG_IS_FLOAT64(JS_VALUE_GET_TAG(op2))) {
double a, b;
if (JS_VALUE_GET_TAG(op1) == JS_TAG_INT) {
a = JS_VALUE_GET_INT(op1);
} else {
a = JS_VALUE_GET_FLOAT64(op1);
}
if (JS_VALUE_GET_TAG(op2) == JS_TAG_INT) {
b = JS_VALUE_GET_INT(op2);
} else {
b = JS_VALUE_GET_FLOAT64(op2);
}
d = a * b;
mul_fp_res: mul_fp_res:
sp[-2] = __JS_NewFloat64(ctx, d); sp[-2] = __JS_NewFloat64(ctx, d);
sp--; sp--;
@@ -14126,8 +14161,35 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
} }
} }
BREAK; BREAK;
CASE(OP_mul_float):
{
CASE_OP_mul_float_entry:
JSValue op1 = sp[-2], op2 = sp[-1], res;
if (likely(JS_VALUE_IS_BOTH_FLOAT(op1,op2)))
res = __JS_NewFloat64(ctx, JS_VALUE_GET_FLOAT64(op1) * JS_VALUE_GET_FLOAT64(op2));
else {
SWITCH_OPCODE(OP_mul, OPMUL);
}
sp[-2] = res;
sp--;
}
BREAK;
CASE(OP_sub_float):
{
CASE_OP_sub_float_entry:
JSValue op1 = sp[-2], op2 = sp[-1], res;
if (likely(JS_VALUE_IS_BOTH_FLOAT(op1,op2)))
res = __JS_NewFloat64(ctx, JS_VALUE_GET_FLOAT64(op1) - JS_VALUE_GET_FLOAT64(op2));
else {
SWITCH_OPCODE(OP_sub, OPSUB);
}
sp[-2] = res;
sp--;
}
BREAK;
CASE(OP_div): CASE(OP_div):
{ {
OPDIV:
JSValue op1, op2; JSValue op1, op2;
op1 = sp[-2]; op1 = sp[-2];
op2 = sp[-1]; op2 = sp[-1];
@@ -14137,11 +14199,26 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
v2 = JS_VALUE_GET_INT(op2); v2 = JS_VALUE_GET_INT(op2);
sp[-2] = JS_NewFloat64(ctx, (double)v1 / (double)v2); sp[-2] = JS_NewFloat64(ctx, (double)v1 / (double)v2);
sp--; sp--;
} else if (JS_VALUE_IS_BOTH_FLOAT(op1, op2)) {
SWITCH_OPCODE(OP_div_float, CASE_OP_div_float_entry);
} else { } else {
goto binary_arith_slow; goto binary_arith_slow;
} }
} }
BREAK; BREAK;
CASE(OP_div_float):
{
CASE_OP_div_float_entry:
JSValue op1 = sp[-2], op2 = sp[-1], res;
if (likely(JS_VALUE_IS_BOTH_FLOAT(op1,op2)))
res = __JS_NewFloat64(ctx, JS_VALUE_GET_FLOAT64(op1) / JS_VALUE_GET_FLOAT64(op2));
else {
SWITCH_OPCODE(OP_div, OPDIV);
}
sp[-2] = res;
sp--;
}
BREAK;
CASE(OP_mod): CASE(OP_mod):
{ {
JSValue op1, op2; JSValue op1, op2;

View File

@@ -263,6 +263,10 @@ static inline JS_BOOL JS_VALUE_IS_NAN(JSValue v)
#define JS_VALUE_IS_BOTH_INT(v1, v2) ((JS_VALUE_GET_TAG(v1) | JS_VALUE_GET_TAG(v2)) == 0) #define JS_VALUE_IS_BOTH_INT(v1, v2) ((JS_VALUE_GET_TAG(v1) | JS_VALUE_GET_TAG(v2)) == 0)
#define JS_VALUE_IS_BOTH_FLOAT(v1, v2) (JS_TAG_IS_FLOAT64(JS_VALUE_GET_TAG(v1)) && JS_TAG_IS_FLOAT64(JS_VALUE_GET_TAG(v2))) #define JS_VALUE_IS_BOTH_FLOAT(v1, v2) (JS_TAG_IS_FLOAT64(JS_VALUE_GET_TAG(v1)) && JS_TAG_IS_FLOAT64(JS_VALUE_GET_TAG(v2)))
#define JS_TAG_IS_STRING(v1) (v1 == JS_TAG_STRING || v1 == JS_TAG_STRING_ROPE)
#define JS_TAG_IS_NUMBER(v1) (JS_TAG_IS_FLOAT64(v1) || v1 == JS_TAG_INT)
#define JS_VALUE_HAS_REF_COUNT(v) ((unsigned)JS_VALUE_GET_TAG(v) >= (unsigned)JS_TAG_FIRST) #define JS_VALUE_HAS_REF_COUNT(v) ((unsigned)JS_VALUE_GET_TAG(v) >= (unsigned)JS_TAG_FIRST)
/* special values */ /* special values */