[INFER] More fixes for stock JM behavior, bug 647048.

This commit is contained in:
Brian Hackett
2011-04-01 17:26:34 -07:00
parent 34e3947863
commit 1aa9a11b32
19 changed files with 229 additions and 100 deletions

View File

@@ -3070,9 +3070,9 @@ JS_NewCompartmentAndGlobalObject(JSContext *cx, JSClass *clasp, JSPrincipals *pr
AutoHoldCompartment hold(compartment); AutoHoldCompartment hold(compartment);
JSCompartment *saved = cx->compartment; JSCompartment *saved = cx->compartment;
cx->compartment = compartment; cx->setCompartment(compartment);
JSObject *obj = JS_NewGlobalObject(cx, clasp); JSObject *obj = JS_NewGlobalObject(cx, clasp);
cx->compartment = saved; cx->setCompartment(saved);
return obj; return obj;
} }

View File

@@ -107,6 +107,8 @@
#include "jstracer.h" #include "jstracer.h"
#include "jsvector.h" #include "jsvector.h"
#include "jswrapper.h" #include "jswrapper.h"
#include "methodjit/StubCalls.h"
#include "methodjit/StubCalls-inl.h"
#include "jsatominlines.h" #include "jsatominlines.h"
#include "jscntxtinlines.h" #include "jscntxtinlines.h"
@@ -667,8 +669,11 @@ array_length_setter(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value
if (oldcap > newlen) if (oldcap > newlen)
obj->shrinkDenseArrayElements(cx, newlen); obj->shrinkDenseArrayElements(cx, newlen);
jsuint oldinit = obj->getDenseArrayInitializedLength(); jsuint oldinit = obj->getDenseArrayInitializedLength();
if (oldinit > newlen) if (oldinit > newlen) {
obj->setDenseArrayInitializedLength(newlen); obj->setDenseArrayInitializedLength(newlen);
if (!cx->typeInferenceEnabled())
obj->backfillDenseArrayHoles();
}
} else if (oldlen - newlen < (1 << 24)) { } else if (oldlen - newlen < (1 << 24)) {
do { do {
--oldlen; --oldlen;
@@ -3499,10 +3504,11 @@ NewArray(JSContext *cx, jsuint length, JSObject *proto)
if (allocateCapacity) { if (allocateCapacity) {
if (!obj->ensureSlots(cx, length)) if (!obj->ensureSlots(cx, length))
return NULL; return NULL;
if (!cx->typeInferenceEnabled())
obj->backfillDenseArrayHoles();
} }
if (!cx->typeInferenceEnabled())
obj->backfillDenseArrayHoles();
return obj; return obj;
} }
@@ -3521,14 +3527,7 @@ NewDenseAllocatedArray(JSContext *cx, uint32 length, JSObject *proto)
JSObject * JS_FASTCALL JSObject * JS_FASTCALL
NewDenseAllocatedEmptyArray(JSContext *cx, uint length, JSObject *proto) NewDenseAllocatedEmptyArray(JSContext *cx, uint length, JSObject *proto)
{ {
JSObject *obj = NewArray<true>(cx, length, proto); return 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;
} }
JSObject * JS_FASTCALL JSObject * JS_FASTCALL
@@ -3537,6 +3536,20 @@ NewDenseUnallocatedArray(JSContext *cx, uint32 length, JSObject *proto)
return NewArray<false>(cx, length, 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 * JSObject *
NewDenseCopiedArray(JSContext *cx, uintN length, Value *vp, JSObject *proto) NewDenseCopiedArray(JSContext *cx, uintN length, Value *vp, JSObject *proto)
{ {
@@ -3546,11 +3559,15 @@ NewDenseCopiedArray(JSContext *cx, uintN length, Value *vp, JSObject *proto)
JS_ASSERT(obj->getDenseArrayCapacity() >= length); JS_ASSERT(obj->getDenseArrayCapacity() >= length);
if (vp) { 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)); memcpy(obj->getDenseArrayElements(), vp, length * sizeof(Value));
obj->setDenseArrayInitializedLength(length);
} else {
obj->setDenseArrayInitializedLength(0);
} }
return obj; return obj;

View File

@@ -89,9 +89,16 @@ inline JSObject::EnsureDenseResult
JSObject::ensureDenseArrayElements(JSContext *cx, uintN index, uintN extra) JSObject::ensureDenseArrayElements(JSContext *cx, uintN index, uintN extra)
{ {
JS_ASSERT(isDenseArray()); JS_ASSERT(isDenseArray());
uintN currentCapacity = numSlots(); uintN currentCapacity = numSlots();
uintN initLength = getDenseArrayInitializedLength(); 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; uintN requiredCapacity;
if (extra == 1) { if (extra == 1) {
/* Optimize for the common case. */ /* Optimize for the common case. */

View File

@@ -1958,6 +1958,7 @@ JSContext::resetCompartment()
} }
compartment = scopeobj->compartment(); compartment = scopeobj->compartment();
inferenceEnabled = compartment->types.inferenceEnabled;
if (isExceptionPending()) if (isExceptionPending())
wrapPendingException(); wrapPendingException();

View File

@@ -1648,6 +1648,8 @@ struct JSContext
/* GC heap compartment. */ /* GC heap compartment. */
JSCompartment *compartment; JSCompartment *compartment;
inline void setCompartment(JSCompartment *compartment);
/* Currently executing frame and regs, set by stack operations. */ /* Currently executing frame and regs, set by stack operations. */
JS_REQUIRES_STACK JS_REQUIRES_STACK
JSFrameRegs *regs; JSFrameRegs *regs;
@@ -1939,6 +1941,8 @@ struct JSContext
bool profilingEnabled; bool profilingEnabled;
#endif #endif
bool inferenceEnabled;
/* Caller must be holding runtime->gcLock. */ /* Caller must be holding runtime->gcLock. */
void updateJITEnabled(); void updateJITEnabled();

View File

@@ -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 #ifdef DEBUG
# define EVAL_CACHE_METER(x) (cx->compartment->evalCacheMeter.x++) # define EVAL_CACHE_METER(x) (cx->compartment->evalCacheMeter.x++)
#else #else
@@ -597,7 +604,7 @@ class PreserveCompartment {
} }
~PreserveCompartment() { ~PreserveCompartment() {
cx->compartment = oldCompartment; cx->setCompartment(oldCompartment);
} }
}; };
@@ -608,14 +615,14 @@ class SwitchToCompartment : public PreserveCompartment {
: PreserveCompartment(cx) : PreserveCompartment(cx)
{ {
JS_GUARD_OBJECT_NOTIFIER_INIT; JS_GUARD_OBJECT_NOTIFIER_INIT;
cx->compartment = newCompartment; cx->setCompartment(newCompartment);
} }
SwitchToCompartment(JSContext *cx, JSObject *target JS_GUARD_OBJECT_NOTIFIER_PARAM) SwitchToCompartment(JSContext *cx, JSObject *target JS_GUARD_OBJECT_NOTIFIER_PARAM)
: PreserveCompartment(cx) : PreserveCompartment(cx)
{ {
JS_GUARD_OBJECT_NOTIFIER_INIT; JS_GUARD_OBJECT_NOTIFIER_INIT;
cx->compartment = target->getCompartment(); cx->setCompartment(target->getCompartment());
} }
JS_DECL_USE_GUARD_OBJECT_NOTIFIER JS_DECL_USE_GUARD_OBJECT_NOTIFIER

View File

@@ -402,12 +402,12 @@ JS_ClearTrap(JSContext *cx, JSScript *script, jsbytecode *pc,
#ifdef JS_METHODJIT #ifdef JS_METHODJIT
if (script->hasJITCode()) { if (script->hasJITCode()) {
JSCompartment *oldCompartment = cx->compartment; JSCompartment *oldCompartment = cx->compartment;
cx->compartment = script->compartment; cx->setCompartment(script->compartment);
mjit::Recompiler recompiler(cx, script); mjit::Recompiler recompiler(cx, script);
recompiler.recompile(); recompiler.recompile();
cx->compartment = oldCompartment; cx->setCompartment(oldCompartment);
} }
#endif #endif
} }

