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.
|
||||
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);
|
||||
|
||||
|
@ -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>();
|
||||
}
|
||||
|
@ -113,6 +113,9 @@ class BaselineInspector
|
||||
|
||||
JSObject *getTemplateObject(jsbytecode *pc);
|
||||
JSObject *getTemplateObjectForNative(jsbytecode *pc, Native native);
|
||||
|
||||
DeclEnvObject *templateDeclEnvObject();
|
||||
CallObject *templateCallObject();
|
||||
};
|
||||
|
||||
} // namespace jit
|
||||
|
@ -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++) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -697,6 +697,8 @@ class IonBuilder : public MIRGenerator
|
||||
return NULL;
|
||||
}
|
||||
|
||||
JSAtomState &names() { return compartment->runtimeFromAnyThread()->atomState; }
|
||||
|
||||
private:
|
||||
bool init();
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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>(),
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user