mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 719135 - Move some arithmetic operations to jsinterpinlines. r=dvander
This commit is contained in:
parent
60292745ec
commit
d509a9c8b2
@ -1094,6 +1094,11 @@ class TypeScript
|
||||
static inline void MonitorString(JSContext *cx, JSScript *script, jsbytecode *pc);
|
||||
static inline void MonitorUnknown(JSContext *cx, JSScript *script, jsbytecode *pc);
|
||||
|
||||
static inline void GetPcScript(JSContext *cx, JSScript **script, jsbytecode **pc);
|
||||
static inline void MonitorOverflow(JSContext *cx);
|
||||
static inline void MonitorString(JSContext *cx);
|
||||
static inline void MonitorUnknown(JSContext *cx);
|
||||
|
||||
/*
|
||||
* Monitor a bytecode pushing any value. This must be called for any opcode
|
||||
* which is JOF_TYPESET, and where either the script has not been analyzed
|
||||
|
@ -595,6 +595,40 @@ TypeScript::MonitorUnknown(JSContext *cx, JSScript *script, jsbytecode *pc)
|
||||
TypeDynamicResult(cx, script, pc, Type::UnknownType());
|
||||
}
|
||||
|
||||
/* static */ inline void
|
||||
TypeScript::GetPcScript(JSContext *cx, JSScript **script, jsbytecode **pc)
|
||||
{
|
||||
*script = cx->fp()->script();
|
||||
*pc = cx->regs().pc;
|
||||
}
|
||||
|
||||
/* static */ inline void
|
||||
TypeScript::MonitorOverflow(JSContext *cx)
|
||||
{
|
||||
JSScript *script;
|
||||
jsbytecode *pc;
|
||||
GetPcScript(cx, &script, &pc);
|
||||
MonitorOverflow(cx, script, pc);
|
||||
}
|
||||
|
||||
/* static */ inline void
|
||||
TypeScript::MonitorString(JSContext *cx)
|
||||
{
|
||||
JSScript *script;
|
||||
jsbytecode *pc;
|
||||
GetPcScript(cx, &script, &pc);
|
||||
MonitorString(cx, script, pc);
|
||||
}
|
||||
|
||||
/* static */ inline void
|
||||
TypeScript::MonitorUnknown(JSContext *cx)
|
||||
{
|
||||
JSScript *script;
|
||||
jsbytecode *pc;
|
||||
GetPcScript(cx, &script, &pc);
|
||||
MonitorUnknown(cx, script, pc);
|
||||
}
|
||||
|
||||
/* static */ inline void
|
||||
TypeScript::MonitorAssign(JSContext *cx, JSScript *script, jsbytecode *pc,
|
||||
JSObject *obj, jsid id, const js::Value &rval)
|
||||
|
@ -2413,145 +2413,51 @@ END_CASE(JSOP_URSH)
|
||||
|
||||
BEGIN_CASE(JSOP_ADD)
|
||||
{
|
||||
Value rval = regs.sp[-1];
|
||||
Value lval = regs.sp[-2];
|
||||
|
||||
if (lval.isInt32() && rval.isInt32()) {
|
||||
int32_t l = lval.toInt32(), r = rval.toInt32();
|
||||
int32_t sum = l + r;
|
||||
if (JS_UNLIKELY(bool((l ^ sum) & (r ^ sum) & 0x80000000))) {
|
||||
regs.sp[-2].setDouble(double(l) + double(r));
|
||||
TypeScript::MonitorOverflow(cx, script, regs.pc);
|
||||
} else {
|
||||
regs.sp[-2].setInt32(sum);
|
||||
}
|
||||
regs.sp--;
|
||||
} else
|
||||
#if JS_HAS_XML_SUPPORT
|
||||
if (IsXML(lval) && IsXML(rval)) {
|
||||
if (!js_ConcatenateXML(cx, &lval.toObject(), &rval.toObject(), &rval))
|
||||
goto error;
|
||||
regs.sp[-2] = rval;
|
||||
regs.sp--;
|
||||
TypeScript::MonitorUnknown(cx, script, regs.pc);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
/*
|
||||
* If either operand is an object, any non-integer result must be
|
||||
* reported to inference.
|
||||
*/
|
||||
bool lIsObject = lval.isObject(), rIsObject = rval.isObject();
|
||||
|
||||
if (!ToPrimitive(cx, &lval))
|
||||
goto error;
|
||||
if (!ToPrimitive(cx, &rval))
|
||||
goto error;
|
||||
bool lIsString, rIsString;
|
||||
if ((lIsString = lval.isString()) | (rIsString = rval.isString())) {
|
||||
JSString *lstr, *rstr;
|
||||
if (lIsString) {
|
||||
lstr = lval.toString();
|
||||
} else {
|
||||
lstr = ToString(cx, lval);
|
||||
if (!lstr)
|
||||
goto error;
|
||||
regs.sp[-2].setString(lstr);
|
||||
}
|
||||
if (rIsString) {
|
||||
rstr = rval.toString();
|
||||
} else {
|
||||
rstr = ToString(cx, rval);
|
||||
if (!rstr)
|
||||
goto error;
|
||||
regs.sp[-1].setString(rstr);
|
||||
}
|
||||
JSString *str = js_ConcatStrings(cx, lstr, rstr);
|
||||
if (!str)
|
||||
goto error;
|
||||
if (lIsObject || rIsObject)
|
||||
TypeScript::MonitorString(cx, script, regs.pc);
|
||||
regs.sp[-2].setString(str);
|
||||
regs.sp--;
|
||||
} else {
|
||||
double l, r;
|
||||
if (!ToNumber(cx, lval, &l) || !ToNumber(cx, rval, &r))
|
||||
goto error;
|
||||
l += r;
|
||||
if (!regs.sp[-2].setNumber(l) &&
|
||||
(lIsObject || rIsObject || (!lval.isDouble() && !rval.isDouble()))) {
|
||||
TypeScript::MonitorOverflow(cx, script, regs.pc);
|
||||
}
|
||||
regs.sp--;
|
||||
}
|
||||
}
|
||||
Value rval = regs.sp[-1];
|
||||
if (!AddOperation(cx, lval, rval, ®s.sp[-2]))
|
||||
goto error;
|
||||
regs.sp--;
|
||||
}
|
||||
END_CASE(JSOP_ADD)
|
||||
|
||||
#define BINARY_OP(OP) \
|
||||
JS_BEGIN_MACRO \
|
||||
Value rval = regs.sp[-1]; \
|
||||
Value lval = regs.sp[-2]; \
|
||||
double d1, d2; \
|
||||
if (!ToNumber(cx, lval, &d1) || !ToNumber(cx, rval, &d2)) \
|
||||
goto error; \
|
||||
double d = d1 OP d2; \
|
||||
regs.sp--; \
|
||||
if (!regs.sp[-1].setNumber(d) && \
|
||||
!(lval.isDouble() || rval.isDouble())) { \
|
||||
TypeScript::MonitorOverflow(cx, script, regs.pc); \
|
||||
} \
|
||||
JS_END_MACRO
|
||||
|
||||
BEGIN_CASE(JSOP_SUB)
|
||||
BINARY_OP(-);
|
||||
{
|
||||
Value lval = regs.sp[-2];
|
||||
Value rval = regs.sp[-1];
|
||||
if (!SubOperation(cx, lval, rval, ®s.sp[-2]))
|
||||
goto error;
|
||||
regs.sp--;
|
||||
}
|
||||
END_CASE(JSOP_SUB)
|
||||
|
||||
BEGIN_CASE(JSOP_MUL)
|
||||
BINARY_OP(*);
|
||||
{
|
||||
Value lval = regs.sp[-2];
|
||||
Value rval = regs.sp[-1];
|
||||
if (!MulOperation(cx, lval, rval, ®s.sp[-2]))
|
||||
goto error;
|
||||
regs.sp--;
|
||||
}
|
||||
END_CASE(JSOP_MUL)
|
||||
|
||||
#undef BINARY_OP
|
||||
|
||||
BEGIN_CASE(JSOP_DIV)
|
||||
{
|
||||
Value rval = regs.sp[-1];
|
||||
Value lval = regs.sp[-2];
|
||||
double d1, d2;
|
||||
if (!ToNumber(cx, lval, &d1) || !ToNumber(cx, rval, &d2))
|
||||
Value rval = regs.sp[-1];
|
||||
if (!DivOperation(cx, lval, rval, ®s.sp[-2]))
|
||||
goto error;
|
||||
regs.sp--;
|
||||
|
||||
regs.sp[-1].setNumber(NumberDiv(d1, d2));
|
||||
|
||||
if (d2 == 0 || (regs.sp[-1].isDouble() && !(lval.isDouble() || rval.isDouble())))
|
||||
TypeScript::MonitorOverflow(cx, script, regs.pc);
|
||||
}
|
||||
END_CASE(JSOP_DIV)
|
||||
|
||||
BEGIN_CASE(JSOP_MOD)
|
||||
{
|
||||
Value &lref = regs.sp[-2];
|
||||
Value &rref = regs.sp[-1];
|
||||
int32_t l, r;
|
||||
if (lref.isInt32() && rref.isInt32() &&
|
||||
(l = lref.toInt32()) >= 0 && (r = rref.toInt32()) > 0) {
|
||||
int32_t mod = l % r;
|
||||
regs.sp--;
|
||||
regs.sp[-1].setInt32(mod);
|
||||
} else {
|
||||
double d1, d2;
|
||||
if (!ToNumber(cx, regs.sp[-2], &d1) || !ToNumber(cx, regs.sp[-1], &d2))
|
||||
goto error;
|
||||
regs.sp--;
|
||||
if (d2 == 0) {
|
||||
regs.sp[-1].setDouble(js_NaN);
|
||||
} else {
|
||||
d1 = js_fmod(d1, d2);
|
||||
regs.sp[-1].setDouble(d1);
|
||||
}
|
||||
TypeScript::MonitorOverflow(cx, script, regs.pc);
|
||||
}
|
||||
Value lval = regs.sp[-2];
|
||||
Value rval = regs.sp[-1];
|
||||
if (!ModOperation(cx, lval, rval, ®s.sp[-2]))
|
||||
goto error;
|
||||
regs.sp--;
|
||||
}
|
||||
END_CASE(JSOP_MOD)
|
||||
|
||||
|
@ -44,13 +44,16 @@
|
||||
#include "jsapi.h"
|
||||
#include "jsbool.h"
|
||||
#include "jscompartment.h"
|
||||
#include "jsinfer.h"
|
||||
#include "jsinterp.h"
|
||||
#include "jslibmath.h"
|
||||
#include "jsnum.h"
|
||||
#include "jsprobes.h"
|
||||
#include "jsstr.h"
|
||||
#include "methodjit/MethodJIT.h"
|
||||
|
||||
#include "jsfuninlines.h"
|
||||
#include "jsinferinlines.h"
|
||||
#include "jspropertycacheinlines.h"
|
||||
#include "jstypedarrayinlines.h"
|
||||
|
||||
@ -511,6 +514,137 @@ InterpreterFrames::enableInterruptsIfRunning(JSScript *script)
|
||||
enabler.enableInterrupts();
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE bool
|
||||
AddOperation(JSContext *cx, const Value &lhs, const Value &rhs, Value *res)
|
||||
{
|
||||
Value lval = lhs;
|
||||
Value rval = rhs;
|
||||
|
||||
if (lval.isInt32() && rval.isInt32()) {
|
||||
int32_t l = lval.toInt32(), r = rval.toInt32();
|
||||
int32_t sum = l + r;
|
||||
if (JS_UNLIKELY(bool((l ^ sum) & (r ^ sum) & 0x80000000))) {
|
||||
res->setDouble(double(l) + double(r));
|
||||
types::TypeScript::MonitorOverflow(cx);
|
||||
} else {
|
||||
res->setInt32(sum);
|
||||
}
|
||||
} else
|
||||
#if JS_HAS_XML_SUPPORT
|
||||
if (IsXML(lval) && IsXML(rval)) {
|
||||
if (!js_ConcatenateXML(cx, &lval.toObject(), &rval.toObject(), res))
|
||||
return false;
|
||||
types::TypeScript::MonitorUnknown(cx);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
/*
|
||||
* If either operand is an object, any non-integer result must be
|
||||
* reported to inference.
|
||||
*/
|
||||
bool lIsObject = lval.isObject(), rIsObject = rval.isObject();
|
||||
|
||||
if (!ToPrimitive(cx, &lval))
|
||||
return false;
|
||||
if (!ToPrimitive(cx, &rval))
|
||||
return false;
|
||||
bool lIsString, rIsString;
|
||||
if ((lIsString = lval.isString()) | (rIsString = rval.isString())) {
|
||||
js::AutoStringRooter lstr(cx), rstr(cx);
|
||||
if (lIsString) {
|
||||
lstr.setString(lval.toString());
|
||||
} else {
|
||||
lstr.setString(ToString(cx, lval));
|
||||
if (!lstr.string())
|
||||
return false;
|
||||
}
|
||||
if (rIsString) {
|
||||
rstr.setString(rval.toString());
|
||||
} else {
|
||||
rstr.setString(ToString(cx, rval));
|
||||
if (!rstr.string())
|
||||
return false;
|
||||
}
|
||||
JSString *str = js_ConcatStrings(cx, lstr.string(), rstr.string());
|
||||
if (!str)
|
||||
return false;
|
||||
if (lIsObject || rIsObject)
|
||||
types::TypeScript::MonitorString(cx);
|
||||
res->setString(str);
|
||||
} else {
|
||||
double l, r;
|
||||
if (!ToNumber(cx, lval, &l) || !ToNumber(cx, rval, &r))
|
||||
return false;
|
||||
l += r;
|
||||
if (!res->setNumber(l) &&
|
||||
(lIsObject || rIsObject || (!lval.isDouble() && !rval.isDouble()))) {
|
||||
types::TypeScript::MonitorOverflow(cx);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE bool
|
||||
SubOperation(JSContext *cx, const Value &lhs, const Value &rhs, Value *res)
|
||||
{
|
||||
double d1, d2;
|
||||
if (!ToNumber(cx, lhs, &d1) || !ToNumber(cx, rhs, &d2))
|
||||
return false;
|
||||
double d = d1 - d2;
|
||||
if (!res->setNumber(d) && !(lhs.isDouble() || rhs.isDouble()))
|
||||
types::TypeScript::MonitorOverflow(cx);
|
||||
return true;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE bool
|
||||
MulOperation(JSContext *cx, const Value &lhs, const Value &rhs, Value *res)
|
||||
{
|
||||
double d1, d2;
|
||||
if (!ToNumber(cx, lhs, &d1) || !ToNumber(cx, rhs, &d2))
|
||||
return false;
|
||||
double d = d1 * d2;
|
||||
if (!res->setNumber(d) && !(lhs.isDouble() || rhs.isDouble()))
|
||||
types::TypeScript::MonitorOverflow(cx);
|
||||
return true;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE bool
|
||||
DivOperation(JSContext *cx, const Value &lhs, const Value &rhs, Value *res)
|
||||
{
|
||||
double d1, d2;
|
||||
if (!ToNumber(cx, lhs, &d1) || !ToNumber(cx, rhs, &d2))
|
||||
return false;
|
||||
res->setNumber(NumberDiv(d1, d2));
|
||||
|
||||
if (d2 == 0 || (res->isDouble() && !(lhs.isDouble() || rhs.isDouble())))
|
||||
types::TypeScript::MonitorOverflow(cx);
|
||||
return true;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE bool
|
||||
ModOperation(JSContext *cx, const Value &lhs, const Value &rhs, Value *res)
|
||||
{
|
||||
int32_t l, r;
|
||||
if (lhs.isInt32() && rhs.isInt32() &&
|
||||
(l = lhs.toInt32()) >= 0 && (r = rhs.toInt32()) > 0) {
|
||||
int32_t mod = l % r;
|
||||
res->setInt32(mod);
|
||||
return true;
|
||||
}
|
||||
|
||||
double d1, d2;
|
||||
if (!ToNumber(cx, lhs, &d1) || !ToNumber(cx, rhs, &d2))
|
||||
return false;
|
||||
|
||||
if (d2 == 0)
|
||||
res->setDouble(js_NaN);
|
||||
else
|
||||
res->setDouble(js_fmod(d1, d2));
|
||||
types::TypeScript::MonitorOverflow(cx);
|
||||
return true;
|
||||
}
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
#endif /* jsinterpinlines_h__ */
|
||||
|
Loading…
Reference in New Issue
Block a user