mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-01 08:42:13 +00:00
Bug 928776 - Create template call and decl env objects in baseline, r=jandem.
This commit is contained in:
parent
bb44a6154b
commit
b5e0c11e2f
@ -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);
|
||||||
|
|
||||||
|
@ -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>();
|
||||||
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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++) {
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -697,6 +697,8 @@ class IonBuilder : public MIRGenerator
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JSAtomState &names() { return compartment->runtimeFromAnyThread()->atomState; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool init();
|
bool init();
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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>(),
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user