Compare commits
2 Commits
024d796ca4
...
add_opt
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0bd752fc8c | ||
|
|
b64e35604a |
@@ -158,31 +158,4 @@ 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')
|
|
||||||
|
|
||||||
// Get function metadata
|
|
||||||
var fn_info = js.fn_info(advance)
|
|
||||||
log.console(`${fn_info.filename}:${fn_info.line}:${fn_info.column}: function: ${fn_info.name}`)
|
|
||||||
|
|
||||||
// Display arguments
|
|
||||||
if (fn_info.args && fn_info.args.length > 0) {
|
|
||||||
log.console(` args: ${fn_info.args.join(' ')}`)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Display local variables
|
|
||||||
if (fn_info.locals && fn_info.locals.length > 0) {
|
|
||||||
log.console(' locals:')
|
|
||||||
for (var i = 0; i < fn_info.locals.length; i++) {
|
|
||||||
var local = fn_info.locals[i]
|
|
||||||
log.console(` ${local.index}: ${local.type} ${local.name}`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Display stack size
|
|
||||||
log.console(` stack_size: ${fn_info.stack_size}`)
|
|
||||||
|
|
||||||
// Display disassembly
|
|
||||||
log.console(js.disassemble(advance))
|
|
||||||
log.console(js.disassemble(advance).length)
|
|
||||||
|
|
||||||
$stop()
|
$stop()
|
||||||
@@ -210,6 +210,10 @@ DEF( mul, 1, 2, 1, none)
|
|||||||
DEF( div, 1, 2, 1, none)
|
DEF( div, 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_int, 1, 2, 1, none)
|
||||||
|
DEF( add_float, 1, 2, 1, none)
|
||||||
|
DEF( add_string, 1, 2, 1, none)
|
||||||
|
DEF( add_nullnum, 1, 2, 1, none)
|
||||||
DEF( sub, 1, 2, 1, none)
|
DEF( sub, 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)
|
||||||
|
|||||||
186
source/quickjs.c
186
source/quickjs.c
@@ -6780,7 +6780,7 @@ JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj,
|
|||||||
if (unlikely(tag != JS_TAG_OBJECT)) {
|
if (unlikely(tag != JS_TAG_OBJECT)) {
|
||||||
switch(tag) {
|
switch(tag) {
|
||||||
case JS_TAG_NULL:
|
case JS_TAG_NULL:
|
||||||
return JS_ThrowTypeErrorAtom(ctx, "cannot read property '%s' of null", prop);
|
return JS_NULL;
|
||||||
case JS_TAG_EXCEPTION:
|
case JS_TAG_EXCEPTION:
|
||||||
return JS_EXCEPTION;
|
return JS_EXCEPTION;
|
||||||
case JS_TAG_STRING:
|
case JS_TAG_STRING:
|
||||||
@@ -12670,6 +12670,18 @@ 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 PATCH_OPCODE(new_op) do { \
|
||||||
|
const uint8_t *instr_ptr = pc - 1; \
|
||||||
|
uint8_t *bc = (uint8_t *)b->byte_code_buf; \
|
||||||
|
size_t instr_idx = (size_t)(instr_ptr - b->byte_code_buf); \
|
||||||
|
bc[instr_idx] = (new_op); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define SWITCH_OPCODE(new_op, target_label) do { \
|
||||||
|
PATCH_OPCODE(new_op); \
|
||||||
|
goto target_label; \
|
||||||
|
} while (0)
|
||||||
|
#define DEOPT(target_label) goto target_label
|
||||||
#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,
|
||||||
@@ -12685,6 +12697,18 @@ 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 PATCH_OPCODE(new_op) do { \
|
||||||
|
const uint8_t *instr_ptr = pc - 1; \
|
||||||
|
uint8_t *bc = (uint8_t *)b->byte_code_buf; \
|
||||||
|
size_t instr_idx = (size_t)(instr_ptr - b->byte_code_buf); \
|
||||||
|
bc[instr_idx] = (new_op); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define SWITCH_OPCODE(new_op, target_label) do { \
|
||||||
|
PATCH_OPCODE(new_op); \
|
||||||
|
goto target_label; \
|
||||||
|
} while (0)
|
||||||
|
#define DEOPT(target_label) goto target_label
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (js_poll_interrupts(caller_ctx))
|
if (js_poll_interrupts(caller_ctx))
|
||||||
@@ -14275,58 +14299,120 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
|
|||||||
goto exception;
|
goto exception;
|
||||||
}
|
}
|
||||||
BREAK;
|
BREAK;
|
||||||
|
CASE(OP_add): {
|
||||||
|
OPADD:
|
||||||
|
JSValue op1 = sp[-2], op2 = sp[-1], res;
|
||||||
|
int tag1 = JS_VALUE_GET_TAG(op1);
|
||||||
|
int tag2 = JS_VALUE_GET_TAG(op2);
|
||||||
|
|
||||||
CASE(OP_add):
|
if (tag1 == JS_TAG_NULL || tag2 == JS_TAG_NULL) {
|
||||||
{
|
int other = (tag1 == JS_TAG_NULL) ? tag2 : tag1;
|
||||||
JSValue op1 = sp[-2], op2 = sp[-1], res;
|
if (JS_TAG_IS_NUMBER(other) || other == JS_TAG_NULL) {
|
||||||
int tag1 = JS_VALUE_GET_NORM_TAG(op1);
|
PATCH_OPCODE(OP_add_nullnum);
|
||||||
int tag2 = JS_VALUE_GET_NORM_TAG(op2);
|
res = JS_NULL;
|
||||||
|
|
||||||
/* 1) both ints? keep fast int path with overflow check */
|
|
||||||
if (likely(JS_VALUE_IS_BOTH_INT(op1, op2))) {
|
|
||||||
int64_t tmp = (int64_t)JS_VALUE_GET_INT(op1)
|
|
||||||
+ JS_VALUE_GET_INT(op2);
|
|
||||||
if (likely((int)tmp == tmp)) {
|
|
||||||
res = JS_NewInt32(ctx, (int)tmp);
|
|
||||||
} else {
|
|
||||||
res = __JS_NewFloat64(ctx, (double)JS_VALUE_GET_INT(op1) + (double)JS_VALUE_GET_INT(op2));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* 2) both floats? */
|
|
||||||
else if (JS_VALUE_IS_BOTH_FLOAT(op1, op2)) {
|
|
||||||
res = __JS_NewFloat64(ctx,
|
|
||||||
JS_VALUE_GET_FLOAT64(op1)
|
|
||||||
+ JS_VALUE_GET_FLOAT64(op2));
|
|
||||||
}
|
|
||||||
/* 3) both strings? */
|
|
||||||
else if (JS_IsString(op1) && JS_IsString(op2)) {
|
|
||||||
res = JS_ConcatString(ctx, op1, op2);
|
|
||||||
if (JS_IsException(res))
|
|
||||||
goto exception;
|
|
||||||
}
|
|
||||||
/* 4) mixed int/float? promote to float */
|
|
||||||
// TODO: Seems slow
|
|
||||||
else if ((tag1 == JS_TAG_INT && tag2 == JS_TAG_FLOAT64) ||
|
|
||||||
(tag1 == JS_TAG_FLOAT64 && tag2 == JS_TAG_INT)) {
|
|
||||||
double a, b;
|
|
||||||
if(tag1 == JS_TAG_INT)
|
|
||||||
a = (double)JS_VALUE_GET_INT(op1);
|
|
||||||
else
|
|
||||||
a = JS_VALUE_GET_FLOAT64(op1);
|
|
||||||
if(tag2 == JS_TAG_INT)
|
|
||||||
b = (double)JS_VALUE_GET_INT(op2);
|
|
||||||
else
|
|
||||||
b = JS_VALUE_GET_FLOAT64(op2);
|
|
||||||
res = __JS_NewFloat64(ctx, a + b);
|
|
||||||
}
|
|
||||||
/* 5) anything else → throw */
|
|
||||||
else {
|
|
||||||
JS_ThrowTypeError(ctx, "cannot concatenate with string");
|
|
||||||
goto exception;
|
|
||||||
}
|
|
||||||
|
|
||||||
sp[-2] = res;
|
sp[-2] = res;
|
||||||
sp--;
|
sp--;
|
||||||
|
BREAK;
|
||||||
|
}
|
||||||
|
goto add_type_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tag1 == JS_TAG_STRING || tag2 == JS_TAG_STRING) {
|
||||||
|
if (tag1 == JS_TAG_STRING && tag2 == JS_TAG_STRING) {
|
||||||
|
PATCH_OPCODE(OP_add_string);
|
||||||
|
res = JS_ConcatString(ctx, op1, op2);
|
||||||
|
if (JS_IsException(res)) goto exception;
|
||||||
|
sp[-2] = res;
|
||||||
|
sp--;
|
||||||
|
BREAK;
|
||||||
|
}
|
||||||
|
goto add_type_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (likely((tag1 | tag2) == 0)) {
|
||||||
|
int64_t tmp = (int64_t)JS_VALUE_GET_INT(op1) + (int64_t)JS_VALUE_GET_INT(op2);
|
||||||
|
if (likely((int32_t)tmp == tmp)) {
|
||||||
|
PATCH_OPCODE(OP_add_int);
|
||||||
|
res = JS_NewInt32(ctx, (int32_t)tmp);
|
||||||
|
} else {
|
||||||
|
res = __JS_NewFloat64(ctx, (double)tmp);
|
||||||
|
}
|
||||||
|
sp[-2] = res;
|
||||||
|
sp--;
|
||||||
|
BREAK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (JS_TAG_IS_NUMBER(tag1) && JS_TAG_IS_NUMBER(tag2)) {
|
||||||
|
PATCH_OPCODE(OP_add_float);
|
||||||
|
res = __JS_NewFloat64(ctx, JS_VALUE_GET_FLOAT64(op1) + JS_VALUE_GET_FLOAT64(op2));
|
||||||
|
sp[-2] = res;
|
||||||
|
sp--;
|
||||||
|
BREAK;
|
||||||
|
}
|
||||||
|
|
||||||
|
add_type_error:
|
||||||
|
/* throw your “illegal +” error */
|
||||||
|
goto exception;
|
||||||
|
}
|
||||||
|
CASE(OP_add_int):
|
||||||
|
{
|
||||||
|
CASE_OP_add_int_entry:
|
||||||
|
JSValue op1 = sp[-2], op2 = sp[-1];
|
||||||
|
|
||||||
|
if (likely((JS_VALUE_GET_TAG(op1) | JS_VALUE_GET_TAG(op2)) == 0)) {
|
||||||
|
int64_t tmp = (int64_t)JS_VALUE_GET_INT(op1) + (int64_t)JS_VALUE_GET_INT(op2);
|
||||||
|
if (likely((int32_t)tmp == tmp)) {
|
||||||
|
sp[-2] = JS_NewInt32(ctx, (int32_t)tmp);
|
||||||
|
sp--;
|
||||||
|
} else {
|
||||||
|
DEOPT(OPADD);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
DEOPT(OPADD);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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));
|
||||||
|
sp[-2] = res;
|
||||||
|
sp--;
|
||||||
|
} else {
|
||||||
|
DEOPT(OPADD);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BREAK;
|
||||||
|
CASE(OP_add_string): {
|
||||||
|
CASE_OP_add_string_entry:
|
||||||
|
JSValue op1 = sp[-2], op2 = sp[-1], res;
|
||||||
|
int t1 = JS_VALUE_GET_TAG(op1), t2 = JS_VALUE_GET_TAG(op2);
|
||||||
|
|
||||||
|
if (likely(t1 == JS_TAG_STRING && t2 == JS_TAG_STRING)) {
|
||||||
|
res = JS_ConcatString(ctx, op1, op2);
|
||||||
|
if (JS_IsException(res)) goto exception;
|
||||||
|
sp[-2] = res;
|
||||||
|
sp--;
|
||||||
|
} else {
|
||||||
|
DEOPT(OPADD);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BREAK;
|
||||||
|
CASE(OP_add_nullnum): {
|
||||||
|
CASE_OP_add_nullnum_entry:
|
||||||
|
JSValue op1 = sp[-2], op2 = sp[-1];
|
||||||
|
int t1 = JS_VALUE_GET_TAG(op1), t2 = JS_VALUE_GET_TAG(op2);
|
||||||
|
|
||||||
|
if ((t1 == JS_TAG_NULL && (JS_TAG_IS_NUMBER(t2) || t2 == JS_TAG_NULL)) ||
|
||||||
|
(t2 == JS_TAG_NULL && (JS_TAG_IS_NUMBER(t1) || t1 == JS_TAG_NULL))) {
|
||||||
|
sp[-2] = JS_NULL;
|
||||||
|
sp--;
|
||||||
|
} else {
|
||||||
|
DEOPT(OPADD);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
BREAK;
|
BREAK;
|
||||||
CASE(OP_add_loc):
|
CASE(OP_add_loc):
|
||||||
|
|||||||
@@ -262,7 +262,8 @@ 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 */
|
||||||
|
|||||||
@@ -165,6 +165,7 @@ return {
|
|||||||
if (!caught) throw "string + null should throw"
|
if (!caught) throw "string + null should throw"
|
||||||
},
|
},
|
||||||
|
|
||||||
|
<<<<<<< Updated upstream
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// COMPARISON OPERATORS
|
// COMPARISON OPERATORS
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -1530,4 +1531,16 @@ return {
|
|||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
=======
|
||||||
|
test_string_plus_string_works: function() {
|
||||||
|
var x = "hello" + " world"
|
||||||
|
if (x != "hello world") throw "string + string should work"
|
||||||
|
},
|
||||||
|
|
||||||
|
null_access: function() {
|
||||||
|
var val = {}
|
||||||
|
var nn = val.a
|
||||||
|
if (nn != null) throw "val.a should return null"
|
||||||
|
},
|
||||||
|
>>>>>>> Stashed changes
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user