Bug 1467191 - Unifies some implementations of CacheIR ops that perform a callVM. r=mgaudet

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

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Adam Holm 2019-06-13 02:28:50 +00:00
parent f8f9b8becc
commit 46d3b5f507
5 changed files with 286 additions and 273 deletions

View File

@ -59,63 +59,48 @@ BaselineCacheIRCompiler::BaselineCacheIRCompiler(
CACHE_IR_SHARED_OPS(DEFINE_SHARED_OP)
#undef DEFINE_SHARED_OP
enum class CallCanGC { CanGC, CanNotGC };
// Instructions that have to perform a callVM require a stub frame. Call its
// enter() and leave() methods to enter/leave the stub frame.
class MOZ_RAII AutoStubFrame {
BaselineCacheIRCompiler& compiler;
// AutoStubFrame methods
AutoStubFrame::AutoStubFrame(BaselineCacheIRCompiler& compiler)
: compiler(compiler)
#ifdef DEBUG
uint32_t framePushedAtEnterStubFrame_;
,
framePushedAtEnterStubFrame_(0)
#endif
{
}
void AutoStubFrame::enter(MacroAssembler& masm, Register scratch,
CallCanGC canGC) {
MOZ_ASSERT(compiler.allocator.stackPushed() == 0);
EmitBaselineEnterStubFrame(masm, scratch);
#ifdef DEBUG
framePushedAtEnterStubFrame_ = masm.framePushed();
#endif
AutoStubFrame(const AutoStubFrame&) = delete;
void operator=(const AutoStubFrame&) = delete;
public:
explicit AutoStubFrame(BaselineCacheIRCompiler& compiler)
: compiler(compiler)
#ifdef DEBUG
,
framePushedAtEnterStubFrame_(0)
#endif
{
MOZ_ASSERT(!compiler.preparedForVMCall_);
compiler.preparedForVMCall_ = true;
if (canGC == CallCanGC::CanGC) {
compiler.makesGCCalls_ = true;
}
void enter(MacroAssembler& masm, Register scratch,
CallCanGC canGC = CallCanGC::CanGC) {
MOZ_ASSERT(compiler.allocator.stackPushed() == 0);
EmitBaselineEnterStubFrame(masm, scratch);
}
void AutoStubFrame::leave(MacroAssembler& masm, bool calledIntoIon) {
MOZ_ASSERT(compiler.preparedForVMCall_);
compiler.preparedForVMCall_ = false;
#ifdef DEBUG
framePushedAtEnterStubFrame_ = masm.framePushed();
#endif
MOZ_ASSERT(!compiler.preparedForVMCall_);
compiler.preparedForVMCall_ = true;
if (canGC == CallCanGC::CanGC) {
compiler.makesGCCalls_ = true;
}
masm.setFramePushed(framePushedAtEnterStubFrame_);
if (calledIntoIon) {
masm.adjustFrame(sizeof(intptr_t)); // Calls into ion have this extra.
}
void leave(MacroAssembler& masm, bool calledIntoIon = false) {
MOZ_ASSERT(compiler.preparedForVMCall_);
compiler.preparedForVMCall_ = false;
#ifdef DEBUG
masm.setFramePushed(framePushedAtEnterStubFrame_);
if (calledIntoIon) {
masm.adjustFrame(sizeof(intptr_t)); // Calls into ion have this extra.
}
#endif
EmitBaselineLeaveStubFrame(masm, calledIntoIon);
}
EmitBaselineLeaveStubFrame(masm, calledIntoIon);
}
#ifdef DEBUG
~AutoStubFrame() { MOZ_ASSERT(!compiler.preparedForVMCall_); }
AutoStubFrame::~AutoStubFrame() { MOZ_ASSERT(!compiler.preparedForVMCall_); }
#endif
};
} // namespace jit
} // namespace js
@ -652,81 +637,6 @@ bool BaselineCacheIRCompiler::emitCallProxyGetResult() {
return true;
}
bool BaselineCacheIRCompiler::emitCallProxyGetByValueResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
Register obj = allocator.useRegister(masm, reader.objOperandId());
ValueOperand idVal = allocator.useValueRegister(masm, reader.valOperandId());
AutoScratchRegister scratch(allocator, masm);
allocator.discardStack(masm);
AutoStubFrame stubFrame(*this);
stubFrame.enter(masm, scratch);
masm.Push(idVal);
masm.Push(obj);
using Fn =
bool (*)(JSContext*, HandleObject, HandleValue, MutableHandleValue);
callVM<Fn, ProxyGetPropertyByValue>(masm);
stubFrame.leave(masm);
return true;
}
bool BaselineCacheIRCompiler::emitCallProxyHasPropResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
Register obj = allocator.useRegister(masm, reader.objOperandId());
ValueOperand idVal = allocator.useValueRegister(masm, reader.valOperandId());
bool hasOwn = reader.readBool();
AutoScratchRegister scratch(allocator, masm);
allocator.discardStack(masm);
AutoStubFrame stubFrame(*this);
stubFrame.enter(masm, scratch);
masm.Push(idVal);
masm.Push(obj);
using Fn =
bool (*)(JSContext*, HandleObject, HandleValue, MutableHandleValue);
if (hasOwn) {
callVM<Fn, ProxyHasOwn>(masm);
} else {
callVM<Fn, ProxyHas>(masm);
}
stubFrame.leave(masm);
return true;
}
bool BaselineCacheIRCompiler::emitCallNativeGetElementResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
Register obj = allocator.useRegister(masm, reader.objOperandId());
Register index = allocator.useRegister(masm, reader.int32OperandId());
AutoScratchRegister scratch(allocator, masm);
allocator.discardStack(masm);
AutoStubFrame stubFrame(*this);
stubFrame.enter(masm, scratch);
masm.Push(index);
masm.Push(TypedOrValueRegister(MIRType::Object, AnyRegister(obj)));
masm.Push(obj);
using Fn = bool (*)(JSContext*, HandleNativeObject, HandleValue, int32_t,
MutableHandleValue);
callVM<Fn, NativeGetElement>(masm);
stubFrame.leave(masm);
return true;
}
bool BaselineCacheIRCompiler::emitGuardFrameHasNoArgumentsObject() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
FailurePath* failure;
@ -1819,28 +1729,6 @@ bool BaselineCacheIRCompiler::emitCallAddOrUpdateSparseElementHelper() {
return true;
}
bool BaselineCacheIRCompiler::emitCallGetSparseElementResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
Register obj = allocator.useRegister(masm, reader.objOperandId());
Register id = allocator.useRegister(masm, reader.int32OperandId());
AutoScratchRegister scratch(allocator, masm);
allocator.discardStack(masm);
AutoStubFrame stubFrame(*this);
stubFrame.enter(masm, scratch);
masm.Push(id);
masm.Push(obj);
using Fn = bool (*)(JSContext * cx, HandleArrayObject obj, int32_t int_id,
MutableHandleValue result);
callVM<Fn, GetSparseElementHelper>(masm);
stubFrame.leave(masm);
return true;
}
bool BaselineCacheIRCompiler::emitMegamorphicSetElement() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
Register obj = allocator.useRegister(masm, reader.objOperandId());

