[JAEGER] Added JSOP_ADD,SUB,MUL,DIV,MOD.
This commit is contained in:
@@ -40,6 +40,7 @@
|
|||||||
#include "MethodJIT.h"
|
#include "MethodJIT.h"
|
||||||
#include "jsnum.h"
|
#include "jsnum.h"
|
||||||
#include "jsbool.h"
|
#include "jsbool.h"
|
||||||
|
#include "jslibmath.h"
|
||||||
#include "Compiler.h"
|
#include "Compiler.h"
|
||||||
#include "StubCalls.h"
|
#include "StubCalls.h"
|
||||||
#include "assembler/jit/ExecutableAllocator.h"
|
#include "assembler/jit/ExecutableAllocator.h"
|
||||||
@@ -453,6 +454,26 @@ mjit::Compiler::generateMethod()
|
|||||||
jsop_bitop(op);
|
jsop_bitop(op);
|
||||||
END_CASE(JSOP_RSH)
|
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)
|
BEGIN_CASE(JSOP_VOID)
|
||||||
frame.pop();
|
frame.pop();
|
||||||
frame.push(UndefinedTag());
|
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_bindname(uint32 index);
|
||||||
void jsop_setglobal(uint32 index);
|
void jsop_setglobal(uint32 index);
|
||||||
void jsop_getglobal(uint32 index);
|
void jsop_getglobal(uint32 index);
|
||||||
|
void jsop_binary(JSOp op, VoidStub stub);
|
||||||
void emitReturn();
|
void emitReturn();
|
||||||
void dispatchCall(VoidPtrStubUInt32 stub);
|
void dispatchCall(VoidPtrStubUInt32 stub);
|
||||||
|
|
||||||
|
|||||||
@@ -1264,3 +1264,169 @@ stubs::NotEqual(VMFrame &f)
|
|||||||
return InlineEqualityOp(f, false, true);
|
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 BitAnd(VMFrame &f);
|
||||||
void JS_FASTCALL Lsh(VMFrame &f);
|
void JS_FASTCALL Lsh(VMFrame &f);
|
||||||
void JS_FASTCALL Rsh(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);
|
JSBool JS_FASTCALL ValueToBoolean(VMFrame &f);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user