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..f7453d1682e97e7fa7b28ed65d70d3f6f06c1195 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_); |
+ // TODO(mips): Commenting out, to simplify arch-independent changes. |
+ // 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,55 @@ void RelocInfo::set_target_object(Object* target) { |
Address* RelocInfo::target_reference_address() { |
ASSERT(rmode_ == EXTERNAL_REFERENCE); |
- return reinterpret_cast<Address*>(pc_); |
+ // TODO(mips): Commenting out, to simplify arch-independent changes. |
+ // 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 |
+ // debug-mips.cc BreakLocationIterator::SetDebugBreakAtReturn(), or |
+ // debug break slot per BreakLocationIterator::SetDebugBreakAtSlot(). |
+ 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 |
+ // debug-mips.cc BreakLocationIterator::SetDebugBreakAtReturn(), or |
+ // debug break slot per BreakLocationIterator::SetDebugBreakAtSlot(). |
+ Assembler::set_target_address_at(pc_, target); |
} |
@@ -169,9 +219,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 +231,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 +315,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(); |
} |