diff options
Diffstat (limited to 'deps/v8/src/mips/deoptimizer-mips.cc')
-rw-r--r-- | deps/v8/src/mips/deoptimizer-mips.cc | 202 |
1 files changed, 16 insertions, 186 deletions
diff --git a/deps/v8/src/mips/deoptimizer-mips.cc b/deps/v8/src/mips/deoptimizer-mips.cc index 57d3880ede..16f75b8632 100644 --- a/deps/v8/src/mips/deoptimizer-mips.cc +++ b/deps/v8/src/mips/deoptimizer-mips.cc @@ -101,12 +101,7 @@ void Deoptimizer::PatchCodeForDeoptimization(Isolate* isolate, Code* code) { void Deoptimizer::PatchInterruptCodeAt(Code* unoptimized_code, Address pc_after, - Code* interrupt_code, Code* replacement_code) { - ASSERT(!InterruptCodeIsPatched(unoptimized_code, - pc_after, - interrupt_code, - replacement_code)); static const int kInstrSize = Assembler::kInstrSize; // Replace the sltu instruction with load-imm 1 to at, so beq is not taken. CodePatcher patcher(pc_after - 6 * kInstrSize, 1); @@ -123,12 +118,7 @@ void Deoptimizer::PatchInterruptCodeAt(Code* unoptimized_code, void Deoptimizer::RevertInterruptCodeAt(Code* unoptimized_code, Address pc_after, - Code* interrupt_code, - Code* replacement_code) { - ASSERT(InterruptCodeIsPatched(unoptimized_code, - pc_after, - interrupt_code, - replacement_code)); + Code* interrupt_code) { static const int kInstrSize = Assembler::kInstrSize; // Restore the sltu instruction so beq can be taken again. CodePatcher patcher(pc_after - 6 * kInstrSize, 1); @@ -143,191 +133,33 @@ void Deoptimizer::RevertInterruptCodeAt(Code* unoptimized_code, #ifdef DEBUG -bool Deoptimizer::InterruptCodeIsPatched(Code* unoptimized_code, - Address pc_after, - Code* interrupt_code, - Code* replacement_code) { +Deoptimizer::InterruptPatchState Deoptimizer::GetInterruptPatchState( + Isolate* isolate, + Code* unoptimized_code, + Address pc_after) { static const int kInstrSize = Assembler::kInstrSize; ASSERT(Assembler::IsBeq(Assembler::instr_at(pc_after - 5 * kInstrSize))); if (Assembler::IsAddImmediate( Assembler::instr_at(pc_after - 6 * kInstrSize))) { + Code* osr_builtin = + isolate->builtins()->builtin(Builtins::kOnStackReplacement); ASSERT(reinterpret_cast<uint32_t>( Assembler::target_address_at(pc_after - 4 * kInstrSize)) == - reinterpret_cast<uint32_t>(replacement_code->entry())); - return true; + reinterpret_cast<uint32_t>(osr_builtin->entry())); + return PATCHED_FOR_OSR; } else { + // Get the interrupt stub code object to match against from cache. + Code* interrupt_builtin = + isolate->builtins()->builtin(Builtins::kInterruptCheck); ASSERT(reinterpret_cast<uint32_t>( Assembler::target_address_at(pc_after - 4 * kInstrSize)) == - reinterpret_cast<uint32_t>(interrupt_code->entry())); - return false; + reinterpret_cast<uint32_t>(interrupt_builtin->entry())); + return NOT_PATCHED; } } #endif // DEBUG -static int LookupBailoutId(DeoptimizationInputData* data, BailoutId ast_id) { - ByteArray* translations = data->TranslationByteArray(); - int length = data->DeoptCount(); - for (int i = 0; i < length; i++) { - if (data->AstId(i) == ast_id) { - TranslationIterator it(translations, data->TranslationIndex(i)->value()); - int value = it.Next(); - ASSERT(Translation::BEGIN == static_cast<Translation::Opcode>(value)); - // Read the number of frames. - value = it.Next(); - if (value == 1) return i; - } - } - UNREACHABLE(); - return -1; -} - - -void Deoptimizer::DoComputeOsrOutputFrame() { - DeoptimizationInputData* data = DeoptimizationInputData::cast( - compiled_code_->deoptimization_data()); - unsigned ast_id = data->OsrAstId()->value(); - - int bailout_id = LookupBailoutId(data, BailoutId(ast_id)); - unsigned translation_index = data->TranslationIndex(bailout_id)->value(); - ByteArray* translations = data->TranslationByteArray(); - - TranslationIterator iterator(translations, translation_index); - Translation::Opcode opcode = - static_cast<Translation::Opcode>(iterator.Next()); - ASSERT(Translation::BEGIN == opcode); - USE(opcode); - int count = iterator.Next(); - iterator.Skip(1); // Drop JS frame count. - ASSERT(count == 1); - USE(count); - - opcode = static_cast<Translation::Opcode>(iterator.Next()); - USE(opcode); - ASSERT(Translation::JS_FRAME == opcode); - unsigned node_id = iterator.Next(); - USE(node_id); - ASSERT(node_id == ast_id); - int closure_id = iterator.Next(); - USE(closure_id); - ASSERT_EQ(Translation::kSelfLiteralId, closure_id); - unsigned height = iterator.Next(); - unsigned height_in_bytes = height * kPointerSize; - USE(height_in_bytes); - - unsigned fixed_size = ComputeFixedSize(function_); - unsigned input_frame_size = input_->GetFrameSize(); - ASSERT(fixed_size + height_in_bytes == input_frame_size); - - unsigned stack_slot_size = compiled_code_->stack_slots() * kPointerSize; - unsigned outgoing_height = data->ArgumentsStackHeight(bailout_id)->value(); - unsigned outgoing_size = outgoing_height * kPointerSize; - unsigned output_frame_size = fixed_size + stack_slot_size + outgoing_size; - ASSERT(outgoing_size == 0); // OSR does not happen in the middle of a call. - - if (FLAG_trace_osr) { - PrintF("[on-stack replacement: begin 0x%08" V8PRIxPTR " ", - reinterpret_cast<intptr_t>(function_)); - PrintFunctionName(); - PrintF(" => node=%u, frame=%d->%d]\n", - ast_id, - input_frame_size, - output_frame_size); - } - - // There's only one output frame in the OSR case. - output_count_ = 1; - output_ = new FrameDescription*[1]; - output_[0] = new(output_frame_size) FrameDescription( - output_frame_size, function_); - output_[0]->SetFrameType(StackFrame::JAVA_SCRIPT); - - // Clear the incoming parameters in the optimized frame to avoid - // confusing the garbage collector. - unsigned output_offset = output_frame_size - kPointerSize; - int parameter_count = function_->shared()->formal_parameter_count() + 1; - for (int i = 0; i < parameter_count; ++i) { - output_[0]->SetFrameSlot(output_offset, 0); - output_offset -= kPointerSize; - } - - // Translate the incoming parameters. This may overwrite some of the - // incoming argument slots we've just cleared. - int input_offset = input_frame_size - kPointerSize; - bool ok = true; - int limit = input_offset - (parameter_count * kPointerSize); - while (ok && input_offset > limit) { - ok = DoOsrTranslateCommand(&iterator, &input_offset); - } - - // There are no translation commands for the caller's pc and fp, the - // context, and the function. Set them up explicitly. - for (int i = StandardFrameConstants::kCallerPCOffset; - ok && i >= StandardFrameConstants::kMarkerOffset; - i -= kPointerSize) { - uint32_t input_value = input_->GetFrameSlot(input_offset); - if (FLAG_trace_osr) { - const char* name = "UNKNOWN"; - switch (i) { - case StandardFrameConstants::kCallerPCOffset: - name = "caller's pc"; - break; - case StandardFrameConstants::kCallerFPOffset: - name = "fp"; - break; - case StandardFrameConstants::kContextOffset: - name = "context"; - break; - case StandardFrameConstants::kMarkerOffset: - name = "function"; - break; - } - PrintF(" [sp + %d] <- 0x%08x ; [sp + %d] (fixed part - %s)\n", - output_offset, - input_value, - input_offset, - name); - } - - output_[0]->SetFrameSlot(output_offset, input_->GetFrameSlot(input_offset)); - input_offset -= kPointerSize; - output_offset -= kPointerSize; - } - - // Translate the rest of the frame. - while (ok && input_offset >= 0) { - ok = DoOsrTranslateCommand(&iterator, &input_offset); - } - - // If translation of any command failed, continue using the input frame. - if (!ok) { - delete output_[0]; - output_[0] = input_; - output_[0]->SetPc(reinterpret_cast<uint32_t>(from_)); - } else { - // Set up the frame pointer and the context pointer. - output_[0]->SetRegister(fp.code(), input_->GetRegister(fp.code())); - output_[0]->SetRegister(cp.code(), input_->GetRegister(cp.code())); - - unsigned pc_offset = data->OsrPcOffset()->value(); - uint32_t pc = reinterpret_cast<uint32_t>( - compiled_code_->entry() + pc_offset); - output_[0]->SetPc(pc); - } - Code* continuation = isolate_->builtins()->builtin(Builtins::kNotifyOSR); - output_[0]->SetContinuation( - reinterpret_cast<uint32_t>(continuation->entry())); - - if (FLAG_trace_osr) { - PrintF("[on-stack replacement translation %s: 0x%08" V8PRIxPTR " ", - ok ? "finished" : "aborted", - reinterpret_cast<intptr_t>(function_)); - PrintFunctionName(); - PrintF(" => pc=0x%0x]\n", output_[0]->GetPc()); - } -} - - void Deoptimizer::FillInputFrame(Address tos, JavaScriptFrame* frame) { // Set the register values. The values are not important as there are no // callee saved registers in JavaScript frames, so all registers are @@ -542,10 +374,8 @@ void Deoptimizer::EntryGenerator::Generate() { } // Push state, pc, and continuation from the last output frame. - if (type() != OSR) { - __ lw(t2, MemOperand(a2, FrameDescription::state_offset())); - __ push(t2); - } + __ lw(t2, MemOperand(a2, FrameDescription::state_offset())); + __ push(t2); __ lw(t2, MemOperand(a2, FrameDescription::pc_offset())); __ push(t2); |