mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Introduce asInt and asDouble to check for the type of values based on the actual value since some 32-bit integers hide out in doubles.
This commit is contained in:
parent
cef5e9becc
commit
2df2214a9e
@ -45,6 +45,8 @@
|
||||
#include "jscntxt.h"
|
||||
#include "jsscript.h"
|
||||
#include "jsprf.h"
|
||||
#include "jsinterp.h"
|
||||
#include "jsscope.h"
|
||||
|
||||
using namespace avmplus;
|
||||
using namespace nanojit;
|
||||
@ -331,6 +333,24 @@ static inline int getType(jsval v)
|
||||
return JSVAL_TAG(v);
|
||||
}
|
||||
|
||||
static inline bool isInt(jsval v)
|
||||
{
|
||||
return getType(v) == JSVAL_INT;
|
||||
}
|
||||
|
||||
static inline bool isDouble(jsval v)
|
||||
{
|
||||
return (getType(v) == JSVAL_DOUBLE) && !isInt(v);
|
||||
}
|
||||
|
||||
static inline jsint asInt(jsval v)
|
||||
{
|
||||
JS_ASSERT(isInt(v));
|
||||
if (JSVAL_IS_DOUBLE(v))
|
||||
return js_DoubleToECMAInt32(*JSVAL_TO_DOUBLE(v));
|
||||
return JSVAL_TO_INT(v);
|
||||
}
|
||||
|
||||
/* Write out a type map for the current scopes and all outer scopes,
|
||||
up until the entry scope. */
|
||||
static void
|
||||
@ -376,10 +396,7 @@ unbox_jsval(jsval v, int t, double* slot)
|
||||
*(bool*)slot = JSVAL_TO_BOOLEAN(v);
|
||||
break;
|
||||
case JSVAL_INT:
|
||||
if (JSVAL_IS_DOUBLE(v))
|
||||
*(jsint*)slot = js_DoubleToECMAInt32(*JSVAL_TO_DOUBLE(v));
|
||||
else
|
||||
*(jsint*)slot = JSVAL_TO_INT(v);
|
||||
*(jsint*)slot = asInt(v);
|
||||
break;
|
||||
case JSVAL_DOUBLE:
|
||||
*(jsdouble*)slot = *JSVAL_TO_DOUBLE(v);
|
||||
@ -465,7 +482,7 @@ void
|
||||
TraceRecorder::import(jsval* p, char *prefix, int index)
|
||||
{
|
||||
JS_ASSERT(onFrame(p));
|
||||
LIns *ins = lir->insLoad(JSVAL_IS_DOUBLE(*p) ? LIR_ldq : LIR_ld,
|
||||
LIns *ins = lir->insLoad(isDouble(*p) ? LIR_ldq : LIR_ld,
|
||||
fragment->sp, -fragmentInfo->nativeStackBase + nativeFrameOffset(p) + 8);
|
||||
tracker.set(p, ins);
|
||||
#ifdef DEBUG
|
||||
@ -684,7 +701,7 @@ TraceRecorder::stack(int n, LIns* i)
|
||||
bool
|
||||
TraceRecorder::inc(jsval& v, jsint incr, bool pre)
|
||||
{
|
||||
if (JSVAL_IS_INT(v)) {
|
||||
if (isInt(v)) {
|
||||
LIns* before = get(&v);
|
||||
LIns* after = lir->ins2i(LIR_add, before, incr);
|
||||
guard(false, lir->ins1(LIR_ov, after));
|
||||
@ -700,27 +717,27 @@ TraceRecorder::cmp(LOpcode op, bool negate)
|
||||
{
|
||||
jsval& r = stackval(-1);
|
||||
jsval& l = stackval(-2);
|
||||
if (JSVAL_IS_INT(l) && JSVAL_IS_INT(r)) {
|
||||
if (isInt(l) && isInt(r)) {
|
||||
LIns* x = lir->ins2(op, get(&l), get(&r));
|
||||
if (negate)
|
||||
x = lir->ins2i(LIR_eq, x, 0);
|
||||
bool cond;
|
||||
switch (op) {
|
||||
case LIR_lt:
|
||||
cond = JSVAL_TO_INT(l) < JSVAL_TO_INT(r);
|
||||
cond = asInt(l) < asInt(r);
|
||||
break;
|
||||
case LIR_gt:
|
||||
cond = JSVAL_TO_INT(l) > JSVAL_TO_INT(r);
|
||||
cond = asInt(l) > asInt(r);
|
||||
break;
|
||||
case LIR_le:
|
||||
cond = JSVAL_TO_INT(l) <= JSVAL_TO_INT(r);
|
||||
cond = asInt(l) <= asInt(r);
|
||||
break;
|
||||
case LIR_ge:
|
||||
cond = JSVAL_TO_INT(l) >= JSVAL_TO_INT(r);
|
||||
cond = asInt(l) >= asInt(r);
|
||||
break;
|
||||
default:
|
||||
JS_ASSERT(cond == LIR_eq);
|
||||
cond = JSVAL_TO_INT(l) == JSVAL_TO_INT(r);
|
||||
cond = asInt(l) == asInt(r);
|
||||
break;
|
||||
}
|
||||
/* The interpreter fuses comparisons and the following branch,
|
||||
@ -745,7 +762,7 @@ TraceRecorder::ibinary(LOpcode op, bool ov)
|
||||
{
|
||||
jsval& r = stackval(-1);
|
||||
jsval& l = stackval(-2);
|
||||
if (JSVAL_IS_INT(l) && JSVAL_IS_INT(r)) {
|
||||
if (isInt(l) && isInt(r)) {
|
||||
LIns* result = lir->ins2(op, get(&l), get(&r));
|
||||
if (ov)
|
||||
guard(false, lir->ins1(LIR_ov, result));
|
||||
@ -755,6 +772,22 @@ TraceRecorder::ibinary(LOpcode op, bool ov)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
TraceRecorder::map_is_native(JSObjectMap* map, LIns* map_ins)
|
||||
{
|
||||
LIns* ops = lir->insLoadi(map_ins, offsetof(JSObjectMap, ops));
|
||||
if (map->ops == &js_ObjectOps) {
|
||||
guard(true, lir->ins2i(LIR_eq, ops, (long)&js_ObjectOps));
|
||||
return true;
|
||||
}
|
||||
LIns* n = lir->insLoadi(ops, offsetof(JSObjectOps, newObjectMap));
|
||||
if (map->ops->newObjectMap == js_ObjectOps.newObjectMap) {
|
||||
guard(true, lir->ins2i(LIR_eq, n, (long)js_ObjectOps.newObjectMap));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TraceRecorder::JSOP_INTERRUPT()
|
||||
{
|
||||
return false;
|
||||
@ -1194,8 +1227,12 @@ bool TraceRecorder::JSOP_POPN()
|
||||
}
|
||||
bool TraceRecorder::JSOP_BINDNAME()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
/* BINDNAME is a no-op for the recorder. We wait until we hit the
|
||||
SETNAME/SETPROP that uses it. This is safe because the
|
||||
interpreter calculates here the scope we will use and we
|
||||
will use that value to guard against in SETNAME/SETPROP. */
|
||||
return true;
|
||||
}
|
||||
bool TraceRecorder::JSOP_SETNAME()
|
||||
{
|
||||
return false;
|
||||
|
@ -133,6 +133,8 @@ class TraceRecorder {
|
||||
bool inc(jsval& v, jsint incr, bool pre);
|
||||
bool cmp(nanojit::LOpcode op, bool negate = false);
|
||||
bool ibinary(nanojit::LOpcode op, bool ov = false);
|
||||
|
||||
bool map_is_native(JSObjectMap* map, nanojit::LIns* map_ins);
|
||||
public:
|
||||
TraceRecorder(JSContext* cx, nanojit::Fragmento*, nanojit::Fragment*);
|
||||
~TraceRecorder();
|
||||
|
Loading…
Reference in New Issue
Block a user