Index: src/ia32/deoptimizer-ia32.cc |
diff --git a/src/ia32/deoptimizer-ia32.cc b/src/ia32/deoptimizer-ia32.cc |
index 898969018534250f2cb29ab13b75dfbf66be9be2..79a63766d24d9e98e38c913488513a32ee37eaba 100644 |
--- a/src/ia32/deoptimizer-ia32.cc |
+++ b/src/ia32/deoptimizer-ia32.cc |
@@ -55,6 +55,81 @@ static void ZapCodeRange(Address start, Address end) { |
} |
+void Deoptimizer::EnsureRelocSpaceForLazyDeoptimization(Handle<Code> code) { |
+ HandleScope scope; |
+ |
+ // 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 = code->GetIsolate()->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) { |
HandleScope scope; |
AssertNoAllocation no_allocation; |