Bug 928776 - Create template call and decl env objects in baseline, r=jandem.

This commit is contained in:
Brian Hackett 2013-10-23 08:01:41 -06:00
parent bb44a6154b
commit b5e0c11e2f
11 changed files with 80 additions and 40 deletions

View File

@ -87,6 +87,8 @@ BaselineCompiler::compile()
// Pin analysis info during compilation. // Pin analysis info during compilation.
types::AutoEnterAnalysis autoEnterAnalysis(cx); types::AutoEnterAnalysis autoEnterAnalysis(cx);
JS_ASSERT(!script->hasBaselineScript());
if (!emitPrologue()) if (!emitPrologue())
return Method_Error; return Method_Error;
@ -94,7 +96,6 @@ BaselineCompiler::compile()
if (status != Method_Compiled) if (status != Method_Compiled)
return status; return status;
if (!emitEpilogue()) if (!emitEpilogue())
return Method_Error; return Method_Error;
@ -111,7 +112,22 @@ BaselineCompiler::compile()
if (!code) if (!code)
return Method_Error; return Method_Error;
JS_ASSERT(!script->hasBaselineScript()); JSObject *templateScope = nullptr;
if (script->function()) {
RootedFunction fun(cx, script->function());
if (fun->isHeavyweight()) {
templateScope = CallObject::createTemplateObject(cx, script, gc::TenuredHeap);
if (!templateScope)
return Method_Error;
if (fun->isNamedLambda()) {
RootedObject declEnvObject(cx, DeclEnvObject::createTemplateObject(cx, fun, gc::TenuredHeap));
if (!declEnvObject)
return Method_Error;
templateScope->as<ScopeObject>().setEnclosingScope(declEnvObject);
}
}
}
// Encode the pc mapping table. See PCMappingIndexEntry for // Encode the pc mapping table. See PCMappingIndexEntry for
// more information. // more information.
@ -168,6 +184,7 @@ BaselineCompiler::compile()
return Method_Error; return Method_Error;
baselineScript->setMethod(code); baselineScript->setMethod(code);
baselineScript->setTemplateScope(templateScope);
script->setBaselineScript(baselineScript); script->setBaselineScript(baselineScript);

View File

@ -423,3 +423,21 @@ BaselineInspector::getTemplateObjectForNative(jsbytecode *pc, Native native)
return NULL; return NULL;
} }
DeclEnvObject *
BaselineInspector::templateDeclEnvObject()
{
JSObject *res = &templateCallObject()->as<ScopeObject>().enclosingScope();
JS_ASSERT(res);
return &res->as<DeclEnvObject>();
}
CallObject *
BaselineInspector::templateCallObject()
{
JSObject *res = baselineScript()->templateScope();
JS_ASSERT(res);
return &res->as<CallObject>();
}

View File

@ -113,6 +113,9 @@ class BaselineInspector
JSObject *getTemplateObject(jsbytecode *pc); JSObject *getTemplateObject(jsbytecode *pc);
JSObject *getTemplateObjectForNative(jsbytecode *pc, Native native); JSObject *getTemplateObjectForNative(jsbytecode *pc, Native native);
DeclEnvObject *templateDeclEnvObject();
CallObject *templateCallObject();
}; };
} // namespace jit } // namespace jit

View File

