[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);
JSCompartment *saved = cx->compartment;
cx->compartment = compartment;
cx->setCompartment(compartment);
JSObject *obj = JS_NewGlobalObject(cx, clasp);
cx->compartment = saved;
cx->setCompartment(saved);
return obj;
}

View File

@@ -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;
}

View File

@@ -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. */

View File

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

View File

@@ -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();

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
# 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

View File

@@ -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
}

View File

@@ -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 *

View File

@@ -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;
}

View File

@@ -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();

View File

@@ -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);

View File

@@ -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)

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
* 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));

View File

@@ -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();

View File

@@ -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));
}

View File

@@ -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

View File

@@ -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

View File

@@ -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);

View File

@@ -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 */
/*