diff options
Diffstat (limited to 'deps/v8/src/mips/assembler-mips-inl.h')
-rw-r--r-- | deps/v8/src/mips/assembler-mips-inl.h | 183 |
1 files changed, 143 insertions, 40 deletions
diff --git a/deps/v8/src/mips/assembler-mips-inl.h b/deps/v8/src/mips/assembler-mips-inl.h index 2e634617c2..b5ffe7391b 100644 --- a/deps/v8/src/mips/assembler-mips-inl.h +++ b/deps/v8/src/mips/assembler-mips-inl.h @@ -30,7 +30,7 @@ // The original source code covered by the above license above has been // modified significantly by Google Inc. -// Copyright 2010 the V8 project authors. All rights reserved. +// Copyright 2011 the V8 project authors. All rights reserved. #ifndef V8_MIPS_ASSEMBLER_MIPS_INL_H_ @@ -38,22 +38,14 @@ #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 and MemOperand. Operand::Operand(int32_t immediate, RelocInfo::Mode rmode) { rm_ = no_reg; @@ -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(); } @@ -90,11 +80,15 @@ bool Operand::is_reg() const { // ----------------------------------------------------------------------------- -// RelocInfo +// RelocInfo. void RelocInfo::apply(intptr_t delta) { - // On MIPS we do not use pc relative addressing, so we don't need to patch the - // code here. + if (IsInternalReference(rmode_)) { + // Absolute code pointer inside code object moves with the code object. + byte* p = reinterpret_cast<byte*>(pc_); + int count = Assembler::RelocateInternalReference(p, delta); + CPU::FlushICache(p, count * sizeof(uint32_t)); + } } @@ -110,6 +104,11 @@ Address RelocInfo::target_address_address() { } +int RelocInfo::target_address_size() { + return Assembler::kExternalTargetSize; +} + + void RelocInfo::set_target_address(Address target) { ASSERT(IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY); Assembler::set_target_address_at(pc_, target); @@ -130,8 +129,12 @@ 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_); + reconstructed_obj_ptr_ = + reinterpret_cast<Object*>(Assembler::target_address_at(pc_)); + return &reconstructed_obj_ptr_; } @@ -143,23 +146,52 @@ void RelocInfo::set_target_object(Object* target) { Address* RelocInfo::target_reference_address() { ASSERT(rmode_ == EXTERNAL_REFERENCE); - return reinterpret_cast<Address*>(pc_); + reconstructed_adr_ptr_ = Assembler::target_address_at(pc_); + return &reconstructed_adr_ptr_; +} + + +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 +201,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,18 +213,80 @@ 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) { + Object** p = target_object_address(); + Object* orig = *p; + visitor->VisitPointer(p); + if (*p != orig) { + set_target_object(*p); + } + } else if (RelocInfo::IsCodeTarget(mode)) { + visitor->VisitCodeTarget(this); + } else if (mode == RelocInfo::GLOBAL_PROPERTY_CELL) { + visitor->VisitGlobalPropertyCell(this); + } else if (mode == RelocInfo::EXTERNAL_REFERENCE) { + visitor->VisitExternalReference(target_reference_address()); +#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(heap, this); + } else if (mode == RelocInfo::GLOBAL_PROPERTY_CELL) { + StaticVisitor::VisitGlobalPropertyCell(heap, 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(heap, this); +#endif + } else if (mode == RelocInfo::RUNTIME_ENTRY) { + StaticVisitor::VisitRuntimeEntry(this); + } } // ----------------------------------------------------------------------------- -// Assembler +// Assembler. void Assembler::CheckBuffer() { @@ -203,10 +296,20 @@ void Assembler::CheckBuffer() { } +void Assembler::CheckTrampolinePoolQuick() { + if (pc_offset() >= next_buffer_check_) { + CheckTrampolinePool(); + } +} + + void Assembler::emit(Instr x) { - CheckBuffer(); + if (!is_buffer_growth_blocked()) { + CheckBuffer(); + } *reinterpret_cast<Instr*>(pc_) = x; pc_ += kInstrSize; + CheckTrampolinePoolQuick(); } |