зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1635375 - Add a buildIC method to WarpBuilder that handles both transpiling and Ion IC cases. r=iain
Having all logic for an IC site in WarpBuilder::buildIC will make it easier to make future changes (like bailing out for cold Baseline ICs). It also enforces all ICs are handled consistently and it de-duplicates code for JSOps that use the same CacheKind. This patch also adds transpiler support for some JSOps (In, InstanceOf, etc) and we now assert the transpiler (buildIC) is called with the right number of inputs (based on the CacheKind). Differential Revision: https://phabricator.services.mozilla.com/D73811
This commit is contained in:
Родитель
c4c65f1eaf
Коммит
4b3230f224
|
@ -1855,6 +1855,7 @@ bool BaselineCacheIRCompiler::init(CacheKind kind) {
|
|||
allowDoubleResult_.emplace(true);
|
||||
|
||||
size_t numInputs = writer_.numInputOperands();
|
||||
MOZ_ASSERT(numInputs == NumInputsForCacheKind(kind));
|
||||
|
||||
// Baseline passes the first 2 inputs in R0/R1, other Values are stored on
|
||||
// the stack.
|
||||
|
|
|
@ -51,6 +51,38 @@ const uint32_t js::jit::CacheIROpArgLengths[] = {
|
|||
#undef ARGLENGTH
|
||||
};
|
||||
|
||||
#ifdef DEBUG
|
||||
size_t js::jit::NumInputsForCacheKind(CacheKind kind) {
|
||||
switch (kind) {
|
||||
case CacheKind::NewObject:
|
||||
case CacheKind::GetIntrinsic:
|
||||
return 0;
|
||||
case CacheKind::GetProp:
|
||||
case CacheKind::TypeOf:
|
||||
case CacheKind::GetIterator:
|
||||
case CacheKind::ToBool:
|
||||
case CacheKind::UnaryArith:
|
||||
case CacheKind::GetName:
|
||||
case CacheKind::BindName:
|
||||
case CacheKind::Call:
|
||||
return 1;
|
||||
case CacheKind::Compare:
|
||||
case CacheKind::GetElem:
|
||||
case CacheKind::GetPropSuper:
|
||||
case CacheKind::SetProp:
|
||||
case CacheKind::In:
|
||||
case CacheKind::HasOwn:
|
||||
case CacheKind::InstanceOf:
|
||||
case CacheKind::BinaryArith:
|
||||
return 2;
|
||||
case CacheKind::GetElemSuper:
|
||||
case CacheKind::SetElem:
|
||||
return 3;
|
||||
}
|
||||
MOZ_CRASH("Invalid kind");
|
||||
}
|
||||
#endif
|
||||
|
||||
void CacheIRWriter::assertSameCompartment(JSObject* obj) {
|
||||
cx_->debugOnlyCheck(obj);
|
||||
}
|
||||
|
|
|
@ -181,6 +181,10 @@ enum class CacheKind : uint8_t {
|
|||
|
||||
extern const char* const CacheKindNames[];
|
||||
|
||||
#ifdef DEBUG
|
||||
extern size_t NumInputsForCacheKind(CacheKind kind);
|
||||
#endif
|
||||
|
||||
enum class CacheOp {
|
||||
#define DEFINE_OP(op, ...) op,
|
||||
CACHE_IR_OPS(DEFINE_OP)
|
||||
|
|
|
@ -281,6 +281,7 @@ bool IonCacheIRCompiler::init() {
|
|||
}
|
||||
|
||||
size_t numInputs = writer_.numInputOperands();
|
||||
MOZ_ASSERT(numInputs == NumInputsForCacheKind(ic_->kind()));
|
||||
|
||||
AllocatableGeneralRegisterSet available;
|
||||
|
||||
|
|
|
@ -6,6 +6,9 @@
|
|||
|
||||
#include "jit/WarpBuilder.h"
|
||||
|
||||
#include "mozilla/DebugOnly.h"
|
||||
|
||||
#include "jit/CacheIR.h"
|
||||
#include "jit/MIR.h"
|
||||
#include "jit/MIRGenerator.h"
|
||||
#include "jit/MIRGraph.h"
|
||||
|
@ -839,15 +842,7 @@ bool WarpBuilder::build_Pos(BytecodeLocation loc) {
|
|||
|
||||
bool WarpBuilder::buildUnaryOp(BytecodeLocation loc) {
|
||||
MDefinition* value = current->pop();
|
||||
|
||||
if (auto* snapshot = getOpSnapshot<WarpCacheIR>(loc)) {
|
||||
return buildCacheIR(loc, snapshot, {value});
|
||||
}
|
||||
|
||||
MInstruction* ins = MUnaryCache::New(alloc(), value);
|
||||
current->add(ins);
|
||||
current->push(ins);
|
||||
return resumeAfter(ins, loc);
|
||||
return buildIC(loc, CacheKind::UnaryArith, {value});
|
||||
}
|
||||
|
||||
bool WarpBuilder::build_Inc(BytecodeLocation loc) { return buildUnaryOp(loc); }
|
||||
|
@ -863,15 +858,7 @@ bool WarpBuilder::build_BitNot(BytecodeLocation loc) {
|
|||
bool WarpBuilder::buildBinaryOp(BytecodeLocation loc) {
|
||||
MDefinition* right = current->pop();
|
||||
MDefinition* left = current->pop();
|
||||
|
||||
if (auto* snapshot = getOpSnapshot<WarpCacheIR>(loc)) {
|
||||
return buildCacheIR(loc, snapshot, {left, right});
|
||||
}
|
||||
|
||||
MInstruction* ins = MBinaryCache::New(alloc(), left, right, MIRType::Value);
|
||||
current->add(ins);
|
||||
current->push(ins);
|
||||
return resumeAfter(ins, loc);
|
||||
return buildIC(loc, CacheKind::BinaryArith, {left, right});
|
||||
}
|
||||
|
||||
bool WarpBuilder::build_Add(BytecodeLocation loc) { return buildBinaryOp(loc); }
|
||||
|
@ -909,15 +896,7 @@ bool WarpBuilder::build_Ursh(BytecodeLocation loc) {
|
|||
bool WarpBuilder::buildCompareOp(BytecodeLocation loc) {
|
||||
MDefinition* right = current->pop();
|
||||
MDefinition* left = current->pop();
|
||||
|
||||
if (auto* snapshot = getOpSnapshot<WarpCacheIR>(loc)) {
|
||||
return buildCacheIR(loc, snapshot, {left, right});
|
||||
}
|
||||
|
||||
MInstruction* ins = MBinaryCache::New(alloc(), left, right, MIRType::Boolean);
|
||||
current->add(ins);
|
||||
current->push(ins);
|
||||
return resumeAfter(ins, loc);
|
||||
return buildIC(loc, CacheKind::Compare, {left, right});
|
||||
}
|
||||
|
||||
bool WarpBuilder::build_Eq(BytecodeLocation loc) { return buildCompareOp(loc); }
|
||||
|
@ -1601,10 +1580,7 @@ bool WarpBuilder::build_EnvCallee(BytecodeLocation loc) {
|
|||
|
||||
bool WarpBuilder::build_Iter(BytecodeLocation loc) {
|
||||
MDefinition* obj = current->pop();
|
||||
MInstruction* ins = MGetIteratorCache::New(alloc(), obj);
|
||||
current->add(ins);
|
||||
current->push(ins);
|
||||
return resumeAfter(ins, loc);
|
||||
return buildIC(loc, CacheKind::GetIterator, {obj});
|
||||
}
|
||||
|
||||
bool WarpBuilder::build_IterNext(BytecodeLocation) {
|
||||
|
@ -1763,19 +1739,9 @@ MConstant* WarpBuilder::globalLexicalEnvConstant() {
|
|||
return constant(ObjectValue(*globalLexical));
|
||||
}
|
||||
|
||||
bool WarpBuilder::buildGetNameOp(BytecodeLocation loc, MDefinition* env) {
|
||||
if (auto* snapshot = getOpSnapshot<WarpCacheIR>(loc)) {
|
||||
return buildCacheIR(loc, snapshot, {env});
|
||||
}
|
||||
|
||||
MGetNameCache* ins = MGetNameCache::New(alloc(), env);
|
||||
current->add(ins);
|
||||
current->push(ins);
|
||||
return resumeAfter(ins, loc);
|
||||
}
|
||||
|
||||
bool WarpBuilder::build_GetName(BytecodeLocation loc) {
|
||||
return buildGetNameOp(loc, current->environmentChain());
|
||||
MDefinition* env = current->environmentChain();
|
||||
return buildIC(loc, CacheKind::GetName, {env});
|
||||
}
|
||||
|
||||
bool WarpBuilder::build_GetGName(BytecodeLocation loc) {
|
||||
|
@ -1800,22 +1766,13 @@ bool WarpBuilder::build_GetGName(BytecodeLocation loc) {
|
|||
return true;
|
||||
}
|
||||
|
||||
return buildGetNameOp(loc, globalLexicalEnvConstant());
|
||||
}
|
||||
|
||||
bool WarpBuilder::buildBindNameOp(BytecodeLocation loc, MDefinition* env) {
|
||||
if (auto* snapshot = getOpSnapshot<WarpCacheIR>(loc)) {
|
||||
return buildCacheIR(loc, snapshot, {env});
|
||||
}
|
||||
|
||||
MBindNameCache* ins = MBindNameCache::New(alloc(), env);
|
||||
current->add(ins);
|
||||
current->push(ins);
|
||||
return resumeAfter(ins, loc);
|
||||
MDefinition* env = globalLexicalEnvConstant();
|
||||
return buildIC(loc, CacheKind::GetName, {env});
|
||||
}
|
||||
|
||||
bool WarpBuilder::build_BindName(BytecodeLocation loc) {
|
||||
return buildBindNameOp(loc, current->environmentChain());
|
||||
MDefinition* env = current->environmentChain();
|
||||
return buildIC(loc, CacheKind::BindName, {env});
|
||||
}
|
||||
|
||||
bool WarpBuilder::build_BindGName(BytecodeLocation loc) {
|
||||
|
@ -1823,31 +1780,13 @@ bool WarpBuilder::build_BindGName(BytecodeLocation loc) {
|
|||
return build_BindName(loc);
|
||||
}
|
||||
|
||||
return buildBindNameOp(loc, globalLexicalEnvConstant());
|
||||
}
|
||||
|
||||
bool WarpBuilder::buildGetPropOp(BytecodeLocation loc, MDefinition* val,
|
||||
MDefinition* id) {
|
||||
// For now pass monitoredResult = true to get the behavior we want (no
|
||||
// TI-related restrictions apply, similar to the Baseline IC).
|
||||
// See also IonGetPropertyICFlags.
|
||||
bool monitoredResult = true;
|
||||
auto* ins = MGetPropertyCache::New(alloc(), val, id, monitoredResult);
|
||||
current->add(ins);
|
||||
current->push(ins);
|
||||
return resumeAfter(ins, loc);
|
||||
MDefinition* env = globalLexicalEnvConstant();
|
||||
return buildIC(loc, CacheKind::BindName, {env});
|
||||
}
|
||||
|
||||
bool WarpBuilder::build_GetProp(BytecodeLocation loc) {
|
||||
PropertyName* name = loc.getPropertyName(script_);
|
||||
MDefinition* val = current->pop();
|
||||
|
||||
if (auto* snapshot = getOpSnapshot<WarpCacheIR>(loc)) {
|
||||
return buildCacheIR(loc, snapshot, {val});
|
||||
}
|
||||
|
||||
MConstant* id = constant(StringValue(name));
|
||||
return buildGetPropOp(loc, val, id);
|
||||
return buildIC(loc, CacheKind::GetProp, {val});
|
||||
}
|
||||
|
||||
bool WarpBuilder::build_CallProp(BytecodeLocation loc) {
|
||||
|
@ -1861,47 +1800,18 @@ bool WarpBuilder::build_Length(BytecodeLocation loc) {
|
|||
bool WarpBuilder::build_GetElem(BytecodeLocation loc) {
|
||||
MDefinition* id = current->pop();
|
||||
MDefinition* val = current->pop();
|
||||
|
||||
if (auto* snapshot = getOpSnapshot<WarpCacheIR>(loc)) {
|
||||
return buildCacheIR(loc, snapshot, {val, id});
|
||||
}
|
||||
|
||||
return buildGetPropOp(loc, val, id);
|
||||
return buildIC(loc, CacheKind::GetElem, {val, id});
|
||||
}
|
||||
|
||||
bool WarpBuilder::build_CallElem(BytecodeLocation loc) {
|
||||
return build_GetElem(loc);
|
||||
}
|
||||
|
||||
bool WarpBuilder::buildSetPropOp(BytecodeLocation loc, MDefinition* obj,
|
||||
MDefinition* id, MDefinition* val) {
|
||||
// We need a GC post barrier and we don't know whether the prototype has
|
||||
// indexed properties so we need to check for holes. We don't need a TI
|
||||
// barrier.
|
||||
bool strict = loc.isStrictSetOp();
|
||||
bool needsPostBarrier = true;
|
||||
bool needsTypeBarrier = false;
|
||||
bool guardHoles = true;
|
||||
auto* ins =
|
||||
MSetPropertyCache::New(alloc(), obj, id, val, strict, needsPostBarrier,
|
||||
needsTypeBarrier, guardHoles);
|
||||
current->add(ins);
|
||||
current->push(val);
|
||||
return resumeAfter(ins, loc);
|
||||
}
|
||||
|
||||
bool WarpBuilder::build_SetProp(BytecodeLocation loc) {
|
||||
PropertyName* name = loc.getPropertyName(script_);
|
||||
MDefinition* val = current->pop();
|
||||
MDefinition* obj = current->pop();
|
||||
|
||||
if (auto* snapshot = getOpSnapshot<WarpCacheIR>(loc)) {
|
||||
current->push(val);
|
||||
return buildCacheIR(loc, snapshot, {obj, val});
|
||||
}
|
||||
|
||||
MConstant* id = constant(StringValue(name));
|
||||
return buildSetPropOp(loc, obj, id, val);
|
||||
current->push(val);
|
||||
return buildIC(loc, CacheKind::SetProp, {obj, val});
|
||||
}
|
||||
|
||||
bool WarpBuilder::build_StrictSetProp(BytecodeLocation loc) {
|
||||
|
@ -1928,19 +1838,17 @@ bool WarpBuilder::build_InitGLexical(BytecodeLocation loc) {
|
|||
MOZ_ASSERT(!script_->hasNonSyntacticScope());
|
||||
|
||||
MDefinition* globalLexical = globalLexicalEnvConstant();
|
||||
MDefinition* val = current->pop();
|
||||
MDefinition* val = current->peek(-1);
|
||||
|
||||
PropertyName* name = loc.getPropertyName(script_);
|
||||
MConstant* id = constant(StringValue(name));
|
||||
|
||||
return buildSetPropOp(loc, globalLexical, id, val);
|
||||
return buildIC(loc, CacheKind::SetProp, {globalLexical, val});
|
||||
}
|
||||
|
||||
bool WarpBuilder::build_SetElem(BytecodeLocation loc) {
|
||||
MDefinition* val = current->pop();
|
||||
MDefinition* id = current->pop();
|
||||
MDefinition* obj = current->pop();
|
||||
return buildSetPropOp(loc, obj, id, val);
|
||||
current->push(val);
|
||||
return buildIC(loc, CacheKind::SetElem, {obj, id, val});
|
||||
}
|
||||
|
||||
bool WarpBuilder::build_StrictSetElem(BytecodeLocation loc) {
|
||||
|
@ -2313,31 +2221,19 @@ bool WarpBuilder::build_InitHiddenElemSetter(BytecodeLocation loc) {
|
|||
bool WarpBuilder::build_In(BytecodeLocation loc) {
|
||||
MDefinition* obj = current->pop();
|
||||
MDefinition* id = current->pop();
|
||||
|
||||
MInCache* ins = MInCache::New(alloc(), id, obj);
|
||||
current->add(ins);
|
||||
current->push(ins);
|
||||
return resumeAfter(ins, loc);
|
||||
return buildIC(loc, CacheKind::In, {id, obj});
|
||||
}
|
||||
|
||||
bool WarpBuilder::build_HasOwn(BytecodeLocation loc) {
|
||||
MDefinition* obj = current->pop();
|
||||
MDefinition* id = current->pop();
|
||||
|
||||
MHasOwnCache* ins = MHasOwnCache::New(alloc(), obj, id);
|
||||
current->add(ins);
|
||||
current->push(ins);
|
||||
return resumeAfter(ins, loc);
|
||||
return buildIC(loc, CacheKind::HasOwn, {id, obj});
|
||||
}
|
||||
|
||||
bool WarpBuilder::build_Instanceof(BytecodeLocation loc) {
|
||||
MDefinition* rhs = current->pop();
|
||||
MDefinition* obj = current->pop();
|
||||
|
||||
MInstanceOfCache* ins = MInstanceOfCache::New(alloc(), obj, rhs);
|
||||
current->add(ins);
|
||||
current->push(ins);
|
||||
return resumeAfter(ins, loc);
|
||||
return buildIC(loc, CacheKind::InstanceOf, {obj, rhs});
|
||||
}
|
||||
|
||||
bool WarpBuilder::build_NewTarget(BytecodeLocation loc) {
|
||||
|
@ -2426,55 +2322,23 @@ bool WarpBuilder::build_GetImport(BytecodeLocation loc) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool WarpBuilder::buildGetPropSuperOp(BytecodeLocation loc, MDefinition* obj,
|
||||
MDefinition* receiver, MDefinition* id) {
|
||||
auto* ins = MGetPropSuperCache::New(alloc(), obj, receiver, id);
|
||||
current->add(ins);
|
||||
current->push(ins);
|
||||
return resumeAfter(ins, loc);
|
||||
}
|
||||
|
||||
bool WarpBuilder::build_GetPropSuper(BytecodeLocation loc) {
|
||||
MDefinition* obj = current->pop();
|
||||
MDefinition* receiver = current->pop();
|
||||
|
||||
PropertyName* name = loc.getPropertyName(script_);
|
||||
MConstant* id = constant(StringValue(name));
|
||||
|
||||
return buildGetPropSuperOp(loc, obj, receiver, id);
|
||||
return buildIC(loc, CacheKind::GetPropSuper, {obj, receiver});
|
||||
}
|
||||
|
||||
bool WarpBuilder::build_GetElemSuper(BytecodeLocation loc) {
|
||||
MDefinition* obj = current->pop();
|
||||
MDefinition* id = current->pop();
|
||||
MDefinition* receiver = current->pop();
|
||||
|
||||
return buildGetPropSuperOp(loc, obj, receiver, id);
|
||||
}
|
||||
|
||||
bool WarpBuilder::buildInitPropOp(BytecodeLocation loc, MDefinition* obj,
|
||||
MDefinition* id, MDefinition* val) {
|
||||
// We need a GC post barrier. We don't need a TI barrier. We pass true for
|
||||
// guardHoles, although the prototype chain is ignored for InitProp/InitElem.
|
||||
bool strict = false;
|
||||
bool needsPostBarrier = true;
|
||||
bool needsTypeBarrier = false;
|
||||
bool guardHoles = true;
|
||||
auto* ins =
|
||||
MSetPropertyCache::New(alloc(), obj, id, val, strict, needsPostBarrier,
|
||||
needsTypeBarrier, guardHoles);
|
||||
current->add(ins);
|
||||
return resumeAfter(ins, loc);
|
||||
return buildIC(loc, CacheKind::GetElemSuper, {obj, id, receiver});
|
||||
}
|
||||
|
||||
bool WarpBuilder::build_InitProp(BytecodeLocation loc) {
|
||||
MDefinition* val = current->pop();
|
||||
MDefinition* obj = current->peek(-1);
|
||||
|
||||
PropertyName* name = loc.getPropertyName(script_);
|
||||
MConstant* id = constant(StringValue(name));
|
||||
|
||||
return buildInitPropOp(loc, obj, id, val);
|
||||
return buildIC(loc, CacheKind::SetProp, {obj, val});
|
||||
}
|
||||
|
||||
bool WarpBuilder::build_InitLockedProp(BytecodeLocation loc) {
|
||||
|
@ -2489,7 +2353,7 @@ bool WarpBuilder::build_InitElem(BytecodeLocation loc) {
|
|||
MDefinition* val = current->pop();
|
||||
MDefinition* id = current->pop();
|
||||
MDefinition* obj = current->peek(-1);
|
||||
return buildInitPropOp(loc, obj, id, val);
|
||||
return buildIC(loc, CacheKind::SetElem, {obj, id, val});
|
||||
}
|
||||
|
||||
bool WarpBuilder::build_InitHiddenElem(BytecodeLocation loc) {
|
||||
|
@ -2507,7 +2371,7 @@ bool WarpBuilder::build_InitElemArray(BytecodeLocation loc) {
|
|||
// TODO: we can probably just use MStoreElement like IonBuilder's fast path.
|
||||
// Simpler than IonBuilder because we don't have to worry about maintaining TI
|
||||
// invariants.
|
||||
return buildInitPropOp(loc, obj, indexConst, val);
|
||||
return buildIC(loc, CacheKind::SetElem, {obj, indexConst, val});
|
||||
}
|
||||
|
||||
bool WarpBuilder::build_InitElemInc(BytecodeLocation loc) {
|
||||
|
@ -2521,7 +2385,7 @@ bool WarpBuilder::build_InitElemInc(BytecodeLocation loc) {
|
|||
current->add(nextIndex);
|
||||
current->push(nextIndex);
|
||||
|
||||
return buildInitPropOp(loc, obj, index, val);
|
||||
return buildIC(loc, CacheKind::SetElem, {obj, index, val});
|
||||
}
|
||||
|
||||
static LambdaFunctionInfo LambdaInfoFromSnapshot(JSFunction* fun,
|
||||
|
@ -2818,13 +2682,171 @@ bool WarpBuilder::build_ThrowSetConst(BytecodeLocation loc) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool WarpBuilder::buildCacheIR(BytecodeLocation loc,
|
||||
const WarpCacheIR* snapshot,
|
||||
std::initializer_list<MDefinition*> inputs) {
|
||||
MDefinitionStackVector inputs_;
|
||||
if (!inputs_.append(inputs.begin(), inputs.end())) {
|
||||
return false;
|
||||
bool WarpBuilder::buildIC(BytecodeLocation loc, CacheKind kind,
|
||||
std::initializer_list<MDefinition*> inputs) {
|
||||
MOZ_ASSERT(loc.opHasIC());
|
||||
|
||||
mozilla::DebugOnly<size_t> numInputs = inputs.size();
|
||||
MOZ_ASSERT(numInputs == NumInputsForCacheKind(kind));
|
||||
|
||||
if (auto* snapshot = getOpSnapshot<WarpCacheIR>(loc)) {
|
||||
MDefinitionStackVector inputs_;
|
||||
if (!inputs_.append(inputs.begin(), inputs.end())) {
|
||||
return false;
|
||||
}
|
||||
return TranspileCacheIRToMIR(mirGen_, loc, current, snapshot, inputs_);
|
||||
}
|
||||
|
||||
return TranspileCacheIRToMIR(mirGen_, loc, current, snapshot, inputs_);
|
||||
// Work around std::initializer_list not defining operator[].
|
||||
auto getInput = [&](size_t index) -> MDefinition* {
|
||||
MOZ_ASSERT(index < numInputs);
|
||||
return inputs.begin()[index];
|
||||
};
|
||||
|
||||
switch (kind) {
|
||||
case CacheKind::UnaryArith: {
|
||||
MOZ_ASSERT(numInputs == 1);
|
||||
auto* ins = MUnaryCache::New(alloc(), getInput(0));
|
||||
current->add(ins);
|
||||
current->push(ins);
|
||||
return resumeAfter(ins, loc);
|
||||
}
|
||||
case CacheKind::BinaryArith: {
|
||||
MOZ_ASSERT(numInputs == 2);
|
||||
auto* ins =
|
||||
MBinaryCache::New(alloc(), getInput(0), getInput(1), MIRType::Value);
|
||||
current->add(ins);
|
||||
current->push(ins);
|
||||
return resumeAfter(ins, loc);
|
||||
}
|
||||
case CacheKind::Compare: {
|
||||
MOZ_ASSERT(numInputs == 2);
|
||||
auto* ins = MBinaryCache::New(alloc(), getInput(0), getInput(1),
|
||||
MIRType::Boolean);
|
||||
current->add(ins);
|
||||
current->push(ins);
|
||||
return resumeAfter(ins, loc);
|
||||
}
|
||||
case CacheKind::In: {
|
||||
MOZ_ASSERT(numInputs == 2);
|
||||
auto* ins = MInCache::New(alloc(), getInput(0), getInput(1));
|
||||
current->add(ins);
|
||||
current->push(ins);
|
||||
return resumeAfter(ins, loc);
|
||||
}
|
||||
case CacheKind::HasOwn: {
|
||||
MOZ_ASSERT(numInputs == 2);
|
||||
// Note: the MHasOwnCache constructor takes obj/id instead of id/obj.
|
||||
auto* ins = MHasOwnCache::New(alloc(), getInput(1), getInput(0));
|
||||
current->add(ins);
|
||||
current->push(ins);
|
||||
return resumeAfter(ins, loc);
|
||||
}
|
||||
case CacheKind::InstanceOf: {
|
||||
MOZ_ASSERT(numInputs == 2);
|
||||
auto* ins = MInstanceOfCache::New(alloc(), getInput(0), getInput(1));
|
||||
current->add(ins);
|
||||
current->push(ins);
|
||||
return resumeAfter(ins, loc);
|
||||
}
|
||||
case CacheKind::BindName: {
|
||||
MOZ_ASSERT(numInputs == 1);
|
||||
auto* ins = MBindNameCache::New(alloc(), getInput(0));
|
||||
current->add(ins);
|
||||
current->push(ins);
|
||||
return resumeAfter(ins, loc);
|
||||
}
|
||||
case CacheKind::GetIterator: {
|
||||
MOZ_ASSERT(numInputs == 1);
|
||||
auto* ins = MGetIteratorCache::New(alloc(), getInput(0));
|
||||
current->add(ins);
|
||||
current->push(ins);
|
||||
return resumeAfter(ins, loc);
|
||||
}
|
||||
case CacheKind::GetName: {
|
||||
MOZ_ASSERT(numInputs == 1);
|
||||
auto* ins = MGetNameCache::New(alloc(), getInput(0));
|
||||
current->add(ins);
|
||||
current->push(ins);
|
||||
return resumeAfter(ins, loc);
|
||||
}
|
||||
case CacheKind::GetProp: {
|
||||
MOZ_ASSERT(numInputs == 1);
|
||||
PropertyName* name = loc.getPropertyName(script_);
|
||||
MConstant* id = constant(StringValue(name));
|
||||
// For now pass monitoredResult = true to get the behavior we want (no
|
||||
// TI-related restrictions apply, similar to the Baseline IC).
|
||||
// See also IonGetPropertyICFlags.
|
||||
bool monitoredResult = true;
|
||||
auto* ins =
|
||||
MGetPropertyCache::New(alloc(), getInput(0), id, monitoredResult);
|
||||
current->add(ins);
|
||||
current->push(ins);
|
||||
return resumeAfter(ins, loc);
|
||||
}
|
||||
case CacheKind::GetElem: {
|
||||
MOZ_ASSERT(numInputs == 2);
|
||||
bool monitoredResult = true; // See GetProp case above.
|
||||
auto* ins = MGetPropertyCache::New(alloc(), getInput(0), getInput(1),
|
||||
monitoredResult);
|
||||
current->add(ins);
|
||||
current->push(ins);
|
||||
return resumeAfter(ins, loc);
|
||||
}
|
||||
case CacheKind::SetProp: {
|
||||
MOZ_ASSERT(numInputs == 2);
|
||||
PropertyName* name = loc.getPropertyName(script_);
|
||||
MConstant* id = constant(StringValue(name));
|
||||
bool strict = loc.isStrictSetOp();
|
||||
bool needsPostBarrier = true;
|
||||
bool needsTypeBarrier = false;
|
||||
bool guardHoles = true;
|
||||
auto* ins = MSetPropertyCache::New(alloc(), getInput(0), id, getInput(1),
|
||||
strict, needsPostBarrier,
|
||||
needsTypeBarrier, guardHoles);
|
||||
current->add(ins);
|
||||
return resumeAfter(ins, loc);
|
||||
}
|
||||
case CacheKind::SetElem: {
|
||||
MOZ_ASSERT(numInputs == 3);
|
||||
bool strict = loc.isStrictSetOp();
|
||||
bool needsPostBarrier = true;
|
||||
bool needsTypeBarrier = false;
|
||||
bool guardHoles = true;
|
||||
auto* ins = MSetPropertyCache::New(alloc(), getInput(0), getInput(1),
|
||||
getInput(2), strict, needsPostBarrier,
|
||||
needsTypeBarrier, guardHoles);
|
||||
current->add(ins);
|
||||
return resumeAfter(ins, loc);
|
||||
}
|
||||
case CacheKind::GetPropSuper: {
|
||||
MOZ_ASSERT(numInputs == 2);
|
||||
PropertyName* name = loc.getPropertyName(script_);
|
||||
MConstant* id = constant(StringValue(name));
|
||||
auto* ins =
|
||||
MGetPropSuperCache::New(alloc(), getInput(0), getInput(1), id);
|
||||
current->add(ins);
|
||||
current->push(ins);
|
||||
return resumeAfter(ins, loc);
|
||||
}
|
||||
case CacheKind::GetElemSuper: {
|
||||
MOZ_ASSERT(numInputs == 3);
|
||||
// Note: CacheIR expects obj/id/receiver but MGetPropSuperCache takes
|
||||
// obj/receiver/id so swap the last two inputs.
|
||||
auto* ins = MGetPropSuperCache::New(alloc(), getInput(0), getInput(2),
|
||||
getInput(1));
|
||||
current->add(ins);
|
||||
current->push(ins);
|
||||
return resumeAfter(ins, loc);
|
||||
}
|
||||
case CacheKind::GetIntrinsic:
|
||||
case CacheKind::ToBool:
|
||||
case CacheKind::TypeOf:
|
||||
case CacheKind::Call:
|
||||
case CacheKind::NewObject:
|
||||
// We're currently not using an IC or transpiling CacheIR for these kinds.
|
||||
MOZ_CRASH("Unexpected kind");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -142,9 +142,8 @@ class MOZ_STACK_CLASS WarpBuilder {
|
|||
MOZ_MUST_USE bool buildBody();
|
||||
MOZ_MUST_USE bool buildEpilogue();
|
||||
|
||||
MOZ_MUST_USE bool buildCacheIR(BytecodeLocation loc,
|
||||
const WarpCacheIR* snapshot,
|
||||
std::initializer_list<MDefinition*> inputs);
|
||||
MOZ_MUST_USE bool buildIC(BytecodeLocation loc, CacheKind kind,
|
||||
std::initializer_list<MDefinition*> inputs);
|
||||
|
||||
MOZ_MUST_USE bool buildEnvironmentChain();
|
||||
MInstruction* buildNamedLambdaEnv(MDefinition* callee, MDefinition* env,
|
||||
|
@ -164,17 +163,6 @@ class MOZ_STACK_CLASS WarpBuilder {
|
|||
MOZ_MUST_USE bool buildDefLexicalOp(BytecodeLocation loc);
|
||||
MOZ_MUST_USE bool buildCallOp(BytecodeLocation loc);
|
||||
|
||||
MOZ_MUST_USE bool buildGetNameOp(BytecodeLocation loc, MDefinition* env);
|
||||
MOZ_MUST_USE bool buildBindNameOp(BytecodeLocation loc, MDefinition* env);
|
||||
MOZ_MUST_USE bool buildGetPropOp(BytecodeLocation loc, MDefinition* val,
|
||||
MDefinition* id);
|
||||
MOZ_MUST_USE bool buildSetPropOp(BytecodeLocation loc, MDefinition* obj,
|
||||
MDefinition* id, MDefinition* val);
|
||||
MOZ_MUST_USE bool buildInitPropOp(BytecodeLocation loc, MDefinition* obj,
|
||||
MDefinition* id, MDefinition* val);
|
||||
MOZ_MUST_USE bool buildGetPropSuperOp(BytecodeLocation loc, MDefinition* obj,
|
||||
MDefinition* receiver, MDefinition* id);
|
||||
|
||||
MOZ_MUST_USE bool buildInitPropGetterSetterOp(BytecodeLocation loc);
|
||||
MOZ_MUST_USE bool buildInitElemGetterSetterOp(BytecodeLocation loc);
|
||||
|
||||
|
|
|
@ -334,6 +334,7 @@ AbortReasonOr<WarpScriptSnapshot*> WarpOracle::createScriptSnapshot(
|
|||
"GetElemSuper with profiling is not supported on x86");
|
||||
}
|
||||
#endif
|
||||
MOZ_TRY(maybeInlineIC(opSnapshots, script, loc));
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -399,6 +400,9 @@ AbortReasonOr<WarpScriptSnapshot*> WarpOracle::createScriptSnapshot(
|
|||
case JSOp::Pos:
|
||||
case JSOp::Inc:
|
||||
case JSOp::Dec:
|
||||
case JSOp::Neg:
|
||||
case JSOp::BitNot:
|
||||
case JSOp::Iter:
|
||||
case JSOp::Eq:
|
||||
case JSOp::Ne:
|
||||
case JSOp::Lt:
|
||||
|
@ -421,6 +425,24 @@ AbortReasonOr<WarpScriptSnapshot*> WarpOracle::createScriptSnapshot(
|
|||
case JSOp::Lsh:
|
||||
case JSOp::Rsh:
|
||||
case JSOp::Ursh:
|
||||
case JSOp::In:
|
||||
case JSOp::HasOwn:
|
||||
case JSOp::Instanceof:
|
||||
case JSOp::GetPropSuper:
|
||||
case JSOp::InitProp:
|
||||
case JSOp::InitLockedProp:
|
||||
case JSOp::InitHiddenProp:
|
||||
case JSOp::InitElem:
|
||||
case JSOp::InitHiddenElem:
|
||||
case JSOp::InitElemArray:
|
||||
case JSOp::InitElemInc:
|
||||
case JSOp::SetName:
|
||||
case JSOp::StrictSetName:
|
||||
case JSOp::SetGName:
|
||||
case JSOp::StrictSetGName:
|
||||
case JSOp::InitGLexical:
|
||||
case JSOp::SetElem:
|
||||
case JSOp::StrictSetElem:
|
||||
MOZ_TRY(maybeInlineIC(opSnapshots, script, loc));
|
||||
break;
|
||||
|
||||
|
@ -461,8 +483,6 @@ AbortReasonOr<WarpScriptSnapshot*> WarpOracle::createScriptSnapshot(
|
|||
case JSOp::InitLexical:
|
||||
case JSOp::GetArg:
|
||||
case JSOp::SetArg:
|
||||
case JSOp::Neg:
|
||||
case JSOp::BitNot:
|
||||
case JSOp::JumpTarget:
|
||||
case JSOp::LoopHead:
|
||||
case JSOp::IfEq:
|
||||
|
@ -496,7 +516,6 @@ AbortReasonOr<WarpScriptSnapshot*> WarpOracle::createScriptSnapshot(
|
|||
case JSOp::SetAliasedVar:
|
||||
case JSOp::InitAliasedLexical:
|
||||
case JSOp::EnvCallee:
|
||||
case JSOp::Iter:
|
||||
case JSOp::IterNext:
|
||||
case JSOp::MoreIter:
|
||||
case JSOp::EndIter:
|
||||
|
@ -508,13 +527,6 @@ AbortReasonOr<WarpScriptSnapshot*> WarpOracle::createScriptSnapshot(
|
|||
case JSOp::FunApply:
|
||||
case JSOp::New:
|
||||
case JSOp::SuperCall:
|
||||
case JSOp::SetName:
|
||||
case JSOp::StrictSetName:
|
||||
case JSOp::SetGName:
|
||||
case JSOp::StrictSetGName:
|
||||
case JSOp::InitGLexical:
|
||||
case JSOp::SetElem:
|
||||
case JSOp::StrictSetElem:
|
||||
case JSOp::DelProp:
|
||||
case JSOp::StrictDelProp:
|
||||
case JSOp::DelElem:
|
||||
|
@ -547,21 +559,10 @@ AbortReasonOr<WarpScriptSnapshot*> WarpOracle::createScriptSnapshot(
|
|||
case JSOp::InitElemSetter:
|
||||
case JSOp::InitHiddenElemGetter:
|
||||
case JSOp::InitHiddenElemSetter:
|
||||
case JSOp::In:
|
||||
case JSOp::HasOwn:
|
||||
case JSOp::Instanceof:
|
||||
case JSOp::NewTarget:
|
||||
case JSOp::CheckIsObj:
|
||||
case JSOp::CheckIsCallable:
|
||||
case JSOp::CheckObjCoercible:
|
||||
case JSOp::GetPropSuper:
|
||||
case JSOp::InitProp:
|
||||
case JSOp::InitLockedProp:
|
||||
case JSOp::InitHiddenProp:
|
||||
case JSOp::InitElem:
|
||||
case JSOp::InitHiddenElem:
|
||||
case JSOp::InitElemArray:
|
||||
case JSOp::InitElemInc:
|
||||
case JSOp::FunWithProto:
|
||||
case JSOp::SpreadCall:
|
||||
case JSOp::SpreadNew:
|
||||
|
|
Загрузка…
Ссылка в новой задаче