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:
Andreas Gal 2008-07-04 23:53:29 -07:00
parent cef5e9becc
commit 2df2214a9e
2 changed files with 54 additions and 15 deletions

View File

@ -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;

View File

@ -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();