Chromium Code Reviews| Index: src/arm/lithium-codegen-arm.cc |
| =================================================================== |
| --- src/arm/lithium-codegen-arm.cc (revision 7916) |
| +++ src/arm/lithium-codegen-arm.cc (working copy) |
| @@ -85,6 +85,7 @@ |
| return GeneratePrologue() && |
| GenerateBody() && |
| GenerateDeferredCode() && |
| + GenerateDeoptJumpTable() && |
| GenerateSafepointTable(); |
| } |
| @@ -249,13 +250,52 @@ |
| __ jmp(code->exit()); |
| } |
| - // Force constant pool emission at the end of deferred code to make |
| + return !is_aborted(); |
| +} |
| + |
| + |
| +bool LCodeGen::GenerateDeoptJumpTable() { |
| + // Emit previous constant pool entries so that we can safely emit the |
| + // deoptimization jump table. |
| + masm()->CheckConstPool(true, false); |
| + // 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 only one instruction. |
| + if (!is_int24((masm()->pc_offset() / Assembler::kInstrSize) + |
| + deopt_jump_table_.length())) { |
| + Abort("Generated code is too large"); |
| + } |
| + // We also need to check that the jump table will require fewer constant |
|
Søren Thygesen Gjesse
2011/05/18 06:47:13
I think we can avoid this restriction - see below.
Alexandre
2011/05/18 09:13:07
Removed.
On 2011/05/18 06:47:13, Søren Gjesse wro
|
| + // pool entries than the maximum authorized. |
| + // Each deopt entry will require exactly one constant pool entry. |
| + if (deopt_jump_table_.length() > Assembler::MaxNumPRInfo()) { |
| + Abort("Too many deoptimization entries"); |
| + } |
| + |
| + // 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); |
|
Søren Thygesen Gjesse
2011/05/18 06:47:13
How about avoiding using the const pool all togeth
Alexandre
2011/05/18 09:13:07
Done.
I also moved back the forced emission of the
|
| + __ mov(pc, Operand(reinterpret_cast<int32_t>(deopt_jump_table_[i].address), |
| + RelocInfo::RUNTIME_ENTRY)); |
| + } |
| + ASSERT(masm()->InstructionsGeneratedSince(&table_start) == |
| + deopt_jump_table_.length()); |
| + __ RecordComment("]"); |
| + |
| + // Force constant pool emission at the end of the jump table to make |
| // sure that no constant pools are emitted after the official end of |
| // the instruction sequence. |
| masm()->CheckConstPool(true, false); |
| - // Deferred code is the last part of the instruction sequence. Mark |
| - // the generated code as done unless we bailed out. |
| + // 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 +635,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); |
| } |
| } |