Chromium Code Reviews| Index: src/arm/assembler-arm.cc |
| =================================================================== |
| --- src/arm/assembler-arm.cc (revision 7890) |
| +++ src/arm/assembler-arm.cc (working copy) |
| @@ -321,6 +321,7 @@ |
| pc_ = buffer_; |
| reloc_info_writer.Reposition(buffer_ + buffer_size, pc_); |
| num_prinfo_ = 0; |
| + num_deopt_jump_entries_ = 0; |
| next_buffer_check_ = 0; |
| const_pool_blocked_nesting_ = 0; |
| no_const_pool_before_ = 0; |
| @@ -1507,10 +1508,10 @@ |
| if (cond != al) { |
| Label skip; |
| b(&skip, NegateCondition(cond)); |
| - bkpt(0); |
| + bkpt(kBkptStopCode); |
| bind(&skip); |
| } else { |
| - bkpt(0); |
| + bkpt(kBkptStopCode); |
| } |
| #else // ndef CAN_USE_ARMV5_INSTRUCTIONS |
| svc(0x9f0001, cond); |
| @@ -2399,6 +2400,12 @@ |
| } |
| +bool Assembler::IsBkpt(Instr instr, int code) { |
| + ASSERT(is_uint16(code)); |
| + return instr == (al | B24 | B21 | (code >> 4)*B8 | BKPT | (code & 0xf)); |
| +} |
| + |
| + |
| bool Assembler::ImmediateFitsAddrMode1Instruction(int32_t imm32) { |
| uint32_t dummy1; |
| uint32_t dummy2; |
| @@ -2548,28 +2555,48 @@ |
| } |
| +void Assembler::RecordDeoptJumpEntry(Address entry, Condition cond) { |
| + DeoptJumpEntry deopt_jump_entry(pc_offset(), cond, entry); |
| + deopt_jump_entries_[num_deopt_jump_entries_++]= deopt_jump_entry; |
| +} |
| + |
| + |
| void Assembler::CheckConstPool(bool force_emit, bool require_jump) { |
| // Calculate the offset of the next check. It will be overwritten |
| // when a const pool is generated or when const pools are being |
| // blocked for a specific range. |
| next_buffer_check_ = pc_offset() + kCheckConstInterval; |
| - // There is nothing to do if there are no pending relocation info entries. |
| - if (num_prinfo_ == 0) return; |
| + // There is nothing to do if there are no pending relocation info nor |
| + // deoptimization entries. |
| + if ((num_prinfo_ == 0) && (num_deopt_jump_entries_ == 0)) return; |
| // We emit a constant pool at regular intervals of about kDistBetweenPools |
| // or when requested by parameter force_emit (e.g. after each function). |
| // We prefer not to emit a jump unless the max distance is reached or if we |
| // are running low on slots, which can happen if a lot of constants are being |
| // emitted (e.g. --debug-code and many static references). |
| - int dist = pc_offset() - last_const_pool_end_; |
| + int jump_instr = require_jump ? kInstrSize : 0; |
| + int reloc_info_size = num_prinfo_ * kPointerSize; |
| + int deopt_jump_size = num_deopt_jump_entries_ * DeoptJumpEntry::kTotalSize; |
| + int needed_space = jump_instr + |
| + kInstrSize + // For the constant pool marker. |
| + reloc_info_size + deopt_jump_size; |
| + int dist = pc_offset() - last_const_pool_end_ + needed_space; |
| + // TODO(1236125): Cleanup the "magic" number below. We know that |
| + // the code generation will test every kCheckConstIntervalInst. |
| + // Thus we are safe as long as we generate less than 7 constant |
| + // entries per instruction. |
| + int max_dist_at_next_check = |
| + dist + kCheckConstIntervalInst * (kInstrSize + 7 * kInstrSize); |
| + |
| + // The distance between the first instruction after the last constant pool |
| + // and the end of this constant pool must be less than the addressing range. |
| if (!force_emit && dist < kMaxDistBetweenPools && |
| (require_jump || dist < kDistBetweenPools) && |
| - // TODO(1236125): Cleanup the "magic" number below. We know that |
| - // the code generation will test every kCheckConstIntervalInst. |
| - // Thus we are safe as long as we generate less than 7 constant |
| - // entries per instruction. |
| - (num_prinfo_ < (kMaxNumPRInfo - (7 * kCheckConstIntervalInst)))) { |
| + // We are safe as long as we are certain that we will not generate too |
| + // many reloc info or deopt entries in the next kCheckConstIntervalInst. |
| + (max_dist_at_next_check < kMaxDistBetweenPools)) { |
| return; |
| } |
| @@ -2594,18 +2621,13 @@ |
| return; |
| } |
| - int jump_instr = require_jump ? kInstrSize : 0; |
| - |
| // Check that the code buffer is large enough before emitting the constant |
| // pool and relocation information (include the jump over the pool and the |
| // constant pool marker). |
| - int max_needed_space = |
| - jump_instr + kInstrSize + num_prinfo_*(kInstrSize + kMaxRelocSize); |
| - while (buffer_space() <= (max_needed_space + kGap)) GrowBuffer(); |
| + while (buffer_space() <= (needed_space + kGap)) GrowBuffer(); |
| // Block recursive calls to CheckConstPool. |
| - BlockConstPoolBefore(pc_offset() + jump_instr + kInstrSize + |
| - num_prinfo_*kInstrSize); |
| + BlockConstPoolScope block_const_pool(this); |
| // Don't bother to check for the emit calls below. |
| next_buffer_check_ = no_const_pool_before_; |
| @@ -2617,9 +2639,55 @@ |
| // Put down constant pool marker "Undefined instruction" as specified by |
| // A5.6 (ARMv7) Instruction set encoding. |
| - emit(kConstantPoolMarker | num_prinfo_); |
| + int constant_pool_size = reloc_info_size + deopt_jump_size; |
| + ASSERT(((constant_pool_size / kPointerSize) & ~kConstantPoolLengthMask) == 0); |
| + emit(kConstantPoolMarker | (constant_pool_size / kPointerSize)); |
| + int start_of_const_pool = pc_offset(); |
| + USE(start_of_const_pool); |
| + |
| + // Emit the deoptimization jump table. |
|
Søren Thygesen Gjesse
2011/05/16 07:26:39
This emitting of the deopt-jump table in parts ins
|
| + RecordComment("[ Deoptimization jump table"); |
| + for (int i = 0; i < num_deopt_jump_entries_; i++) { |
| + // Patch the code at the deoptimization site. |
| + DeoptJumpEntry& deopt_jump_entry = deopt_jump_entries_[i]; |
| + // Get the offset to the current pc. |
| + int new_offset = |
| + (pc_offset() - deopt_jump_entry.pc_offset() - kPcLoadDelta); |
| + // Compute the location of the deoptimization site. |
| + Instr* deopt_site = |
| + reinterpret_cast<Instr*>(buffer_ + deopt_jump_entry.pc_offset()); |
| + // The code to patch is (See LCodeGen::DeoptimizeIf()): |
| + // bkpt kBkptUninitializedCode |
| + |
| + // Check that the instruction to patch is indeed |
| + // a bkpt kBkptUninitializedCode. |
| + ASSERT(IsBkpt(*deopt_site, kBkptUninitializedCode)); |
| + // We need to patch the instruction with a branch jumping here. |
| + ASSERT((new_offset & 3) == 0); |
| + int imm24 = new_offset >> 2; |
| + ASSERT(is_int24(imm24)); |
|
Søren Thygesen Gjesse
2011/05/16 07:26:39
Please use the CodePatcher class for this.
CodePa
|
| + *deopt_site = (deopt_jump_entry.cond() | B27 | B25 | (imm24 & kImm24Mask)); |
| + |
| + // Emit the jump to the corresponding deoptimization entry. |
| + // We need to manually register this relocation information, because we need |
| + // it to be emitted in this constant pool after this jump table. |
| + RelocInfo local_rinfo(pc_, |
| + RelocInfo::RUNTIME_ENTRY, |
| + reinterpret_cast<intptr_t>(deopt_jump_entry.entry())); |
| + // We are generating instructions in the constant pool. |
| + // We are sure the instruction cache will be flushed for these instructions: |
| + // the constant pools (and deoptimization jump tables) are intricated in |
| + // the generated code, and will be flushed along with it when needed. |
| + ldr(pc, MemOperand(pc, 0)); |
| + prinfo_[num_prinfo_++] = local_rinfo; |
| + reloc_info_writer.Write(&local_rinfo); |
| + } |
| + num_deopt_jump_entries_ = 0; |
| + RecordComment("]"); |
| + |
| // Emit constant pool entries. |
| + RecordComment("[ Constant pool entries"); |
| for (int i = 0; i < num_prinfo_; i++) { |
| RelocInfo& rinfo = prinfo_[i]; |
| ASSERT(rinfo.rmode() != RelocInfo::COMMENT && |
| @@ -2642,6 +2710,7 @@ |
| emit(rinfo.data()); |
| } |
| num_prinfo_ = 0; |
| + RecordComment("]"); |
| last_const_pool_end_ = pc_offset(); |
| RecordComment("]"); |
| @@ -2649,6 +2718,7 @@ |
| if (after_pool.is_linked()) { |
| bind(&after_pool); |
| } |
| + ASSERT(constant_pool_size == (pc_offset() - start_of_const_pool)); |
| // Since a constant pool was just emitted, move the check offset forward by |
| // the standard interval. |