Bug 1541404 part 1 - Move initEnvironmentChain from BaselineCompiler to BaselineCodeGen. r=djvj

Also has some other minor prologue-related changes. The interpreter code here
is slightly less optimal than it could be, but that will be easier to address
in follow-up changes.

Differential Revision: https://phabricator.services.mozilla.com/D25930

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Jan de Mooij 2019-04-12 14:08:03 +00:00
Родитель 2fcda12c4d
Коммит fba2d34e37
2 изменённых файлов: 96 добавлений и 22 удалений

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

@ -1005,18 +1005,89 @@ void BaselineCompilerCodeGen::emitPreInitEnvironmentChain(
template <>
void BaselineInterpreterCodeGen::emitPreInitEnvironmentChain(
Register nonFunctionEnv) {
MOZ_CRASH("NYI: interpreter emitPreInitEnvironmentChain");
Label notFunction, done;
masm.branchTestPtr(Assembler::NonZero, frame.addressOfCalleeToken(),
Imm32(CalleeTokenScriptBit), &notFunction);
{
masm.storePtr(ImmPtr(nullptr), frame.addressOfEnvironmentChain());
masm.jump(&done);
}
masm.bind(&notFunction);
{ masm.storePtr(nonFunctionEnv, frame.addressOfEnvironmentChain()); }
masm.bind(&done);
}
template <>
bool BaselineCompilerCodeGen::initEnvironmentChain() {
void BaselineCompilerCodeGen::emitInitFrameFields() {
masm.store32(Imm32(0), frame.addressOfFlags());
}
template <>
void BaselineInterpreterCodeGen::emitInitFrameFields() {
MOZ_CRASH("NYI: interpreter emitInitFrameFields");
}
template <>
template <typename F1, typename F2>
bool BaselineCompilerCodeGen::initEnvironmentChainHelper(
const F1& initFunctionEnv, const F2& initGlobalOrEvalEnv,
Register scratch) {
if (handler.function()) {
return initFunctionEnv();
}
if (handler.module()) {
return true;
}
return initGlobalOrEvalEnv();
}
template <>
template <typename F1, typename F2>
bool BaselineInterpreterCodeGen::initEnvironmentChainHelper(
const F1& initFunctionEnv, const F2& initGlobalOrEvalEnv,
Register scratch) {
// There are three cases:
//
// 1) Function script: use code emitted by initFunctionEnv.
// 2) Module script: no-op.
// 3) Global or eval script: use code emitted by initGlobalOrEvalEnv.
Label notFunction, done;
masm.loadPtr(frame.addressOfCalleeToken(), scratch);
masm.branchTestPtr(Assembler::NonZero, scratch, Imm32(CalleeTokenScriptBit),
&notFunction);
{
if (!initFunctionEnv()) {
return false;
}
masm.jump(&done);
}
masm.bind(&notFunction);
{
masm.andPtr(Imm32(uint32_t(CalleeTokenMask)), scratch);
masm.branchTest32(Assembler::NonZero,
Address(scratch, JSScript::offsetOfImmutableFlags()),
Imm32(uint32_t(JSScript::ImmutableFlags::IsModule)),
&done);
{
if (!initGlobalOrEvalEnv()) {
return false;
}
}
}
masm.bind(&done);
return true;
}
template <typename Handler>
bool BaselineCodeGen<Handler>::initEnvironmentChain() {
CallVMPhase phase = POST_INITIALIZE;
if (handler.needsEarlyStackCheck()) {
phase = CHECK_OVER_RECURSED;
}
RootedFunction fun(cx, handler.function());
if (fun) {
auto initFunctionEnv = [this, phase]() {
// Use callee->environment as env chain. Note that we do this also
// for needsSomeEnvironmentObject functions, so that the env chain
// slot is properly initialized if the call triggers GC.
@ -1026,7 +1097,7 @@ bool BaselineCompilerCodeGen::initEnvironmentChain() {
masm.loadPtr(Address(callee, JSFunction::offsetOfEnvironment()), scope);
masm.storePtr(scope, frame.addressOfEnvironmentChain());
if (fun->needsFunctionEnvironmentObjects()) {
auto initEnv = [this, phase]() {
// Call into the VM to create the proper environment objects.
prepareVMCall();
@ -1034,11 +1105,14 @@ bool BaselineCompilerCodeGen::initEnvironmentChain() {
pushArg(R0.scratchReg());
using Fn = bool (*)(JSContext*, BaselineFrame*);
if (!callVMNonOp<Fn, jit::InitFunctionEnvironmentObjects>(phase)) {
return false;
}
}
} else if (!handler.module()) {
return callVMNonOp<Fn, jit::InitFunctionEnvironmentObjects>(phase);
};
return emitTestScriptFlag(
JSScript::ImmutableFlags::NeedsFunctionEnvironmentObjects, true,
initEnv, R2.scratchReg());
};
auto initGlobalOrEvalEnv = [this, phase]() {
// EnvironmentChain pointer in BaselineFrame has already been initialized
// in prologue, but we need to check for redeclaration errors in global and
// eval scripts.
@ -1050,17 +1124,11 @@ bool BaselineCompilerCodeGen::initEnvironmentChain() {
pushArg(R0.scratchReg());
using Fn = bool (*)(JSContext*, HandleObject, HandleScript);
if (!callVMNonOp<Fn, js::CheckGlobalOrEvalDeclarationConflicts>(phase)) {
return false;
}
}
return callVMNonOp<Fn, js::CheckGlobalOrEvalDeclarationConflicts>(phase);
};
return true;
}
template <>
bool BaselineInterpreterCodeGen::initEnvironmentChain() {
MOZ_CRASH("NYI: interpreter initEnvironmentChain");
return initEnvironmentChainHelper(initFunctionEnv, initGlobalOrEvalEnv,
R2.scratchReg());
}
template <typename Handler>
@ -6055,8 +6123,8 @@ bool BaselineCodeGen<Handler>::emitPrologue() {
// Initialize BaselineFrame. For eval scripts, the env chain
// is passed in R1, so we have to be careful not to clobber it.
// Initialize BaselineFrame::flags.
masm.store32(Imm32(0), frame.addressOfFlags());
// Initialize BaselineFrame::flags and interpreter fields.
emitInitFrameFields();
// Handle env chain pre-initialization (in case GC gets run
// during stack check). For global and eval scripts, the env

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

@ -476,11 +476,17 @@ class BaselineCodeGen {
MOZ_MUST_USE bool emitStackCheck();
MOZ_MUST_USE bool emitArgumentTypeChecks();
MOZ_MUST_USE bool emitDebugPrologue();
template <typename F1, typename F2>
MOZ_MUST_USE bool initEnvironmentChainHelper(const F1& initFunctionEnv,
const F2& initGlobalOrEvalEnv,
Register scratch);
MOZ_MUST_USE bool initEnvironmentChain();
MOZ_MUST_USE bool emitTraceLoggerEnter();
MOZ_MUST_USE bool emitTraceLoggerExit();
void emitInitFrameFields();
void emitIsDebuggeeCheck();
void emitInitializeLocals();
void emitPreInitEnvironmentChain(Register nonFunctionEnv);