vendor/v8/src/ia32/deoptimizer-ia32.cc in mustang-0.0.1 vs vendor/v8/src/ia32/deoptimizer-ia32.cc in mustang-0.1.0

- old
+ new

@@ -53,15 +53,93 @@ while (size-- > 0) destroyer.masm()->int3(); #endif } -void Deoptimizer::DeoptimizeFunction(JSFunction* function) { - AssertNoAllocation no_allocation; +void Deoptimizer::EnsureRelocSpaceForLazyDeoptimization(Handle<Code> code) { + Isolate* isolate = code->GetIsolate(); + HandleScope scope(isolate); + // Compute the size of relocation information needed for the code + // patching in Deoptimizer::DeoptimizeFunction. + int min_reloc_size = 0; + Address prev_reloc_address = code->instruction_start(); + Address code_start_address = code->instruction_start(); + SafepointTable table(*code); + for (unsigned i = 0; i < table.length(); ++i) { + Address curr_reloc_address = code_start_address + table.GetPcOffset(i); + ASSERT_GE(curr_reloc_address, prev_reloc_address); + SafepointEntry safepoint_entry = table.GetEntry(i); + int deoptimization_index = safepoint_entry.deoptimization_index(); + if (deoptimization_index != Safepoint::kNoDeoptimizationIndex) { + // The gap code is needed to get to the state expected at the + // bailout and we need to skip the call opcode to get to the + // address that needs reloc. + curr_reloc_address += safepoint_entry.gap_code_size() + 1; + int pc_delta = curr_reloc_address - prev_reloc_address; + // We use RUNTIME_ENTRY reloc info which has a size of 2 bytes + // if encodable with small pc delta encoding and up to 6 bytes + // otherwise. + if (pc_delta <= RelocInfo::kMaxSmallPCDelta) { + min_reloc_size += 2; + } else { + min_reloc_size += 6; + } + prev_reloc_address = curr_reloc_address; + } + } + + // If the relocation information is not big enough we create a new + // relocation info object that is padded with comments to make it + // big enough for lazy doptimization. + int reloc_length = code->relocation_info()->length(); + if (min_reloc_size > reloc_length) { + int comment_reloc_size = RelocInfo::kMinRelocCommentSize; + // Padding needed. + int min_padding = min_reloc_size - reloc_length; + // Number of comments needed to take up at least that much space. + int additional_comments = + (min_padding + comment_reloc_size - 1) / comment_reloc_size; + // Actual padding size. + int padding = additional_comments * comment_reloc_size; + // Allocate new relocation info and copy old relocation to the end + // of the new relocation info array because relocation info is + // written and read backwards. + Factory* factory = isolate->factory(); + Handle<ByteArray> new_reloc = + factory->NewByteArray(reloc_length + padding, TENURED); + memcpy(new_reloc->GetDataStartAddress() + padding, + code->relocation_info()->GetDataStartAddress(), + reloc_length); + // Create a relocation writer to write the comments in the padding + // space. Use position 0 for everything to ensure short encoding. + RelocInfoWriter reloc_info_writer( + new_reloc->GetDataStartAddress() + padding, 0); + intptr_t comment_string + = reinterpret_cast<intptr_t>(RelocInfo::kFillerCommentString); + RelocInfo rinfo(0, RelocInfo::COMMENT, comment_string); + for (int i = 0; i < additional_comments; ++i) { +#ifdef DEBUG + byte* pos_before = reloc_info_writer.pos(); +#endif + reloc_info_writer.Write(&rinfo); + ASSERT(RelocInfo::kMinRelocCommentSize == + pos_before - reloc_info_writer.pos()); + } + // Replace relocation information on the code object. + code->set_relocation_info(*new_reloc); + } +} + + +void Deoptimizer::DeoptimizeFunction(JSFunction* function) { if (!function->IsOptimized()) return; + Isolate* isolate = function->GetIsolate(); + HandleScope scope(isolate); + AssertNoAllocation no_allocation; + // Get the optimized code. Code* code = function->code(); Address code_start_address = code->instruction_start(); // We will overwrite the code's relocation info in-place. Relocation info @@ -116,24 +194,31 @@ // Handle the junk part after the new relocation info. We will create // a non-live object in the extra space at the end of the former reloc info. Address junk_address = reloc_info->address() + reloc_info->Size(); ASSERT(junk_address <= reloc_end_address); - Heap::CreateFillerObjectAt(junk_address, reloc_end_address - junk_address); + isolate->heap()->CreateFillerObjectAt(junk_address, + reloc_end_address - junk_address); // Add the deoptimizing code to the list. DeoptimizingCodeListNode* node = new DeoptimizingCodeListNode(code); - node->set_next(deoptimizing_code_list_); - deoptimizing_code_list_ = node; + DeoptimizerData* data = isolate->deoptimizer_data(); + node->set_next(data->deoptimizing_code_list_); + data->deoptimizing_code_list_ = node; // Set the code for the function to non-optimized version. function->ReplaceCode(function->shared()->code()); if (FLAG_trace_deopt) { PrintF("[forced deoptimization: "); function->PrintName(); PrintF(" / %x]\n", reinterpret_cast<uint32_t>(function)); +#ifdef DEBUG + if (FLAG_print_code) { + code->PrintLn(); + } +#endif } } void Deoptimizer::PatchStackCheckCodeAt(Address pc_after, @@ -282,17 +367,35 @@ 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 = 0; ok && i < 4; i++) { + for (int i = StandardFrameConstants::kCallerPCOffset; + ok && i >= StandardFrameConstants::kMarkerOffset; + i -= kPointerSize) { uint32_t input_value = input_->GetFrameSlot(input_offset); if (FLAG_trace_osr) { - PrintF(" [esp + %d] <- 0x%08x ; [esp + %d] (fixed part)\n", + 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(" [esp + %d] <- 0x%08x ; [esp + %d] (fixed part - %s)\n", output_offset, input_value, - input_offset); + input_offset, + name); } output_[0]->SetFrameSlot(output_offset, input_->GetFrameSlot(input_offset)); input_offset -= kPointerSize; output_offset -= kPointerSize; } @@ -315,11 +418,12 @@ unsigned pc_offset = data->OsrPcOffset()->value(); uint32_t pc = reinterpret_cast<uint32_t>( optimized_code_->entry() + pc_offset); output_[0]->SetPc(pc); } - Code* continuation = Builtins::builtin(Builtins::NotifyOSR); + Code* continuation = + function->GetIsolate()->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 " ", @@ -482,13 +586,14 @@ FullCodeGenerator::StateField::decode(pc_and_state); output_frame->SetState(Smi::FromInt(state)); // Set the continuation for the topmost frame. if (is_topmost) { + Builtins* builtins = isolate_->builtins(); Code* continuation = (bailout_type_ == EAGER) - ? Builtins::builtin(Builtins::NotifyDeoptimized) - : Builtins::builtin(Builtins::NotifyLazyDeoptimized); + ? builtins->builtin(Builtins::kNotifyDeoptimized) + : builtins->builtin(Builtins::kNotifyLazyDeoptimized); output_frame->SetContinuation( reinterpret_cast<uint32_t>(continuation->entry())); } if (output_count_ - 1 == frame_index) iterator->Done(); @@ -499,10 +604,12 @@ void Deoptimizer::EntryGenerator::Generate() { GeneratePrologue(); CpuFeatures::Scope scope(SSE2); + Isolate* isolate = masm()->isolate(); + // Save all general purpose registers before messing with them. const int kNumberOfRegisters = Register::kNumRegisters; const int kDoubleRegsSize = kDoubleSize * XMMRegister::kNumAllocatableRegisters; @@ -532,18 +639,20 @@ } __ sub(edx, Operand(ebp)); __ neg(edx); // Allocate a new deoptimizer object. - __ PrepareCallCFunction(5, eax); + __ PrepareCallCFunction(6, eax); __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); __ mov(Operand(esp, 0 * kPointerSize), eax); // Function. __ mov(Operand(esp, 1 * kPointerSize), Immediate(type())); // Bailout type. __ mov(Operand(esp, 2 * kPointerSize), ebx); // Bailout id. __ mov(Operand(esp, 3 * kPointerSize), ecx); // Code address or 0. __ mov(Operand(esp, 4 * kPointerSize), edx); // Fp-to-sp delta. - __ CallCFunction(ExternalReference::new_deoptimizer_function(), 5); + __ mov(Operand(esp, 5 * kPointerSize), + Immediate(ExternalReference::isolate_address())); + __ CallCFunction(ExternalReference::new_deoptimizer_function(isolate), 6); // Preserve deoptimizer object in register eax and get the input // frame descriptor pointer. __ mov(ebx, Operand(eax, Deoptimizer::input_offset())); @@ -587,10 +696,11 @@ // Compute the output frame in the deoptimizer. __ push(eax); __ PrepareCallCFunction(1, ebx); __ mov(Operand(esp, 0 * kPointerSize), eax); - __ CallCFunction(ExternalReference::compute_output_frames_function(), 1); + __ CallCFunction( + ExternalReference::compute_output_frames_function(isolate), 1); __ pop(eax); // Replace the current frame with the output frames. Label outer_push_loop, inner_push_loop; // Outer loop state: eax = current FrameDescription**, edx = one past the