From e66f276e464f2e75c01ffc20014647ac38d0cab5 Mon Sep 17 00:00:00 2001 From: "erik.corry@gmail.com" Date: Wed, 26 May 2010 08:34:07 +0000 Subject: [PATCH] The way reloc entries are visited by the ObjectVisitor is architecture dependent, so we push it down to the architecture dependent files. Currently all architectures visit in almost the same way, but this is about to change on ARM with movw/movt. Review URL: http://codereview.chromium.org/2218002 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4721 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/arm/assembler-arm-inl.h | 26 ++++++++++++++++++++++++++ src/assembler.h | 21 +++++++++++++++++++-- src/ia32/assembler-ia32-inl.h | 26 ++++++++++++++++++++++++++ src/objects.cc | 17 +---------------- src/serialize.cc | 4 ++-- src/x64/assembler-x64-inl.h | 31 +++++++++++++++++++++++++++++++ 6 files changed, 105 insertions(+), 20 deletions(-) diff --git a/src/arm/assembler-arm-inl.h b/src/arm/assembler-arm-inl.h index a5c5bd1..e292cef 100644 --- a/src/arm/assembler-arm-inl.h +++ b/src/arm/assembler-arm-inl.h @@ -39,6 +39,7 @@ #include "arm/assembler-arm.h" #include "cpu.h" +#include "debug.h" namespace v8 { @@ -73,6 +74,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); @@ -162,6 +168,26 @@ bool RelocInfo::IsPatchedReturnSequence() { } +void RelocInfo::Visit(ObjectVisitor* visitor) { + RelocInfo::Mode mode = rmode(); + if (mode == RelocInfo::EMBEDDED_OBJECT) { + visitor->VisitPointer(target_object_address()); + } else if (RelocInfo::IsCodeTarget(mode)) { + visitor->VisitCodeTarget(this); + } else if (mode == RelocInfo::EXTERNAL_REFERENCE) { + visitor->VisitExternalReference(target_reference_address()); +#ifdef ENABLE_DEBUGGER_SUPPORT + } else if (Debug::has_break_points() && + RelocInfo::IsJSReturn(mode) && + IsPatchedReturnSequence()) { + visitor->VisitDebugTarget(this); +#endif + } else if (mode == RelocInfo::RUNTIME_ENTRY) { + visitor->VisitRuntimeEntry(this); + } +} + + Operand::Operand(int32_t immediate, RelocInfo::Mode rmode) { rm_ = no_reg; imm32_ = immediate; diff --git a/src/assembler.h b/src/assembler.h index f2a6c8b..74613b3 100644 --- a/src/assembler.h +++ b/src/assembler.h @@ -38,6 +38,7 @@ #include "runtime.h" #include "top.h" #include "token.h" +#include "objects.h" namespace v8 { namespace internal { @@ -199,9 +200,23 @@ class RelocInfo BASE_EMBEDDED { INLINE(Object** target_object_address()); INLINE(void set_target_object(Object* target)); - // Read the address of the word containing the target_address. Can only - // be called if IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY. + // Read the address of the word containing the target_address in an + // instruction stream. What this means exactly is architecture-independent. + // 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. Architecture-independent code shouldn't + // dereference the pointer it gets back from this. INLINE(Address target_address_address()); + // This indicates how much space a target takes up when deserializing a code + // stream. For most architectures this is just the size of a pointer. For + // an instruction like movw/movt 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 forwards in memory after a target is resolved + // and written. In this case the target_address_address function above + // 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. + INLINE(int target_address_size()); // Read/modify the reference in the instruction this relocation // applies to; can only be called if rmode_ is external_reference @@ -216,6 +231,8 @@ class RelocInfo BASE_EMBEDDED { INLINE(Object** call_object_address()); INLINE(void set_call_object(Object* target)); + inline void Visit(ObjectVisitor* v); + // Patch the code with some other code. void PatchCode(byte* instructions, int instruction_count); diff --git a/src/ia32/assembler-ia32-inl.h b/src/ia32/assembler-ia32-inl.h index 1d88220..9c96e19 100644 --- a/src/ia32/assembler-ia32-inl.h +++ b/src/ia32/assembler-ia32-inl.h @@ -38,6 +38,7 @@ #define V8_IA32_ASSEMBLER_IA32_INL_H_ #include "cpu.h" +#include "debug.h" namespace v8 { namespace internal { @@ -77,6 +78,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); @@ -148,6 +154,26 @@ bool RelocInfo::IsPatchedReturnSequence() { } +void RelocInfo::Visit(ObjectVisitor* visitor) { + RelocInfo::Mode mode = rmode(); + if (mode == RelocInfo::EMBEDDED_OBJECT) { + visitor->VisitPointer(target_object_address()); + } else if (RelocInfo::IsCodeTarget(mode)) { + visitor->VisitCodeTarget(this); + } else if (mode == RelocInfo::EXTERNAL_REFERENCE) { + visitor->VisitExternalReference(target_reference_address()); +#ifdef ENABLE_DEBUGGER_SUPPORT + } else if (Debug::has_break_points() && + RelocInfo::IsJSReturn(mode) && + IsPatchedReturnSequence()) { + visitor->VisitDebugTarget(this); +#endif + } else if (mode == RelocInfo::RUNTIME_ENTRY) { + visitor->VisitRuntimeEntry(this); + } +} + + Immediate::Immediate(int x) { x_ = x; rmode_ = RelocInfo::NONE; diff --git a/src/objects.cc b/src/objects.cc index 71b2f36..e5e1a4e 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -5271,22 +5271,7 @@ void Code::CodeIterateBody(ObjectVisitor* v) { RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY); for (RelocIterator it(this, mode_mask); !it.done(); it.next()) { - RelocInfo::Mode rmode = it.rinfo()->rmode(); - if (rmode == RelocInfo::EMBEDDED_OBJECT) { - v->VisitPointer(it.rinfo()->target_object_address()); - } else if (RelocInfo::IsCodeTarget(rmode)) { - v->VisitCodeTarget(it.rinfo()); - } else if (rmode == RelocInfo::EXTERNAL_REFERENCE) { - v->VisitExternalReference(it.rinfo()->target_reference_address()); -#ifdef ENABLE_DEBUGGER_SUPPORT - } else if (Debug::has_break_points() && - RelocInfo::IsJSReturn(rmode) && - it.rinfo()->IsPatchedReturnSequence()) { - v->VisitDebugTarget(it.rinfo()); -#endif - } else if (rmode == RelocInfo::RUNTIME_ENTRY) { - v->VisitRuntimeEntry(it.rinfo()); - } + it.rinfo()->Visit(v); } ScopeInfo<>::IterateScopeInfo(this, v); diff --git a/src/serialize.cc b/src/serialize.cc index a3a2ba9..06c6df7 100644 --- a/src/serialize.cc +++ b/src/serialize.cc @@ -1299,7 +1299,7 @@ void Serializer::ObjectSerializer::VisitRuntimeEntry(RelocInfo* rinfo) { } sink_->Put(kExternalReference + representation, "ExternalReference"); sink_->PutInt(encoding, "reference id"); - bytes_processed_so_far_ += Assembler::kExternalTargetSize; + bytes_processed_so_far_ += rinfo->target_address_size(); } @@ -1309,7 +1309,7 @@ void Serializer::ObjectSerializer::VisitCodeTarget(RelocInfo* rinfo) { OutputRawData(target_start); Code* target = Code::GetCodeFromTargetAddress(rinfo->target_address()); serializer_->SerializeObject(target, kFromCode, kFirstInstruction); - bytes_processed_so_far_ += Assembler::kCallTargetSize; + bytes_processed_so_far_ += rinfo->target_address_size(); } diff --git a/src/x64/assembler-x64-inl.h b/src/x64/assembler-x64-inl.h index be7cfe0..4c69510 100644 --- a/src/x64/assembler-x64-inl.h +++ b/src/x64/assembler-x64-inl.h @@ -29,6 +29,7 @@ #define V8_X64_ASSEMBLER_X64_INL_H_ #include "cpu.h" +#include "debug.h" #include "memory.h" namespace v8 { @@ -229,6 +230,15 @@ Address RelocInfo::target_address_address() { } +int RelocInfo::target_address_size() { + if (IsCodedSpecially()) { + return Assembler::kCallTargetSize; + } else { + return Assembler::kExternalTargetSize; + } +} + + void RelocInfo::set_target_address(Address target) { ASSERT(IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY); if (IsCodeTarget(rmode_)) { @@ -320,6 +330,27 @@ Object** RelocInfo::call_object_address() { pc_ + Assembler::kPatchReturnSequenceAddressOffset); } + +void RelocInfo::Visit(ObjectVisitor* visitor) { + RelocInfo::Mode mode = rmode(); + if (mode == RelocInfo::EMBEDDED_OBJECT) { + visitor->VisitPointer(target_object_address()); + } else if (RelocInfo::IsCodeTarget(mode)) { + visitor->VisitCodeTarget(this); + } else if (mode == RelocInfo::EXTERNAL_REFERENCE) { + visitor->VisitExternalReference(target_reference_address()); +#ifdef ENABLE_DEBUGGER_SUPPORT + } else if (Debug::has_break_points() && + RelocInfo::IsJSReturn(mode) && + IsPatchedReturnSequence()) { + visitor->VisitDebugTarget(this); +#endif + } else if (mode == RelocInfo::RUNTIME_ENTRY) { + visitor->VisitRuntimeEntry(this); + } +} + + // ----------------------------------------------------------------------------- // Implementation of Operand -- 2.7.4