| 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 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 142 // ----------------------------------------------------------------------------- | 142 // ----------------------------------------------------------------------------- |
| 143 // Implementation of RelocInfo | 143 // Implementation of RelocInfo |
| 144 | 144 |
| 145 const int RelocInfo::kApplyMask = 1 << RelocInfo::INTERNAL_REFERENCE | | 145 const int RelocInfo::kApplyMask = 1 << RelocInfo::INTERNAL_REFERENCE | |
| 146 1 << RelocInfo::INTERNAL_REFERENCE_ENCODED; | 146 1 << RelocInfo::INTERNAL_REFERENCE_ENCODED; |
| 147 | 147 |
| 148 | 148 |
| 149 bool RelocInfo::IsCodedSpecially() { | 149 bool RelocInfo::IsCodedSpecially() { |
| 150 // The deserializer needs to know whether a pointer is specially | 150 // The deserializer needs to know whether a pointer is specially |
| 151 // coded. Being specially coded on PPC means that it is a lis/ori | 151 // coded. Being specially coded on PPC means that it is a lis/ori |
| 152 // instruction sequence, and these are always the case inside code | 152 // instruction sequence or is an out of line constant pool entry, |
| 153 // objects. | 153 // and these are always the case inside code objects. |
| 154 return true; | 154 return true; |
| 155 } | 155 } |
| 156 | 156 |
| 157 | 157 |
| 158 bool RelocInfo::IsInConstantPool() { | 158 bool RelocInfo::IsInConstantPool() { |
| 159 if (FLAG_enable_embedded_constant_pool) { |
| 160 Address constant_pool = host_->constant_pool(); |
| 161 return (constant_pool && |
| 162 (pc_ >= constant_pool || Assembler::IsConstantPoolLoadStart(pc_))); |
| 163 } |
| 159 return false; | 164 return false; |
| 160 } | 165 } |
| 161 | 166 |
| 162 | 167 |
| 163 // ----------------------------------------------------------------------------- | 168 // ----------------------------------------------------------------------------- |
| 164 // Implementation of Operand and MemOperand | 169 // Implementation of Operand and MemOperand |
| 165 // See assembler-ppc-inl.h for inlined constructors | 170 // See assembler-ppc-inl.h for inlined constructors |
| 166 | 171 |
| 167 Operand::Operand(Handle<Object> handle) { | 172 Operand::Operand(Handle<Object> handle) { |
| 168 AllowDeferredHandleDereference using_raw_address; | 173 AllowDeferredHandleDereference using_raw_address; |
| (...skipping 26 matching lines...) Expand all Loading... |
| 195 } | 200 } |
| 196 | 201 |
| 197 | 202 |
| 198 // ----------------------------------------------------------------------------- | 203 // ----------------------------------------------------------------------------- |
| 199 // Specific instructions, constants, and masks. | 204 // Specific instructions, constants, and masks. |
| 200 | 205 |
| 201 | 206 |
| 202 Assembler::Assembler(Isolate* isolate, void* buffer, int buffer_size) | 207 Assembler::Assembler(Isolate* isolate, void* buffer, int buffer_size) |
| 203 : AssemblerBase(isolate, buffer, buffer_size), | 208 : AssemblerBase(isolate, buffer, buffer_size), |
| 204 recorded_ast_id_(TypeFeedbackId::None()), | 209 recorded_ast_id_(TypeFeedbackId::None()), |
| 210 constant_pool_builder_(), |
| 205 positions_recorder_(this) { | 211 positions_recorder_(this) { |
| 206 reloc_info_writer.Reposition(buffer_ + buffer_size_, pc_); | 212 reloc_info_writer.Reposition(buffer_ + buffer_size_, pc_); |
| 207 | 213 |
| 208 no_trampoline_pool_before_ = 0; | 214 no_trampoline_pool_before_ = 0; |
| 209 trampoline_pool_blocked_nesting_ = 0; | 215 trampoline_pool_blocked_nesting_ = 0; |
| 216 constant_pool_entry_sharing_blocked_nesting_ = 0; |
| 210 // We leave space (kMaxBlockTrampolineSectionSize) | 217 // We leave space (kMaxBlockTrampolineSectionSize) |
| 211 // for BlockTrampolinePoolScope buffer. | 218 // for BlockTrampolinePoolScope buffer. |
| 212 next_buffer_check_ = | 219 next_buffer_check_ = |
| 213 FLAG_force_long_branches ? kMaxInt : kMaxCondBranchReach - | 220 FLAG_force_long_branches ? kMaxInt : kMaxCondBranchReach - |
| 214 kMaxBlockTrampolineSectionSize; | 221 kMaxBlockTrampolineSectionSize; |
| 215 internal_trampoline_exception_ = false; | 222 internal_trampoline_exception_ = false; |
| 216 last_bound_pos_ = 0; | 223 last_bound_pos_ = 0; |
| 217 trampoline_emitted_ = FLAG_force_long_branches; | 224 trampoline_emitted_ = FLAG_force_long_branches; |
| 218 unbound_labels_count_ = 0; | 225 unbound_labels_count_ = 0; |
| 219 ClearRecordedAstId(); | 226 ClearRecordedAstId(); |
| 220 relocations_.reserve(128); | 227 relocations_.reserve(128); |
| 221 } | 228 } |
| 222 | 229 |
| 223 | 230 |
| 224 void Assembler::GetCode(CodeDesc* desc) { | 231 void Assembler::GetCode(CodeDesc* desc) { |
| 232 // Emit constant pool if necessary. |
| 233 int offset = EmitConstantPool(); |
| 234 |
| 225 EmitRelocations(); | 235 EmitRelocations(); |
| 226 | 236 |
| 227 // Set up code descriptor. | 237 // Set up code descriptor. |
| 228 desc->buffer = buffer_; | 238 desc->buffer = buffer_; |
| 229 desc->buffer_size = buffer_size_; | 239 desc->buffer_size = buffer_size_; |
| 230 desc->instr_size = pc_offset(); | 240 desc->instr_size = pc_offset(); |
| 231 desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos(); | 241 desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos(); |
| 242 desc->constant_pool_size = (offset ? desc->instr_size - offset : 0); |
| 232 desc->origin = this; | 243 desc->origin = this; |
| 233 } | 244 } |
| 234 | 245 |
| 235 | 246 |
| 236 void Assembler::Align(int m) { | 247 void Assembler::Align(int m) { |
| 237 #if V8_TARGET_ARCH_PPC64 | 248 #if V8_TARGET_ARCH_PPC64 |
| 238 DCHECK(m >= 4 && base::bits::IsPowerOfTwo64(m)); | 249 DCHECK(m >= 4 && base::bits::IsPowerOfTwo64(m)); |
| 239 #else | 250 #else |
| 240 DCHECK(m >= 4 && base::bits::IsPowerOfTwo32(m)); | 251 DCHECK(m >= 4 && base::bits::IsPowerOfTwo32(m)); |
| 241 #endif | 252 #endif |
| (...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 465 int32_t offset = target_pos + SIGN_EXT_IMM16(operands & kImm16Mask); | 476 int32_t offset = target_pos + SIGN_EXT_IMM16(operands & kImm16Mask); |
| 466 CodePatcher patcher(reinterpret_cast<byte*>(buffer_ + pos), 2, | 477 CodePatcher patcher(reinterpret_cast<byte*>(buffer_ + pos), 2, |
| 467 CodePatcher::DONT_FLUSH); | 478 CodePatcher::DONT_FLUSH); |
| 468 patcher.masm()->bitwise_add32(dst, base, offset); | 479 patcher.masm()->bitwise_add32(dst, base, offset); |
| 469 break; | 480 break; |
| 470 } | 481 } |
| 471 case kUnboundMovLabelAddrOpcode: { | 482 case kUnboundMovLabelAddrOpcode: { |
| 472 // Load the address of the label in a register. | 483 // Load the address of the label in a register. |
| 473 Register dst = Register::from_code(instr_at(pos + kInstrSize)); | 484 Register dst = Register::from_code(instr_at(pos + kInstrSize)); |
| 474 CodePatcher patcher(reinterpret_cast<byte*>(buffer_ + pos), | 485 CodePatcher patcher(reinterpret_cast<byte*>(buffer_ + pos), |
| 475 kMovInstructions, CodePatcher::DONT_FLUSH); | 486 kMovInstructionsNoConstantPool, |
| 487 CodePatcher::DONT_FLUSH); |
| 476 // Keep internal references relative until EmitRelocations. | 488 // Keep internal references relative until EmitRelocations. |
| 477 patcher.masm()->bitwise_mov(dst, target_pos); | 489 patcher.masm()->bitwise_mov(dst, target_pos); |
| 478 break; | 490 break; |
| 479 } | 491 } |
| 480 case kUnboundJumpTableEntryOpcode: { | 492 case kUnboundJumpTableEntryOpcode: { |
| 481 CodePatcher patcher(reinterpret_cast<byte*>(buffer_ + pos), | 493 CodePatcher patcher(reinterpret_cast<byte*>(buffer_ + pos), |
| 482 kPointerSize / kInstrSize, CodePatcher::DONT_FLUSH); | 494 kPointerSize / kInstrSize, CodePatcher::DONT_FLUSH); |
| 483 // Keep internal references relative until EmitRelocations. | 495 // Keep internal references relative until EmitRelocations. |
| 484 patcher.masm()->emit_ptr(target_pos); | 496 patcher.masm()->emit_ptr(target_pos); |
| 485 break; | 497 break; |
| (...skipping 1007 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1493 Label instructions; | 1505 Label instructions; |
| 1494 DCHECK(pc_offset() == 0); | 1506 DCHECK(pc_offset() == 0); |
| 1495 emit_label_addr(&instructions); | 1507 emit_label_addr(&instructions); |
| 1496 emit_ptr(0); | 1508 emit_ptr(0); |
| 1497 emit_ptr(0); | 1509 emit_ptr(0); |
| 1498 bind(&instructions); | 1510 bind(&instructions); |
| 1499 #endif | 1511 #endif |
| 1500 } | 1512 } |
| 1501 | 1513 |
| 1502 | 1514 |
| 1515 int Assembler::instructions_required_for_mov(const Operand& x) const { |
| 1516 bool canOptimize = |
| 1517 !(x.must_output_reloc_info(this) || is_trampoline_pool_blocked()); |
| 1518 if (use_constant_pool_for_mov(x, canOptimize)) { |
| 1519 // Current usage guarantees that all constant pool references can |
| 1520 // use the same sequence. |
| 1521 return kMovInstructionsConstantPool; |
| 1522 } |
| 1523 DCHECK(!canOptimize); |
| 1524 return kMovInstructionsNoConstantPool; |
| 1525 } |
| 1526 |
| 1527 |
| 1528 bool Assembler::use_constant_pool_for_mov(const Operand& x, |
| 1529 bool canOptimize) const { |
| 1530 if (!FLAG_enable_embedded_constant_pool || !is_constant_pool_available() || |
| 1531 is_constant_pool_full()) { |
| 1532 // If there is no constant pool available, we must use a mov |
| 1533 // immediate sequence. |
| 1534 return false; |
| 1535 } |
| 1536 |
| 1537 intptr_t value = x.immediate(); |
| 1538 if (canOptimize && is_int16(value)) { |
| 1539 // Prefer a single-instruction load-immediate. |
| 1540 return false; |
| 1541 } |
| 1542 |
| 1543 return true; |
| 1544 } |
| 1545 |
| 1546 |
| 1503 void Assembler::EnsureSpaceFor(int space_needed) { | 1547 void Assembler::EnsureSpaceFor(int space_needed) { |
| 1504 if (buffer_space() <= (kGap + space_needed)) { | 1548 if (buffer_space() <= (kGap + space_needed)) { |
| 1505 GrowBuffer(space_needed); | 1549 GrowBuffer(space_needed); |
| 1506 } | 1550 } |
| 1507 } | 1551 } |
| 1508 | 1552 |
| 1509 | 1553 |
| 1510 bool Operand::must_output_reloc_info(const Assembler* assembler) const { | 1554 bool Operand::must_output_reloc_info(const Assembler* assembler) const { |
| 1511 if (rmode_ == RelocInfo::EXTERNAL_REFERENCE) { | 1555 if (rmode_ == RelocInfo::EXTERNAL_REFERENCE) { |
| 1512 if (assembler != NULL && assembler->predictable_code_size()) return true; | 1556 if (assembler != NULL && assembler->predictable_code_size()) return true; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1525 // Todo - break this dependency so we can optimize mov() in general | 1569 // Todo - break this dependency so we can optimize mov() in general |
| 1526 // and only use the generic version when we require a fixed sequence | 1570 // and only use the generic version when we require a fixed sequence |
| 1527 void Assembler::mov(Register dst, const Operand& src) { | 1571 void Assembler::mov(Register dst, const Operand& src) { |
| 1528 intptr_t value = src.immediate(); | 1572 intptr_t value = src.immediate(); |
| 1529 bool relocatable = src.must_output_reloc_info(this); | 1573 bool relocatable = src.must_output_reloc_info(this); |
| 1530 bool canOptimize; | 1574 bool canOptimize; |
| 1531 | 1575 |
| 1532 canOptimize = | 1576 canOptimize = |
| 1533 !(relocatable || (is_trampoline_pool_blocked() && !is_int16(value))); | 1577 !(relocatable || (is_trampoline_pool_blocked() && !is_int16(value))); |
| 1534 | 1578 |
| 1579 if (use_constant_pool_for_mov(src, canOptimize)) { |
| 1580 DCHECK(is_constant_pool_available()); |
| 1581 if (relocatable) { |
| 1582 RecordRelocInfo(src.rmode_); |
| 1583 } |
| 1584 ConstantPoolAddEntry(src.rmode_, value); |
| 1585 #if V8_TARGET_ARCH_PPC64 |
| 1586 ld(dst, MemOperand(kConstantPoolRegister, 0)); |
| 1587 #else |
| 1588 lwz(dst, MemOperand(kConstantPoolRegister, 0)); |
| 1589 #endif |
| 1590 return; |
| 1591 } |
| 1592 |
| 1535 if (canOptimize) { | 1593 if (canOptimize) { |
| 1536 if (is_int16(value)) { | 1594 if (is_int16(value)) { |
| 1537 li(dst, Operand(value)); | 1595 li(dst, Operand(value)); |
| 1538 } else { | 1596 } else { |
| 1539 uint16_t u16; | 1597 uint16_t u16; |
| 1540 #if V8_TARGET_ARCH_PPC64 | 1598 #if V8_TARGET_ARCH_PPC64 |
| 1541 if (is_int32(value)) { | 1599 if (is_int32(value)) { |
| 1542 #endif | 1600 #endif |
| 1543 lis(dst, Operand(value >> 16)); | 1601 lis(dst, Operand(value >> 16)); |
| 1544 #if V8_TARGET_ARCH_PPC64 | 1602 #if V8_TARGET_ARCH_PPC64 |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1666 DCHECK(is_int26(link)); | 1724 DCHECK(is_int26(link)); |
| 1667 DCHECK(is_int16(delta)); | 1725 DCHECK(is_int16(delta)); |
| 1668 | 1726 |
| 1669 BlockTrampolinePoolScope block_trampoline_pool(this); | 1727 BlockTrampolinePoolScope block_trampoline_pool(this); |
| 1670 emit(kUnboundAddLabelOffsetOpcode | (link & kImm26Mask)); | 1728 emit(kUnboundAddLabelOffsetOpcode | (link & kImm26Mask)); |
| 1671 emit(dst.code() * B21 | base.code() * B16 | (delta & kImm16Mask)); | 1729 emit(dst.code() * B21 | base.code() * B16 | (delta & kImm16Mask)); |
| 1672 } | 1730 } |
| 1673 } | 1731 } |
| 1674 | 1732 |
| 1675 | 1733 |
| 1734 // TODO(mbrandy): allow loading internal reference from constant pool |
| 1676 void Assembler::mov_label_addr(Register dst, Label* label) { | 1735 void Assembler::mov_label_addr(Register dst, Label* label) { |
| 1677 CheckBuffer(); | 1736 CheckBuffer(); |
| 1678 RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE_ENCODED); | 1737 RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE_ENCODED); |
| 1679 int position = link(label); | 1738 int position = link(label); |
| 1680 if (label->is_bound()) { | 1739 if (label->is_bound()) { |
| 1681 // Keep internal references relative until EmitRelocations. | 1740 // Keep internal references relative until EmitRelocations. |
| 1682 bitwise_mov(dst, position); | 1741 bitwise_mov(dst, position); |
| 1683 } else { | 1742 } else { |
| 1684 // Encode internal reference to unbound label. We use a dummy opcode | 1743 // Encode internal reference to unbound label. We use a dummy opcode |
| 1685 // such that it won't collide with any opcode that might appear in the | 1744 // such that it won't collide with any opcode that might appear in the |
| 1686 // label's chain. Encode the destination register in the 2nd instruction. | 1745 // label's chain. Encode the destination register in the 2nd instruction. |
| 1687 int link = position - pc_offset(); | 1746 int link = position - pc_offset(); |
| 1688 DCHECK_EQ(0, link & 3); | 1747 DCHECK_EQ(0, link & 3); |
| 1689 link >>= 2; | 1748 link >>= 2; |
| 1690 DCHECK(is_int26(link)); | 1749 DCHECK(is_int26(link)); |
| 1691 | 1750 |
| 1692 // When the label is bound, these instructions will be patched | 1751 // When the label is bound, these instructions will be patched |
| 1693 // with a multi-instruction mov sequence that will load the | 1752 // with a multi-instruction mov sequence that will load the |
| 1694 // destination register with the address of the label. | 1753 // destination register with the address of the label. |
| 1695 // | 1754 // |
| 1696 // target_at extracts the link and target_at_put patches the instructions. | 1755 // target_at extracts the link and target_at_put patches the instructions. |
| 1697 BlockTrampolinePoolScope block_trampoline_pool(this); | 1756 BlockTrampolinePoolScope block_trampoline_pool(this); |
| 1698 emit(kUnboundMovLabelAddrOpcode | (link & kImm26Mask)); | 1757 emit(kUnboundMovLabelAddrOpcode | (link & kImm26Mask)); |
| 1699 emit(dst.code()); | 1758 emit(dst.code()); |
| 1700 DCHECK(kMovInstructions >= 2); | 1759 DCHECK(kMovInstructionsNoConstantPool >= 2); |
| 1701 for (int i = 0; i < kMovInstructions - 2; i++) nop(); | 1760 for (int i = 0; i < kMovInstructionsNoConstantPool - 2; i++) nop(); |
| 1702 } | 1761 } |
| 1703 } | 1762 } |
| 1704 | 1763 |
| 1705 | 1764 |
| 1706 void Assembler::emit_label_addr(Label* label) { | 1765 void Assembler::emit_label_addr(Label* label) { |
| 1707 CheckBuffer(); | 1766 CheckBuffer(); |
| 1708 RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE); | 1767 RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE); |
| 1709 int position = link(label); | 1768 int position = link(label); |
| 1710 if (label->is_bound()) { | 1769 if (label->is_bound()) { |
| 1711 // Keep internal references relative until EmitRelocations. | 1770 // Keep internal references relative until EmitRelocations. |
| (...skipping 661 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2373 // Number of branches to unbound label at this point is zero, so we can | 2432 // Number of branches to unbound label at this point is zero, so we can |
| 2374 // move next buffer check to maximum. | 2433 // move next buffer check to maximum. |
| 2375 next_buffer_check_ = | 2434 next_buffer_check_ = |
| 2376 pc_offset() + kMaxCondBranchReach - kMaxBlockTrampolineSectionSize; | 2435 pc_offset() + kMaxCondBranchReach - kMaxBlockTrampolineSectionSize; |
| 2377 } | 2436 } |
| 2378 return; | 2437 return; |
| 2379 } | 2438 } |
| 2380 | 2439 |
| 2381 | 2440 |
| 2382 Handle<ConstantPoolArray> Assembler::NewConstantPool(Isolate* isolate) { | 2441 Handle<ConstantPoolArray> Assembler::NewConstantPool(Isolate* isolate) { |
| 2383 DCHECK(!FLAG_enable_ool_constant_pool); | 2442 UNREACHABLE(); |
| 2384 return isolate->factory()->empty_constant_pool_array(); | 2443 return isolate->factory()->empty_constant_pool_array(); |
| 2385 } | 2444 } |
| 2386 | 2445 |
| 2387 | 2446 |
| 2388 void Assembler::PopulateConstantPool(ConstantPoolArray* constant_pool) { | 2447 void Assembler::PopulateConstantPool(ConstantPoolArray* constant_pool) { |
| 2389 DCHECK(!FLAG_enable_ool_constant_pool); | 2448 UNREACHABLE(); |
| 2449 } |
| 2450 |
| 2451 |
| 2452 ConstantPoolBuilder::ConstantPoolBuilder() : size_(0) { entries_.reserve(64); } |
| 2453 |
| 2454 |
| 2455 void ConstantPoolBuilder::AddEntry(ConstantPoolEntry& entry, bool sharing_ok) { |
| 2456 DCHECK(!IsEmitted()); |
| 2457 |
| 2458 if (sharing_ok) { |
| 2459 // Try to merge entries |
| 2460 size_t i; |
| 2461 std::vector<ConstantPoolEntry>::const_iterator it; |
| 2462 for (it = entries_.begin(), i = 0; it != entries_.end(); it++, i++) { |
| 2463 if (it->merged_index_ != -2 && entry.IsEqual(*it)) { |
| 2464 // Merge with found entry. |
| 2465 entry.merged_index_ = i; |
| 2466 break; |
| 2467 } |
| 2468 } |
| 2469 } else { |
| 2470 // Ensure this entry remains unique |
| 2471 entry.merged_index_ = -2; |
| 2472 } |
| 2473 |
| 2474 entries_.push_back(entry); |
| 2475 |
| 2476 if (entry.merged_index_ < 0) { |
| 2477 // Not merged, so update the appropriate count and size. |
| 2478 number_of_entries_.increment(entry.type()); |
| 2479 size_ = number_of_entries_.size(); |
| 2480 } |
| 2481 } |
| 2482 |
| 2483 |
| 2484 void ConstantPoolBuilder::EmitGroup(Assembler* assm, int entrySize) { |
| 2485 int base = label_.pos(); |
| 2486 for (std::vector<ConstantPoolEntry>::iterator entry = entries_.begin(); |
| 2487 entry != entries_.end(); entry++) { |
| 2488 #if !V8_TARGET_ARCH_PPC64 |
| 2489 // Skip entries not in the requested group based on size. |
| 2490 if (entry->size() != entrySize) continue; |
| 2491 #endif |
| 2492 |
| 2493 // Update constant pool if necessary and get the entry's offset. |
| 2494 int offset; |
| 2495 if (entry->merged_index_ < 0) { |
| 2496 offset = assm->pc_offset() - base; |
| 2497 entry->merged_index_ = offset; // Stash offset for merged entries. |
| 2498 #if V8_TARGET_ARCH_PPC64 |
| 2499 assm->emit_ptr(entry->value_); |
| 2500 #else |
| 2501 if (entrySize == kDoubleSize) { |
| 2502 assm->emit_double(entry->value64_); |
| 2503 } else { |
| 2504 assm->emit_ptr(entry->value_); |
| 2505 } |
| 2506 #endif |
| 2507 } else { |
| 2508 DCHECK(entry->merged_index_ < (entry - entries_.begin())); |
| 2509 offset = entries_[entry->merged_index_].merged_index_; |
| 2510 } |
| 2511 |
| 2512 // Patch load instruction with correct offset. |
| 2513 assm->SetConstantPoolOffset(entry->position_, offset); |
| 2514 } |
| 2515 } |
| 2516 |
| 2517 |
| 2518 // Emit and return position of pool. Zero implies no constant pool. |
| 2519 int ConstantPoolBuilder::Emit(Assembler* assm) { |
| 2520 bool empty = IsEmpty(); |
| 2521 bool emitted = IsEmitted(); |
| 2522 |
| 2523 if (!emitted) { |
| 2524 // Mark start of constant pool. Align if necessary. |
| 2525 if (!empty) assm->CodeTargetAlign(); |
| 2526 assm->bind(&label_); |
| 2527 } |
| 2528 |
| 2529 int position = empty ? 0 : label_.pos(); |
| 2530 |
| 2531 if (!(emitted || empty)) { |
| 2532 // Emit in groups based on size. We don't support 32-bit |
| 2533 // constants in 64-bit mode so the only non-pointer-sized entries |
| 2534 // are doubles in 32-bit mode. |
| 2535 #if !V8_TARGET_ARCH_PPC64 |
| 2536 // Emit any doubles first for alignment purposes. |
| 2537 if (number_of_entries_.count_of(INT64)) { |
| 2538 EmitGroup(assm, kDoubleSize); |
| 2539 } |
| 2540 #endif |
| 2541 EmitGroup(assm, kPointerSize); |
| 2542 DCHECK(position > 0); |
| 2543 DCHECK(assm->pc_offset() - position == size_); |
| 2544 } |
| 2545 |
| 2546 return position; |
| 2390 } | 2547 } |
| 2391 } | 2548 } |
| 2392 } // namespace v8::internal | 2549 } // namespace v8::internal |
| 2393 | 2550 |
| 2394 #endif // V8_TARGET_ARCH_PPC | 2551 #endif // V8_TARGET_ARCH_PPC |
| OLD | NEW |