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.
types::AutoEnterAnalysis autoEnterAnalysis(cx);
JS_ASSERT(!script->hasBaselineScript());
if (!emitPrologue())
return Method_Error;
@ -94,7 +96,6 @@ BaselineCompiler::compile()
if (status != Method_Compiled)
return status;
if (!emitEpilogue())
return Method_Error;
@ -111,7 +112,22 @@ BaselineCompiler::compile()
if (!code)
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
// more information.
@ -168,6 +184,7 @@ BaselineCompiler::compile()
return Method_Error;
baselineScript->setMethod(code);
baselineScript->setTemplateScope(templateScope);
script->setBaselineScript(baselineScript);

View File

@ -423,3 +423,21 @@ BaselineInspector::getTemplateObjectForNative(jsbytecode *pc, Native native)
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 *getTemplateObjectForNative(jsbytecode *pc, Native native);
DeclEnvObject *templateDeclEnvObject();
CallObject *templateCallObject();
};
} // namespace jit

View File

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

View File

@ -104,6 +104,10 @@ struct BaselineScript
// Code pointer containing the actual 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.
FallbackICStubSpace fallbackStubSpace_;
@ -225,6 +229,14 @@ struct BaselineScript
method_ = code;
}
JSObject *templateScope() const {
return templateScope_;
}
void setTemplateScope(JSObject *templateScope) {
JS_ASSERT(!templateScope_);
templateScope_ = templateScope;
}
void toggleBarriers(bool enabled) {
method()->togglePreBarriers(enabled);
}

View File

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

View File

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

View File

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

View File

@ -491,6 +491,8 @@ NewCallObject(JSContext *cx, HandleScript script,
HandleShape shape, HandleTypeObject type, HeapSlot *slots)
{
JSObject *obj = CallObject::create(cx, script, shape, type, slots);
if (!obj)
return nullptr;
#ifdef JSGC_GENERATIONAL
// 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)
{
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();
}
inline void setEnclosingScope(HandleObject obj);
void setEnclosingScope(HandleObject obj);
/*
* Get or set an aliased variable contained in this scope. Unaliased