mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 940852 - Record baseline frame information before Ion compilation, r=jandem.
This commit is contained in:
parent
1390b9dc37
commit
28436d4108
@ -1637,6 +1637,13 @@ IonCompile(JSContext *cx, JSScript *script,
|
||||
|
||||
BaselineInspector inspector(script);
|
||||
|
||||
BaselineFrameInspector *baselineFrameInspector = nullptr;
|
||||
if (baselineFrame) {
|
||||
baselineFrameInspector = NewBaselineFrameInspector(temp, baselineFrame);
|
||||
if (!baselineFrameInspector)
|
||||
return AbortReason_Alloc;
|
||||
}
|
||||
|
||||
AutoFlushCache afc("IonCompile", cx->runtime()->jitRuntime());
|
||||
|
||||
AutoTempAllocatorRooter root(cx, temp);
|
||||
@ -1647,7 +1654,7 @@ IonCompile(JSContext *cx, JSScript *script,
|
||||
IonBuilder *builder = alloc->new_<IonBuilder>((JSContext *) nullptr,
|
||||
CompileCompartment::get(cx->compartment()),
|
||||
temp, graph, constraints,
|
||||
&inspector, info, baselineFrame);
|
||||
&inspector, info, baselineFrameInspector);
|
||||
if (!builder)
|
||||
return AbortReason_Alloc;
|
||||
|
||||
|
@ -37,9 +37,73 @@ using namespace js::jit;
|
||||
using mozilla::DebugOnly;
|
||||
using mozilla::Maybe;
|
||||
|
||||
class jit::BaselineFrameInspector
|
||||
{
|
||||
public:
|
||||
types::Type thisType;
|
||||
JSObject *singletonScopeChain;
|
||||
|
||||
Vector<types::Type, 4, IonAllocPolicy> argTypes;
|
||||
Vector<types::Type, 4, IonAllocPolicy> varTypes;
|
||||
|
||||
BaselineFrameInspector(TempAllocator *temp)
|
||||
: thisType(types::Type::UndefinedType()),
|
||||
singletonScopeChain(nullptr),
|
||||
argTypes(*temp),
|
||||
varTypes(*temp)
|
||||
{}
|
||||
};
|
||||
|
||||
BaselineFrameInspector *
|
||||
jit::NewBaselineFrameInspector(TempAllocator *temp, BaselineFrame *frame)
|
||||
{
|
||||
JS_ASSERT(frame);
|
||||
|
||||
BaselineFrameInspector *inspector = temp->lifoAlloc()->new_<BaselineFrameInspector>(temp);
|
||||
if (!inspector)
|
||||
return nullptr;
|
||||
|
||||
// Note: copying the actual values into a temporary structure for use
|
||||
// during compilation could capture nursery pointers, so the values' types
|
||||
// are recorded instead.
|
||||
|
||||
inspector->thisType = types::GetValueType(frame->thisValue());
|
||||
|
||||
if (frame->scopeChain()->hasSingletonType())
|
||||
inspector->singletonScopeChain = frame->scopeChain();
|
||||
|
||||
JSScript *script = frame->script();
|
||||
|
||||
if (script->function()) {
|
||||
if (!inspector->argTypes.reserve(frame->numFormalArgs()))
|
||||
return nullptr;
|
||||
for (size_t i = 0; i < frame->numFormalArgs(); i++) {
|
||||
if (script->formalIsAliased(i))
|
||||
inspector->argTypes.infallibleAppend(types::Type::UndefinedType());
|
||||
else if (!script->argsObjAliasesFormals())
|
||||
inspector->argTypes.infallibleAppend(types::GetValueType(frame->unaliasedFormal(i)));
|
||||
else if (frame->hasArgsObj())
|
||||
inspector->argTypes.infallibleAppend(types::GetValueType(frame->argsObj().arg(i)));
|
||||
else
|
||||
inspector->argTypes.infallibleAppend(types::Type::UndefinedType());
|
||||
}
|
||||
}
|
||||
|
||||
if (!inspector->varTypes.reserve(frame->script()->nfixed))
|
||||
return nullptr;
|
||||
for (size_t i = 0; i < frame->script()->nfixed; i++) {
|
||||
if (script->varIsAliased(i))
|
||||
inspector->varTypes.infallibleAppend(types::Type::UndefinedType());
|
||||
else
|
||||
inspector->varTypes.infallibleAppend(types::GetValueType(frame->unaliasedVar(i)));
|
||||
}
|
||||
|
||||
return inspector;
|
||||
}
|
||||
|
||||
IonBuilder::IonBuilder(JSContext *analysisContext, CompileCompartment *comp, TempAllocator *temp, MIRGraph *graph,
|
||||
types::CompilerConstraintList *constraints,
|
||||
BaselineInspector *inspector, CompileInfo *info, BaselineFrame *baselineFrame,
|
||||
BaselineInspector *inspector, CompileInfo *info, BaselineFrameInspector *baselineFrame,
|
||||
size_t inliningDepth, uint32_t loopDepth)
|
||||
: MIRGenerator(comp, temp, graph, info),
|
||||
backgroundCodegen_(nullptr),
|
||||
@ -859,7 +923,7 @@ IonBuilder::initParameters()
|
||||
// frame to determine possible initial types for 'this' and parameters.
|
||||
|
||||
if (thisTypes->empty() && baselineFrame_) {
|
||||
if (!thisTypes->addType(types::GetValueType(baselineFrame_->thisValue()), alloc_->lifoAlloc()))
|
||||
if (!thisTypes->addType(baselineFrame_->thisType, alloc_->lifoAlloc()))
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -872,7 +936,7 @@ IonBuilder::initParameters()
|
||||
if (types->empty() && baselineFrame_ &&
|
||||
!script_->baselineScript()->modifiesArguments())
|
||||
{
|
||||
if (!types->addType(types::GetValueType(baselineFrame_->argv()[i]), alloc_->lifoAlloc()))
|
||||
if (!types->addType(baselineFrame_->argTypes[i], alloc_->lifoAlloc()))
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -5814,30 +5878,23 @@ IonBuilder::newPendingLoopHeader(MBasicBlock *predecessor, jsbytecode *pc, bool
|
||||
|
||||
MPhi *phi = block->getSlot(i)->toPhi();
|
||||
|
||||
// Get the value from the baseline frame.
|
||||
Value existingValue;
|
||||
// Get the type from the baseline frame.
|
||||
types::Type existingType = types::Type::UndefinedType();
|
||||
uint32_t arg = i - info().firstArgSlot();
|
||||
uint32_t var = i - info().firstLocalSlot();
|
||||
if (info().fun() && i == info().thisSlot()) {
|
||||
existingValue = baselineFrame_->thisValue();
|
||||
} else if (arg < info().nargs()) {
|
||||
if (info().needsArgsObj())
|
||||
existingValue = baselineFrame_->argsObj().arg(arg);
|
||||
else
|
||||
existingValue = baselineFrame_->unaliasedFormal(arg);
|
||||
} else {
|
||||
existingValue = baselineFrame_->unaliasedVar(var);
|
||||
}
|
||||
if (info().fun() && i == info().thisSlot())
|
||||
existingType = baselineFrame_->thisType;
|
||||
else if (arg < info().nargs())
|
||||
existingType = baselineFrame_->argTypes[arg];
|
||||
else
|
||||
existingType = baselineFrame_->varTypes[var];
|
||||
|
||||
// Extract typeset from value.
|
||||
MIRType type = existingValue.isDouble()
|
||||
? MIRType_Double
|
||||
: MIRTypeFromValueType(existingValue.extractNonDoubleType());
|
||||
types::Type ntype = types::GetValueType(existingValue);
|
||||
types::TemporaryTypeSet *typeSet =
|
||||
alloc_->lifoAlloc()->new_<types::TemporaryTypeSet>(ntype);
|
||||
alloc_->lifoAlloc()->new_<types::TemporaryTypeSet>(existingType);
|
||||
if (!typeSet)
|
||||
return nullptr;
|
||||
MIRType type = MIRTypeFromValueType(typeSet->getKnownTypeTag());
|
||||
phi->addBackedgeType(type, typeSet);
|
||||
}
|
||||
}
|
||||
@ -9110,7 +9167,7 @@ IonBuilder::jsop_this()
|
||||
}
|
||||
|
||||
if (thisTypes->getKnownTypeTag() == JSVAL_TYPE_OBJECT ||
|
||||
(thisTypes->empty() && baselineFrame_ && baselineFrame_->thisValue().isObject()))
|
||||
(thisTypes->empty() && baselineFrame_ && baselineFrame_->thisType.isSomeObject()))
|
||||
{
|
||||
// This is safe, because if the entry type of |this| is an object, it
|
||||
// will necessarily be an object throughout the entire function. OSR
|
||||
@ -9294,12 +9351,13 @@ IonBuilder::hasStaticScopeObject(ScopeCoordinate sc, JSObject **pcall)
|
||||
// entering the Ion code a different call object will be created.
|
||||
|
||||
if (script() == outerScript && baselineFrame_ && info().osrPc()) {
|
||||
JSObject *scope = baselineFrame_->scopeChain();
|
||||
if (scope->is<CallObject>() &&
|
||||
scope->as<CallObject>().callee().nonLazyScript() == outerScript)
|
||||
JSObject *singletonScope = baselineFrame_->singletonScopeChain;
|
||||
if (singletonScope &&
|
||||
singletonScope->is<CallObject>() &&
|
||||
singletonScope->as<CallObject>().callee().nonLazyScript() == outerScript)
|
||||
{
|
||||
JS_ASSERT(scope->hasSingletonType());
|
||||
*pcall = scope;
|
||||
JS_ASSERT(singletonScope->hasSingletonType());
|
||||
*pcall = singletonScope;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -24,6 +24,12 @@ namespace jit {
|
||||
class CodeGenerator;
|
||||
class CallInfo;
|
||||
class BaselineInspector;
|
||||
class BaselineFrameInspector;
|
||||
|
||||
// Records information about a baseline frame for compilation that is stable
|
||||
// when later used off thread.
|
||||
BaselineFrameInspector *
|
||||
NewBaselineFrameInspector(TempAllocator *temp, BaselineFrame *frame);
|
||||
|
||||
class IonBuilder : public MIRGenerator
|
||||
{
|
||||
@ -207,7 +213,7 @@ class IonBuilder : public MIRGenerator
|
||||
public:
|
||||
IonBuilder(JSContext *analysisContext, CompileCompartment *comp, TempAllocator *temp, MIRGraph *graph,
|
||||
types::CompilerConstraintList *constraints,
|
||||
BaselineInspector *inspector, CompileInfo *info, BaselineFrame *baselineFrame,
|
||||
BaselineInspector *inspector, CompileInfo *info, BaselineFrameInspector *baselineFrame,
|
||||
size_t inliningDepth = 0, uint32_t loopDepth = 0);
|
||||
|
||||
bool build();
|
||||
@ -745,7 +751,7 @@ class IonBuilder : public MIRGenerator
|
||||
bool init();
|
||||
|
||||
JSContext *analysisContext;
|
||||
BaselineFrame *baselineFrame_;
|
||||
BaselineFrameInspector *baselineFrame_;
|
||||
AbortReason abortReason_;
|
||||
TypeRepresentationSetHash *reprSetHash_;
|
||||
|
||||
|
@ -209,6 +209,10 @@ class Type
|
||||
return (JSValueType) data;
|
||||
}
|
||||
|
||||
bool isSomeObject() const {
|
||||
return data == JSVAL_TYPE_OBJECT || data > JSVAL_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
bool isAnyObject() const {
|
||||
return data == JSVAL_TYPE_OBJECT;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user