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:
Jan de Mooij 2020-03-27 06:53:18 +00:00
Родитель 4eba5b3fbc
Коммит 51ef388a63
3 изменённых файлов: 263 добавлений и 238 удалений

Просмотреть файл

@ -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
}
}