[JAEGER] Added JSOP_ADD,SUB,MUL,DIV,MOD.

This commit is contained in:
David Anderson
2010-06-04 19:31:46 -07:00
parent d584e5fc77
commit aa425f1920
4 changed files with 262 additions and 0 deletions

View File

@@ -40,6 +40,7 @@
#include "MethodJIT.h"
#include "jsnum.h"
#include "jsbool.h"
#include "jslibmath.h"
#include "Compiler.h"
#include "StubCalls.h"
#include "assembler/jit/ExecutableAllocator.h"
@@ -453,6 +454,26 @@ mjit::Compiler::generateMethod()
jsop_bitop(op);
END_CASE(JSOP_RSH)
BEGIN_CASE(JSOP_ADD)
jsop_binary(op, stubs::Add);
END_CASE(JSOP_ADD)
BEGIN_CASE(JSOP_SUB)
jsop_binary(op, stubs::Sub);
END_CASE(JSOP_SUB)
BEGIN_CASE(JSOP_MUL)
jsop_binary(op, stubs::Mul);
END_CASE(JSOP_MUL)
BEGIN_CASE(JSOP_DIV)
jsop_binary(op, stubs::Div);
END_CASE(JSOP_DIV)
BEGIN_CASE(JSOP_MOD)
jsop_binary(op, stubs::Mod);
END_CASE(JSOP_MOD)
BEGIN_CASE(JSOP_VOID)
frame.pop();
frame.push(UndefinedTag());
@@ -867,3 +888,72 @@ mjit::Compiler::emitStubCmpOp(BoolStub stub, jsbytecode *target, JSOp fused)
}
}
void
mjit::Compiler::jsop_binary(JSOp op, VoidStub stub)
{
FrameEntry *rhs = frame.peek(-1);
FrameEntry *lhs = frame.peek(-2);
if (lhs->isConstant() && rhs->isConstant()) {
const Value &L = lhs->getValue();
const Value &R = rhs->getValue();
if ((L.isPrimitive() && R.isPrimitive()) &&
(op != JSOP_ADD || (!L.isString() && !R.isString())))
{
/* Constant fold. */
double dL, dR;
ValueToNumber(cx, L, &dL);
ValueToNumber(cx, R, &dR);
switch (op) {
case JSOP_ADD:
dL += dR;
break;
case JSOP_SUB:
dL -= dR;
break;
case JSOP_MUL:
dL *= dR;
break;
case JSOP_DIV:
if (dR == 0) {
#ifdef XP_WIN
if (JSDOUBLE_IS_NaN(dR))
dL = js_NaN;
else
#endif
if (dL == 0 || JSDOUBLE_IS_NaN(dL))
dL = js_NaN;
else if (JSDOUBLE_IS_NEG(dL) != JSDOUBLE_IS_NEG(dR))
dL = cx->runtime->negativeInfinityValue.asDouble();
else
dL = cx->runtime->positiveInfinityValue.asDouble();
} else {
dL /= dR;
}
break;
case JSOP_MOD:
if (dL == 0)
dL = js_NaN;
else
dL = js_fmod(dR, dL);
break;
default:
JS_NOT_REACHED("NYI");
break;
}
frame.popn(2);
Value v;
v.setNumber(dL);
frame.push(v);
return;
}
}
/* Can't constant fold, slow paths. */
prepareStubCall();
stubCall(stub, Uses(2), Defs(1));
frame.popn(2);
frame.pushSynced();
}

View File

@@ -131,6 +131,7 @@ class Compiler
void jsop_bindname(uint32 index);
void jsop_setglobal(uint32 index);
void jsop_getglobal(uint32 index);
void jsop_binary(JSOp op, VoidStub stub);
void emitReturn();
void dispatchCall(VoidPtrStubUInt32 stub);

View File

