зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1618198 part 31 - Turn JSOp whitelist into a blacklist. r=iain
At this point WarpBuilder supports the same JSOps as IonBuilder, except for JSOp::Eval and JSOp::StrictEval (the IonBuilder code for these ops relies on TI and we should consider using either a Call IC or MEval calling a VM function). We now get a compiler warning in WarpOracle and WarpBuilder when a new JSOp is added but not handled in WarpOracle/WarpBuilder. WarpOracle is slightly more efficient now because it has one switch-statement instead of two. Differential Revision: https://phabricator.services.mozilla.com/D68340 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
4eba5b3fbc
Коммит
51ef388a63
|
@ -10,6 +10,7 @@
|
|||
#include "jit/MIRGenerator.h"
|
||||
#include "jit/MIRGraph.h"
|
||||
#include "jit/WarpOracle.h"
|
||||
#include "vm/Opcodes.h"
|
||||
|
||||
#include "jit/JitScript-inl.h"
|
||||
#include "vm/BytecodeIterator-inl.h"
|
||||
|
@ -356,24 +357,26 @@ bool WarpBuilder::buildBody() {
|
|||
|
||||
JSOp op = loc.getOp();
|
||||
|
||||
#define BUILD_OP(OP) \
|
||||
#define BUILD_OP(OP, ...) \
|
||||
case JSOp::OP: \
|
||||
if (MOZ_UNLIKELY(!this->build_##OP(loc))) { \
|
||||
return false; \
|
||||
} \
|
||||
break;
|
||||
switch (op) {
|
||||
WARP_OPCODE_LIST(BUILD_OP)
|
||||
default:
|
||||
// WarpOracle should have aborted compilation.
|
||||
MOZ_CRASH("Unexpected op");
|
||||
}
|
||||
switch (op) { FOR_EACH_OPCODE(BUILD_OP) }
|
||||
#undef BUILD_OP
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#define DEF_OP(OP) \
|
||||
bool WarpBuilder::build_##OP(BytecodeLocation) { \
|
||||
MOZ_CRASH("Unsupported op"); \
|
||||
}
|
||||
WARP_UNSUPPORTED_OPCODE_LIST(DEF_OP)
|
||||
#undef DEF_OP
|
||||
|
||||
bool WarpBuilder::buildEpilogue() { return true; }
|
||||
|
||||
bool WarpBuilder::build_Nop(BytecodeLocation) { return true; }
|
||||
|
|
|
@ -11,216 +11,59 @@
|
|||
#include "jit/MIR.h"
|
||||
#include "jit/MIRBuilderShared.h"
|
||||
#include "jit/WarpOracle.h"
|
||||
#include "vm/Opcodes.h"
|
||||
|
||||
namespace js {
|
||||
namespace jit {
|
||||
|
||||
// JS bytecode ops supported by WarpBuilder. Once we support most opcodes
|
||||
// this should be replaced with the FOR_EACH_OPCODE macro.
|
||||
#define WARP_OPCODE_LIST(_) \
|
||||
_(Nop) \
|
||||
_(NopDestructuring) \
|
||||
_(TryDestructuring) \
|
||||
_(Lineno) \
|
||||
_(DebugLeaveLexicalEnv) \
|
||||
_(Undefined) \
|
||||
_(Void) \
|
||||
_(Null) \
|
||||
_(Hole) \
|
||||
_(Uninitialized) \
|
||||
_(IsConstructing) \
|
||||
_(False) \
|
||||
_(True) \
|
||||
_(Zero) \
|
||||
_(One) \
|
||||
_(Int8) \
|
||||
_(Uint16) \
|
||||
_(Uint24) \
|
||||
_(Int32) \
|
||||
_(Double) \
|
||||
_(ResumeIndex) \
|
||||
_(BigInt) \
|
||||
_(String) \
|
||||
_(Symbol) \
|
||||
_(RegExp) \
|
||||
_(Pop) \
|
||||
_(PopN) \
|
||||
_(Dup) \
|
||||
_(Dup2) \
|
||||
_(DupAt) \
|
||||
_(Swap) \
|
||||
_(Pick) \
|
||||
_(Unpick) \
|
||||
_(GetLocal) \
|
||||
_(SetLocal) \
|
||||
_(InitLexical) \
|
||||
_(GetArg) \
|
||||
_(SetArg) \
|
||||
_(ToNumeric) \
|
||||
_(Pos) \
|
||||
_(Inc) \
|
||||
_(Dec) \
|
||||
_(Neg) \
|
||||
_(BitNot) \
|
||||
_(Add) \
|
||||
_(Sub) \
|
||||
_(Mul) \
|
||||
_(Div) \
|
||||
_(Mod) \
|
||||
_(Pow) \
|
||||
_(BitAnd) \
|
||||
_(BitOr) \
|
||||
_(BitXor) \
|
||||
_(Lsh) \
|
||||
_(Rsh) \
|
||||
_(Ursh) \
|
||||
_(Eq) \
|
||||
_(Ne) \
|
||||
_(Lt) \
|
||||
_(Le) \
|
||||
_(Gt) \
|
||||
_(Ge) \
|
||||
_(StrictEq) \
|
||||
_(StrictNe) \
|
||||
_(JumpTarget) \
|
||||
_(LoopHead) \
|
||||
_(IfEq) \
|
||||
_(IfNe) \
|
||||
_(And) \
|
||||
_(Or) \
|
||||
_(Case) \
|
||||
_(Default) \
|
||||
_(Coalesce) \
|
||||
_(Goto) \
|
||||
_(DebugCheckSelfHosted) \
|
||||
_(DynamicImport) \
|
||||
_(Not) \
|
||||
_(ToString) \
|
||||
_(DefVar) \
|
||||
_(DefLet) \
|
||||
_(DefConst) \
|
||||
_(DefFun) \
|
||||
_(BindVar) \
|
||||
_(MutateProto) \
|
||||
_(Callee) \
|
||||
_(ClassConstructor) \
|
||||
_(DerivedConstructor) \
|
||||
_(ToAsyncIter) \
|
||||
_(ToId) \
|
||||
_(Typeof) \
|
||||
_(TypeofExpr) \
|
||||
_(Arguments) \
|
||||
_(ObjWithProto) \
|
||||
_(GetAliasedVar) \
|
||||
_(SetAliasedVar) \
|
||||
_(InitAliasedLexical) \
|
||||
_(EnvCallee) \
|
||||
_(Iter) \
|
||||
_(IterNext) \
|
||||
_(MoreIter) \
|
||||
_(EndIter) \
|
||||
_(IsNoIter) \
|
||||
_(Call) \
|
||||
_(CallIgnoresRv) \
|
||||
_(CallIter) \
|
||||
_(FunCall) \
|
||||
_(FunApply) \
|
||||
_(New) \
|
||||
_(SuperCall) \
|
||||
_(FunctionThis) \
|
||||
_(GlobalThis) \
|
||||
_(GetName) \
|
||||
_(GetGName) \
|
||||
_(BindName) \
|
||||
_(BindGName) \
|
||||
_(GetProp) \
|
||||
_(CallProp) \
|
||||
_(Length) \
|
||||
_(GetElem) \
|
||||
_(CallElem) \
|
||||
_(SetProp) \
|
||||
_(StrictSetProp) \
|
||||
_(SetName) \
|
||||
_(StrictSetName) \
|
||||
_(SetGName) \
|
||||
_(StrictSetGName) \
|
||||
_(InitGLexical) \
|
||||
_(SetElem) \
|
||||
_(StrictSetElem) \
|
||||
_(DelProp) \
|
||||
_(StrictDelProp) \
|
||||
_(DelElem) \
|
||||
_(StrictDelElem) \
|
||||
_(SetFunName) \
|
||||
_(PushLexicalEnv) \
|
||||
_(PopLexicalEnv) \
|
||||
_(FreshenLexicalEnv) \
|
||||
_(RecreateLexicalEnv) \
|
||||
_(ImplicitThis) \
|
||||
_(GImplicitThis) \
|
||||
_(CheckClassHeritage) \
|
||||
_(CheckThis) \
|
||||
_(CheckThisReinit) \
|
||||
_(CheckReturn) \
|
||||
_(CheckLexical) \
|
||||
_(CheckAliasedLexical) \
|
||||
_(InitHomeObject) \
|
||||
_(SuperBase) \
|
||||
_(SuperFun) \
|
||||
_(BuiltinProto) \
|
||||
_(GetIntrinsic) \
|
||||
_(ImportMeta) \
|
||||
_(CallSiteObj) \
|
||||
_(NewArray) \
|
||||
_(NewArrayCopyOnWrite) \
|
||||
_(NewObject) \
|
||||
_(NewObjectWithGroup) \
|
||||
_(NewInit) \
|
||||
_(Object) \
|
||||
_(InitPropGetter) \
|
||||
_(InitPropSetter) \
|
||||
_(InitHiddenPropGetter) \
|
||||
_(InitHiddenPropSetter) \
|
||||
_(InitElemGetter) \
|
||||
_(InitElemSetter) \
|
||||
_(InitHiddenElemGetter) \
|
||||
_(InitHiddenElemSetter) \
|
||||
_(In) \
|
||||
_(HasOwn) \
|
||||
_(Instanceof) \
|
||||
_(NewTarget) \
|
||||
_(CheckIsObj) \
|
||||
_(CheckIsCallable) \
|
||||
_(CheckObjCoercible) \
|
||||
_(GetImport) \
|
||||
_(GetPropSuper) \
|
||||
_(GetElemSuper) \
|
||||
_(InitProp) \
|
||||
_(InitLockedProp) \
|
||||
_(InitHiddenProp) \
|
||||
_(InitElem) \
|
||||
_(InitHiddenElem) \
|
||||
_(InitElemArray) \
|
||||
_(InitElemInc) \
|
||||
_(Lambda) \
|
||||
_(LambdaArrow) \
|
||||
_(FunWithProto) \
|
||||
_(SpreadCall) \
|
||||
_(SpreadNew) \
|
||||
_(SpreadSuperCall) \
|
||||
_(OptimizeSpreadCall) \
|
||||
_(Debugger) \
|
||||
_(InstrumentationActive) \
|
||||
_(InstrumentationCallback) \
|
||||
_(InstrumentationScriptId) \
|
||||
_(TableSwitch) \
|
||||
_(Rest) \
|
||||
_(Try) \
|
||||
_(Throw) \
|
||||
_(ThrowSetConst) \
|
||||
_(SetRval) \
|
||||
_(Return) \
|
||||
_(RetRval)
|
||||
// JSOps not yet supported by WarpBuilder. See warning at the end of the list.
|
||||
#define WARP_UNSUPPORTED_OPCODE_LIST(_) \
|
||||
/* Intentionally not implemented */ \
|
||||
_(ForceInterpreter) \
|
||||
/* With */ \
|
||||
_(EnterWith) \
|
||||
_(LeaveWith) \
|
||||
/* Eval */ \
|
||||
_(Eval) \
|
||||
_(StrictEval) \
|
||||
_(SpreadEval) \
|
||||
_(StrictSpreadEval) \
|
||||
/* Super */ \
|
||||
_(SetPropSuper) \
|
||||
_(SetElemSuper) \
|
||||
_(StrictSetPropSuper) \
|
||||
_(StrictSetElemSuper) \
|
||||
/* Environments (bug 1366470) */ \
|
||||
_(PushVarEnv) \
|
||||
/* Compound assignment */ \
|
||||
_(GetBoundName) \
|
||||
/* Generators / Async (bug 1317690) */ \
|
||||
_(IsGenClosing) \
|
||||
_(InitialYield) \
|
||||
_(Yield) \
|
||||
_(FinalYieldRval) \
|
||||
_(Resume) \
|
||||
_(ResumeKind) \
|
||||
_(CheckResumeKind) \
|
||||
_(AfterYield) \
|
||||
_(Await) \
|
||||
_(TrySkipAwait) \
|
||||
_(Generator) \
|
||||
_(AsyncAwait) \
|
||||
_(AsyncResolve) \
|
||||
/* Catch/finally */ \
|
||||
_(Exception) \
|
||||
_(Finally) \
|
||||
_(Gosub) \
|
||||
_(Retsub) \
|
||||
/* Misc */ \
|
||||
_(DelName) \
|
||||
_(GetRval) \
|
||||
_(SetIntrinsic) \
|
||||
_(ThrowMsg)
|
||||
// === !! WARNING WARNING WARNING !! ===
|
||||
// Do you really want to sacrifice performance by not implementing this
|
||||
// operation in the optimizing compiler?
|
||||
|
||||
class MIRGenerator;
|
||||
class MIRGraph;
|
||||
|
@ -328,8 +171,8 @@ class MOZ_STACK_CLASS WarpBuilder {
|
|||
bool usesEnvironmentChain() const;
|
||||
MDefinition* walkEnvironmentChain(uint32_t numHops);
|
||||
|
||||
#define BUILD_OP(OP) MOZ_MUST_USE bool build_##OP(BytecodeLocation loc);
|
||||
WARP_OPCODE_LIST(BUILD_OP)
|
||||
#define BUILD_OP(OP, ...) MOZ_MUST_USE bool build_##OP(BytecodeLocation loc);
|
||||
FOR_EACH_OPCODE(BUILD_OP)
|
||||
#undef BUILD_OP
|
||||
|
||||
public:
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "vm/BytecodeIterator.h"
|
||||
#include "vm/BytecodeLocation.h"
|
||||
#include "vm/Instrumentation.h"
|
||||
#include "vm/Opcodes.h"
|
||||
|
||||
#include "vm/BytecodeIterator-inl.h"
|
||||
#include "vm/BytecodeLocation-inl.h"
|
||||
|
@ -192,31 +193,11 @@ AbortReasonOr<WarpScriptSnapshot*> WarpOracle::createScriptSnapshot(
|
|||
mozilla::Maybe<int32_t> instrumentationScriptId;
|
||||
JSObject* instrumentationCallback = nullptr;
|
||||
|
||||
// Analyze the bytecode to look for opcodes we can't compile yet. Eventually
|
||||
// this loop will also be responsible for copying IC data.
|
||||
// Analyze the bytecode. Abort compilation for unsupported ops and create
|
||||
// WarpOpSnapshots.
|
||||
for (BytecodeLocation loc : AllBytecodesIterable(script)) {
|
||||
JSOp op = loc.getOp();
|
||||
switch (op) {
|
||||
#define OP_CASE(OP) case JSOp::OP:
|
||||
WARP_OPCODE_LIST(OP_CASE)
|
||||
#undef OP_CASE
|
||||
break;
|
||||
|
||||
default:
|
||||
#ifdef DEBUG
|
||||
return abort(AbortReason::Disable, "Unsupported opcode: %s",
|
||||
CodeName(op));
|
||||
#else
|
||||
return abort(AbortReason::Disable, "Unsupported opcode: %u",
|
||||
uint8_t(op));
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t offset = loc.bytecodeToOffset(script);
|
||||
|
||||
// Allocate op snapshots for data we'll need off-thread.
|
||||
// TODO: merge this switch-statement with the previous one when we overhaul
|
||||
// WARP_OPCODE_LIST.
|
||||
switch (op) {
|
||||
case JSOp::Arguments:
|
||||
if (script->needsArgsObj()) {
|
||||
|
@ -403,8 +384,206 @@ AbortReasonOr<WarpScriptSnapshot*> WarpOracle::createScriptSnapshot(
|
|||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
case JSOp::Nop:
|
||||
case JSOp::NopDestructuring:
|
||||
case JSOp::TryDestructuring:
|
||||
case JSOp::Lineno:
|
||||
case JSOp::DebugLeaveLexicalEnv:
|
||||
case JSOp::Undefined:
|
||||
case JSOp::Void:
|
||||
case JSOp::Null:
|
||||
case JSOp::Hole:
|
||||
case JSOp::Uninitialized:
|
||||
case JSOp::IsConstructing:
|
||||
case JSOp::False:
|
||||
case JSOp::True:
|
||||
case JSOp::Zero:
|
||||
case JSOp::One:
|
||||
case JSOp::Int8:
|
||||
case JSOp::Uint16:
|
||||
case JSOp::Uint24:
|
||||
case JSOp::Int32:
|
||||
case JSOp::Double:
|
||||
case JSOp::ResumeIndex:
|
||||
case JSOp::BigInt:
|
||||
case JSOp::String:
|
||||
case JSOp::Symbol:
|
||||
case JSOp::Pop:
|
||||
case JSOp::PopN:
|
||||
case JSOp::Dup:
|
||||
case JSOp::Dup2:
|
||||
case JSOp::DupAt:
|
||||
case JSOp::Swap:
|
||||
case JSOp::Pick:
|
||||
case JSOp::Unpick:
|
||||
case JSOp::GetLocal:
|
||||
case JSOp::SetLocal:
|
||||
case JSOp::InitLexical:
|
||||
case JSOp::GetArg:
|
||||
case JSOp::SetArg:
|
||||
case JSOp::ToNumeric:
|
||||
case JSOp::Pos:
|
||||
case JSOp::Inc:
|
||||
case JSOp::Dec:
|
||||
case JSOp::Neg:
|
||||
case JSOp::BitNot:
|
||||
case JSOp::Add:
|
||||
case JSOp::Sub:
|
||||
case JSOp::Mul:
|
||||
case JSOp::Div:
|
||||
case JSOp::Mod:
|
||||
case JSOp::Pow:
|
||||
case JSOp::BitAnd:
|
||||
case JSOp::BitOr:
|
||||
case JSOp::BitXor:
|
||||
case JSOp::Lsh:
|
||||
case JSOp::Rsh:
|
||||
case JSOp::Ursh:
|
||||
case JSOp::Eq:
|
||||
case JSOp::Ne:
|
||||
case JSOp::Lt:
|
||||
case JSOp::Le:
|
||||
case JSOp::Gt:
|
||||
case JSOp::Ge:
|
||||
case JSOp::StrictEq:
|
||||
case JSOp::StrictNe:
|
||||
case JSOp::JumpTarget:
|
||||
case JSOp::LoopHead:
|
||||
case JSOp::IfEq:
|
||||
case JSOp::IfNe:
|
||||
case JSOp::And:
|
||||
case JSOp::Or:
|
||||
case JSOp::Case:
|
||||
case JSOp::Default:
|
||||
case JSOp::Coalesce:
|
||||
case JSOp::Goto:
|
||||
case JSOp::DebugCheckSelfHosted:
|
||||
case JSOp::DynamicImport:
|
||||
case JSOp::Not:
|
||||
case JSOp::ToString:
|
||||
case JSOp::DefVar:
|
||||
case JSOp::DefLet:
|
||||
case JSOp::DefConst:
|
||||
case JSOp::DefFun:
|
||||
case JSOp::BindVar:
|
||||
case JSOp::MutateProto:
|
||||
case JSOp::Callee:
|
||||
case JSOp::ClassConstructor:
|
||||
case JSOp::DerivedConstructor:
|
||||
case JSOp::ToAsyncIter:
|
||||
case JSOp::ToId:
|
||||
case JSOp::Typeof:
|
||||
case JSOp::TypeofExpr:
|
||||
case JSOp::ObjWithProto:
|
||||
case JSOp::GetAliasedVar:
|
||||
case JSOp::SetAliasedVar:
|
||||
case JSOp::InitAliasedLexical:
|
||||
case JSOp::EnvCallee:
|
||||
case JSOp::Iter:
|
||||
case JSOp::IterNext:
|
||||
case JSOp::MoreIter:
|
||||
case JSOp::EndIter:
|
||||
case JSOp::IsNoIter:
|
||||
case JSOp::Call:
|
||||
case JSOp::CallIgnoresRv:
|
||||
case JSOp::CallIter:
|
||||
case JSOp::FunCall:
|
||||
case JSOp::FunApply:
|
||||
case JSOp::New:
|
||||
case JSOp::SuperCall:
|
||||
case JSOp::GetName:
|
||||
case JSOp::GetGName:
|
||||
case JSOp::BindName:
|
||||
case JSOp::BindGName:
|
||||
case JSOp::GetProp:
|
||||
case JSOp::CallProp:
|
||||
case JSOp::Length:
|
||||
case JSOp::GetElem:
|
||||
case JSOp::CallElem:
|
||||
case JSOp::SetProp:
|
||||
case JSOp::StrictSetProp:
|
||||
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:
|
||||
case JSOp::StrictDelElem:
|
||||
case JSOp::SetFunName:
|
||||
case JSOp::PushLexicalEnv:
|
||||
case JSOp::PopLexicalEnv:
|
||||
case JSOp::FreshenLexicalEnv:
|
||||
case JSOp::RecreateLexicalEnv:
|
||||
case JSOp::ImplicitThis:
|
||||
case JSOp::GImplicitThis:
|
||||
case JSOp::CheckClassHeritage:
|
||||
case JSOp::CheckThis:
|
||||
case JSOp::CheckThisReinit:
|
||||
case JSOp::CheckReturn:
|
||||
case JSOp::CheckLexical:
|
||||
case JSOp::CheckAliasedLexical:
|
||||
case JSOp::InitHomeObject:
|
||||
case JSOp::SuperBase:
|
||||
case JSOp::SuperFun:
|
||||
case JSOp::NewArray:
|
||||
case JSOp::NewObject:
|
||||
case JSOp::NewObjectWithGroup:
|
||||
case JSOp::NewInit:
|
||||
case JSOp::InitPropGetter:
|
||||
case JSOp::InitPropSetter:
|
||||
case JSOp::InitHiddenPropGetter:
|
||||
case JSOp::InitHiddenPropSetter:
|
||||
case JSOp::InitElemGetter:
|
||||
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:
|
||||
case JSOp::SpreadSuperCall:
|
||||
case JSOp::OptimizeSpreadCall:
|
||||
case JSOp::Debugger:
|
||||
case JSOp::TableSwitch:
|
||||
case JSOp::Try:
|
||||
case JSOp::Throw:
|
||||
case JSOp::ThrowSetConst:
|
||||
case JSOp::SetRval:
|
||||
case JSOp::Return:
|
||||
case JSOp::RetRval:
|
||||
// Supported by WarpBuilder. Nothing to do.
|
||||
break;
|
||||
|
||||
// Unsupported ops. Don't use a 'default' here, we want to trigger a
|
||||
// compiler warning when adding a new JSOp.
|
||||
#define DEF_CASE(OP) case JSOp::OP:
|
||||
WARP_UNSUPPORTED_OPCODE_LIST(DEF_CASE)
|
||||
#undef DEF_CASE
|
||||
#ifdef DEBUG
|
||||
return abort(AbortReason::Disable, "Unsupported opcode: %s",
|
||||
CodeName(op));
|
||||
#else
|
||||
return abort(AbortReason::Disable, "Unsupported opcode: %u",
|
||||
uint8_t(op));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче