[JAEGER] Added JSOP_ADD,SUB,MUL,DIV,MOD.
This commit is contained in:
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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 ®s = 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 ®s = 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 ®s = 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 ®s = 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 ®s = 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user