Index: src/arm/lithium-codegen-arm.cc |
=================================================================== |
--- src/arm/lithium-codegen-arm.cc (revision 7959) |
+++ src/arm/lithium-codegen-arm.cc (working copy) |
@@ -85,6 +85,7 @@ |
return GeneratePrologue() && |
GenerateBody() && |
GenerateDeferredCode() && |
+ GenerateDeoptJumpTable() && |
GenerateSafepointTable(); |
} |
@@ -249,13 +250,43 @@ |
__ jmp(code->exit()); |
} |
- // Force constant pool emission at the end of deferred code to make |
- // sure that no constant pools are emitted after the official end of |
- // the instruction sequence. |
+ // Force constant pool emission at the end of the deferred code to make |
+ // sure that no constant pools are emitted after. |
masm()->CheckConstPool(true, false); |
- // Deferred code is the last part of the instruction sequence. Mark |
- // the generated code as done unless we bailed out. |
+ return !is_aborted(); |
+} |
+ |
+ |
+bool LCodeGen::GenerateDeoptJumpTable() { |
+ // Check that the jump table is accessible from everywhere in the function |
+ // code, ie that offsets to the table can be encoded in the 24bit signed |
+ // immediate of a branch instruction. |
+ // To simplify we consider the code size from the first instruction to the |
+ // end of the jump table. We also don't consider the pc load delta. |
+ // Each entry in the jump table generates one instruction and inlines one |
+ // 32bit data after it. |
+ if (!is_int24((masm()->pc_offset() / Assembler::kInstrSize) + |
+ deopt_jump_table_.length() * 2)) { |
+ Abort("Generated code is too large"); |
+ } |
+ |
+ // Block the constant pool emission during the jump table emission. |
+ __ BlockConstPoolFor(deopt_jump_table_.length()); |
+ __ RecordComment("[ Deoptimisation jump table"); |
+ Label table_start; |
+ __ bind(&table_start); |
+ for (int i = 0; i < deopt_jump_table_.length(); i++) { |
+ __ bind(&deopt_jump_table_[i].label); |
+ __ ldr(pc, MemOperand(pc, Assembler::kInstrSize - Assembler::kPcLoadDelta)); |
+ __ dd(reinterpret_cast<uint32_t>(deopt_jump_table_[i].address)); |
+ } |
+ ASSERT(masm()->InstructionsGeneratedSince(&table_start) == |
+ deopt_jump_table_.length() * 2); |
+ __ RecordComment("]"); |
+ |
+ // The deoptimization jump table is the last part of the instruction |
+ // sequence. Mark the generated code as done unless we bailed out. |
if (!is_aborted()) status_ = DONE; |
return !is_aborted(); |
} |
@@ -595,19 +626,18 @@ |
return; |
} |
+ if (FLAG_trap_on_deopt) __ stop("trap_on_deopt", cc); |
+ |
if (cc == al) { |
- if (FLAG_trap_on_deopt) __ stop("trap_on_deopt"); |
__ Jump(entry, RelocInfo::RUNTIME_ENTRY); |
} else { |
- if (FLAG_trap_on_deopt) { |
- Label done; |
- __ b(&done, NegateCondition(cc)); |
- __ stop("trap_on_deopt"); |
- __ Jump(entry, RelocInfo::RUNTIME_ENTRY); |
- __ bind(&done); |
- } else { |
- __ Jump(entry, RelocInfo::RUNTIME_ENTRY, cc); |
+ // We often have several deopts to the same entry, reuse the last |
+ // jump entry if this is the case. |
+ if (deopt_jump_table_.is_empty() || |
+ (deopt_jump_table_.last().address != entry)) { |
+ deopt_jump_table_.Add(JumpTableEntry(entry)); |
} |
+ __ b(cc, &deopt_jump_table_.last().label); |
} |
} |