View File

@@ -226,7 +226,7 @@ UseNewType(JSContext *cx, JSScript *script, jsbytecode *pc);
inline bool inline bool
JSContext::typeInferenceEnabled() JSContext::typeInferenceEnabled()
{ {
return compartment->types.inferenceEnabled; return inferenceEnabled;
} }
inline js::types::TypeObject * inline js::types::TypeObject *

View File

@@ -389,13 +389,13 @@ AutoCompartment::enter()
if (origin != destination) { if (origin != destination) {
LeaveTrace(context); LeaveTrace(context);
context->compartment = destination; context->setCompartment(destination);
JSObject *scopeChain = target->getGlobal(); JSObject *scopeChain = target->getGlobal();
JS_ASSERT(scopeChain->isNative()); JS_ASSERT(scopeChain->isNative());
frame.construct(); frame.construct();
if (!context->stack().pushDummyFrame(context, *scopeChain, &frame.ref())) { if (!context->stack().pushDummyFrame(context, *scopeChain, &frame.ref())) {
context->compartment = origin; context->setCompartment(origin);
return false; return false;
} }

View File

@@ -1916,11 +1916,15 @@ mjit::Compiler::generateMethod()
END_CASE(JSOP_SETELEM); END_CASE(JSOP_SETELEM);
BEGIN_CASE(JSOP_CALLNAME) BEGIN_CASE(JSOP_CALLNAME)
{
uint32 index = fullAtomIndex(PC);
prepareStubCall(Uses(0)); prepareStubCall(Uses(0));
masm.move(Imm32(fullAtomIndex(PC)), Registers::ArgReg1); masm.move(Imm32(index), Registers::ArgReg1);
INLINE_STUBCALL(stubs::CallName); INLINE_STUBCALL(stubs::CallName);
pushSyncedEntry(0); pushSyncedEntry(0);
pushSyncedEntry(1); pushSyncedEntry(1);
frame.extra(frame.peek(-2)).name = script->getAtom(index);
}
END_CASE(JSOP_CALLNAME) END_CASE(JSOP_CALLNAME)
BEGIN_CASE(JSOP_EVAL) BEGIN_CASE(JSOP_EVAL)
@@ -1959,7 +1963,11 @@ mjit::Compiler::generateMethod()
END_CASE(JSOP_CALL) END_CASE(JSOP_CALL)
BEGIN_CASE(JSOP_NAME) 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) END_CASE(JSOP_NAME)
BEGIN_CASE(JSOP_DOUBLE) BEGIN_CASE(JSOP_DOUBLE)
@@ -2480,9 +2488,13 @@ mjit::Compiler::generateMethod()
BEGIN_CASE(JSOP_GETGNAME) BEGIN_CASE(JSOP_GETGNAME)
BEGIN_CASE(JSOP_CALLGNAME) 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) if (op == JSOP_CALLGNAME)
jsop_callgname_epilogue(); jsop_callgname_epilogue();
}
END_CASE(JSOP_GETGNAME) END_CASE(JSOP_GETGNAME)
BEGIN_CASE(JSOP_SETGNAME) BEGIN_CASE(JSOP_SETGNAME)
@@ -2629,8 +2641,11 @@ mjit::Compiler::generateMethod()
unsigned nuses = analyze::GetUseCount(script, oldPC - script->code); unsigned nuses = analyze::GetUseCount(script, oldPC - script->code);
unsigned ndefs = analyze::GetDefCount(script, oldPC - script->code); unsigned ndefs = analyze::GetDefCount(script, oldPC - script->code);
for (unsigned i = 0; i < ndefs; i++) { for (unsigned i = 0; i < ndefs; i++) {
frame.learnTypeSet(opinfo->stackDepth - nuses + i, FrameEntry *fe = frame.getStack(opinfo->stackDepth - nuses + i);
script->types->pushed(oldPC - script->code, 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) if (callingNew)
frame.discardFe(origThis); 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 * 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 * 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); js_ReportOutOfMemory(cx);
return false; 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]); types::TypeSet::Clone(cx, types, &callIC.argTypes[0]);
for (unsigned i = 0; i < argc; i++) { 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]); types::TypeSet::Clone(cx, types, &callIC.argTypes[i + 1]);
} }
} }
@@ -3587,6 +3608,91 @@ mjit::Compiler::inlineCallHelper(uint32 callImmArgc, bool callingNew)
#endif #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. */ /* Maximum number of calls we will inline at the same site. */
static const uint32 INLINE_SITE_LIMIT = 5; 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 *origCallee = frame.peek(-(argc + 2));
FrameEntry *origThis = frame.peek(-(argc + 1)); 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) if (!types || types->getKnownTypeTag(cx) != JSVAL_TYPE_OBJECT)
return Compile_InlineAbort; return Compile_InlineAbort;
@@ -4497,7 +4603,7 @@ mjit::Compiler::testSingletonPropertyTypes(FrameEntry *top, jsid id, bool *testO
{ {
*testObject = false; *testObject = false;
types::TypeSet *types = frame.getTypeSet(top); types::TypeSet *types = frame.extra(top).types;
if (!types) if (!types)
return false; return false;
@@ -4619,7 +4725,7 @@ mjit::Compiler::jsop_setprop(JSAtom *atom, bool usePropCache)
pic.atom = atom; pic.atom = atom;
if (monitored(PC)) { if (monitored(PC)) {
types::TypeSet *types = frame.getTypeSet(rhs); types::TypeSet *types = frame.extra(rhs).types;
pic.typeMonitored = true; pic.typeMonitored = true;
pic.rhsTypes = (types::ClonedTypeSet *) ::js_calloc(sizeof(types::ClonedTypeSet)); pic.rhsTypes = (types::ClonedTypeSet *) ::js_calloc(sizeof(types::ClonedTypeSet));
if (!pic.rhsTypes) { if (!pic.rhsTypes) {
@@ -6048,7 +6154,10 @@ mjit::Compiler::jsop_newinit()
INLINE_STUBCALL(stubs::NewInitObject); INLINE_STUBCALL(stubs::NewInitObject);
} }
frame.takeReg(Registers::ReturnReg); 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; return true;
} }
@@ -6211,6 +6320,10 @@ mjit::Compiler::jumpAndTrace(Jump j, jsbytecode *target, Jump *slow, bool *tramp
# if JS_MONOIC # if JS_MONOIC
ic.addrLabel = stubcc.masm.moveWithPatch(ImmPtr(NULL), Registers::ArgReg1); 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 # endif
/* Save and restore compiler-tracked PC, so cx->regs is right in InvokeTracer. */ /* 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, Jump no = stubcc.masm.branchTestPtr(Assembler::Zero, Registers::ReturnReg,
Registers::ReturnReg); Registers::ReturnReg);
if (!cx->typeInferenceEnabled())
stubcc.masm.loadPtr(FrameAddress(offsetof(VMFrame, regs.fp)), JSFrameReg);
stubcc.masm.jump(Registers::ReturnReg); stubcc.masm.jump(Registers::ReturnReg);
no.linkTo(stubcc.masm.label(), &stubcc.masm); no.linkTo(stubcc.masm.label(), &stubcc.masm);
if (!cx->typeInferenceEnabled())
stubcc.masm.loadPtr(FrameAddress(offsetof(VMFrame, regs.fp)), JSFrameReg);
#ifdef JS_MONOIC #ifdef JS_MONOIC
nonzero.linkTo(stubcc.masm.label(), &stubcc.masm);
ic.jumpTarget = target; ic.jumpTarget = target;
ic.fastTrampoline = !consistent; ic.fastTrampoline = !consistent;
ic.trampolineStart = stubcc.masm.label(); ic.trampolineStart = stubcc.masm.label();

View File

@@ -680,6 +680,7 @@ class Compiler : public BaseCompiler
/* Fast builtins. */ /* Fast builtins. */
JSObject *pushedSingleton(unsigned pushed); JSObject *pushedSingleton(unsigned pushed);
CompileStatus callArrayBuiltin(uint32 argc, bool callingNew);
CompileStatus inlineNativeFunction(uint32 argc, bool callingNew); CompileStatus inlineNativeFunction(uint32 argc, bool callingNew);
CompileStatus inlineScriptedFunction(uint32 argc, bool callingNew); CompileStatus inlineScriptedFunction(uint32 argc, bool callingNew);
CompileStatus compileMathAbsInt(FrameEntry *arg); CompileStatus compileMathAbsInt(FrameEntry *arg);

View File

@@ -321,7 +321,7 @@ mjit::Compiler::inlineNativeFunction(uint32 argc, bool callingNew)
{ {
JS_ASSERT(!callingNew); JS_ASSERT(!callingNew);
if (cx->typeInferenceEnabled()) if (!cx->typeInferenceEnabled())
return Compile_InlineAbort; return Compile_InlineAbort;
if (applyTricks == LazyArgsObj) if (applyTricks == LazyArgsObj)

View File

@@ -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 * special equality operator on either object, if that passes then
* this is a pointer comparison. * this is a pointer comparison.
*/ */
types::TypeSet *lhsTypes = frame.getTypeSet(lhs); types::TypeSet *lhsTypes = frame.extra(lhs).types;
types::TypeSet *rhsTypes = frame.getTypeSet(rhs); types::TypeSet *rhsTypes = frame.extra(rhs).types;
types::ObjectKind lhsKind = types::ObjectKind lhsKind =
lhsTypes ? lhsTypes->getKnownObjectKind(cx) : types::OBJECT_UNKNOWN; lhsTypes ? lhsTypes->getKnownObjectKind(cx) : types::OBJECT_UNKNOWN;
types::ObjectKind rhsKind = types::ObjectKind rhsKind =
@@ -1189,7 +1189,7 @@ mjit::Compiler::jsop_setelem(bool popGuaranteed)
frame.forgetConstantData(obj); frame.forgetConstantData(obj);
if (cx->typeInferenceEnabled()) { if (cx->typeInferenceEnabled()) {
types::TypeSet *types = frame.getTypeSet(obj); types::TypeSet *types = frame.extra(obj).types;
types::ObjectKind kind = types types::ObjectKind kind = types
? types->getKnownObjectKind(cx) ? types->getKnownObjectKind(cx)
: types::OBJECT_UNKNOWN; : types::OBJECT_UNKNOWN;
@@ -1509,7 +1509,7 @@ mjit::Compiler::jsop_getelem(bool isCall)
frame.forgetConstantData(obj); frame.forgetConstantData(obj);
if (cx->typeInferenceEnabled()) { if (cx->typeInferenceEnabled()) {
types::TypeSet *types = frame.getTypeSet(obj); types::TypeSet *types = frame.extra(obj).types;
types::ObjectKind kind = types types::ObjectKind kind = types
? types->getKnownObjectKind(cx) ? types->getKnownObjectKind(cx)
: types::OBJECT_UNKNOWN; : types::OBJECT_UNKNOWN;
@@ -1950,7 +1950,7 @@ mjit::Compiler::jsop_initmethod()
JSAtom *atom = script->getAtom(fullAtomIndex(PC)); JSAtom *atom = script->getAtom(fullAtomIndex(PC));
/* Initializers with INITMETHOD are not fast yet. */ /* Initializers with INITMETHOD are not fast yet. */
JS_ASSERT(!obj->initializerObject()); JS_ASSERT(!frame.extra(obj).initObject);
prepareStubCall(Uses(2)); prepareStubCall(Uses(2));
masm.move(ImmPtr(atom), Registers::ArgReg1); masm.move(ImmPtr(atom), Registers::ArgReg1);
@@ -1964,7 +1964,7 @@ mjit::Compiler::jsop_initprop()
FrameEntry *fe = frame.peek(-1); FrameEntry *fe = frame.peek(-1);
JSAtom *atom = script->getAtom(fullAtomIndex(PC)); JSAtom *atom = script->getAtom(fullAtomIndex(PC));
JSObject *baseobj = obj->initializerObject(); JSObject *baseobj = frame.extra(obj).initObject;
if (!baseobj || monitored(PC)) { if (!baseobj || monitored(PC)) {
prepareStubCall(Uses(2)); prepareStubCall(Uses(2));
@@ -2005,7 +2005,7 @@ mjit::Compiler::jsop_initelem()
* cases, as well as those where INITELEM is used on an object initializer * cases, as well as those where INITELEM is used on an object initializer
* or a non-fast array 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]); JSOp next = JSOp(PC[JSOP_INITELEM_LENGTH]);
prepareStubCall(Uses(3)); prepareStubCall(Uses(3));

View File

@@ -138,14 +138,6 @@ class FrameEntry
bool isCopy() const { return !!copy; } bool isCopy() const { return !!copy; }
bool isCopied() const { return copied; } bool isCopied() const { return copied; }
inline bool initializerArray() {
return initArray;
}
inline JSObject *initializerObject() {
return initObject;
}
private: private:
void setType(JSValueType type_) { void setType(JSValueType type_) {
type.setConstant(); type.setConstant();

View File

@@ -204,7 +204,7 @@ FrameState::pop()
forgetAllRegs(fe); forgetAllRegs(fe);
a->typeSets[fe - spBase] = NULL; a->extraArray[fe - spBase].reset();
} }
inline void inline void
@@ -238,7 +238,7 @@ FrameState::rawPush()
if (!sp->isTracked()) if (!sp->isTracked())
addToTracker(sp); addToTracker(sp);
a->typeSets[sp - spBase] = NULL; a->extraArray[sp - spBase].reset();
return sp++; return sp++;
} }
@@ -403,16 +403,6 @@ FrameState::pushInt32(RegisterID payload)
regstate(payload).associate(fe, RematInfo::DATA); 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 inline void
FrameState::pushUntypedPayload(JSValueType type, RegisterID payload) FrameState::pushUntypedPayload(JSValueType type, RegisterID payload)
{ {
@@ -870,20 +860,6 @@ FrameState::forgetType(FrameEntry *fe)
fe->type.setMemory(); 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 inline void
FrameState::learnType(FrameEntry *fe, JSValueType type, bool unsync) FrameState::learnType(FrameEntry *fe, JSValueType type, bool unsync)
{ {
@@ -1058,7 +1034,8 @@ FrameState::getOrTrack(uint32 index)
inline FrameEntry * inline FrameEntry *
FrameState::getStack(uint32 slot) FrameState::getStack(uint32 slot)
{ {
JS_ASSERT(slot < uint32(sp - spBase)); if (slot >= uint32(sp - spBase))
return NULL;
return getOrTrack(uint32(&spBase[slot] - entries)); return getOrTrack(uint32(&spBase[slot] - entries));
} }

View File

@@ -127,7 +127,7 @@ FrameState::pushActiveFrame(JSScript *script, uint32 argc,
size_t totalBytes = sizeof(ActiveFrame) + size_t totalBytes = sizeof(ActiveFrame) +
sizeof(FrameEntry) * nentries + // entries[] sizeof(FrameEntry) * nentries + // entries[]
sizeof(FrameEntry *) * nentries + // tracker.entries sizeof(FrameEntry *) * nentries + // tracker.entries
sizeof(types::TypeSet *) * script->nslots; // typeSets sizeof(StackEntryExtra) * script->nslots; // extraArray
uint8 *cursor = (uint8 *)cx->calloc(totalBytes); uint8 *cursor = (uint8 *)cx->calloc(totalBytes);
if (!cursor) if (!cursor)
@@ -164,8 +164,8 @@ FrameState::pushActiveFrame(JSScript *script, uint32 argc,
newa->tracker.entries = (FrameEntry **)cursor; newa->tracker.entries = (FrameEntry **)cursor;
cursor += sizeof(FrameEntry *) * nentries; cursor += sizeof(FrameEntry *) * nentries;
newa->typeSets = (types::TypeSet **)cursor; newa->extraArray = (StackEntryExtra *)cursor;
cursor += sizeof(types::TypeSet *) * script->nslots; cursor += sizeof(StackEntryExtra) * script->nslots;
JS_ASSERT(reinterpret_cast<uint8 *>(newa) + totalBytes == cursor); JS_ASSERT(reinterpret_cast<uint8 *>(newa) + totalBytes == cursor);
@@ -1108,7 +1108,8 @@ FrameState::discardForJoin(jsbytecode *target, uint32 stackDepth)
sp = spBase + stackDepth; sp = spBase + stackDepth;
PodZero(a->typeSets, stackDepth); for (unsigned i = 0; i < stackDepth; i++)
a->extraArray[i].reset();
return true; return true;
} }
@@ -2443,7 +2444,7 @@ FrameState::forgetEntry(FrameEntry *fe)
} }
if (fe >= sp) if (fe >= sp)
a->typeSets[fe - spBase] = NULL; a->extraArray[fe - spBase].reset();
} }
void void

View File

@@ -326,12 +326,6 @@ class FrameState
*/ */
inline void pushInt32(RegisterID payload); 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. * Pops a value off the operation stack, freeing any of its resources.
*/ */
@@ -673,11 +667,18 @@ class FrameState
*/ */
void discardFe(FrameEntry *fe); void discardFe(FrameEntry *fe);
/* Get a set with the possible types of a stack fe, or NULL. */ /* Compiler-owned metadata about stack entries, reset on push/pop/copy. */
inline types::TypeSet *getTypeSet(FrameEntry *fe); struct StackEntryExtra {
bool initArray;
/* Mark a stack index as holding a particular type set. */ JSObject *initObject;
inline void learnTypeSet(unsigned slot, types::TypeSet *types); 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 * Helper function. Tests if a slot's type is null. Condition must
@@ -1031,8 +1032,8 @@ class FrameState
/* Vector of tracked slot indexes. */ /* Vector of tracked slot indexes. */
Tracker tracker; Tracker tracker;
/* Type sets for the stack contents. */ /* Compiler-owned metadata for the stack contents. */
types::TypeSet **typeSets; StackEntryExtra *extraArray;
/* /*
* Register ownership state. This can't be used alone; to find whether an * Register ownership state. This can't be used alone; to find whether an

View File

@@ -191,6 +191,8 @@ InlineReturn(VMFrame &f)
void JS_FASTCALL void JS_FASTCALL
stubs::SlowCall(VMFrame &f, uint32 argc) stubs::SlowCall(VMFrame &f, uint32 argc)
{ {
printf("CALL\n");
Value *vp = f.regs.sp - (argc + 2); Value *vp = f.regs.sp - (argc + 2);
if (!Invoke(f.cx, InvokeArgsAlreadyOnTheStack(vp, argc), 0)) if (!Invoke(f.cx, InvokeArgsAlreadyOnTheStack(vp, argc), 0))
@@ -200,6 +202,8 @@ stubs::SlowCall(VMFrame &f, uint32 argc)
void JS_FASTCALL void JS_FASTCALL
stubs::SlowNew(VMFrame &f, uint32 argc) stubs::SlowNew(VMFrame &f, uint32 argc)
{ {
printf("NEW\n");
JSContext *cx = f.cx; JSContext *cx = f.cx;
Value *vp = f.regs.sp - (argc + 2); Value *vp = f.regs.sp - (argc + 2);

View File

@@ -232,6 +232,9 @@ void JS_FASTCALL ConvertToTypedFloat(JSContext *cx, Value *vp);
void JS_FASTCALL Exception(VMFrame &f); void JS_FASTCALL Exception(VMFrame &f);
JSObject * JS_FASTCALL
NewDenseUnallocatedArray(VMFrame &f, uint32 length);
} /* namespace stubs */ } /* namespace stubs */
/* /*