Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 1994-2006 Sun Microsystems Inc. | 1 // Copyright (c) 1994-2006 Sun Microsystems Inc. |
| 2 // All Rights Reserved. | 2 // All Rights Reserved. |
| 3 // | 3 // |
| 4 // Redistribution and use in source and binary forms, with or without | 4 // Redistribution and use in source and binary forms, with or without |
| 5 // modification, are permitted provided that the following conditions | 5 // modification, are permitted provided that the following conditions |
| 6 // are met: | 6 // are met: |
| 7 // | 7 // |
| 8 // - Redistributions of source code must retain the above copyright notice, | 8 // - Redistributions of source code must retain the above copyright notice, |
| 9 // this list of conditions and the following disclaimer. | 9 // this list of conditions and the following disclaimer. |
| 10 // | 10 // |
| (...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 314 buffer_ = static_cast<byte*>(buffer); | 314 buffer_ = static_cast<byte*>(buffer); |
| 315 buffer_size_ = buffer_size; | 315 buffer_size_ = buffer_size; |
| 316 own_buffer_ = false; | 316 own_buffer_ = false; |
| 317 } | 317 } |
| 318 | 318 |
| 319 // Setup buffer pointers. | 319 // Setup buffer pointers. |
| 320 ASSERT(buffer_ != NULL); | 320 ASSERT(buffer_ != NULL); |
| 321 pc_ = buffer_; | 321 pc_ = buffer_; |
| 322 reloc_info_writer.Reposition(buffer_ + buffer_size, pc_); | 322 reloc_info_writer.Reposition(buffer_ + buffer_size, pc_); |
| 323 num_prinfo_ = 0; | 323 num_prinfo_ = 0; |
| 324 num_deopt_jump_entries_ = 0; | |
| 324 next_buffer_check_ = 0; | 325 next_buffer_check_ = 0; |
| 325 const_pool_blocked_nesting_ = 0; | 326 const_pool_blocked_nesting_ = 0; |
| 326 no_const_pool_before_ = 0; | 327 no_const_pool_before_ = 0; |
| 327 last_const_pool_end_ = 0; | 328 last_const_pool_end_ = 0; |
| 328 last_bound_pos_ = 0; | 329 last_bound_pos_ = 0; |
| 329 ast_id_for_reloc_info_ = kNoASTId; | 330 ast_id_for_reloc_info_ = kNoASTId; |
| 330 } | 331 } |
| 331 | 332 |
| 332 | 333 |
| 333 Assembler::~Assembler() { | 334 Assembler::~Assembler() { |
| (...skipping 1166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1500 svc(kStopCode + code, cond); | 1501 svc(kStopCode + code, cond); |
| 1501 } else { | 1502 } else { |
| 1502 svc(kStopCode + kMaxStopCode, cond); | 1503 svc(kStopCode + kMaxStopCode, cond); |
| 1503 } | 1504 } |
| 1504 emit(reinterpret_cast<Instr>(msg)); | 1505 emit(reinterpret_cast<Instr>(msg)); |
| 1505 #else // def __arm__ | 1506 #else // def __arm__ |
| 1506 #ifdef CAN_USE_ARMV5_INSTRUCTIONS | 1507 #ifdef CAN_USE_ARMV5_INSTRUCTIONS |
| 1507 if (cond != al) { | 1508 if (cond != al) { |
| 1508 Label skip; | 1509 Label skip; |
| 1509 b(&skip, NegateCondition(cond)); | 1510 b(&skip, NegateCondition(cond)); |
| 1510 bkpt(0); | 1511 bkpt(kBkptStopCode); |
| 1511 bind(&skip); | 1512 bind(&skip); |
| 1512 } else { | 1513 } else { |
| 1513 bkpt(0); | 1514 bkpt(kBkptStopCode); |
| 1514 } | 1515 } |
| 1515 #else // ndef CAN_USE_ARMV5_INSTRUCTIONS | 1516 #else // ndef CAN_USE_ARMV5_INSTRUCTIONS |
| 1516 svc(0x9f0001, cond); | 1517 svc(0x9f0001, cond); |
| 1517 #endif // ndef CAN_USE_ARMV5_INSTRUCTIONS | 1518 #endif // ndef CAN_USE_ARMV5_INSTRUCTIONS |
| 1518 #endif // def __arm__ | 1519 #endif // def __arm__ |
| 1519 } | 1520 } |
| 1520 | 1521 |
| 1521 | 1522 |
| 1522 void Assembler::bkpt(uint32_t imm16) { // v5 and above | 1523 void Assembler::bkpt(uint32_t imm16) { // v5 and above |
| 1523 ASSERT(is_uint16(imm16)); | 1524 ASSERT(is_uint16(imm16)); |
| (...skipping 868 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2392 } | 2393 } |
| 2393 | 2394 |
| 2394 | 2395 |
| 2395 bool Assembler::IsNop(Instr instr, int type) { | 2396 bool Assembler::IsNop(Instr instr, int type) { |
| 2396 // Check for mov rx, rx where x = type. | 2397 // Check for mov rx, rx where x = type. |
| 2397 ASSERT(0 <= type && type <= 14); // mov pc, pc is not a nop. | 2398 ASSERT(0 <= type && type <= 14); // mov pc, pc is not a nop. |
| 2398 return instr == (al | 13*B21 | type*B12 | type); | 2399 return instr == (al | 13*B21 | type*B12 | type); |
| 2399 } | 2400 } |
| 2400 | 2401 |
| 2401 | 2402 |
| 2403 bool Assembler::IsBkpt(Instr instr, int code) { | |
| 2404 ASSERT(is_uint16(code)); | |
| 2405 return instr == (al | B24 | B21 | (code >> 4)*B8 | BKPT | (code & 0xf)); | |
| 2406 } | |
| 2407 | |
| 2408 | |
| 2402 bool Assembler::ImmediateFitsAddrMode1Instruction(int32_t imm32) { | 2409 bool Assembler::ImmediateFitsAddrMode1Instruction(int32_t imm32) { |
| 2403 uint32_t dummy1; | 2410 uint32_t dummy1; |
| 2404 uint32_t dummy2; | 2411 uint32_t dummy2; |
| 2405 return fits_shifter(imm32, &dummy1, &dummy2, NULL); | 2412 return fits_shifter(imm32, &dummy1, &dummy2, NULL); |
| 2406 } | 2413 } |
| 2407 | 2414 |
| 2408 | 2415 |
| 2409 void Assembler::BlockConstPoolFor(int instructions) { | 2416 void Assembler::BlockConstPoolFor(int instructions) { |
| 2410 BlockConstPoolBefore(pc_offset() + instructions * kInstrSize); | 2417 BlockConstPoolBefore(pc_offset() + instructions * kInstrSize); |
| 2411 } | 2418 } |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2541 RelocInfo reloc_info_with_ast_id(pc_, rmode, ast_id_for_reloc_info_); | 2548 RelocInfo reloc_info_with_ast_id(pc_, rmode, ast_id_for_reloc_info_); |
| 2542 ast_id_for_reloc_info_ = kNoASTId; | 2549 ast_id_for_reloc_info_ = kNoASTId; |
| 2543 reloc_info_writer.Write(&reloc_info_with_ast_id); | 2550 reloc_info_writer.Write(&reloc_info_with_ast_id); |
| 2544 } else { | 2551 } else { |
| 2545 reloc_info_writer.Write(&rinfo); | 2552 reloc_info_writer.Write(&rinfo); |
| 2546 } | 2553 } |
| 2547 } | 2554 } |
| 2548 } | 2555 } |
| 2549 | 2556 |
| 2550 | 2557 |
| 2558 void Assembler::RecordDeoptJumpEntry(Address entry, Condition cond) { | |
| 2559 DeoptJumpEntry deopt_jump_entry(pc_offset(), cond, entry); | |
| 2560 deopt_jump_entries_[num_deopt_jump_entries_++]= deopt_jump_entry; | |
| 2561 } | |
| 2562 | |
| 2563 | |
| 2551 void Assembler::CheckConstPool(bool force_emit, bool require_jump) { | 2564 void Assembler::CheckConstPool(bool force_emit, bool require_jump) { |
| 2552 // Calculate the offset of the next check. It will be overwritten | 2565 // Calculate the offset of the next check. It will be overwritten |
| 2553 // when a const pool is generated or when const pools are being | 2566 // when a const pool is generated or when const pools are being |
| 2554 // blocked for a specific range. | 2567 // blocked for a specific range. |
| 2555 next_buffer_check_ = pc_offset() + kCheckConstInterval; | 2568 next_buffer_check_ = pc_offset() + kCheckConstInterval; |
| 2556 | 2569 |
| 2557 // There is nothing to do if there are no pending relocation info entries. | 2570 // There is nothing to do if there are no pending relocation info nor |
| 2558 if (num_prinfo_ == 0) return; | 2571 // deoptimization entries. |
| 2572 if ((num_prinfo_ == 0) && (num_deopt_jump_entries_ == 0)) return; | |
| 2559 | 2573 |
| 2560 // We emit a constant pool at regular intervals of about kDistBetweenPools | 2574 // We emit a constant pool at regular intervals of about kDistBetweenPools |
| 2561 // or when requested by parameter force_emit (e.g. after each function). | 2575 // or when requested by parameter force_emit (e.g. after each function). |
| 2562 // We prefer not to emit a jump unless the max distance is reached or if we | 2576 // We prefer not to emit a jump unless the max distance is reached or if we |
| 2563 // are running low on slots, which can happen if a lot of constants are being | 2577 // are running low on slots, which can happen if a lot of constants are being |
| 2564 // emitted (e.g. --debug-code and many static references). | 2578 // emitted (e.g. --debug-code and many static references). |
| 2565 int dist = pc_offset() - last_const_pool_end_; | 2579 int jump_instr = require_jump ? kInstrSize : 0; |
| 2580 int reloc_info_size = num_prinfo_ * kPointerSize; | |
| 2581 int deopt_jump_size = num_deopt_jump_entries_ * DeoptJumpEntry::kTotalSize; | |
| 2582 int needed_space = jump_instr + | |
| 2583 kInstrSize + // For the constant pool marker. | |
| 2584 reloc_info_size + deopt_jump_size; | |
| 2585 int dist = pc_offset() - last_const_pool_end_ + needed_space; | |
| 2586 // TODO(1236125): Cleanup the "magic" number below. We know that | |
| 2587 // the code generation will test every kCheckConstIntervalInst. | |
| 2588 // Thus we are safe as long as we generate less than 7 constant | |
| 2589 // entries per instruction. | |
| 2590 int max_dist_at_next_check = | |
| 2591 dist + kCheckConstIntervalInst * (kInstrSize + 7 * kInstrSize); | |
| 2592 | |
| 2593 // The distance between the first instruction after the last constant pool | |
| 2594 // and the end of this constant pool must be less than the addressing range. | |
| 2566 if (!force_emit && dist < kMaxDistBetweenPools && | 2595 if (!force_emit && dist < kMaxDistBetweenPools && |
| 2567 (require_jump || dist < kDistBetweenPools) && | 2596 (require_jump || dist < kDistBetweenPools) && |
| 2568 // TODO(1236125): Cleanup the "magic" number below. We know that | 2597 // We are safe as long as we are certain that we will not generate too |
| 2569 // the code generation will test every kCheckConstIntervalInst. | 2598 // many reloc info or deopt entries in the next kCheckConstIntervalInst. |
| 2570 // Thus we are safe as long as we generate less than 7 constant | 2599 (max_dist_at_next_check < kMaxDistBetweenPools)) { |
| 2571 // entries per instruction. | |
| 2572 (num_prinfo_ < (kMaxNumPRInfo - (7 * kCheckConstIntervalInst)))) { | |
| 2573 return; | 2600 return; |
| 2574 } | 2601 } |
| 2575 | 2602 |
| 2576 // If we did not return by now, we need to emit the constant pool soon. | 2603 // If we did not return by now, we need to emit the constant pool soon. |
| 2577 | 2604 |
| 2578 // However, some small sequences of instructions must not be broken up by the | 2605 // However, some small sequences of instructions must not be broken up by the |
| 2579 // insertion of a constant pool; such sequences are protected by setting | 2606 // insertion of a constant pool; such sequences are protected by setting |
| 2580 // either const_pool_blocked_nesting_ or no_const_pool_before_, which are | 2607 // either const_pool_blocked_nesting_ or no_const_pool_before_, which are |
| 2581 // both checked here. Also, recursive calls to CheckConstPool are blocked by | 2608 // both checked here. Also, recursive calls to CheckConstPool are blocked by |
| 2582 // no_const_pool_before_. | 2609 // no_const_pool_before_. |
| 2583 if (const_pool_blocked_nesting_ > 0 || pc_offset() < no_const_pool_before_) { | 2610 if (const_pool_blocked_nesting_ > 0 || pc_offset() < no_const_pool_before_) { |
| 2584 // Emission is currently blocked; make sure we try again as soon as | 2611 // Emission is currently blocked; make sure we try again as soon as |
| 2585 // possible. | 2612 // possible. |
| 2586 if (const_pool_blocked_nesting_ > 0) { | 2613 if (const_pool_blocked_nesting_ > 0) { |
| 2587 next_buffer_check_ = pc_offset() + kInstrSize; | 2614 next_buffer_check_ = pc_offset() + kInstrSize; |
| 2588 } else { | 2615 } else { |
| 2589 next_buffer_check_ = no_const_pool_before_; | 2616 next_buffer_check_ = no_const_pool_before_; |
| 2590 } | 2617 } |
| 2591 | 2618 |
| 2592 // Something is wrong if emission is forced and blocked at the same time. | 2619 // Something is wrong if emission is forced and blocked at the same time. |
| 2593 ASSERT(!force_emit); | 2620 ASSERT(!force_emit); |
| 2594 return; | 2621 return; |
| 2595 } | 2622 } |
| 2596 | 2623 |
| 2597 int jump_instr = require_jump ? kInstrSize : 0; | |
| 2598 | |
| 2599 // Check that the code buffer is large enough before emitting the constant | 2624 // Check that the code buffer is large enough before emitting the constant |
| 2600 // pool and relocation information (include the jump over the pool and the | 2625 // pool and relocation information (include the jump over the pool and the |
| 2601 // constant pool marker). | 2626 // constant pool marker). |
| 2602 int max_needed_space = | 2627 while (buffer_space() <= (needed_space + kGap)) GrowBuffer(); |
| 2603 jump_instr + kInstrSize + num_prinfo_*(kInstrSize + kMaxRelocSize); | |
| 2604 while (buffer_space() <= (max_needed_space + kGap)) GrowBuffer(); | |
| 2605 | 2628 |
| 2606 // Block recursive calls to CheckConstPool. | 2629 // Block recursive calls to CheckConstPool. |
| 2607 BlockConstPoolBefore(pc_offset() + jump_instr + kInstrSize + | 2630 BlockConstPoolScope block_const_pool(this); |
| 2608 num_prinfo_*kInstrSize); | |
| 2609 // Don't bother to check for the emit calls below. | 2631 // Don't bother to check for the emit calls below. |
| 2610 next_buffer_check_ = no_const_pool_before_; | 2632 next_buffer_check_ = no_const_pool_before_; |
| 2611 | 2633 |
| 2612 // Emit jump over constant pool if necessary. | 2634 // Emit jump over constant pool if necessary. |
| 2613 Label after_pool; | 2635 Label after_pool; |
| 2614 if (require_jump) b(&after_pool); | 2636 if (require_jump) b(&after_pool); |
| 2615 | 2637 |
| 2616 RecordComment("[ Constant Pool"); | 2638 RecordComment("[ Constant Pool"); |
| 2617 | 2639 |
| 2618 // Put down constant pool marker "Undefined instruction" as specified by | 2640 // Put down constant pool marker "Undefined instruction" as specified by |
| 2619 // A5.6 (ARMv7) Instruction set encoding. | 2641 // A5.6 (ARMv7) Instruction set encoding. |
| 2620 emit(kConstantPoolMarker | num_prinfo_); | 2642 int constant_pool_size = reloc_info_size + deopt_jump_size; |
| 2643 ASSERT(((constant_pool_size / kPointerSize) & ~kConstantPoolLengthMask) == 0); | |
| 2644 emit(kConstantPoolMarker | (constant_pool_size / kPointerSize)); | |
| 2645 | |
| 2646 int start_of_const_pool = pc_offset(); | |
| 2647 USE(start_of_const_pool); | |
| 2648 | |
| 2649 // 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
| |
| 2650 RecordComment("[ Deoptimization jump table"); | |
| 2651 for (int i = 0; i < num_deopt_jump_entries_; i++) { | |
| 2652 // Patch the code at the deoptimization site. | |
| 2653 DeoptJumpEntry& deopt_jump_entry = deopt_jump_entries_[i]; | |
| 2654 // Get the offset to the current pc. | |
| 2655 int new_offset = | |
| 2656 (pc_offset() - deopt_jump_entry.pc_offset() - kPcLoadDelta); | |
| 2657 // Compute the location of the deoptimization site. | |
| 2658 Instr* deopt_site = | |
| 2659 reinterpret_cast<Instr*>(buffer_ + deopt_jump_entry.pc_offset()); | |
| 2660 // The code to patch is (See LCodeGen::DeoptimizeIf()): | |
| 2661 // bkpt kBkptUninitializedCode | |
| 2662 | |
| 2663 // Check that the instruction to patch is indeed | |
| 2664 // a bkpt kBkptUninitializedCode. | |
| 2665 ASSERT(IsBkpt(*deopt_site, kBkptUninitializedCode)); | |
| 2666 // We need to patch the instruction with a branch jumping here. | |
| 2667 ASSERT((new_offset & 3) == 0); | |
| 2668 int imm24 = new_offset >> 2; | |
| 2669 ASSERT(is_int24(imm24)); | |
|
Søren Thygesen Gjesse
2011/05/16 07:26:39
Please use the CodePatcher class for this.
CodePa
| |
| 2670 *deopt_site = (deopt_jump_entry.cond() | B27 | B25 | (imm24 & kImm24Mask)); | |
| 2671 | |
| 2672 // Emit the jump to the corresponding deoptimization entry. | |
| 2673 // We need to manually register this relocation information, because we need | |
| 2674 // it to be emitted in this constant pool after this jump table. | |
| 2675 RelocInfo local_rinfo(pc_, | |
| 2676 RelocInfo::RUNTIME_ENTRY, | |
| 2677 reinterpret_cast<intptr_t>(deopt_jump_entry.entry())); | |
| 2678 // We are generating instructions in the constant pool. | |
| 2679 // We are sure the instruction cache will be flushed for these instructions: | |
| 2680 // the constant pools (and deoptimization jump tables) are intricated in | |
| 2681 // the generated code, and will be flushed along with it when needed. | |
| 2682 ldr(pc, MemOperand(pc, 0)); | |
| 2683 prinfo_[num_prinfo_++] = local_rinfo; | |
| 2684 reloc_info_writer.Write(&local_rinfo); | |
| 2685 } | |
| 2686 num_deopt_jump_entries_ = 0; | |
| 2687 RecordComment("]"); | |
| 2621 | 2688 |
| 2622 // Emit constant pool entries. | 2689 // Emit constant pool entries. |
| 2690 RecordComment("[ Constant pool entries"); | |
| 2623 for (int i = 0; i < num_prinfo_; i++) { | 2691 for (int i = 0; i < num_prinfo_; i++) { |
| 2624 RelocInfo& rinfo = prinfo_[i]; | 2692 RelocInfo& rinfo = prinfo_[i]; |
| 2625 ASSERT(rinfo.rmode() != RelocInfo::COMMENT && | 2693 ASSERT(rinfo.rmode() != RelocInfo::COMMENT && |
| 2626 rinfo.rmode() != RelocInfo::POSITION && | 2694 rinfo.rmode() != RelocInfo::POSITION && |
| 2627 rinfo.rmode() != RelocInfo::STATEMENT_POSITION); | 2695 rinfo.rmode() != RelocInfo::STATEMENT_POSITION); |
| 2628 Instr instr = instr_at(rinfo.pc()); | 2696 Instr instr = instr_at(rinfo.pc()); |
| 2629 | 2697 |
| 2630 // Instruction to patch must be a ldr/str [pc, #offset]. | 2698 // Instruction to patch must be a ldr/str [pc, #offset]. |
| 2631 // P and U set, B and W clear, Rn == pc, offset12 still 0. | 2699 // P and U set, B and W clear, Rn == pc, offset12 still 0. |
| 2632 ASSERT((instr & (7*B25 | P | U | B | W | 15*B16 | kOff12Mask)) == | 2700 ASSERT((instr & (7*B25 | P | U | B | W | 15*B16 | kOff12Mask)) == |
| 2633 (2*B25 | P | U | pc.code()*B16)); | 2701 (2*B25 | P | U | pc.code()*B16)); |
| 2634 int delta = pc_ - rinfo.pc() - 8; | 2702 int delta = pc_ - rinfo.pc() - 8; |
| 2635 ASSERT(delta >= -4); // instr could be ldr pc, [pc, #-4] followed by targ32 | 2703 ASSERT(delta >= -4); // instr could be ldr pc, [pc, #-4] followed by targ32 |
| 2636 if (delta < 0) { | 2704 if (delta < 0) { |
| 2637 instr &= ~U; | 2705 instr &= ~U; |
| 2638 delta = -delta; | 2706 delta = -delta; |
| 2639 } | 2707 } |
| 2640 ASSERT(is_uint12(delta)); | 2708 ASSERT(is_uint12(delta)); |
| 2641 instr_at_put(rinfo.pc(), instr + delta); | 2709 instr_at_put(rinfo.pc(), instr + delta); |
| 2642 emit(rinfo.data()); | 2710 emit(rinfo.data()); |
| 2643 } | 2711 } |
| 2644 num_prinfo_ = 0; | 2712 num_prinfo_ = 0; |
| 2713 RecordComment("]"); | |
| 2645 last_const_pool_end_ = pc_offset(); | 2714 last_const_pool_end_ = pc_offset(); |
| 2646 | 2715 |
| 2647 RecordComment("]"); | 2716 RecordComment("]"); |
| 2648 | 2717 |
| 2649 if (after_pool.is_linked()) { | 2718 if (after_pool.is_linked()) { |
| 2650 bind(&after_pool); | 2719 bind(&after_pool); |
| 2651 } | 2720 } |
| 2721 ASSERT(constant_pool_size == (pc_offset() - start_of_const_pool)); | |
| 2652 | 2722 |
| 2653 // Since a constant pool was just emitted, move the check offset forward by | 2723 // Since a constant pool was just emitted, move the check offset forward by |
| 2654 // the standard interval. | 2724 // the standard interval. |
| 2655 next_buffer_check_ = pc_offset() + kCheckConstInterval; | 2725 next_buffer_check_ = pc_offset() + kCheckConstInterval; |
| 2656 } | 2726 } |
| 2657 | 2727 |
| 2658 | 2728 |
| 2659 } } // namespace v8::internal | 2729 } } // namespace v8::internal |
| 2660 | 2730 |
| 2661 #endif // V8_TARGET_ARCH_ARM | 2731 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |