diff --git a/js/src/jit/BaselineBailouts.cpp b/js/src/jit/BaselineBailouts.cpp index d7e1445bae3c..d1bed20e6d2e 100644 --- a/js/src/jit/BaselineBailouts.cpp +++ b/js/src/jit/BaselineBailouts.cpp @@ -1343,10 +1343,10 @@ jit::BailoutIonToBaseline(JSContext *cx, JitActivation *activation, IonBailoutIt return BAILOUT_RETURN_FATAL_ERROR; JitSpew(JitSpew_BaselineBailouts, " Incoming frame ptr = %p", builder.startFrame()); - AutoValueVector instructionResults(cx); + RInstructionResults instructionResults; SnapshotIterator snapIter(iter); - if (!snapIter.initIntructionResults(instructionResults)) + if (!snapIter.initInstructionResults(cx, &instructionResults)) return BAILOUT_RETURN_FATAL_ERROR; #ifdef TRACK_SNAPSHOTS diff --git a/js/src/jit/IonFrames.cpp b/js/src/jit/IonFrames.cpp index edca38935cd8..b2be61bf848a 100644 --- a/js/src/jit/IonFrames.cpp +++ b/js/src/jit/IonFrames.cpp @@ -1436,6 +1436,71 @@ OsiIndex::returnPointDisplacement() const return callPointDisplacement_ + Assembler::PatchWrite_NearCallSize(); } +RInstructionResults::RInstructionResults() + : results_(nullptr), + fp_(nullptr) +{ +} + +RInstructionResults::RInstructionResults(RInstructionResults&& src) + : results_(mozilla::Move(src.results_)), + fp_(src.fp_) +{ + src.fp_ = nullptr; +} + +RInstructionResults& +RInstructionResults::operator=(RInstructionResults&& rhs) +{ + MOZ_ASSERT(&rhs != this, "self-moves are prohibited"); + this->~RInstructionResults(); + new(this) RInstructionResults(mozilla::Move(rhs)); + return *this; +} + +RInstructionResults::~RInstructionResults() +{ + // results_ is freed by the UniquePtr. +} + +bool +RInstructionResults::init(JSContext *cx, uint32_t numResults, IonJSFrameLayout *fp) +{ + if (numResults) { + results_ = cx->make_unique(); + if (!results_ || !results_->growBy(numResults)) + return false; + + Value guard = MagicValue(JS_ION_BAILOUT); + for (size_t i = 0; i < numResults; i++) + (*results_)[i].init(guard); + } + + fp_ = fp; + return true; +} + +bool +RInstructionResults::isInitialized() const +{ + MOZ_ASSERT_IF(results_, fp_); + return results_; +} + +IonJSFrameLayout * +RInstructionResults::frame() const +{ + MOZ_ASSERT(isInitialized()); + return fp_; +} + +RelocatableValue& +RInstructionResults::operator [](size_t index) +{ + return (*results_)[index]; +} + + SnapshotIterator::SnapshotIterator(IonScript *ionScript, SnapshotOffset snapshotOffset, IonJSFrameLayout *fp, const MachineState &machine) : snapshot_(ionScript->snapshots(), @@ -1699,7 +1764,7 @@ SnapshotIterator::skipInstruction() } bool -SnapshotIterator::initIntructionResults(AutoValueVector &results) +SnapshotIterator::initInstructionResults(JSContext *cx, RInstructionResults *results) { MOZ_ASSERT(recover_.numInstructionsRead() == 1); @@ -1710,13 +1775,9 @@ SnapshotIterator::initIntructionResults(AutoValueVector &results) MOZ_ASSERT(recover_.numInstructions() > 1); size_t numResults = recover_.numInstructions() - 1; - if (!results.reserve(numResults)) + instructionResults_ = results; + if (!instructionResults_->isInitialized() && !instructionResults_->init(cx, numResults, fp_)) return false; - - for (size_t i = 0; i < numResults; i++) - results.infallibleAppend(MagicValue(JS_ION_BAILOUT)); - - instructionResults_ = &results; return true; } @@ -1725,7 +1786,7 @@ SnapshotIterator::storeInstructionResult(Value v) { uint32_t currIns = recover_.numInstructionsRead() - 1; MOZ_ASSERT((*instructionResults_)[currIns].isMagic(JS_ION_BAILOUT)); - (*instructionResults_)[currIns].set(v); + (*instructionResults_)[currIns] = v; } Value diff --git a/js/src/jit/JitFrameIterator.h b/js/src/jit/JitFrameIterator.h index 89a923f3891a..e03890032350 100644 --- a/js/src/jit/JitFrameIterator.h +++ b/js/src/jit/JitFrameIterator.h @@ -266,6 +266,32 @@ class JitFrameIterator #endif }; +class RInstructionResults +{ + // Vector of results of recover instructions. + typedef mozilla::Vector Values; + mozilla::UniquePtr > results_; + + // The frame pointer is used as a key to check if the current frame already + // bailed out. + IonJSFrameLayout *fp_; + + public: + RInstructionResults(); + RInstructionResults(RInstructionResults&& src); + + RInstructionResults& operator=(RInstructionResults&& rhs); + + ~RInstructionResults(); + + bool init(JSContext *cx, uint32_t numResults, IonJSFrameLayout *fp); + bool isInitialized() const; + + IonJSFrameLayout *frame() const; + + RelocatableValue& operator[](size_t index); +}; + class RResumePoint; // Reads frame information in snapshot-encoding order (that is, outermost frame @@ -277,7 +303,7 @@ class SnapshotIterator IonJSFrameLayout *fp_; MachineState machine_; IonScript *ionScript_; - AutoValueVector *instructionResults_; + RInstructionResults *instructionResults_; private: // Read a spilled register from the machine state. @@ -369,7 +395,7 @@ class SnapshotIterator // recover instructions. This vector should be registered before the // beginning of the iteration. This function is in charge of allocating // enough space for all instructions results, and return false iff it fails. - bool initIntructionResults(AutoValueVector &results); + bool initInstructionResults(JSContext *cx, RInstructionResults *results); void storeInstructionResult(Value v);