@@ -1264,3 +1264,169 @@ stubs::NotEqual(VMFrame &f)
return InlineEqualityOp(f, false, true);
}
static inline bool
DefaultValue(VMFrame &f, JSType hint, Value &v, int n)
{
JS_ASSERT(v.isObject());
if (!v.asObject().defaultValue(f.cx, hint, &f.regs.sp[n]))
return false;
v = f.regs.sp[n];
return true;
}
void JS_FASTCALL
stubs::Add(VMFrame &f)
{
JSContext *cx = f.cx;
JSFrameRegs &regs = f.regs;
Value rval = regs.sp[-1];
Value lval = regs.sp[-2];
if (BothInt32(lval, rval)) {
int32_t l = lval.asInt32(), r = rval.asInt32();
int32_t sum = l + r;
regs.sp--;
if (JS_UNLIKELY(bool((l ^ sum) & (r ^ sum) & 0x80000000)))
regs.sp[-1].setDouble(double(l) + double(r));
else
regs.sp[-1].setInt32(sum);
} else
#if JS_HAS_XML_SUPPORT
if (lval.isNonFunObj() && lval.asObject().isXML() &&
rval.isNonFunObj() && rval.asObject().isXML()) {
if (!js_ConcatenateXML(cx, &lval.asObject(), &rval.asObject(), &rval))
THROW();
regs.sp--;
regs.sp[-1] = rval;
} else
#endif
{
if (lval.isObject() && !DefaultValue(f, JSTYPE_VOID, lval, -2))
THROW();
if (rval.isObject() && !DefaultValue(f, JSTYPE_VOID, rval, -1))
THROW();
bool lIsString, rIsString;
if ((lIsString = lval.isString()) | (rIsString = rval.isString())) {
JSString *lstr, *rstr;
if (lIsString) {
lstr = lval.asString();
} else {
lstr = js_ValueToString(cx, lval);
if (!lstr)
THROW();
regs.sp[-2].setString(lstr);
}
if (rIsString) {
rstr = rval.asString();
} else {
rstr = js_ValueToString(cx, rval);
if (!rstr)
THROW();
regs.sp[-1].setString(rstr);
}
JSString *str = js_ConcatStrings(cx, lstr, rstr);
if (!str)
THROW();
regs.sp--;
regs.sp[-1].setString(str);
} else {
double l, r;
if (!ValueToNumber(cx, lval, &l) || !ValueToNumber(cx, rval, &r))
THROW();
l += r;
regs.sp--;
regs.sp[-1].setNumber(l);
}
}
}
void JS_FASTCALL
stubs::Sub(VMFrame &f)
{
JSContext *cx = f.cx;
JSFrameRegs &regs = f.regs;
double d1, d2;
if (!ValueToNumber(cx, regs.sp[-2], &d1) ||
!ValueToNumber(cx, regs.sp[-1], &d2)) {
THROW();
}
double d = d1 - d2;
regs.sp[-2].setNumber(d);
}
void JS_FASTCALL
stubs::Mul(VMFrame &f)
{
JSContext *cx = f.cx;
JSFrameRegs &regs = f.regs;
double d1, d2;
if (!ValueToNumber(cx, regs.sp[-2], &d1) ||
!ValueToNumber(cx, regs.sp[-1], &d2)) {
THROW();
}
double d = d1 * d2;
regs.sp[-2].setNumber(d);
}
void JS_FASTCALL
stubs::Div(VMFrame &f)
{
JSContext *cx = f.cx;
JSRuntime *rt = cx->runtime;
JSFrameRegs &regs = f.regs;
double d1, d2;
if (!ValueToNumber(cx, regs.sp[-2], &d1) ||
!ValueToNumber(cx, regs.sp[-1], &d2)) {
THROW();
}
if (d2 == 0) {
const Value *vp;
#ifdef XP_WIN
/* XXX MSVC miscompiles such that (NaN == 0) */
if (JSDOUBLE_IS_NaN(d2))
vp = &rt->NaNValue;
else
#endif
if (d1 == 0 || JSDOUBLE_IS_NaN(d1))
vp = &rt->NaNValue;
else if (JSDOUBLE_IS_NEG(d1) != JSDOUBLE_IS_NEG(d2))
vp = &rt->negativeInfinityValue;
else
vp = &rt->positiveInfinityValue;
regs.sp[-2] = *vp;
} else {
d1 /= d2;
regs.sp[-2].setNumber(d1);
}
}
void JS_FASTCALL
stubs::Mod(VMFrame &f)
{
JSContext *cx = f.cx;
JSFrameRegs &regs = f.regs;
Value &lref = regs.sp[-2];
Value &rref = regs.sp[-1];
int32_t l, r;
if (lref.isInt32() && rref.isInt32() &&
(l = lref.asInt32()) >= 0 && (r = rref.asInt32()) > 0) {
int32_t mod = l % r;
regs.sp[-2].setInt32(mod);
} else {
double d1, d2;
if (!ValueToNumber(cx, regs.sp[-2], &d1) ||
!ValueToNumber(cx, regs.sp[-1], &d2)) {
THROW();
}
if (d2 == 0) {
regs.sp[-2].setDouble(js_NaN);
} else {
d1 = js_fmod(d1, d2);
regs.sp[-2].setDouble(d1);
}
}
}

View File

@@ -71,6 +71,11 @@ JSBool JS_FASTCALL NotEqual(VMFrame &f);
void JS_FASTCALL BitAnd(VMFrame &f);
void JS_FASTCALL Lsh(VMFrame &f);
void JS_FASTCALL Rsh(VMFrame &f);
void JS_FASTCALL Add(VMFrame &f);
void JS_FASTCALL Sub(VMFrame &f);
void JS_FASTCALL Mul(VMFrame &f);
void JS_FASTCALL Div(VMFrame &f);
void JS_FASTCALL Mod(VMFrame &f);
JSBool JS_FASTCALL ValueToBoolean(VMFrame &f);