View File

@ -17,6 +17,7 @@
#include "jit/IonIC.h"
#include "jit/SharedICHelpers.h"
#include "jit/SharedICRegisters.h"
#include "proxy/Proxy.h"
#include "vm/GeneratorObject.h"
#include "builtin/Boolean-inl.h"
@ -4390,6 +4391,86 @@ bool CacheIRCompiler::emitMetaTwoByte() {
return true;
}
bool CacheIRCompiler::emitCallNativeGetElementResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
AutoCallVM callvm(masm, this, allocator);
Register obj = allocator.useRegister(masm, reader.objOperandId());
Register index = allocator.useRegister(masm, reader.int32OperandId());
allocator.discardStack(masm);
callvm.prepare();
masm.Push(index);
masm.Push(TypedOrValueRegister(MIRType::Object, AnyRegister(obj)));
masm.Push(obj);
using Fn = bool (*)(JSContext*, HandleNativeObject, HandleValue, int32_t,
MutableHandleValue);
callVM<Fn, NativeGetElement>(masm);
return true;
}
bool CacheIRCompiler::emitCallProxyHasPropResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
AutoCallVM callvm(masm, this, allocator);
Register obj = allocator.useRegister(masm, reader.objOperandId());
ValueOperand idVal = allocator.useValueRegister(masm, reader.valOperandId());
bool hasOwn = reader.readBool();
callvm.prepare();
masm.Push(idVal);
masm.Push(obj);
using Fn =
bool (*)(JSContext*, HandleObject, HandleValue, MutableHandleValue);
if (hasOwn) {
callVM<Fn, ProxyHasOwn>(masm);
} else {
callVM<Fn, ProxyHas>(masm);
}
return true;
}
bool CacheIRCompiler::emitCallProxyGetByValueResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
AutoCallVM callvm(masm, this, allocator);
Register obj = allocator.useRegister(masm, reader.objOperandId());
ValueOperand idVal = allocator.useValueRegister(masm, reader.valOperandId());
callvm.prepare();
masm.Push(idVal);
masm.Push(obj);
using Fn =
bool (*)(JSContext*, HandleObject, HandleValue, MutableHandleValue);
callVM<Fn, ProxyGetPropertyByValue>(masm);
return true;
}
bool CacheIRCompiler::emitCallGetSparseElementResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
AutoCallVM callvm(masm, this, allocator);
Register obj = allocator.useRegister(masm, reader.objOperandId());
Register id = allocator.useRegister(masm, reader.int32OperandId());
callvm.prepare();
masm.Push(id);
masm.Push(obj);
using Fn = bool (*)(JSContext * cx, HandleArrayObject obj, int32_t int_id,
MutableHandleValue result);
callVM<Fn, GetSparseElementHelper>(masm);
return true;
}
template <typename Fn, Fn fn>
void CacheIRCompiler::callVM(MacroAssembler& masm) {
VMFunctionId id = VMFunctionToId<Fn, fn>::id;
@ -4431,12 +4512,55 @@ bool CacheIRCompiler::isBaseline() { return mode_ == Mode::Baseline; }
bool CacheIRCompiler::isIon() { return mode_ == Mode::Ion; }
BaselineCacheIRCompiler& CacheIRCompiler::asBaseline() {
BaselineCacheIRCompiler* CacheIRCompiler::asBaseline() {
MOZ_ASSERT(this->isBaseline());
return *static_cast<BaselineCacheIRCompiler*>(this);
return static_cast<BaselineCacheIRCompiler*>(this);
}
IonCacheIRCompiler& CacheIRCompiler::asIon() {
IonCacheIRCompiler* CacheIRCompiler::asIon() {
MOZ_ASSERT(this->isIon());
return *static_cast<IonCacheIRCompiler*>(this);
return static_cast<IonCacheIRCompiler*>(this);
}
AutoCallVM::AutoCallVM(MacroAssembler& masm, CacheIRCompiler* compiler,
CacheRegisterAllocator& allocator)
: masm_(masm), compiler_(compiler), allocator_(allocator) {
// Ion needs to `prepareVMCall` before it can callVM
// Ion also needs to initialize AutoOutputRegister and AutoSaveLiveRegisters
// values
if (compiler_->mode_ == CacheIRCompiler::Mode::Ion) {
// Will need to use a downcast here as well, in order to pass the
// stub to AutoSaveLiveRegisters
IonCacheIRCompiler* ionCompiler = compiler_->asIon();
save_.emplace(*ionCompiler);
output_.emplace(*ionCompiler);
return;
}
MOZ_ASSERT(compiler_->mode_ == CacheIRCompiler::Mode::Baseline);
stubFrame_.emplace(*compiler_->asBaseline());
scratch_.emplace(allocator_, masm_);
}
void AutoCallVM::prepare() {
allocator_.discardStack(masm_);
MOZ_ASSERT(compiler_ != nullptr);
if (compiler_->mode_ == CacheIRCompiler::Mode::Ion) {
compiler_->asIon()->prepareVMCall(masm_, *save_.ptr());
return;
}
MOZ_ASSERT(compiler_->mode_ == CacheIRCompiler::Mode::Baseline);
stubFrame_->enter(masm_, scratch_.ref());
}
AutoCallVM::~AutoCallVM() {
if (compiler_->mode_ == CacheIRCompiler::Mode::Ion) {
if (output_.isSome()) {
masm_.storeCallResultValue(output_.ref());
}
return;
}
MOZ_ASSERT(compiler_->mode_ == CacheIRCompiler::Mode::Baseline);
stubFrame_->leave(masm_);
}

View File

@ -131,6 +131,10 @@ class IonCacheIRCompiler;
_(CallNumberToString) \
_(BooleanToString) \
_(CallIsSuspendedGeneratorResult) \
_(CallNativeGetElementResult) \
_(CallProxyHasPropResult) \
_(CallProxyGetByValueResult) \
_(CallGetSparseElementResult) \
_(MetaTwoByte) \
_(WrapResult)
@ -708,6 +712,9 @@ class AutoOutputRegister;
class MOZ_RAII CacheIRCompiler {
protected:
friend class AutoOutputRegister;
friend class AutoStubFrame;
friend class AutoSaveLiveRegisters;
friend class AutoCallVM;
enum class Mode { Baseline, Ion };
@ -715,8 +722,8 @@ class MOZ_RAII CacheIRCompiler {
bool isBaseline();
bool isIon();
BaselineCacheIRCompiler& asBaseline();
IonCacheIRCompiler& asIon();
BaselineCacheIRCompiler* asBaseline();
IonCacheIRCompiler* asIon();
JSContext* cx_;
CacheIRReader reader;
@ -946,6 +953,46 @@ class MOZ_RAII AutoOutputRegister {
operator TypedOrValueRegister() const { return output_; }
};
enum class CallCanGC { CanGC, CanNotGC };
// Instructions that have to perform a callVM require a stub frame. Call its
// enter() and leave() methods to enter/leave the stub frame.
// Hoisted from jit/BaselineCacheIRCompiler.cpp. See there for method
// definitions.
class MOZ_RAII AutoStubFrame {
BaselineCacheIRCompiler& compiler;
#ifdef DEBUG
uint32_t framePushedAtEnterStubFrame_;
#endif
AutoStubFrame(const AutoStubFrame&) = delete;
void operator=(const AutoStubFrame&) = delete;
public:
explicit AutoStubFrame(BaselineCacheIRCompiler& compiler);
void enter(MacroAssembler& masm, Register scratch,
CallCanGC canGC = CallCanGC::CanGC);
void leave(MacroAssembler& masm, bool calledIntoIon = false);
#ifdef DEBUG
~AutoStubFrame();
#endif
};
// AutoSaveLiveRegisters must be used when we make a call that can GC. The
// constructor ensures all live registers are stored on the stack (where the GC
// expects them) and the destructor restores these registers.
class MOZ_RAII AutoSaveLiveRegisters {
IonCacheIRCompiler& compiler_;
AutoSaveLiveRegisters(const AutoSaveLiveRegisters&) = delete;
void operator=(const AutoSaveLiveRegisters&) = delete;
public:
explicit AutoSaveLiveRegisters(IonCacheIRCompiler& compiler);
~AutoSaveLiveRegisters();
};
// Like AutoScratchRegister, but reuse a register of |output| if possible.
class MOZ_RAII AutoScratchRegisterMaybeOutput {
mozilla::Maybe<AutoScratchRegister> scratch_;
@ -969,6 +1016,65 @@ class MOZ_RAII AutoScratchRegisterMaybeOutput {
operator Register() const { return scratchReg_; }
};
// AutoCallVM is a wrapper class that unifies methods shared by
// IonCacheIRCompiler and BaselineCacheIRCompiler that perform a callVM, but
// require stub specific functionality before performing the VM call.
//
// Expected Usage:
//
// OPs with implementations that may be unified by this class must:
// - Be listed in the CACHEIR_OPS list but not in the CACHE_IR_SHARED_OPS
// list
// - Differ only in their use of `AutoSaveLiveRegisters`,
// `AutoOutputRegister`, and `AutoScratchRegister`. The Ion
// implementation will use `AutoSaveLiveRegisters` and
// `AutoOutputRegister`, while the Baseline implementation will use
// `AutoScratchRegister`.
// - Both use the `callVM` method.
//
// Using AutoCallVM:
// - The constructor initializes `AutoOutputRegister` and
// `AutoSaveLiveRegisters` variables for CacheIRCompilers with the mode
// Ion, and initializes `AutoScratchRegister` and `AutoStubFrame`
// variables for CacheIRCompilers with mode Baseline.
// - The `prepare()` method calls the IonCacheIRCompiler method
// `prepareVMCall` for IonCacheIRCompilers, calls the `enter()` method of
// `AutoStubFrame` for BaselineCacheIRCompilers, and calls the
// `discardStack` method of the `Register` class for both compiler types.
// - The destructor calls the `masm` method `storeCallResultValue` for
// IonCacheIRCompilers, and calls the `leave` method of `AutoStubFrame`
// for BaselineCacheIRCompilers.
//
// Expected Usage Example:
// See: `CacheIRCompiler::emitCallGetSparseElementResult()`
//
// Restrictions:
// - OPs that do not meet the criteria listed above can not be unified with
// AutoCallVM
//
class MOZ_RAII AutoCallVM {
MacroAssembler& masm_;
CacheIRCompiler* compiler_;
CacheRegisterAllocator& allocator_;
// Baseline specific stuff
mozilla::Maybe<AutoStubFrame> stubFrame_;
mozilla::Maybe<AutoScratchRegister> scratch_;
// Ion specific stuff
mozilla::Maybe<AutoOutputRegister> output_;
mozilla::Maybe<AutoSaveLiveRegisters> save_;
public:
AutoCallVM(MacroAssembler& masm, CacheIRCompiler* compiler,
CacheRegisterAllocator& allocator);
void prepare();
~AutoCallVM();
};
// See the 'Sharing Baseline stub code' comment in CacheIR.h for a description
// of this class.
class CacheIRStubInfo {

View File

@ -33,8 +33,6 @@ using mozilla::Maybe;
namespace js {
namespace jit {
class AutoSaveLiveRegisters;
// IonCacheIRCompiler compiles CacheIR to IonIC native code.
IonCacheIRCompiler::IonCacheIRCompiler(
JSContext* cx, const CacheIRWriter& writer, IonIC* ic, IonScript* ionScript,
@ -88,30 +86,22 @@ void IonCacheIRCompiler::pushStubCodePointer() {
// AutoSaveLiveRegisters must be used when we make a call that can GC. The
// constructor ensures all live registers are stored on the stack (where the GC
// expects them) and the destructor restores these registers.
class MOZ_RAII AutoSaveLiveRegisters {
IonCacheIRCompiler& compiler_;
AutoSaveLiveRegisters(const AutoSaveLiveRegisters&) = delete;
void operator=(const AutoSaveLiveRegisters&) = delete;
public:
explicit AutoSaveLiveRegisters(IonCacheIRCompiler& compiler)
: compiler_(compiler) {
MOZ_ASSERT(compiler_.liveRegs_.isSome());
compiler_.allocator.saveIonLiveRegisters(
compiler_.masm, compiler_.liveRegs_.ref(),
compiler_.ic_->scratchRegisterForEntryJump(), compiler_.ionScript_);
compiler_.savedLiveRegs_ = true;
}
~AutoSaveLiveRegisters() {
MOZ_ASSERT(compiler_.stubJitCodeOffset_.isSome(),
"Must have pushed JitCode* pointer");
compiler_.allocator.restoreIonLiveRegisters(compiler_.masm,
compiler_.liveRegs_.ref());
MOZ_ASSERT(compiler_.masm.framePushed() ==
compiler_.ionScript_->frameSize());
}
};
AutoSaveLiveRegisters::AutoSaveLiveRegisters(IonCacheIRCompiler& compiler)
: compiler_(compiler) {
MOZ_ASSERT(compiler_.liveRegs_.isSome());
MOZ_ASSERT(compiler_.ic_);
compiler_.allocator.saveIonLiveRegisters(
compiler_.masm, compiler_.liveRegs_.ref(),
compiler_.ic_->scratchRegisterForEntryJump(), compiler_.ionScript_);
compiler_.savedLiveRegs_ = true;
}
AutoSaveLiveRegisters::~AutoSaveLiveRegisters() {
MOZ_ASSERT(compiler_.stubJitCodeOffset_.isSome(),
"Must have pushed JitCode* pointer");
compiler_.allocator.restoreIonLiveRegisters(compiler_.masm,
compiler_.liveRegs_.ref());
MOZ_ASSERT(compiler_.masm.framePushed() == compiler_.ionScript_->frameSize());
}
} // namespace jit
} // namespace js
@ -1108,81 +1098,6 @@ bool IonCacheIRCompiler::emitCallProxyGetResult() {
return true;
}
bool IonCacheIRCompiler::emitCallProxyGetByValueResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
AutoSaveLiveRegisters save(*this);
AutoOutputRegister output(*this);
Register obj = allocator.useRegister(masm, reader.objOperandId());
ValueOperand idVal = allocator.useValueRegister(masm, reader.valOperandId());
allocator.discardStack(masm);
prepareVMCall(masm, save);
masm.Push(idVal);
masm.Push(obj);
using Fn =
bool (*)(JSContext*, HandleObject, HandleValue, MutableHandleValue);
callVM<Fn, ProxyGetPropertyByValue>(masm);
masm.storeCallResultValue(output);
return true;
}
bool IonCacheIRCompiler::emitCallProxyHasPropResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
AutoSaveLiveRegisters save(*this);
AutoOutputRegister output(*this);
Register obj = allocator.useRegister(masm, reader.objOperandId());
ValueOperand idVal = allocator.useValueRegister(masm, reader.valOperandId());
bool hasOwn = reader.readBool();
allocator.discardStack(masm);
prepareVMCall(masm, save);
masm.Push(idVal);
masm.Push(obj);
using Fn =
bool (*)(JSContext*, HandleObject, HandleValue, MutableHandleValue);
if (hasOwn) {
callVM<Fn, ProxyHasOwn>(masm);
} else {
callVM<Fn, ProxyHas>(masm);
}
masm.storeCallResultValue(output);
return true;
}
bool IonCacheIRCompiler::emitCallNativeGetElementResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
AutoSaveLiveRegisters save(*this);
AutoOutputRegister output(*this);
Register obj = allocator.useRegister(masm, reader.objOperandId());
Register index = allocator.useRegister(masm, reader.int32OperandId());
allocator.discardStack(masm);
prepareVMCall(masm, save);
masm.Push(index);
masm.Push(TypedOrValueRegister(MIRType::Object, AnyRegister(obj)));
masm.Push(obj);
using Fn = bool (*)(JSContext*, HandleNativeObject, HandleValue, int32_t,
MutableHandleValue);
callVM<Fn, NativeGetElement>(masm);
masm.storeCallResultValue(output);
return true;
}
bool IonCacheIRCompiler::emitGuardFrameHasNoArgumentsObject() {
MOZ_CRASH("Baseline-specific op");
}
@ -2200,27 +2115,6 @@ bool IonCacheIRCompiler::emitCallAddOrUpdateSparseElementHelper() {
return true;
}
bool IonCacheIRCompiler::emitCallGetSparseElementResult() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
AutoSaveLiveRegisters save(*this);
AutoOutputRegister output(*this);
Register obj = allocator.useRegister(masm, reader.objOperandId());
Register id = allocator.useRegister(masm, reader.int32OperandId());
allocator.discardStack(masm);
prepareVMCall(masm, save);
masm.Push(id);
masm.Push(obj);
using Fn = bool (*)(JSContext * cx, HandleArrayObject obj, int32_t int_id,
MutableHandleValue result);
callVM<Fn, GetSparseElementHelper>(masm);
masm.storeCallResultValue(output);
return true;
}
bool IonCacheIRCompiler::emitMegamorphicSetElement() {
JitSpew(JitSpew_Codegen, __FUNCTION__);
AutoSaveLiveRegisters save(*this);

View File

@ -7,6 +7,7 @@
#ifndef jit_IonCacheIRCompiler_h
#define jit_IonCacheIRCompiler_h
#include "mozilla/Maybe.h"
#include "jit/CacheIR.h"
#include "jit/CacheIRCompiler.h"
#include "jit/IonIC.h"
@ -18,6 +19,7 @@ namespace jit {
class MOZ_RAII IonCacheIRCompiler : public CacheIRCompiler {
public:
friend class AutoSaveLiveRegisters;
friend class AutoCallVM;
IonCacheIRCompiler(JSContext* cx, const CacheIRWriter& writer, IonIC* ic,
IonScript* ionScript, IonICStub* stub,
@ -41,10 +43,9 @@ class MOZ_RAII IonCacheIRCompiler : public CacheIRCompiler {
CodeOffsetJump rejoinOffset_;
Vector<CodeOffset, 4, SystemAllocPolicy> nextCodeOffsets_;
Maybe<LiveRegisterSet> liveRegs_;
Maybe<CodeOffset> stubJitCodeOffset_;
mozilla::Maybe<LiveRegisterSet> liveRegs_;
mozilla::Maybe<CodeOffset> stubJitCodeOffset_;
private:
bool savedLiveRegs_;
template <typename T>