[INFER] More fixes for stock JM behavior, bug 647048.
This commit is contained in:
@@ -3070,9 +3070,9 @@ JS_NewCompartmentAndGlobalObject(JSContext *cx, JSClass *clasp, JSPrincipals *pr
|
||||
AutoHoldCompartment hold(compartment);
|
||||
|
||||
JSCompartment *saved = cx->compartment;
|
||||
cx->compartment = compartment;
|
||||
cx->setCompartment(compartment);
|
||||
JSObject *obj = JS_NewGlobalObject(cx, clasp);
|
||||
cx->compartment = saved;
|
||||
cx->setCompartment(saved);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
@@ -107,6 +107,8 @@
|
||||
#include "jstracer.h"
|
||||
#include "jsvector.h"
|
||||
#include "jswrapper.h"
|
||||
#include "methodjit/StubCalls.h"
|
||||
#include "methodjit/StubCalls-inl.h"
|
||||
|
||||
#include "jsatominlines.h"
|
||||
#include "jscntxtinlines.h"
|
||||
@@ -667,8 +669,11 @@ array_length_setter(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value
|
||||
if (oldcap > newlen)
|
||||
obj->shrinkDenseArrayElements(cx, newlen);
|
||||
jsuint oldinit = obj->getDenseArrayInitializedLength();
|
||||
if (oldinit > newlen)
|
||||
if (oldinit > newlen) {
|
||||
obj->setDenseArrayInitializedLength(newlen);
|
||||
if (!cx->typeInferenceEnabled())
|
||||
obj->backfillDenseArrayHoles();
|
||||
}
|
||||
} else if (oldlen - newlen < (1 << 24)) {
|
||||
do {
|
||||
--oldlen;
|
||||
@@ -3499,9 +3504,10 @@ NewArray(JSContext *cx, jsuint length, JSObject *proto)
|
||||
if (allocateCapacity) {
|
||||
if (!obj->ensureSlots(cx, length))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!cx->typeInferenceEnabled())
|
||||
obj->backfillDenseArrayHoles();
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
@@ -3521,14 +3527,7 @@ NewDenseAllocatedArray(JSContext *cx, uint32 length, JSObject *proto)
|
||||
JSObject * JS_FASTCALL
|
||||
NewDenseAllocatedEmptyArray(JSContext *cx, uint length, JSObject *proto)
|
||||
{
|
||||
JSObject *obj = NewArray<true>(cx, length, proto);
|
||||
if (!obj)
|
||||
return NULL;
|
||||
obj->setDenseArrayInitializedLength(length);
|
||||
if (!obj->setDenseArrayNotPacked(cx))
|
||||
return NULL;
|
||||
ClearValueRange(obj->getSlots(), length, true);
|
||||
return obj;
|
||||
return NewArray<true>(cx, length, proto);
|
||||
}
|
||||
|
||||
JSObject * JS_FASTCALL
|
||||
@@ -3537,6 +3536,20 @@ NewDenseUnallocatedArray(JSContext *cx, uint32 length, JSObject *proto)
|
||||
return NewArray<false>(cx, length, proto);
|
||||
}
|
||||
|
||||
#ifdef JS_METHODJIT
|
||||
JSObject * JS_FASTCALL
|
||||
mjit::stubs::NewDenseUnallocatedArray(VMFrame &f, uint32 length)
|
||||
{
|
||||
JSObject *proto = (JSObject *) f.scratch;
|
||||
JSObject *obj = NewArray<false>(f.cx, length, proto);
|
||||
if (!obj) {
|
||||
js_ReportOutOfMemory(f.cx);
|
||||
THROWV(NULL);
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
#endif
|
||||
|
||||
JSObject *
|
||||
NewDenseCopiedArray(JSContext *cx, uintN length, Value *vp, JSObject *proto)
|
||||
{
|
||||
@@ -3546,12 +3559,16 @@ NewDenseCopiedArray(JSContext *cx, uintN length, Value *vp, JSObject *proto)
|
||||
|
||||
JS_ASSERT(obj->getDenseArrayCapacity() >= length);
|
||||
|
||||
if (cx->typeInferenceEnabled()) {
|
||||
if (vp) {
|
||||
memcpy(obj->getDenseArrayElements(), vp, length * sizeof(Value));
|
||||
obj->setDenseArrayInitializedLength(length);
|
||||
} else {
|
||||
obj->setDenseArrayInitializedLength(0);
|
||||
}
|
||||
} else if (vp) {
|
||||
memcpy(obj->getDenseArrayElements(), vp, length * sizeof(Value));
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
@@ -89,9 +89,16 @@ inline JSObject::EnsureDenseResult
|
||||
JSObject::ensureDenseArrayElements(JSContext *cx, uintN index, uintN extra)
|
||||
{
|
||||
JS_ASSERT(isDenseArray());
|
||||
|
||||
uintN currentCapacity = numSlots();
|
||||
uintN initLength = getDenseArrayInitializedLength();
|
||||
|
||||
/*
|
||||
* Don't take excessive slow paths when inference is disabled, due to
|
||||
* uninitialized slots between initializedLength and capacity.
|
||||
*/
|
||||
JS_ASSERT_IF(!cx->typeInferenceEnabled(), currentCapacity == initLength);
|
||||
|
||||
uintN requiredCapacity;
|
||||
if (extra == 1) {
|
||||
/* Optimize for the common case. */
|
||||
|
||||
@@ -1958,6 +1958,7 @@ JSContext::resetCompartment()
|
||||
}
|
||||
|
||||
compartment = scopeobj->compartment();
|
||||
inferenceEnabled = compartment->types.inferenceEnabled;
|
||||
|
||||
if (isExceptionPending())
|
||||
wrapPendingException();
|
||||
|
||||
@@ -1648,6 +1648,8 @@ struct JSContext
|
||||
/* GC heap compartment. */
|
||||
JSCompartment *compartment;
|
||||
|
||||
inline void setCompartment(JSCompartment *compartment);
|
||||
|
||||
/* Currently executing frame and regs, set by stack operations. */
|
||||
JS_REQUIRES_STACK
|
||||
JSFrameRegs *regs;
|
||||
@@ -1939,6 +1941,8 @@ struct JSContext
|
||||
bool profilingEnabled;
|
||||
#endif
|
||||
|
||||
bool inferenceEnabled;
|
||||
|
||||
/* Caller must be holding runtime->gcLock. */
|
||||
void updateJITEnabled();
|
||||
|
||||
|
||||
@@ -572,6 +572,13 @@ GetMathCache(JSContext *cx)
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
JSContext::setCompartment(JSCompartment *compartment)
|
||||
{
|
||||
this->compartment = compartment;
|
||||
this->inferenceEnabled = compartment ? compartment->types.inferenceEnabled : false;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
# define EVAL_CACHE_METER(x) (cx->compartment->evalCacheMeter.x++)
|
||||
#else
|
||||
@@ -597,7 +604,7 @@ class PreserveCompartment {
|
||||
}
|
||||
|
||||
~PreserveCompartment() {
|
||||
cx->compartment = oldCompartment;
|
||||
cx->setCompartment(oldCompartment);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -608,14 +615,14 @@ class SwitchToCompartment : public PreserveCompartment {
|
||||
: PreserveCompartment(cx)
|
||||
{
|
||||
JS_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
cx->compartment = newCompartment;
|
||||
cx->setCompartment(newCompartment);
|
||||
}
|
||||
|
||||
SwitchToCompartment(JSContext *cx, JSObject *target JS_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
: PreserveCompartment(cx)
|
||||
{
|
||||
JS_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
cx->compartment = target->getCompartment();
|
||||
cx->setCompartment(target->getCompartment());
|
||||
}
|
||||
|
||||
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
|
||||
@@ -402,12 +402,12 @@ JS_ClearTrap(JSContext *cx, JSScript *script, jsbytecode *pc,
|
||||
#ifdef JS_METHODJIT
|
||||
if (script->hasJITCode()) {
|
||||
JSCompartment *oldCompartment = cx->compartment;
|
||||
cx->compartment = script->compartment;
|
||||
cx->setCompartment(script->compartment);
|
||||
|
||||
mjit::Recompiler recompiler(cx, script);
|
||||
recompiler.recompile();
|
||||
|
||||
cx->compartment = oldCompartment;
|
||||
cx->setCompartment(oldCompartment);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -226,7 +226,7 @@ UseNewType(JSContext *cx, JSScript *script, jsbytecode *pc);
|
||||
inline bool
|
||||
JSContext::typeInferenceEnabled()
|
||||
{
|
||||
return compartment->types.inferenceEnabled;
|
||||
return inferenceEnabled;
|
||||
}
|
||||
|
||||
inline js::types::TypeObject *
|
||||
|
||||
@@ -389,13 +389,13 @@ AutoCompartment::enter()
|
||||
if (origin != destination) {
|
||||
LeaveTrace(context);
|
||||
|
||||
context->compartment = destination;
|
||||
context->setCompartment(destination);
|
||||
JSObject *scopeChain = target->getGlobal();
|
||||
JS_ASSERT(scopeChain->isNative());
|
||||
|
||||
frame.construct();
|
||||
if (!context->stack().pushDummyFrame(context, *scopeChain, &frame.ref())) {
|
||||
context->compartment = origin;
|
||||
context->setCompartment(origin);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -1916,11 +1916,15 @@ mjit::Compiler::generateMethod()
|
||||
END_CASE(JSOP_SETELEM);
|
||||
|
||||
BEGIN_CASE(JSOP_CALLNAME)
|
||||
{
|
||||
uint32 index = fullAtomIndex(PC);
|
||||
prepareStubCall(Uses(0));
|
||||
masm.move(Imm32(fullAtomIndex(PC)), Registers::ArgReg1);
|
||||
masm.move(Imm32(index), Registers::ArgReg1);
|
||||
INLINE_STUBCALL(stubs::CallName);
|
||||
pushSyncedEntry(0);
|
||||
pushSyncedEntry(1);
|
||||
frame.extra(frame.peek(-2)).name = script->getAtom(index);
|
||||
}
|
||||
END_CASE(JSOP_CALLNAME)
|
||||
|
||||
BEGIN_CASE(JSOP_EVAL)
|
||||
@@ -1959,7 +1963,11 @@ mjit::Compiler::generateMethod()
|
||||
END_CASE(JSOP_CALL)
|
||||
|
||||
BEGIN_CASE(JSOP_NAME)
|
||||
jsop_name(script->getAtom(fullAtomIndex(PC)), knownPushedType(0));
|
||||
{
|
||||
JSAtom *atom = script->getAtom(fullAtomIndex(PC));
|
||||
jsop_name(atom, knownPushedType(0));
|
||||
frame.extra(frame.peek(-1)).name = atom;
|
||||
}
|
||||
END_CASE(JSOP_NAME)
|
||||
|
||||
BEGIN_CASE(JSOP_DOUBLE)
|
||||
@@ -2480,9 +2488,13 @@ mjit::Compiler::generateMethod()
|
||||
|
||||
BEGIN_CASE(JSOP_GETGNAME)
|
||||
BEGIN_CASE(JSOP_CALLGNAME)
|
||||
jsop_getgname(fullAtomIndex(PC), knownPushedType(0));
|
||||
{
|
||||
uint32 index = fullAtomIndex(PC);
|
||||
jsop_getgname(index, knownPushedType(0));
|
||||
frame.extra(frame.peek(-1)).name = script->getAtom(index);
|
||||
if (op == JSOP_CALLGNAME)
|
||||
jsop_callgname_epilogue();
|
||||
}
|
||||
END_CASE(JSOP_GETGNAME)
|
||||
|
||||
BEGIN_CASE(JSOP_SETGNAME)
|
||||
@@ -2629,8 +2641,11 @@ mjit::Compiler::generateMethod()
|
||||
unsigned nuses = analyze::GetUseCount(script, oldPC - script->code);
|
||||
unsigned ndefs = analyze::GetDefCount(script, oldPC - script->code);
|
||||
for (unsigned i = 0; i < ndefs; i++) {
|
||||
frame.learnTypeSet(opinfo->stackDepth - nuses + i,
|
||||
script->types->pushed(oldPC - script->code, i));
|
||||
FrameEntry *fe = frame.getStack(opinfo->stackDepth - nuses + i);
|
||||
if (fe) {
|
||||
/* fe may be NULL for conditionally pushed entries, e.g. JSOP_AND */
|
||||
frame.extra(fe).types = script->types->pushed(oldPC - script->code, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3246,6 +3261,12 @@ mjit::Compiler::inlineCallHelper(uint32 callImmArgc, bool callingNew)
|
||||
if (callingNew)
|
||||
frame.discardFe(origThis);
|
||||
|
||||
if (!cx->typeInferenceEnabled()) {
|
||||
CompileStatus status = callArrayBuiltin(callImmArgc, callingNew);
|
||||
if (status != Compile_InlineAbort)
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* From the presence of JSOP_FUN{CALL,APPLY}, we speculate that we are
|
||||
* going to call js_fun_{call,apply}. Normally, this call would go through
|
||||
@@ -3378,10 +3399,10 @@ mjit::Compiler::inlineCallHelper(uint32 callImmArgc, bool callingNew)
|
||||
js_ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
types::TypeSet *types = frame.getTypeSet(frame.peek(-(argc + 1)));
|
||||
types::TypeSet *types = frame.extra(frame.peek(-(argc + 1))).types;
|
||||
types::TypeSet::Clone(cx, types, &callIC.argTypes[0]);
|
||||
for (unsigned i = 0; i < argc; i++) {
|
||||
types::TypeSet *types = frame.getTypeSet(frame.peek(-(argc - i)));
|
||||
types::TypeSet *types = frame.extra(frame.peek(-(argc - i))).types;
|
||||
types::TypeSet::Clone(cx, types, &callIC.argTypes[i + 1]);
|
||||
}
|
||||
}
|
||||
@@ -3587,6 +3608,91 @@ mjit::Compiler::inlineCallHelper(uint32 callImmArgc, bool callingNew)
|
||||
#endif
|
||||
}
|
||||
|
||||
CompileStatus
|
||||
mjit::Compiler::callArrayBuiltin(uint32 argc, bool callingNew)
|
||||
{
|
||||
if (applyTricks == LazyArgsObj)
|
||||
return Compile_InlineAbort;
|
||||
|
||||
FrameEntry *origCallee = frame.peek(-(argc + 2));
|
||||
if (origCallee->isNotType(JSVAL_TYPE_OBJECT))
|
||||
return Compile_InlineAbort;
|
||||
|
||||
if (frame.extra(origCallee).name != cx->runtime->atomState.classAtoms[JSProto_Array])
|
||||
return Compile_InlineAbort;
|
||||
|
||||
JSObject *arrayObj;
|
||||
if (!js_GetClassObject(cx, globalObj, JSProto_Array, &arrayObj))
|
||||
return Compile_Error;
|
||||
|
||||
JSObject *arrayProto;
|
||||
if (!js_GetClassPrototype(cx, globalObj, JSProto_Array, &arrayProto))
|
||||
return Compile_Error;
|
||||
|
||||
if (argc > 1)
|
||||
return Compile_InlineAbort;
|
||||
FrameEntry *origArg = (argc == 1) ? frame.peek(-1) : NULL;
|
||||
if (origArg) {
|
||||
if (origArg->isNotType(JSVAL_TYPE_INT32))
|
||||
return Compile_InlineAbort;
|
||||
if (origArg->isConstant() && origArg->getValue().toInt32() < 0)
|
||||
return Compile_InlineAbort;
|
||||
}
|
||||
|
||||
if (!origCallee->isTypeKnown()) {
|
||||
Jump notObject = frame.testObject(Assembler::NotEqual, origCallee);
|
||||
stubcc.linkExit(notObject, Uses(argc + 2));
|
||||
}
|
||||
|
||||
RegisterID reg = frame.tempRegForData(origCallee);
|
||||
Jump notArray = masm.branchPtr(Assembler::NotEqual, reg, ImmPtr(arrayObj));
|
||||
stubcc.linkExit(notArray, Uses(argc + 2));
|
||||
|
||||
int32 knownSize = 0;
|
||||
MaybeRegisterID sizeReg;
|
||||
if (origArg) {
|
||||
if (origArg->isConstant()) {
|
||||
knownSize = origArg->getValue().toInt32();
|
||||
} else {
|
||||
if (!origArg->isTypeKnown()) {
|
||||
Jump notInt = frame.testInt32(Assembler::NotEqual, origArg);
|
||||
stubcc.linkExit(notInt, Uses(argc + 2));
|
||||
}
|
||||
sizeReg = frame.tempRegForData(origArg);
|
||||
Jump belowZero = masm.branch32(Assembler::LessThan, sizeReg.reg(), Imm32(0));
|
||||
stubcc.linkExit(belowZero, Uses(argc + 2));
|
||||
}
|
||||
} else {
|
||||
knownSize = 0;
|
||||
}
|
||||
|
||||
stubcc.leave();
|
||||
stubcc.masm.move(Imm32(argc), Registers::ArgReg1);
|
||||
OOL_STUBCALL(callingNew ? stubs::SlowNew : stubs::SlowCall);
|
||||
|
||||
{
|
||||
PinRegAcrossSyncAndKill p1(frame, sizeReg);
|
||||
frame.popn(argc + 2);
|
||||
frame.syncAndKill(Uses(0));
|
||||
}
|
||||
|
||||
prepareStubCall(Uses(0));
|
||||
masm.storePtr(ImmPtr(arrayProto), FrameAddress(offsetof(VMFrame, scratch)));
|
||||
if (sizeReg.isSet())
|
||||
masm.move(sizeReg.reg(), Registers::ArgReg1);
|
||||
else
|
||||
masm.move(Imm32(knownSize), Registers::ArgReg1);
|
||||
INLINE_STUBCALL(stubs::NewDenseUnallocatedArray);
|
||||
|
||||
frame.takeReg(Registers::ReturnReg);
|
||||
frame.pushTypedPayload(JSVAL_TYPE_OBJECT, Registers::ReturnReg);
|
||||
frame.forgetType(frame.peek(-1));
|
||||
|
||||
stubcc.rejoin(Changes(1));
|
||||
|
||||
return Compile_Okay;
|
||||
}
|
||||
|
||||
/* Maximum number of calls we will inline at the same site. */
|
||||
static const uint32 INLINE_SITE_LIMIT = 5;
|
||||
|
||||
@@ -3608,7 +3714,7 @@ mjit::Compiler::inlineScriptedFunction(uint32 argc, bool callingNew)
|
||||
FrameEntry *origCallee = frame.peek(-(argc + 2));
|
||||
FrameEntry *origThis = frame.peek(-(argc + 1));
|
||||
|
||||
types::TypeSet *types = frame.getTypeSet(origCallee);
|
||||
types::TypeSet *types = frame.extra(origCallee).types;
|
||||
if (!types || types->getKnownTypeTag(cx) != JSVAL_TYPE_OBJECT)
|
||||
return Compile_InlineAbort;
|
||||
|
||||
@@ -4497,7 +4603,7 @@ mjit::Compiler::testSingletonPropertyTypes(FrameEntry *top, jsid id, bool *testO
|
||||
{
|
||||
*testObject = false;
|
||||
|
||||
types::TypeSet *types = frame.getTypeSet(top);
|
||||
types::TypeSet *types = frame.extra(top).types;
|
||||
if (!types)
|
||||
return false;
|
||||
|
||||
@@ -4619,7 +4725,7 @@ mjit::Compiler::jsop_setprop(JSAtom *atom, bool usePropCache)
|
||||
pic.atom = atom;
|
||||
|
||||
if (monitored(PC)) {
|
||||
types::TypeSet *types = frame.getTypeSet(rhs);
|
||||
types::TypeSet *types = frame.extra(rhs).types;
|
||||
pic.typeMonitored = true;
|
||||
pic.rhsTypes = (types::ClonedTypeSet *) ::js_calloc(sizeof(types::ClonedTypeSet));
|
||||
if (!pic.rhsTypes) {
|
||||
@@ -6048,7 +6154,10 @@ mjit::Compiler::jsop_newinit()
|
||||
INLINE_STUBCALL(stubs::NewInitObject);
|
||||
}
|
||||
frame.takeReg(Registers::ReturnReg);
|
||||
frame.pushInitializerObject(Registers::ReturnReg, *PC == JSOP_NEWARRAY, baseobj);
|
||||
frame.pushTypedPayload(JSVAL_TYPE_OBJECT, Registers::ReturnReg);
|
||||
|
||||
frame.extra(frame.peek(-1)).initArray = (*PC == JSOP_NEWARRAY);
|
||||
frame.extra(frame.peek(-1)).initObject = baseobj;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -6211,6 +6320,10 @@ mjit::Compiler::jumpAndTrace(Jump j, jsbytecode *target, Jump *slow, bool *tramp
|
||||
|
||||
# if JS_MONOIC
|
||||
ic.addrLabel = stubcc.masm.moveWithPatch(ImmPtr(NULL), Registers::ArgReg1);
|
||||
|
||||
Jump nonzero = stubcc.masm.branchSub32(Assembler::NonZero, Imm32(1),
|
||||
Address(Registers::ArgReg1,
|
||||
offsetof(TraceICInfo, loopCounter)));
|
||||
# endif
|
||||
|
||||
/* Save and restore compiler-tracked PC, so cx->regs is right in InvokeTracer. */
|
||||
@@ -6225,13 +6338,14 @@ mjit::Compiler::jumpAndTrace(Jump j, jsbytecode *target, Jump *slow, bool *tramp
|
||||
|
||||
Jump no = stubcc.masm.branchTestPtr(Assembler::Zero, Registers::ReturnReg,
|
||||
Registers::ReturnReg);
|
||||
if (!cx->typeInferenceEnabled())
|
||||
stubcc.masm.loadPtr(FrameAddress(offsetof(VMFrame, regs.fp)), JSFrameReg);
|
||||
stubcc.masm.jump(Registers::ReturnReg);
|
||||
no.linkTo(stubcc.masm.label(), &stubcc.masm);
|
||||
|
||||
if (!cx->typeInferenceEnabled())
|
||||
stubcc.masm.loadPtr(FrameAddress(offsetof(VMFrame, regs.fp)), JSFrameReg);
|
||||
|
||||
#ifdef JS_MONOIC
|
||||
nonzero.linkTo(stubcc.masm.label(), &stubcc.masm);
|
||||
|
||||
ic.jumpTarget = target;
|
||||
ic.fastTrampoline = !consistent;
|
||||
ic.trampolineStart = stubcc.masm.label();
|
||||
|
||||
@@ -680,6 +680,7 @@ class Compiler : public BaseCompiler
|
||||
|
||||
/* Fast builtins. */
|
||||
JSObject *pushedSingleton(unsigned pushed);
|
||||
CompileStatus callArrayBuiltin(uint32 argc, bool callingNew);
|
||||
CompileStatus inlineNativeFunction(uint32 argc, bool callingNew);
|
||||
CompileStatus inlineScriptedFunction(uint32 argc, bool callingNew);
|
||||
CompileStatus compileMathAbsInt(FrameEntry *arg);
|
||||
|
||||
@@ -321,7 +321,7 @@ mjit::Compiler::inlineNativeFunction(uint32 argc, bool callingNew)
|
||||
{
|
||||
JS_ASSERT(!callingNew);
|
||||
|
||||
if (cx->typeInferenceEnabled())
|
||||
if (!cx->typeInferenceEnabled())
|
||||
return Compile_InlineAbort;
|
||||
|
||||
if (applyTricks == LazyArgsObj)
|
||||
|
||||
@@ -483,8 +483,8 @@ mjit::Compiler::jsop_equality(JSOp op, BoolStub stub, jsbytecode *target, JSOp f
|
||||
* special equality operator on either object, if that passes then
|
||||
* this is a pointer comparison.
|
||||
*/
|
||||
types::TypeSet *lhsTypes = frame.getTypeSet(lhs);
|
||||
types::TypeSet *rhsTypes = frame.getTypeSet(rhs);
|
||||
types::TypeSet *lhsTypes = frame.extra(lhs).types;
|
||||
types::TypeSet *rhsTypes = frame.extra(rhs).types;
|
||||
types::ObjectKind lhsKind =
|
||||
lhsTypes ? lhsTypes->getKnownObjectKind(cx) : types::OBJECT_UNKNOWN;
|
||||
types::ObjectKind rhsKind =
|
||||
@@ -1189,7 +1189,7 @@ mjit::Compiler::jsop_setelem(bool popGuaranteed)
|
||||
frame.forgetConstantData(obj);
|
||||
|
||||
if (cx->typeInferenceEnabled()) {
|
||||
types::TypeSet *types = frame.getTypeSet(obj);
|
||||
types::TypeSet *types = frame.extra(obj).types;
|
||||
types::ObjectKind kind = types
|
||||
? types->getKnownObjectKind(cx)
|
||||
: types::OBJECT_UNKNOWN;
|
||||
@@ -1509,7 +1509,7 @@ mjit::Compiler::jsop_getelem(bool isCall)
|
||||
frame.forgetConstantData(obj);
|
||||
|
||||
if (cx->typeInferenceEnabled()) {
|
||||
types::TypeSet *types = frame.getTypeSet(obj);
|
||||
types::TypeSet *types = frame.extra(obj).types;
|
||||
types::ObjectKind kind = types
|
||||
? types->getKnownObjectKind(cx)
|
||||
: types::OBJECT_UNKNOWN;
|
||||
@@ -1950,7 +1950,7 @@ mjit::Compiler::jsop_initmethod()
|
||||
JSAtom *atom = script->getAtom(fullAtomIndex(PC));
|
||||
|
||||
/* Initializers with INITMETHOD are not fast yet. */
|
||||
JS_ASSERT(!obj->initializerObject());
|
||||
JS_ASSERT(!frame.extra(obj).initObject);
|
||||
|
||||
prepareStubCall(Uses(2));
|
||||
masm.move(ImmPtr(atom), Registers::ArgReg1);
|
||||
@@ -1964,7 +1964,7 @@ mjit::Compiler::jsop_initprop()
|
||||
FrameEntry *fe = frame.peek(-1);
|
||||
JSAtom *atom = script->getAtom(fullAtomIndex(PC));
|
||||
|
||||
JSObject *baseobj = obj->initializerObject();
|
||||
JSObject *baseobj = frame.extra(obj).initObject;
|
||||
|
||||
if (!baseobj || monitored(PC)) {
|
||||
prepareStubCall(Uses(2));
|
||||
@@ -2005,7 +2005,7 @@ mjit::Compiler::jsop_initelem()
|
||||
* cases, as well as those where INITELEM is used on an object initializer
|
||||
* or a non-fast array initializer.
|
||||
*/
|
||||
if (!id->isConstant() || !obj->initializerArray()) {
|
||||
if (!id->isConstant() || !frame.extra(obj).initArray) {
|
||||
JSOp next = JSOp(PC[JSOP_INITELEM_LENGTH]);
|
||||
|
||||
prepareStubCall(Uses(3));
|
||||
|
||||
@@ -138,14 +138,6 @@ class FrameEntry
|
||||
bool isCopy() const { return !!copy; }
|
||||
bool isCopied() const { return copied; }
|
||||
|
||||
inline bool initializerArray() {
|
||||
return initArray;
|
||||
}
|
||||
|
||||
inline JSObject *initializerObject() {
|
||||
return initObject;
|
||||
}
|
||||
|
||||
private:
|
||||
void setType(JSValueType type_) {
|
||||
type.setConstant();
|
||||
|
||||
@@ -204,7 +204,7 @@ FrameState::pop()
|
||||
|
||||
forgetAllRegs(fe);
|
||||
|
||||
a->typeSets[fe - spBase] = NULL;
|
||||
a->extraArray[fe - spBase].reset();
|
||||
}
|
||||
|
||||
inline void
|
||||
@@ -238,7 +238,7 @@ FrameState::rawPush()
|
||||
if (!sp->isTracked())
|
||||
addToTracker(sp);
|
||||
|
||||
a->typeSets[sp - spBase] = NULL;
|
||||
a->extraArray[sp - spBase].reset();
|
||||
|
||||
return sp++;
|
||||
}
|
||||
@@ -403,16 +403,6 @@ FrameState::pushInt32(RegisterID payload)
|
||||
regstate(payload).associate(fe, RematInfo::DATA);
|
||||
}
|
||||
|
||||
inline void
|
||||
FrameState::pushInitializerObject(RegisterID payload, bool array, JSObject *baseobj)
|
||||
{
|
||||
pushTypedPayload(JSVAL_TYPE_OBJECT, payload);
|
||||
|
||||
FrameEntry *fe = peek(-1);
|
||||
fe->initArray = array;
|
||||
fe->initObject = baseobj;
|
||||
}
|
||||
|
||||
inline void
|
||||
FrameState::pushUntypedPayload(JSValueType type, RegisterID payload)
|
||||
{
|
||||
@@ -870,20 +860,6 @@ FrameState::forgetType(FrameEntry *fe)
|
||||
fe->type.setMemory();
|
||||
}
|
||||
|
||||
inline types::TypeSet *
|
||||
FrameState::getTypeSet(FrameEntry *fe)
|
||||
{
|
||||
JS_ASSERT(fe >= spBase && fe < sp);
|
||||
return a->typeSets[fe - spBase];
|
||||
}
|
||||
|
||||
inline void
|
||||
FrameState::learnTypeSet(unsigned slot, types::TypeSet *types)
|
||||
{
|
||||
if (slot < unsigned(sp - spBase))
|
||||
a->typeSets[slot] = types;
|
||||
}
|
||||
|
||||
inline void
|
||||
FrameState::learnType(FrameEntry *fe, JSValueType type, bool unsync)
|
||||
{
|
||||
@@ -1058,7 +1034,8 @@ FrameState::getOrTrack(uint32 index)
|
||||
inline FrameEntry *
|
||||
FrameState::getStack(uint32 slot)
|
||||
{
|
||||
JS_ASSERT(slot < uint32(sp - spBase));
|
||||
if (slot >= uint32(sp - spBase))
|
||||
return NULL;
|
||||
return getOrTrack(uint32(&spBase[slot] - entries));
|
||||
}
|
||||
|
||||
|
||||
@@ -127,7 +127,7 @@ FrameState::pushActiveFrame(JSScript *script, uint32 argc,
|
||||
size_t totalBytes = sizeof(ActiveFrame) +
|
||||
sizeof(FrameEntry) * nentries + // entries[]
|
||||
sizeof(FrameEntry *) * nentries + // tracker.entries
|
||||
sizeof(types::TypeSet *) * script->nslots; // typeSets
|
||||
sizeof(StackEntryExtra) * script->nslots; // extraArray
|
||||
|
||||
uint8 *cursor = (uint8 *)cx->calloc(totalBytes);
|
||||
if (!cursor)
|
||||
@@ -164,8 +164,8 @@ FrameState::pushActiveFrame(JSScript *script, uint32 argc,
|
||||
newa->tracker.entries = (FrameEntry **)cursor;
|
||||
cursor += sizeof(FrameEntry *) * nentries;
|
||||
|
||||
newa->typeSets = (types::TypeSet **)cursor;
|
||||
cursor += sizeof(types::TypeSet *) * script->nslots;
|
||||
newa->extraArray = (StackEntryExtra *)cursor;
|
||||
cursor += sizeof(StackEntryExtra) * script->nslots;
|
||||
|
||||
JS_ASSERT(reinterpret_cast<uint8 *>(newa) + totalBytes == cursor);
|
||||
|
||||
@@ -1108,7 +1108,8 @@ FrameState::discardForJoin(jsbytecode *target, uint32 stackDepth)
|
||||
|
||||
sp = spBase + stackDepth;
|
||||
|
||||
PodZero(a->typeSets, stackDepth);
|
||||
for (unsigned i = 0; i < stackDepth; i++)
|
||||
a->extraArray[i].reset();
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -2443,7 +2444,7 @@ FrameState::forgetEntry(FrameEntry *fe)
|
||||
}
|
||||
|
||||
if (fe >= sp)
|
||||
a->typeSets[fe - spBase] = NULL;
|
||||
a->extraArray[fe - spBase].reset();
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -326,12 +326,6 @@ class FrameState
|
||||
*/
|
||||
inline void pushInt32(RegisterID payload);
|
||||
|
||||
/*
|
||||
* Pushes an initializer with specified payload, storing whether it is an array
|
||||
* or object whose contents can be initialized in fast paths.
|
||||
*/
|
||||
inline void pushInitializerObject(RegisterID payload, bool array, JSObject *baseobj);
|
||||
|
||||
/*
|
||||
* Pops a value off the operation stack, freeing any of its resources.
|
||||
*/
|
||||
@@ -673,11 +667,18 @@ class FrameState
|
||||
*/
|
||||
void discardFe(FrameEntry *fe);
|
||||
|
||||
/* Get a set with the possible types of a stack fe, or NULL. */
|
||||
inline types::TypeSet *getTypeSet(FrameEntry *fe);
|
||||
|
||||
/* Mark a stack index as holding a particular type set. */
|
||||
inline void learnTypeSet(unsigned slot, types::TypeSet *types);
|
||||
/* Compiler-owned metadata about stack entries, reset on push/pop/copy. */
|
||||
struct StackEntryExtra {
|
||||
bool initArray;
|
||||
JSObject *initObject;
|
||||
types::TypeSet *types;
|
||||
JSAtom *name;
|
||||
void reset() { PodZero(this); }
|
||||
};
|
||||
StackEntryExtra& extra(FrameEntry *fe) {
|
||||
JS_ASSERT(fe >= spBase && fe < sp);
|
||||
return a->extraArray[fe - spBase];
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper function. Tests if a slot's type is null. Condition must
|
||||
@@ -1031,8 +1032,8 @@ class FrameState
|
||||
/* Vector of tracked slot indexes. */
|
||||
Tracker tracker;
|
||||
|
||||
/* Type sets for the stack contents. */
|
||||
types::TypeSet **typeSets;
|
||||
/* Compiler-owned metadata for the stack contents. */
|
||||
StackEntryExtra *extraArray;
|
||||
|
||||
/*
|
||||
* Register ownership state. This can't be used alone; to find whether an
|
||||
|
||||
@@ -191,6 +191,8 @@ InlineReturn(VMFrame &f)
|
||||
void JS_FASTCALL
|
||||
stubs::SlowCall(VMFrame &f, uint32 argc)
|
||||
{
|
||||
printf("CALL\n");
|
||||
|
||||
Value *vp = f.regs.sp - (argc + 2);
|
||||
|
||||
if (!Invoke(f.cx, InvokeArgsAlreadyOnTheStack(vp, argc), 0))
|
||||
@@ -200,6 +202,8 @@ stubs::SlowCall(VMFrame &f, uint32 argc)
|
||||
void JS_FASTCALL
|
||||
stubs::SlowNew(VMFrame &f, uint32 argc)
|
||||
{
|
||||
printf("NEW\n");
|
||||
|
||||
JSContext *cx = f.cx;
|
||||
Value *vp = f.regs.sp - (argc + 2);
|
||||
|
||||
|
||||
@@ -232,6 +232,9 @@ void JS_FASTCALL ConvertToTypedFloat(JSContext *cx, Value *vp);
|
||||
|
||||
void JS_FASTCALL Exception(VMFrame &f);
|
||||
|
||||
JSObject * JS_FASTCALL
|
||||
NewDenseUnallocatedArray(VMFrame &f, uint32 length);
|
||||
|
||||
} /* namespace stubs */
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user