Chromium Code Reviews| Index: src/mips/assembler-mips-inl.h |
| diff --git a/src/mips/assembler-mips-inl.h b/src/mips/assembler-mips-inl.h |
| index 2e634617c2a413bb2ba52f7783dcd82b12086501..0292ebd856a851e0257f22d16533180767301b39 100644 |
| --- a/src/mips/assembler-mips-inl.h |
| +++ b/src/mips/assembler-mips-inl.h |
| @@ -38,21 +38,13 @@ |
| #include "mips/assembler-mips.h" |
| #include "cpu.h" |
| +#include "debug.h" |
| namespace v8 { |
| namespace internal { |
| // ----------------------------------------------------------------------------- |
| -// Condition |
| - |
| -Condition NegateCondition(Condition cc) { |
| - ASSERT(cc != cc_always); |
| - return static_cast<Condition>(cc ^ 1); |
| -} |
| - |
| - |
| -// ----------------------------------------------------------------------------- |
| // Operand and MemOperand |
| Operand::Operand(int32_t immediate, RelocInfo::Mode rmode) { |
| @@ -61,17 +53,13 @@ Operand::Operand(int32_t immediate, RelocInfo::Mode rmode) { |
| rmode_ = rmode; |
| } |
| + |
| Operand::Operand(const ExternalReference& f) { |
| rm_ = no_reg; |
| imm32_ = reinterpret_cast<int32_t>(f.address()); |
| rmode_ = RelocInfo::EXTERNAL_REFERENCE; |
| } |
| -Operand::Operand(const char* s) { |
| - rm_ = no_reg; |
| - imm32_ = reinterpret_cast<int32_t>(s); |
| - rmode_ = RelocInfo::EMBEDDED_STRING; |
| -} |
| Operand::Operand(Smi* value) { |
| rm_ = no_reg; |
| @@ -79,10 +67,12 @@ Operand::Operand(Smi* value) { |
| rmode_ = RelocInfo::NONE; |
| } |
| + |
| Operand::Operand(Register rm) { |
| rm_ = rm; |
| } |
| + |
| bool Operand::is_reg() const { |
| return rm_.is_valid(); |
| } |
| @@ -105,8 +95,29 @@ Address RelocInfo::target_address() { |
| Address RelocInfo::target_address_address() { |
| - ASSERT(IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY); |
| - return reinterpret_cast<Address>(pc_); |
| + ASSERT(IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY |
| + || rmode_ == EMBEDDED_OBJECT |
| + || rmode_ == EXTERNAL_REFERENCE); |
| + // Read the address of the word containing the target_address in an |
| + // instruction stream. |
| + // The only architecture-independent user of this function is the serializer. |
| + // The serializer uses it to find out how many raw bytes of instruction to |
| + // output before the next target. |
| + // For an instructions like LUI/ORI where the target bits are mixed into the |
| + // instruction bits, the size of the target will be zero, indicating that the |
| + // serializer should not step forward in memory after a target is resolved |
| + // and written. In this case the target_address_address function should |
| + // return the end of the instructions to be patched, allowing the |
| + // deserializer to deserialize the instructions as raw bytes and put them in |
| + // place, ready to be patched with the target. In our case, that is the |
| + // address of the instruction that follows LUI/ORI instruction pair. |
| + return reinterpret_cast<Address>( |
| + pc_ + Assembler::kInstructionsFor32BitConstant * Assembler::kInstrSize); |
| +} |
| + |
| + |
| +int RelocInfo::target_address_size() { |
| + return Assembler::kExternalTargetSize; |
| } |
| @@ -130,8 +141,15 @@ Handle<Object> RelocInfo::target_object_handle(Assembler *origin) { |
| Object** RelocInfo::target_object_address() { |
| + // Provide a "natural pointer" to the embedded object, |
| + // which can be de-referenced during heap iteration. |
| ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); |
| - return reinterpret_cast<Object**>(pc_); |
| + // Commenting out, to simplify arch-independednt changes. |
|
Søren Thygesen Gjesse
2011/03/23 23:38:42
I suggest adding a TODO(mips) to the beginning of
Paul Lind
2011/03/26 18:39:17
Done.
|
| + // GC won't work like this, but this commit is for asm/disasm/sim. |
| + // reconstructed_obj_ptr_ = |
| + // reinterpret_cast<Object*>(Assembler::target_address_at(pc_)); |
| + // return &reconstructed_obj_ptr_; |
| + return NULL; |
| } |
| @@ -143,23 +161,53 @@ void RelocInfo::set_target_object(Object* target) { |
| Address* RelocInfo::target_reference_address() { |
| ASSERT(rmode_ == EXTERNAL_REFERENCE); |
| - return reinterpret_cast<Address*>(pc_); |
| + // Commenting out, to simplify arch-independednt changes. |
|
Søren Thygesen Gjesse
2011/03/23 23:38:42
Ditto.
Paul Lind
2011/03/26 18:39:17
Done.
|
| + // GC won't work like this, but this commit is for asm/disasm/sim. |
| + // reconstructed_adr_ptr_ = Assembler::target_address_at(pc_); |
| + // return &reconstructed_adr_ptr_; |
| + return NULL; |
| +} |
| + |
| + |
| +Handle<JSGlobalPropertyCell> RelocInfo::target_cell_handle() { |
| + ASSERT(rmode_ == RelocInfo::GLOBAL_PROPERTY_CELL); |
| + Address address = Memory::Address_at(pc_); |
| + return Handle<JSGlobalPropertyCell>( |
| + reinterpret_cast<JSGlobalPropertyCell**>(address)); |
| +} |
| + |
| + |
| +JSGlobalPropertyCell* RelocInfo::target_cell() { |
| + ASSERT(rmode_ == RelocInfo::GLOBAL_PROPERTY_CELL); |
| + Address address = Memory::Address_at(pc_); |
| + Object* object = HeapObject::FromAddress( |
| + address - JSGlobalPropertyCell::kValueOffset); |
| + return reinterpret_cast<JSGlobalPropertyCell*>(object); |
| +} |
| + |
| + |
| +void RelocInfo::set_target_cell(JSGlobalPropertyCell* cell) { |
| + ASSERT(rmode_ == RelocInfo::GLOBAL_PROPERTY_CELL); |
| + Address address = cell->address() + JSGlobalPropertyCell::kValueOffset; |
| + Memory::Address_at(pc_) = address; |
| } |
| Address RelocInfo::call_address() { |
| - ASSERT(IsPatchedReturnSequence()); |
| - // The 2 instructions offset assumes patched return sequence. |
| - ASSERT(IsJSReturn(rmode())); |
| - return Memory::Address_at(pc_ + 2 * Assembler::kInstrSize); |
| + ASSERT((IsJSReturn(rmode()) && IsPatchedReturnSequence()) || |
| + (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence())); |
| + // The pc_ offset of 0 assumes mips patched return sequence per |
|
Søren Thygesen Gjesse
2011/03/23 23:38:42
patched return sequence -> patched return sequence
Paul Lind
2011/03/26 18:39:17
Done.
|
| + // debug-mips.cc BreakLocationIterator::SetDebugBreakAtReturn(). |
| + return Assembler::target_address_at(pc_); |
| } |
| void RelocInfo::set_call_address(Address target) { |
| - ASSERT(IsPatchedReturnSequence()); |
| - // The 2 instructions offset assumes patched return sequence. |
| - ASSERT(IsJSReturn(rmode())); |
| - Memory::Address_at(pc_ + 2 * Assembler::kInstrSize) = target; |
| + ASSERT((IsJSReturn(rmode()) && IsPatchedReturnSequence()) || |
| + (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence())); |
| + // The pc_ offset of 0 assumes mips patched return sequence per |
|
Søren Thygesen Gjesse
2011/03/23 23:38:42
Ditto.
Paul Lind
2011/03/26 18:39:17
Done.
|
| + // debug-mips.cc BreakLocationIterator::SetDebugBreakAtReturn(). |
| + Assembler::set_target_address_at(pc_, target); |
| } |
| @@ -169,9 +217,8 @@ Object* RelocInfo::call_object() { |
| Object** RelocInfo::call_object_address() { |
| - ASSERT(IsPatchedReturnSequence()); |
| - // The 2 instructions offset assumes patched return sequence. |
| - ASSERT(IsJSReturn(rmode())); |
| + ASSERT((IsJSReturn(rmode()) && IsPatchedReturnSequence()) || |
| + (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence())); |
| return reinterpret_cast<Object**>(pc_ + 2 * Assembler::kInstrSize); |
| } |
| @@ -182,13 +229,76 @@ void RelocInfo::set_call_object(Object* target) { |
| bool RelocInfo::IsPatchedReturnSequence() { |
| -#ifdef DEBUG |
| - PrintF("%s - %d - %s : Checking for jal(r)", |
| - __FILE__, __LINE__, __func__); |
| + Instr instr0 = Assembler::instr_at(pc_); |
| + Instr instr1 = Assembler::instr_at(pc_ + 1 * Assembler::kInstrSize); |
| + Instr instr2 = Assembler::instr_at(pc_ + 2 * Assembler::kInstrSize); |
| + bool patched_return = ((instr0 & kOpcodeMask) == LUI && |
| + (instr1 & kOpcodeMask) == ORI && |
| + (instr2 & kOpcodeMask) == SPECIAL && |
| + (instr2 & kFunctionFieldMask) == JALR); |
| + return patched_return; |
| +} |
| + |
| + |
| +bool RelocInfo::IsPatchedDebugBreakSlotSequence() { |
| + Instr current_instr = Assembler::instr_at(pc_); |
| + return !Assembler::IsNop(current_instr, Assembler::DEBUG_BREAK_NOP); |
| +} |
| + |
| + |
| +void RelocInfo::Visit(ObjectVisitor* visitor) { |
| + RelocInfo::Mode mode = rmode(); |
| + if (mode == RelocInfo::EMBEDDED_OBJECT) { |
| + // RelocInfo is needed when pointer must be updated/serialized, such as |
| + // UpdatingVisitor in mark-compact.cc or Serializer in serialize.cc. |
| + // It is ignored by visitors that do not need it. |
| + // Commenting out, to simplify arch-independednt changes. |
| + // GC won't work like this, but this commit is for asm/disasm/sim. |
| + // visitor->VisitPointer(target_object_address(), this); |
| + } else if (RelocInfo::IsCodeTarget(mode)) { |
| + visitor->VisitCodeTarget(this); |
| + } else if (mode == RelocInfo::EXTERNAL_REFERENCE) { |
| + // RelocInfo is needed when external-references must be serialized by |
| + // Serializer Visitor in serialize.cc. It is ignored by visitors that |
| + // do not need it. |
| + // Commenting out, to simplify arch-independednt changes. |
| + // Serializer won't work like this, but this commit is for asm/disasm/sim. |
| + // visitor->VisitExternalReference(target_reference_address(), this); |
| +#ifdef ENABLE_DEBUGGER_SUPPORT |
| + // TODO(isolates): Get a cached isolate below. |
| + } else if (((RelocInfo::IsJSReturn(mode) && |
| + IsPatchedReturnSequence()) || |
| + (RelocInfo::IsDebugBreakSlot(mode) && |
| + IsPatchedDebugBreakSlotSequence())) && |
| + Isolate::Current()->debug()->has_break_points()) { |
| + visitor->VisitDebugTarget(this); |
| #endif |
| - return ((Assembler::instr_at(pc_) & kOpcodeMask) == SPECIAL) && |
| - (((Assembler::instr_at(pc_) & kFunctionFieldMask) == JAL) || |
| - ((Assembler::instr_at(pc_) & kFunctionFieldMask) == JALR)); |
| + } else if (mode == RelocInfo::RUNTIME_ENTRY) { |
| + visitor->VisitRuntimeEntry(this); |
| + } |
| +} |
| + |
| + |
| +template<typename StaticVisitor> |
| +void RelocInfo::Visit(Heap* heap) { |
| + RelocInfo::Mode mode = rmode(); |
| + if (mode == RelocInfo::EMBEDDED_OBJECT) { |
| + StaticVisitor::VisitPointer(heap, target_object_address()); |
| + } else if (RelocInfo::IsCodeTarget(mode)) { |
| + StaticVisitor::VisitCodeTarget(this); |
| + } else if (mode == RelocInfo::EXTERNAL_REFERENCE) { |
| + StaticVisitor::VisitExternalReference(target_reference_address()); |
| +#ifdef ENABLE_DEBUGGER_SUPPORT |
| + } else if (heap->isolate()->debug()->has_break_points() && |
| + ((RelocInfo::IsJSReturn(mode) && |
| + IsPatchedReturnSequence()) || |
| + (RelocInfo::IsDebugBreakSlot(mode) && |
| + IsPatchedDebugBreakSlotSequence()))) { |
| + StaticVisitor::VisitDebugTarget(this); |
| +#endif |
| + } else if (mode == RelocInfo::RUNTIME_ENTRY) { |
| + StaticVisitor::VisitRuntimeEntry(this); |
| + } |
| } |
| @@ -203,10 +313,18 @@ void Assembler::CheckBuffer() { |
| } |
| +void Assembler::CheckTrampolinePoolQuick() { |
| + if (pc_offset() >= next_buffer_check_) { |
| + CheckTrampolinePool(); |
| + } |
| +} |
| + |
| + |
| void Assembler::emit(Instr x) { |
| CheckBuffer(); |
| *reinterpret_cast<Instr*>(pc_) = x; |
| pc_ += kInstrSize; |
| + CheckTrampolinePoolQuick(); |
| } |