@ -40,6 +40,7 @@ PCMappingSlotInfo::ToSlotLocation(const StackValue *stackVal)
BaselineScript::BaselineScript(uint32_t prologueOffset, uint32_t spsPushToggleOffset) BaselineScript::BaselineScript(uint32_t prologueOffset, uint32_t spsPushToggleOffset)
: method_(nullptr), : method_(nullptr),
templateScope_(nullptr),
fallbackStubSpace_(), fallbackStubSpace_(),
prologueOffset_(prologueOffset), prologueOffset_(prologueOffset),
#ifdef DEBUG #ifdef DEBUG
@ -411,6 +412,8 @@ void
BaselineScript::trace(JSTracer *trc) BaselineScript::trace(JSTracer *trc)
{ {
MarkIonCode(trc, &method_, "baseline-method"); MarkIonCode(trc, &method_, "baseline-method");
if (templateScope_)
MarkObject(trc, &templateScope_, "baseline-template-scope");
// Mark all IC stub codes hanging off the IC stub entries. // Mark all IC stub codes hanging off the IC stub entries.
for (size_t i = 0; i < numICEntries(); i++) { for (size_t i = 0; i < numICEntries(); i++) {

View File

@ -104,6 +104,10 @@ struct BaselineScript
// Code pointer containing the actual method. // Code pointer containing the actual method.
HeapPtr<IonCode> method_; HeapPtr<IonCode> method_;
// For heavyweight scripts, template objects to use for the call object and
// decl env object (linked via the call object's enclosing scope).
HeapPtrObject templateScope_;
// Allocated space for fallback stubs. // Allocated space for fallback stubs.
FallbackICStubSpace fallbackStubSpace_; FallbackICStubSpace fallbackStubSpace_;
@ -225,6 +229,14 @@ struct BaselineScript
method_ = code; method_ = code;
} }
JSObject *templateScope() const {
return templateScope_;
}
void setTemplateScope(JSObject *templateScope) {
JS_ASSERT(!templateScope_);
templateScope_ = templateScope;
}
void toggleBarriers(bool enabled) { void toggleBarriers(bool enabled) {
method()->togglePreBarriers(enabled); method()->togglePreBarriers(enabled);
} }

View File

@ -4525,20 +4525,9 @@ IonBuilder::inlineCalls(CallInfo &callInfo, ObjectVector &targets,
MInstruction * MInstruction *
IonBuilder::createDeclEnvObject(MDefinition *callee, MDefinition *scope) IonBuilder::createDeclEnvObject(MDefinition *callee, MDefinition *scope)
{ {
// Create a template CallObject that we'll use to generate inline object // Get a template CallObject that we'll use to generate inline object
// creation. Even though this template will get discarded at the end of // creation.
// compilation, it is used by the background compilation thread and thus DeclEnvObject *templateObj = inspector->templateDeclEnvObject();
// cannot use the Nursery.
RootedFunction fun(cx, info().fun());
RootedObject templateObj(cx, DeclEnvObject::createTemplateObject(cx, fun, gc::TenuredHeap));
if (!templateObj)
return nullptr;
// Add dummy values on the slot of the template object such as we do not try
// mark uninitialized values.
templateObj->setFixedSlot(DeclEnvObject::enclosingScopeSlot(), MagicValue(JS_GENERIC_MAGIC));
templateObj->setFixedSlot(DeclEnvObject::lambdaSlot(), MagicValue(JS_GENERIC_MAGIC));
// One field is added to the function to handle its name. This cannot be a // One field is added to the function to handle its name. This cannot be a
// dynamic slot because there is still plenty of room on the DeclEnv object. // dynamic slot because there is still plenty of room on the DeclEnv object.
@ -4563,15 +4552,9 @@ IonBuilder::createDeclEnvObject(MDefinition *callee, MDefinition *scope)
MInstruction * MInstruction *
IonBuilder::createCallObject(MDefinition *callee, MDefinition *scope) IonBuilder::createCallObject(MDefinition *callee, MDefinition *scope)
{ {
// Create a template CallObject that we'll use to generate inline object // Get a template CallObject that we'll use to generate inline object
// creation. Even though this template will get discarded at the end of // creation.
// compilation, it is used by the background compilation thread and thus CallObject *templateObj = inspector->templateCallObject();
// cannot use the Nursery.
RootedScript scriptRoot(cx, script());
RootedObject templateObj(cx, CallObject::createTemplateObject(cx, scriptRoot, gc::TenuredHeap));
if (!templateObj)
return nullptr;
// If the CallObject needs dynamic slots, allocate those now. // If the CallObject needs dynamic slots, allocate those now.
MInstruction *slots; MInstruction *slots;
@ -4631,11 +4614,11 @@ IonBuilder::createThisScripted(MDefinition *callee)
// and thus invalidation. // and thus invalidation.
MInstruction *getProto; MInstruction *getProto;
if (!invalidatedIdempotentCache()) { if (!invalidatedIdempotentCache()) {
MGetPropertyCache *getPropCache = MGetPropertyCache::New(callee, cx->names().prototype); MGetPropertyCache *getPropCache = MGetPropertyCache::New(callee, names().prototype);
getPropCache->setIdempotent(); getPropCache->setIdempotent();
getProto = getPropCache; getProto = getPropCache;
} else { } else {
MCallGetProperty *callGetProp = MCallGetProperty::New(callee, cx->names().prototype, MCallGetProperty *callGetProp = MCallGetProperty::New(callee, names().prototype,
/* callprop = */ false); /* callprop = */ false);
callGetProp->setIdempotent(); callGetProp->setIdempotent();
getProto = callGetProp; getProto = callGetProp;
@ -4658,7 +4641,7 @@ IonBuilder::getSingletonPrototype(JSFunction *target)
if (targetType->unknownProperties()) if (targetType->unknownProperties())
return nullptr; return nullptr;
jsid protoid = NameToId(cx->names().prototype); jsid protoid = NameToId(names().prototype);
types::HeapTypeSetKey protoProperty = targetType->property(protoid); types::HeapTypeSetKey protoProperty = targetType->property(protoid);
return protoProperty.singleton(constraints()); return protoProperty.singleton(constraints());
@ -6216,12 +6199,12 @@ IonBuilder::getStaticName(JSObject *staticObject, PropertyName *name, bool *psuc
if (staticObject->is<GlobalObject>()) { if (staticObject->is<GlobalObject>()) {
// Optimize undefined, NaN, and Infinity. // Optimize undefined, NaN, and Infinity.
if (name == cx->names().undefined) if (name == names().undefined)
return pushConstant(UndefinedValue()); return pushConstant(UndefinedValue());
if (name == cx->names().NaN) if (name == names().NaN)
return pushConstant(cx->runtime()->NaNValue); return pushConstant(compartment->runtimeFromAnyThread()->NaNValue);
if (name == cx->names().Infinity) if (name == names().Infinity)
return pushConstant(cx->runtime()->positiveInfinityValue); return pushConstant(compartment->runtimeFromAnyThread()->positiveInfinityValue);
} }
// For the fastest path, the property must be found, and it must be found // For the fastest path, the property must be found, and it must be found
@ -9448,7 +9431,7 @@ IonBuilder::jsop_instanceof()
break; break;
types::HeapTypeSetKey protoProperty = types::HeapTypeSetKey protoProperty =
rhsType->property(NameToId(cx->names().prototype)); rhsType->property(NameToId(names().prototype));
JSObject *protoObject = protoProperty.singleton(constraints()); JSObject *protoObject = protoProperty.singleton(constraints());
if (!protoObject) if (!protoObject)
break; break;

View File

@ -697,6 +697,8 @@ class IonBuilder : public MIRGenerator
return NULL; return NULL;
} }
JSAtomState &names() { return compartment->runtimeFromAnyThread()->atomState; }
private: private:
bool init(); bool init();

View File

@ -8266,7 +8266,7 @@ class MNewDeclEnvObject : public MNullaryInstruction
{ {
CompilerRootObject templateObj_; CompilerRootObject templateObj_;
MNewDeclEnvObject(HandleObject templateObj) MNewDeclEnvObject(JSObject *templateObj)
: MNullaryInstruction(), : MNullaryInstruction(),
templateObj_(templateObj) templateObj_(templateObj)
{ {
@ -8276,7 +8276,7 @@ class MNewDeclEnvObject : public MNullaryInstruction
public: public:
INSTRUCTION_HEADER(NewDeclEnvObject); INSTRUCTION_HEADER(NewDeclEnvObject);
static MNewDeclEnvObject *New(HandleObject templateObj) { static MNewDeclEnvObject *New(JSObject *templateObj) {
return new MNewDeclEnvObject(templateObj); return new MNewDeclEnvObject(templateObj);
} }
@ -8293,7 +8293,7 @@ class MNewCallObject : public MUnaryInstruction
CompilerRootObject templateObj_; CompilerRootObject templateObj_;
bool needsSingletonType_; bool needsSingletonType_;
MNewCallObject(HandleObject templateObj, bool needsSingletonType, MDefinition *slots) MNewCallObject(JSObject *templateObj, bool needsSingletonType, MDefinition *slots)
: MUnaryInstruction(slots), : MUnaryInstruction(slots),
templateObj_(templateObj), templateObj_(templateObj),
needsSingletonType_(needsSingletonType) needsSingletonType_(needsSingletonType)
@ -8304,7 +8304,7 @@ class MNewCallObject : public MUnaryInstruction
public: public:
INSTRUCTION_HEADER(NewCallObject) INSTRUCTION_HEADER(NewCallObject)
static MNewCallObject *New(HandleObject templateObj, bool needsSingletonType, MDefinition *slots) { static MNewCallObject *New(JSObject *templateObj, bool needsSingletonType, MDefinition *slots) {
return new MNewCallObject(templateObj, needsSingletonType, slots); return new MNewCallObject(templateObj, needsSingletonType, slots);
} }

View File

@ -491,6 +491,8 @@ NewCallObject(JSContext *cx, HandleScript script,
HandleShape shape, HandleTypeObject type, HeapSlot *slots) HandleShape shape, HandleTypeObject type, HeapSlot *slots)
{ {
JSObject *obj = CallObject::create(cx, script, shape, type, slots); JSObject *obj = CallObject::create(cx, script, shape, type, slots);
if (!obj)
return nullptr;
#ifdef JSGC_GENERATIONAL #ifdef JSGC_GENERATIONAL
// The JIT creates call objects in the nursery, so elides barriers for // The JIT creates call objects in the nursery, so elides barriers for

View File

@ -165,7 +165,7 @@ js::ScopeCoordinateFunctionScript(JSContext *cx, JSScript *script, jsbytecode *p
/*****************************************************************************/ /*****************************************************************************/
inline void void
ScopeObject::setEnclosingScope(HandleObject obj) ScopeObject::setEnclosingScope(HandleObject obj)
{ {
JS_ASSERT_IF(obj->is<CallObject>() || obj->is<DeclEnvObject>() || obj->is<BlockObject>(), JS_ASSERT_IF(obj->is<CallObject>() || obj->is<DeclEnvObject>() || obj->is<BlockObject>(),

View File

@ -171,7 +171,7 @@ class ScopeObject : public JSObject
return getReservedSlot(SCOPE_CHAIN_SLOT).toObject(); return getReservedSlot(SCOPE_CHAIN_SLOT).toObject();
} }
inline void setEnclosingScope(HandleObject obj); void setEnclosingScope(HandleObject obj);
/* /*
* Get or set an aliased variable contained in this scope. Unaliased * Get or set an aliased variable contained in this scope. Unaliased