From e57d0296dae6d9b2c2d2170f8546bff553c3d869 Mon Sep 17 00:00:00 2001 From: "rmcilroy@chromium.org" Date: Wed, 12 Mar 2014 15:23:54 +0000 Subject: [PATCH] Reland "Pass a Code object to Assembler::(set_)target_address_at for use by ool constant pool." The ool constant pool will require a pointer to the code's constant pool when updating or reading target addresses using set_target_address_at() and target_address_at(). Original Review URL: https://codereview.chromium.org/183803022 R=ulan@chromium.org Review URL: https://codereview.chromium.org/195983002 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@19856 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/a64/assembler-a64-inl.h | 42 ++++++++++++----- src/a64/assembler-a64.h | 13 ++++-- src/a64/frames-a64.h | 2 + src/arm/assembler-arm-inl.h | 24 ++++++---- src/arm/assembler-arm.h | 24 ++++++++-- src/debug.cc | 8 ++-- src/disassembler.cc | 2 +- src/ia32/assembler-ia32-inl.h | 21 +++++---- src/ia32/assembler-ia32.h | 21 +++++++-- src/ia32/frames-ia32.h | 2 + src/ia32/full-codegen-ia32.cc | 9 ++-- src/ic-inl.h | 61 +++++++++++++++++++++--- src/ic.cc | 106 +++++++++++++++++++++++++++++------------- src/ic.h | 61 ++++++++++++++++++------ src/objects-visiting-inl.h | 3 +- src/objects.cc | 3 +- src/serialize.cc | 1 + src/x64/assembler-x64-inl.h | 17 ++++--- src/x64/assembler-x64.h | 21 +++++++-- src/x64/frames-x64.h | 2 + src/x64/full-codegen-x64.cc | 10 ++-- 21 files changed, 335 insertions(+), 118 deletions(-) diff --git a/src/a64/assembler-a64-inl.h b/src/a64/assembler-a64-inl.h index 987cc80..2a930b2 100644 --- a/src/a64/assembler-a64-inl.h +++ b/src/a64/assembler-a64-inl.h @@ -44,7 +44,7 @@ void RelocInfo::apply(intptr_t delta) { void RelocInfo::set_target_address(Address target, WriteBarrierMode mode) { ASSERT(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)); - Assembler::set_target_address_at(pc_, target); + Assembler::set_target_address_at(pc_, host_, target); if (mode == UPDATE_WRITE_BARRIER && host() != NULL && IsCodeTarget(rmode_)) { Object* target_code = Code::GetCodeFromTargetAddress(target); host()->GetHeap()->incremental_marking()->RecordWriteIntoCode( @@ -558,11 +558,18 @@ Address Assembler::target_pointer_address_at(Address pc) { // Read/Modify the code target address in the branch/call instruction at pc. -Address Assembler::target_address_at(Address pc) { +Address Assembler::target_address_at(Address pc, + ConstantPoolArray* constant_pool) { return Memory::Address_at(target_pointer_address_at(pc)); } +Address Assembler::target_address_at(Address pc, Code* code) { + ConstantPoolArray* constant_pool = code ? code->constant_pool() : NULL; + return target_address_at(pc, constant_pool); +} + + Address Assembler::target_address_from_return_address(Address pc) { // Returns the address of the call target from the return address that will // be returned to after a call. @@ -616,12 +623,14 @@ Address Assembler::return_address_from_call_start(Address pc) { void Assembler::deserialization_set_special_target_at( - Address constant_pool_entry, Address target) { + Address constant_pool_entry, Code* code, Address target) { Memory::Address_at(constant_pool_entry) = target; } -void Assembler::set_target_address_at(Address pc, Address target) { +void Assembler::set_target_address_at(Address pc, + ConstantPoolArray* constant_pool, + Address target) { Memory::Address_at(target_pointer_address_at(pc)) = target; // Intuitively, we would think it is necessary to always flush the // instruction cache after patching a target address in the code as follows: @@ -634,6 +643,14 @@ void Assembler::set_target_address_at(Address pc, Address target) { } +void Assembler::set_target_address_at(Address pc, + Code* code, + Address target) { + ConstantPoolArray* constant_pool = code ? code->constant_pool() : NULL; + set_target_address_at(pc, constant_pool, target); +} + + int RelocInfo::target_address_size() { return kPointerSize; } @@ -641,7 +658,7 @@ int RelocInfo::target_address_size() { Address RelocInfo::target_address() { ASSERT(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)); - return Assembler::target_address_at(pc_); + return Assembler::target_address_at(pc_, host_); } @@ -661,21 +678,22 @@ Address RelocInfo::constant_pool_entry_address() { Object* RelocInfo::target_object() { ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); - return reinterpret_cast(Assembler::target_address_at(pc_)); + return reinterpret_cast(Assembler::target_address_at(pc_, host_)); } Handle RelocInfo::target_object_handle(Assembler* origin) { ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); return Handle(reinterpret_cast( - Assembler::target_address_at(pc_))); + Assembler::target_address_at(pc_, host_))); } void RelocInfo::set_target_object(Object* target, WriteBarrierMode mode) { ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); ASSERT(!target->IsConsString()); - Assembler::set_target_address_at(pc_, reinterpret_cast
(target)); + Assembler::set_target_address_at(pc_, host_, + reinterpret_cast
(target)); if (mode == UPDATE_WRITE_BARRIER && host() != NULL && target->IsHeapObject()) { @@ -687,7 +705,7 @@ void RelocInfo::set_target_object(Object* target, WriteBarrierMode mode) { Address RelocInfo::target_reference() { ASSERT(rmode_ == EXTERNAL_REFERENCE); - return Assembler::target_address_at(pc_); + return Assembler::target_address_at(pc_, host_); } @@ -756,14 +774,14 @@ Address RelocInfo::call_address() { (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence())); // For the above sequences the Relocinfo points to the load literal loading // the call address. - return Assembler::target_address_at(pc_); + return Assembler::target_address_at(pc_, host_); } void RelocInfo::set_call_address(Address target) { ASSERT((IsJSReturn(rmode()) && IsPatchedReturnSequence()) || (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence())); - Assembler::set_target_address_at(pc_, target); + Assembler::set_target_address_at(pc_, host_, target); if (host() != NULL) { Object* target_code = Code::GetCodeFromTargetAddress(target); host()->GetHeap()->incremental_marking()->RecordWriteIntoCode( @@ -777,7 +795,7 @@ void RelocInfo::WipeOut() { IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_) || IsExternalReference(rmode_)); - Assembler::set_target_address_at(pc_, NULL); + Assembler::set_target_address_at(pc_, host_, NULL); } diff --git a/src/a64/assembler-a64.h b/src/a64/assembler-a64.h index 1b02308..6713800 100644 --- a/src/a64/assembler-a64.h +++ b/src/a64/assembler-a64.h @@ -783,8 +783,15 @@ class Assembler : public AssemblerBase { inline static Address target_pointer_address_at(Address pc); // Read/Modify the code target address in the branch/call instruction at pc. - inline static Address target_address_at(Address pc); - inline static void set_target_address_at(Address pc, Address target); + inline static Address target_address_at(Address pc, + ConstantPoolArray* constant_pool); + inline static void set_target_address_at(Address pc, + ConstantPoolArray* constant_pool, + Address target); + static inline Address target_address_at(Address pc, Code* code); + static inline void set_target_address_at(Address pc, + Code* code, + Address target); // Return the code target address at a call site from the return address of // that call in the instruction stream. @@ -797,7 +804,7 @@ class Assembler : public AssemblerBase { // This sets the branch destination (which is in the constant pool on ARM). // This is for calls and branches within generated code. inline static void deserialization_set_special_target_at( - Address constant_pool_entry, Address target); + Address constant_pool_entry, Code* code, Address target); // All addresses in the constant pool are the same size as pointers. static const int kSpecialTargetSize = kPointerSize; diff --git a/src/a64/frames-a64.h b/src/a64/frames-a64.h index 5ef7681..d2bbda6 100644 --- a/src/a64/frames-a64.h +++ b/src/a64/frames-a64.h @@ -69,6 +69,8 @@ class ExitFrameConstants : public AllStatic { static const int kSPOffset = -1 * kPointerSize; static const int kCodeOffset = -2 * kPointerSize; static const int kLastExitFrameField = kCodeOffset; + + static const int kConstantPoolOffset = 0; // Not used }; diff --git a/src/arm/assembler-arm-inl.h b/src/arm/assembler-arm-inl.h index e388ed5..89c7a6d 100644 --- a/src/arm/assembler-arm-inl.h +++ b/src/arm/assembler-arm-inl.h @@ -101,7 +101,7 @@ void RelocInfo::apply(intptr_t delta) { Address RelocInfo::target_address() { ASSERT(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)); - return Assembler::target_address_at(pc_); + return Assembler::target_address_at(pc_, host_); } @@ -127,7 +127,7 @@ int RelocInfo::target_address_size() { void RelocInfo::set_target_address(Address target, WriteBarrierMode mode) { ASSERT(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)); - Assembler::set_target_address_at(pc_, target); + Assembler::set_target_address_at(pc_, host_, target); if (mode == UPDATE_WRITE_BARRIER && host() != NULL && IsCodeTarget(rmode_)) { Object* target_code = Code::GetCodeFromTargetAddress(target); host()->GetHeap()->incremental_marking()->RecordWriteIntoCode( @@ -138,21 +138,22 @@ void RelocInfo::set_target_address(Address target, WriteBarrierMode mode) { Object* RelocInfo::target_object() { ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); - return reinterpret_cast(Assembler::target_address_at(pc_)); + return reinterpret_cast(Assembler::target_address_at(pc_, host_)); } Handle RelocInfo::target_object_handle(Assembler* origin) { ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); return Handle(reinterpret_cast( - Assembler::target_address_at(pc_))); + Assembler::target_address_at(pc_, host_))); } void RelocInfo::set_target_object(Object* target, WriteBarrierMode mode) { ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); ASSERT(!target->IsConsString()); - Assembler::set_target_address_at(pc_, reinterpret_cast
(target)); + Assembler::set_target_address_at(pc_, host_, + reinterpret_cast
(target)); if (mode == UPDATE_WRITE_BARRIER && host() != NULL && target->IsHeapObject()) { @@ -164,7 +165,7 @@ void RelocInfo::set_target_object(Object* target, WriteBarrierMode mode) { Address RelocInfo::target_reference() { ASSERT(rmode_ == EXTERNAL_REFERENCE); - return Assembler::target_address_at(pc_); + return Assembler::target_address_at(pc_, host_); } @@ -275,7 +276,7 @@ void RelocInfo::WipeOut() { IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_) || IsExternalReference(rmode_)); - Assembler::set_target_address_at(pc_, NULL); + Assembler::set_target_address_at(pc_, host_, NULL); } @@ -409,7 +410,8 @@ Address Assembler::target_pointer_address_at(Address pc) { } -Address Assembler::target_address_at(Address pc) { +Address Assembler::target_address_at(Address pc, + ConstantPoolArray* constant_pool) { if (IsMovW(Memory::int32_at(pc))) { ASSERT(IsMovT(Memory::int32_at(pc + kInstrSize))); Instruction* instr = Instruction::At(pc); @@ -459,7 +461,7 @@ Address Assembler::return_address_from_call_start(Address pc) { void Assembler::deserialization_set_special_target_at( - Address constant_pool_entry, Address target) { + Address constant_pool_entry, Code* code, Address target) { Memory::Address_at(constant_pool_entry) = target; } @@ -470,7 +472,9 @@ static Instr EncodeMovwImmediate(uint32_t immediate) { } -void Assembler::set_target_address_at(Address pc, Address target) { +void Assembler::set_target_address_at(Address pc, + ConstantPoolArray* constant_pool, + Address target) { if (IsMovW(Memory::int32_at(pc))) { ASSERT(IsMovT(Memory::int32_at(pc + kInstrSize))); uint32_t* instr_ptr = reinterpret_cast(pc); diff --git a/src/arm/assembler-arm.h b/src/arm/assembler-arm.h index c35c80b..5cb4c61 100644 --- a/src/arm/assembler-arm.h +++ b/src/arm/assembler-arm.h @@ -780,9 +780,27 @@ class Assembler : public AssemblerBase { // the branch/call instruction at pc, or the object in a mov. INLINE(static Address target_pointer_address_at(Address pc)); + // Return the address in the constant pool of the code target address used by + // the branch/call instruction at pc, or the object in a mov. + INLINE(static Address target_constant_pool_address_at( + Address pc, ConstantPoolArray* constant_pool)); + // Read/Modify the code target address in the branch/call instruction at pc. - INLINE(static Address target_address_at(Address pc)); - INLINE(static void set_target_address_at(Address pc, Address target)); + INLINE(static Address target_address_at(Address pc, + ConstantPoolArray* constant_pool)); + INLINE(static void set_target_address_at(Address pc, + ConstantPoolArray* constant_pool, + Address target)); + INLINE(static Address target_address_at(Address pc, Code* code)) { + ConstantPoolArray* constant_pool = code ? code->constant_pool() : NULL; + return target_address_at(pc, constant_pool); + } + INLINE(static void set_target_address_at(Address pc, + Code* code, + Address target)) { + ConstantPoolArray* constant_pool = code ? code->constant_pool() : NULL; + set_target_address_at(pc, constant_pool, target); + } // Return the code target address at a call site from the return address // of that call in the instruction stream. @@ -795,7 +813,7 @@ class Assembler : public AssemblerBase { // This sets the branch destination (which is in the constant pool on ARM). // This is for calls and branches within generated code. inline static void deserialization_set_special_target_at( - Address constant_pool_entry, Address target); + Address constant_pool_entry, Code* code, Address target); // Here we are patching the address in the constant pool, not the actual call // instruction. The address in the constant pool is the same size as a diff --git a/src/debug.cc b/src/debug.cc index 7014129..8c4f335 100644 --- a/src/debug.cc +++ b/src/debug.cc @@ -2359,7 +2359,7 @@ void Debug::SetAfterBreakTarget(JavaScriptFrame* frame) { // Continue just after the slot. thread_local_.after_break_target_ = addr + Assembler::kDebugBreakSlotLength; - } else if (IsDebugBreak(Assembler::target_address_at(addr))) { + } else if (IsDebugBreak(Assembler::target_address_at(addr, *code))) { // We now know that there is still a debug break call at the target address, // so the break point is still there and the original code will hold the // address to jump to in order to complete the call which is replaced by a @@ -2370,13 +2370,15 @@ void Debug::SetAfterBreakTarget(JavaScriptFrame* frame) { // Install jump to the call address in the original code. This will be the // call which was overwritten by the call to DebugBreakXXX. - thread_local_.after_break_target_ = Assembler::target_address_at(addr); + thread_local_.after_break_target_ = + Assembler::target_address_at(addr, *original_code); } else { // There is no longer a break point present. Don't try to look in the // original code as the running code will have the right address. This takes // care of the case where the last break point is removed from the function // and therefore no "original code" is available. - thread_local_.after_break_target_ = Assembler::target_address_at(addr); + thread_local_.after_break_target_ = + Assembler::target_address_at(addr, *code); } } diff --git a/src/disassembler.cc b/src/disassembler.cc index f02d43a..2af6422 100644 --- a/src/disassembler.cc +++ b/src/disassembler.cc @@ -200,7 +200,7 @@ static int DecodeIt(Isolate* isolate, // Print all the reloc info for this instruction which are not comments. for (int i = 0; i < pcs.length(); i++) { // Put together the reloc info - RelocInfo relocinfo(pcs[i], rmodes[i], datas[i], NULL); + RelocInfo relocinfo(pcs[i], rmodes[i], datas[i], converter.code()); // Indent the printing of the reloc info. if (i == 0) { diff --git a/src/ia32/assembler-ia32-inl.h b/src/ia32/assembler-ia32-inl.h index 0c35197..8022f05 100644 --- a/src/ia32/assembler-ia32-inl.h +++ b/src/ia32/assembler-ia32-inl.h @@ -85,7 +85,7 @@ void RelocInfo::apply(intptr_t delta) { Address RelocInfo::target_address() { ASSERT(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)); - return Assembler::target_address_at(pc_); + return Assembler::target_address_at(pc_, host_); } @@ -109,7 +109,7 @@ int RelocInfo::target_address_size() { void RelocInfo::set_target_address(Address target, WriteBarrierMode mode) { - Assembler::set_target_address_at(pc_, target); + Assembler::set_target_address_at(pc_, host_, target); ASSERT(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)); if (mode == UPDATE_WRITE_BARRIER && host() != NULL && IsCodeTarget(rmode_)) { Object* target_code = Code::GetCodeFromTargetAddress(target); @@ -202,28 +202,28 @@ Code* RelocInfo::code_age_stub() { ASSERT(rmode_ == RelocInfo::CODE_AGE_SEQUENCE); ASSERT(*pc_ == kCallOpcode); return Code::GetCodeFromTargetAddress( - Assembler::target_address_at(pc_ + 1)); + Assembler::target_address_at(pc_ + 1, host_)); } void RelocInfo::set_code_age_stub(Code* stub) { ASSERT(*pc_ == kCallOpcode); ASSERT(rmode_ == RelocInfo::CODE_AGE_SEQUENCE); - Assembler::set_target_address_at(pc_ + 1, stub->instruction_start()); + Assembler::set_target_address_at(pc_ + 1, host_, stub->instruction_start()); } Address RelocInfo::call_address() { ASSERT((IsJSReturn(rmode()) && IsPatchedReturnSequence()) || (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence())); - return Assembler::target_address_at(pc_ + 1); + return Assembler::target_address_at(pc_ + 1, host_); } void RelocInfo::set_call_address(Address target) { ASSERT((IsJSReturn(rmode()) && IsPatchedReturnSequence()) || (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence())); - Assembler::set_target_address_at(pc_ + 1, target); + Assembler::set_target_address_at(pc_ + 1, host_, target); if (host() != NULL) { Object* target_code = Code::GetCodeFromTargetAddress(target); host()->GetHeap()->incremental_marking()->RecordWriteIntoCode( @@ -254,7 +254,7 @@ void RelocInfo::WipeOut() { Memory::Address_at(pc_) = NULL; } else if (IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)) { // Effectively write zero into the relocation. - Assembler::set_target_address_at(pc_, pc_ + sizeof(int32_t)); + Assembler::set_target_address_at(pc_, host_, pc_ + sizeof(int32_t)); } else { UNREACHABLE(); } @@ -445,12 +445,15 @@ void Assembler::emit_w(const Immediate& x) { } -Address Assembler::target_address_at(Address pc) { +Address Assembler::target_address_at(Address pc, + ConstantPoolArray* constant_pool) { return pc + sizeof(int32_t) + *reinterpret_cast(pc); } -void Assembler::set_target_address_at(Address pc, Address target) { +void Assembler::set_target_address_at(Address pc, + ConstantPoolArray* constant_pool, + Address target) { int32_t* p = reinterpret_cast(pc); *p = target - (pc + sizeof(int32_t)); CPU::FlushICache(p, sizeof(int32_t)); diff --git a/src/ia32/assembler-ia32.h b/src/ia32/assembler-ia32.h index 12e2e3c..7edd307 100644 --- a/src/ia32/assembler-ia32.h +++ b/src/ia32/assembler-ia32.h @@ -624,8 +624,21 @@ class Assembler : public AssemblerBase { void GetCode(CodeDesc* desc); // Read/Modify the code target in the branch/call instruction at pc. - inline static Address target_address_at(Address pc); - inline static void set_target_address_at(Address pc, Address target); + inline static Address target_address_at(Address pc, + ConstantPoolArray* constant_pool); + inline static void set_target_address_at(Address pc, + ConstantPoolArray* constant_pool, + Address target); + static inline Address target_address_at(Address pc, Code* code) { + ConstantPoolArray* constant_pool = code ? code->constant_pool() : NULL; + return target_address_at(pc, constant_pool); + } + static inline void set_target_address_at(Address pc, + Code* code, + Address target) { + ConstantPoolArray* constant_pool = code ? code->constant_pool() : NULL; + set_target_address_at(pc, constant_pool, target); + } // Return the code target address at a call site from the return address // of that call in the instruction stream. @@ -634,8 +647,8 @@ class Assembler : public AssemblerBase { // This sets the branch destination (which is in the instruction on x86). // This is for calls and branches within generated code. inline static void deserialization_set_special_target_at( - Address instruction_payload, Address target) { - set_target_address_at(instruction_payload, target); + Address instruction_payload, Code* code, Address target) { + set_target_address_at(instruction_payload, code, target); } static const int kSpecialTargetSize = kPointerSize; diff --git a/src/ia32/frames-ia32.h b/src/ia32/frames-ia32.h index e0f3e32..2d6145e 100644 --- a/src/ia32/frames-ia32.h +++ b/src/ia32/frames-ia32.h @@ -84,6 +84,8 @@ class ExitFrameConstants : public AllStatic { // FP-relative displacement of the caller's SP. It points just // below the saved PC. static const int kCallerSPDisplacement = +2 * kPointerSize; + + static const int kConstantPoolOffset = 0; // Not used }; diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc index 54c96fd..06da7ba 100644 --- a/src/ia32/full-codegen-ia32.cc +++ b/src/ia32/full-codegen-ia32.cc @@ -4863,6 +4863,7 @@ void BackEdgeTable::PatchAt(Code* unoptimized_code, } Assembler::set_target_address_at(call_target_address, + unoptimized_code, replacement_code->entry()); unoptimized_code->GetHeap()->incremental_marking()->RecordCodeTargetPatch( unoptimized_code, call_target_address, replacement_code); @@ -4880,20 +4881,22 @@ BackEdgeTable::BackEdgeState BackEdgeTable::GetBackEdgeState( if (*jns_instr_address == kJnsInstruction) { ASSERT_EQ(kJnsOffset, *(call_target_address - 2)); ASSERT_EQ(isolate->builtins()->InterruptCheck()->entry(), - Assembler::target_address_at(call_target_address)); + Assembler::target_address_at(call_target_address, + unoptimized_code)); return INTERRUPT; } ASSERT_EQ(kNopByteOne, *jns_instr_address); ASSERT_EQ(kNopByteTwo, *(call_target_address - 2)); - if (Assembler::target_address_at(call_target_address) == + if (Assembler::target_address_at(call_target_address, unoptimized_code) == isolate->builtins()->OnStackReplacement()->entry()) { return ON_STACK_REPLACEMENT; } ASSERT_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(), - Assembler::target_address_at(call_target_address)); + Assembler::target_address_at(call_target_address, + unoptimized_code)); return OSR_AFTER_STACK_CHECK; } diff --git a/src/ic-inl.h b/src/ic-inl.h index e0f807c..ebe0fb9 100644 --- a/src/ic-inl.h +++ b/src/ic-inl.h @@ -50,12 +50,20 @@ Address IC::address() const { // At least one break point is active perform additional test to ensure that // break point locations are updated correctly. - if (debug->IsDebugBreak(Assembler::target_address_at(result))) { + if (debug->IsDebugBreak(Assembler::target_address_at(result, + raw_constant_pool()))) { // If the call site is a call to debug break then return the address in // the original code instead of the address in the running code. This will // cause the original code to be updated and keeps the breakpoint active in // the running code. - return OriginalCodeAddress(); + Code* code = GetCode(); + Code* original_code = GetOriginalCode(); + intptr_t delta = + original_code->instruction_start() - code->instruction_start(); + // Return the address in the original code. This is the place where + // the call which has been overwritten by the DebugBreakXXX resides + // and the place where the inline cache system should look. + return result + delta; } else { // No break point here just return the address of the call. return result; @@ -66,9 +74,45 @@ Address IC::address() const { } -Code* IC::GetTargetAtAddress(Address address) { +ConstantPoolArray* IC::constant_pool() const { + if (!FLAG_enable_ool_constant_pool) { + return NULL; + } else { + Handle result = raw_constant_pool_; +#ifdef ENABLE_DEBUGGER_SUPPORT + Debug* debug = isolate()->debug(); + // First check if any break points are active if not just return the + // original constant pool. + if (!debug->has_break_points()) return *result; + + // At least one break point is active perform additional test to ensure that + // break point locations are updated correctly. + Address target = Assembler::target_address_from_return_address(pc()); + if (debug->IsDebugBreak( + Assembler::target_address_at(target, raw_constant_pool()))) { + // If the call site is a call to debug break then we want to return the + // constant pool for the original code instead of the breakpointed code. + return GetOriginalCode()->constant_pool(); + } +#endif + return *result; + } +} + + +ConstantPoolArray* IC::raw_constant_pool() const { + if (FLAG_enable_ool_constant_pool) { + return *raw_constant_pool_; + } else { + return NULL; + } +} + + +Code* IC::GetTargetAtAddress(Address address, + ConstantPoolArray* constant_pool) { // Get the target address of the IC. - Address target = Assembler::target_address_at(address); + Address target = Assembler::target_address_at(address, constant_pool); // Convert target address to the code object. Code::GetCodeFromTargetAddress // is safe for use during GC where the map might be marked. Code* result = Code::GetCodeFromTargetAddress(target); @@ -77,10 +121,12 @@ Code* IC::GetTargetAtAddress(Address address) { } -void IC::SetTargetAtAddress(Address address, Code* target) { +void IC::SetTargetAtAddress(Address address, + Code* target, + ConstantPoolArray* constant_pool) { ASSERT(target->is_inline_cache_stub() || target->is_compare_ic_stub()); Heap* heap = target->GetHeap(); - Code* old_target = GetTargetAtAddress(address); + Code* old_target = GetTargetAtAddress(address, constant_pool); #ifdef DEBUG // STORE_IC and KEYED_STORE_IC use Code::extra_ic_state() to mark // ICs as strict mode. The strict-ness of the IC must be preserved. @@ -90,7 +136,8 @@ void IC::SetTargetAtAddress(Address address, Code* target) { StoreIC::GetStrictMode(target->extra_ic_state())); } #endif - Assembler::set_target_address_at(address, target->instruction_start()); + Assembler::set_target_address_at( + address, constant_pool, target->instruction_start()); if (heap->gc_state() == Heap::MARK_COMPACT) { heap->mark_compact_collector()->RecordCodeTargetPatch(address, target); } else { diff --git a/src/ic.cc b/src/ic.cc index 9e30aea..316c391 100644 --- a/src/ic.cc +++ b/src/ic.cc @@ -127,6 +127,11 @@ IC::IC(FrameDepth depth, Isolate* isolate) // running DeltaBlue and a ~25% speedup of gbemu with the '--nouse-ic' flag. const Address entry = Isolate::c_entry_fp(isolate->thread_local_top()); + Address constant_pool = NULL; + if (FLAG_enable_ool_constant_pool) { + constant_pool = Memory::Address_at( + entry + ExitFrameConstants::kConstantPoolOffset); + } Address* pc_address = reinterpret_cast(entry + ExitFrameConstants::kCallerPCOffset); Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset); @@ -134,6 +139,10 @@ IC::IC(FrameDepth depth, Isolate* isolate) // StubFailureTrampoline, we need to look one frame further down the stack to // find the frame pointer and the return address stack slot. if (depth == EXTRA_CALL_FRAME) { + if (FLAG_enable_ool_constant_pool) { + constant_pool = Memory::Address_at( + fp + StandardFrameConstants::kConstantPoolOffset); + } const int kCallerPCOffset = StandardFrameConstants::kCallerPCOffset; pc_address = reinterpret_cast(fp + kCallerPCOffset); fp = Memory::Address_at(fp + StandardFrameConstants::kCallerFPOffset); @@ -145,6 +154,11 @@ IC::IC(FrameDepth depth, Isolate* isolate) ASSERT(fp == frame->fp() && pc_address == frame->pc_address()); #endif fp_ = fp; + if (FLAG_enable_ool_constant_pool) { + raw_constant_pool_ = handle( + ConstantPoolArray::cast(reinterpret_cast(constant_pool)), + isolate); + } pc_address_ = StackFrame::ResolveReturnAddressLocation(pc_address); target_ = handle(raw_target(), isolate); state_ = target_->ic_state(); @@ -153,8 +167,7 @@ IC::IC(FrameDepth depth, Isolate* isolate) #ifdef ENABLE_DEBUGGER_SUPPORT -Address IC::OriginalCodeAddress() const { - HandleScope scope(isolate()); +SharedFunctionInfo* IC::GetSharedFunctionInfo() const { // Compute the JavaScript frame for the frame pointer of this IC // structure. We need this to be able to find the function // corresponding to the frame. @@ -164,21 +177,25 @@ Address IC::OriginalCodeAddress() const { // Find the function on the stack and both the active code for the // function and the original code. JSFunction* function = frame->function(); - Handle shared(function->shared(), isolate()); + return function->shared(); +} + + +Code* IC::GetCode() const { + HandleScope scope(isolate()); + Handle shared(GetSharedFunctionInfo(), isolate()); Code* code = shared->code(); + return code; +} + + +Code* IC::GetOriginalCode() const { + HandleScope scope(isolate()); + Handle shared(GetSharedFunctionInfo(), isolate()); ASSERT(Debug::HasDebugInfo(shared)); Code* original_code = Debug::GetDebugInfo(shared)->original_code(); ASSERT(original_code->IsCode()); - // Get the address of the call site in the active code. This is the - // place where the call to DebugBreakXXX is and where the IC - // normally would be. - Address addr = Assembler::target_address_from_return_address(pc()); - // Return the address in the original code. This is the place where - // the call which has been overwritten by the DebugBreakXXX resides - // and the place where the inline cache system should look. - intptr_t delta = - original_code->instruction_start() - code->instruction_start(); - return addr + delta; + return original_code; } #endif @@ -409,21 +426,26 @@ void IC::PostPatching(Address address, Code* target, Code* old_target) { } -void IC::Clear(Isolate* isolate, Address address) { - Code* target = GetTargetAtAddress(address); +void IC::Clear(Isolate* isolate, Address address, + ConstantPoolArray* constant_pool) { + Code* target = GetTargetAtAddress(address, constant_pool); // Don't clear debug break inline cache as it will remove the break point. if (target->is_debug_stub()) return; switch (target->kind()) { - case Code::LOAD_IC: return LoadIC::Clear(isolate, address, target); + case Code::LOAD_IC: + return LoadIC::Clear(isolate, address, target, constant_pool); case Code::KEYED_LOAD_IC: - return KeyedLoadIC::Clear(isolate, address, target); - case Code::STORE_IC: return StoreIC::Clear(isolate, address, target); + return KeyedLoadIC::Clear(isolate, address, target, constant_pool); + case Code::STORE_IC: + return StoreIC::Clear(isolate, address, target, constant_pool); case Code::KEYED_STORE_IC: - return KeyedStoreIC::Clear(isolate, address, target); - case Code::COMPARE_IC: return CompareIC::Clear(isolate, address, target); - case Code::COMPARE_NIL_IC: return CompareNilIC::Clear(address, target); + return KeyedStoreIC::Clear(isolate, address, target, constant_pool); + case Code::COMPARE_IC: + return CompareIC::Clear(isolate, address, target, constant_pool); + case Code::COMPARE_NIL_IC: + return CompareNilIC::Clear(address, target, constant_pool); case Code::BINARY_OP_IC: case Code::TO_BOOLEAN_IC: // Clearing these is tricky and does not @@ -434,40 +456,56 @@ void IC::Clear(Isolate* isolate, Address address) { } -void KeyedLoadIC::Clear(Isolate* isolate, Address address, Code* target) { +void KeyedLoadIC::Clear(Isolate* isolate, + Address address, + Code* target, + ConstantPoolArray* constant_pool) { if (IsCleared(target)) return; // Make sure to also clear the map used in inline fast cases. If we // do not clear these maps, cached code can keep objects alive // through the embedded maps. - SetTargetAtAddress(address, *pre_monomorphic_stub(isolate)); + SetTargetAtAddress(address, *pre_monomorphic_stub(isolate), constant_pool); } -void LoadIC::Clear(Isolate* isolate, Address address, Code* target) { +void LoadIC::Clear(Isolate* isolate, + Address address, + Code* target, + ConstantPoolArray* constant_pool) { if (IsCleared(target)) return; Code* code = target->GetIsolate()->stub_cache()->FindPreMonomorphicIC( Code::LOAD_IC, target->extra_ic_state()); - SetTargetAtAddress(address, code); + SetTargetAtAddress(address, code, constant_pool); } -void StoreIC::Clear(Isolate* isolate, Address address, Code* target) { +void StoreIC::Clear(Isolate* isolate, + Address address, + Code* target, + ConstantPoolArray* constant_pool) { if (IsCleared(target)) return; Code* code = target->GetIsolate()->stub_cache()->FindPreMonomorphicIC( Code::STORE_IC, target->extra_ic_state()); - SetTargetAtAddress(address, code); + SetTargetAtAddress(address, code, constant_pool); } -void KeyedStoreIC::Clear(Isolate* isolate, Address address, Code* target) { +void KeyedStoreIC::Clear(Isolate* isolate, + Address address, + Code* target, + ConstantPoolArray* constant_pool) { if (IsCleared(target)) return; SetTargetAtAddress(address, *pre_monomorphic_stub( - isolate, StoreIC::GetStrictMode(target->extra_ic_state()))); + isolate, StoreIC::GetStrictMode(target->extra_ic_state())), + constant_pool); } -void CompareIC::Clear(Isolate* isolate, Address address, Code* target) { +void CompareIC::Clear(Isolate* isolate, + Address address, + Code* target, + ConstantPoolArray* constant_pool) { ASSERT(target->major_key() == CodeStub::CompareIC); CompareIC::State handler_state; Token::Value op; @@ -475,7 +513,7 @@ void CompareIC::Clear(Isolate* isolate, Address address, Code* target) { &handler_state, &op); // Only clear CompareICs that can retain objects. if (handler_state != KNOWN_OBJECT) return; - SetTargetAtAddress(address, GetRawUninitialized(isolate, op)); + SetTargetAtAddress(address, GetRawUninitialized(isolate, op), constant_pool); PatchInlinedSmiCode(address, DISABLE_INLINED_SMI_CHECK); } @@ -2685,7 +2723,9 @@ RUNTIME_FUNCTION(Code*, CompareIC_Miss) { } -void CompareNilIC::Clear(Address address, Code* target) { +void CompareNilIC::Clear(Address address, + Code* target, + ConstantPoolArray* constant_pool) { if (IsCleared(target)) return; ExtraICState state = target->extra_ic_state(); @@ -2695,7 +2735,7 @@ void CompareNilIC::Clear(Address address, Code* target) { Code* code = NULL; CHECK(stub.FindCodeInCache(&code, target->GetIsolate())); - SetTargetAtAddress(address, code); + SetTargetAtAddress(address, code, constant_pool); } diff --git a/src/ic.h b/src/ic.h index ec9fe8b..7a9d7fb 100644 --- a/src/ic.h +++ b/src/ic.h @@ -101,7 +101,9 @@ class IC { } // Clear the inline cache to initial state. - static void Clear(Isolate* isolate, Address address); + static void Clear(Isolate* isolate, + Address address, + ConstantPoolArray* constant_pool); #ifdef DEBUG bool IsLoadStub() const { @@ -155,14 +157,17 @@ class IC { Isolate* isolate() const { return isolate_; } #ifdef ENABLE_DEBUGGER_SUPPORT - // Computes the address in the original code when the code running is - // containing break points (calls to DebugBreakXXX builtins). - Address OriginalCodeAddress() const; + // Get the shared function info of the caller. + SharedFunctionInfo* GetSharedFunctionInfo() const; + // Get the code object of the caller. + Code* GetCode() const; + // Get the original (non-breakpointed) code object of the caller. + Code* GetOriginalCode() const; #endif // Set the call-site target. void set_target(Code* code) { - SetTargetAtAddress(address(), code); + SetTargetAtAddress(address(), code, constant_pool()); target_set_ = true; } @@ -180,8 +185,11 @@ class IC { Failure* ReferenceError(const char* type, Handle name); // Access the target code for the given IC address. - static inline Code* GetTargetAtAddress(Address address); - static inline void SetTargetAtAddress(Address address, Code* target); + static inline Code* GetTargetAtAddress(Address address, + ConstantPoolArray* constant_pool); + static inline void SetTargetAtAddress(Address address, + Code* target, + ConstantPoolArray* constant_pool); static void PostPatching(Address address, Code* target, Code* old_target); // Compute the handler either by compiling or by retrieving a cached version. @@ -240,7 +248,11 @@ class IC { } private: - Code* raw_target() const { return GetTargetAtAddress(address()); } + Code* raw_target() const { + return GetTargetAtAddress(address(), constant_pool()); + } + inline ConstantPoolArray* constant_pool() const; + inline ConstantPoolArray* raw_constant_pool() const; // Frame pointer for the frame that uses (calls) the IC. Address fp_; @@ -253,6 +265,10 @@ class IC { Isolate* isolate_; + // The constant pool of the code which originally called the IC (which might + // be for the breakpointed copy of the original code). + Handle raw_constant_pool_; + // The original code target that missed. Handle target_; State state_; @@ -373,7 +389,10 @@ class LoadIC: public IC { Representation representation = Representation::Tagged()); - static void Clear(Isolate* isolate, Address address, Code* target); + static void Clear(Isolate* isolate, + Address address, + Code* target, + ConstantPoolArray* constant_pool); friend class IC; }; @@ -443,7 +462,10 @@ class KeyedLoadIC: public LoadIC { return isolate()->builtins()->KeyedLoadIC_String(); } - static void Clear(Isolate* isolate, Address address, Code* target); + static void Clear(Isolate* isolate, + Address address, + Code* target, + ConstantPoolArray* constant_pool); friend class IC; }; @@ -533,7 +555,10 @@ class StoreIC: public IC { IC::set_target(code); } - static void Clear(Isolate* isolate, Address address, Code* target); + static void Clear(Isolate* isolate, + Address address, + Code* target, + ConstantPoolArray* constant_pool); friend class IC; }; @@ -640,7 +665,10 @@ class KeyedStoreIC: public StoreIC { return isolate()->builtins()->KeyedStoreIC_SloppyArguments(); } - static void Clear(Isolate* isolate, Address address, Code* target); + static void Clear(Isolate* isolate, + Address address, + Code* target, + ConstantPoolArray* constant_pool); KeyedAccessStoreMode GetStoreMode(Handle receiver, Handle key, @@ -847,7 +875,10 @@ class CompareIC: public IC { static Code* GetRawUninitialized(Isolate* isolate, Token::Value op); - static void Clear(Isolate* isolate, Address address, Code* target); + static void Clear(Isolate* isolate, + Address address, + Code* target, + ConstantPoolArray* constant_pool); Token::Value op_; @@ -863,7 +894,9 @@ class CompareNilIC: public IC { static Handle GetUninitialized(); - static void Clear(Address address, Code* target); + static void Clear(Address address, + Code* target, + ConstantPoolArray* constant_pool); static MUST_USE_RESULT MaybeObject* DoCompareNilSlow(NilValue nil, Handle object); diff --git a/src/objects-visiting-inl.h b/src/objects-visiting-inl.h index 0b3ec59..db84664 100644 --- a/src/objects-visiting-inl.h +++ b/src/objects-visiting-inl.h @@ -313,7 +313,8 @@ void StaticMarkingVisitor::VisitCodeTarget( && (target->ic_state() == MEGAMORPHIC || target->ic_state() == GENERIC || target->ic_state() == POLYMORPHIC || heap->flush_monomorphic_ics() || Serializer::enabled() || target->ic_age() != heap->global_ic_age())) { - IC::Clear(target->GetIsolate(), rinfo->pc()); + IC::Clear(target->GetIsolate(), rinfo->pc(), + rinfo->host()->constant_pool()); target = Code::GetCodeFromTargetAddress(rinfo->target_address()); } heap->mark_compact_collector()->RecordRelocSlot(rinfo, target); diff --git a/src/objects.cc b/src/objects.cc index 925fd2b..cae443d 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -10629,7 +10629,8 @@ void Code::ClearInlineCaches(Code::Kind* kind) { Code* target(Code::GetCodeFromTargetAddress(info->target_address())); if (target->is_inline_cache_stub()) { if (kind == NULL || *kind == target->kind()) { - IC::Clear(this->GetIsolate(), info->pc()); + IC::Clear(this->GetIsolate(), info->pc(), + info->host()->constant_pool()); } } } diff --git a/src/serialize.cc b/src/serialize.cc index 30a05d5..7e9f4f5 100644 --- a/src/serialize.cc +++ b/src/serialize.cc @@ -983,6 +983,7 @@ void Deserializer::ReadChunk(Object** current, reinterpret_cast
(current); \ Assembler::deserialization_set_special_target_at( \ location_of_branch_data, \ + Code::cast(HeapObject::FromAddress(current_object_address)), \ reinterpret_cast
(new_object)); \ location_of_branch_data += Assembler::kSpecialTargetSize; \ current = reinterpret_cast(location_of_branch_data); \ diff --git a/src/x64/assembler-x64-inl.h b/src/x64/assembler-x64-inl.h index f2ec029..a559b62 100644 --- a/src/x64/assembler-x64-inl.h +++ b/src/x64/assembler-x64-inl.h @@ -205,12 +205,15 @@ void Assembler::emit_optional_rex_32(const Operand& op) { } -Address Assembler::target_address_at(Address pc) { +Address Assembler::target_address_at(Address pc, + ConstantPoolArray* constant_pool) { return Memory::int32_at(pc) + pc + 4; } -void Assembler::set_target_address_at(Address pc, Address target) { +void Assembler::set_target_address_at(Address pc, + ConstantPoolArray* constant_pool, + Address target) { Memory::int32_at(pc) = static_cast(target - pc - 4); CPU::FlushICache(pc, sizeof(int32_t)); } @@ -255,7 +258,7 @@ void RelocInfo::apply(intptr_t delta) { Address RelocInfo::target_address() { ASSERT(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)); - return Assembler::target_address_at(pc_); + return Assembler::target_address_at(pc_, host_); } @@ -284,7 +287,7 @@ int RelocInfo::target_address_size() { void RelocInfo::set_target_address(Address target, WriteBarrierMode mode) { ASSERT(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)); - Assembler::set_target_address_at(pc_, target); + Assembler::set_target_address_at(pc_, host_, target); if (mode == UPDATE_WRITE_BARRIER && host() != NULL && IsCodeTarget(rmode_)) { Object* target_code = Code::GetCodeFromTargetAddress(target); host()->GetHeap()->incremental_marking()->RecordWriteIntoCode( @@ -375,7 +378,7 @@ void RelocInfo::WipeOut() { Memory::Address_at(pc_) = NULL; } else if (IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)) { // Effectively write zero into the relocation. - Assembler::set_target_address_at(pc_, pc_ + sizeof(int32_t)); + Assembler::set_target_address_at(pc_, host_, pc_ + sizeof(int32_t)); } else { UNREACHABLE(); } @@ -414,14 +417,14 @@ Code* RelocInfo::code_age_stub() { ASSERT(rmode_ == RelocInfo::CODE_AGE_SEQUENCE); ASSERT(*pc_ == kCallOpcode); return Code::GetCodeFromTargetAddress( - Assembler::target_address_at(pc_ + 1)); + Assembler::target_address_at(pc_ + 1, host_)); } void RelocInfo::set_code_age_stub(Code* stub) { ASSERT(*pc_ == kCallOpcode); ASSERT(rmode_ == RelocInfo::CODE_AGE_SEQUENCE); - Assembler::set_target_address_at(pc_ + 1, stub->instruction_start()); + Assembler::set_target_address_at(pc_ + 1, host_, stub->instruction_start()); } diff --git a/src/x64/assembler-x64.h b/src/x64/assembler-x64.h index 4214249..09d2e70 100644 --- a/src/x64/assembler-x64.h +++ b/src/x64/assembler-x64.h @@ -555,8 +555,21 @@ class Assembler : public AssemblerBase { // the absolute address of the target. // These functions convert between absolute Addresses of Code objects and // the relative displacements stored in the code. - static inline Address target_address_at(Address pc); - static inline void set_target_address_at(Address pc, Address target); + static inline Address target_address_at(Address pc, + ConstantPoolArray* constant_pool); + static inline void set_target_address_at(Address pc, + ConstantPoolArray* constant_pool, + Address target); + static inline Address target_address_at(Address pc, Code* code) { + ConstantPoolArray* constant_pool = code ? code->constant_pool() : NULL; + return target_address_at(pc, constant_pool); + } + static inline void set_target_address_at(Address pc, + Code* code, + Address target) { + ConstantPoolArray* constant_pool = code ? code->constant_pool() : NULL; + set_target_address_at(pc, constant_pool, target); + } // Return the code target address at a call site from the return address // of that call in the instruction stream. @@ -565,8 +578,8 @@ class Assembler : public AssemblerBase { // This sets the branch destination (which is in the instruction on x64). // This is for calls and branches within generated code. inline static void deserialization_set_special_target_at( - Address instruction_payload, Address target) { - set_target_address_at(instruction_payload, target); + Address instruction_payload, Code* code, Address target) { + set_target_address_at(instruction_payload, code, target); } static inline RelocInfo::Mode RelocInfoNone() { diff --git a/src/x64/frames-x64.h b/src/x64/frames-x64.h index 6eb02a9..1fb77ff 100644 --- a/src/x64/frames-x64.h +++ b/src/x64/frames-x64.h @@ -77,6 +77,8 @@ class ExitFrameConstants : public AllStatic { // FP-relative displacement of the caller's SP. It points just // below the saved PC. static const int kCallerSPDisplacement = kCallerPCOffset + kPCOnStackSize; + + static const int kConstantPoolOffset = 0; // Not used }; diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc index 67d94f9..b146809 100644 --- a/src/x64/full-codegen-x64.cc +++ b/src/x64/full-codegen-x64.cc @@ -4859,6 +4859,7 @@ void BackEdgeTable::PatchAt(Code* unoptimized_code, } Assembler::set_target_address_at(call_target_address, + unoptimized_code, replacement_code->entry()); unoptimized_code->GetHeap()->incremental_marking()->RecordCodeTargetPatch( unoptimized_code, call_target_address, replacement_code); @@ -4876,20 +4877,23 @@ BackEdgeTable::BackEdgeState BackEdgeTable::GetBackEdgeState( if (*jns_instr_address == kJnsInstruction) { ASSERT_EQ(kJnsOffset, *(call_target_address - 2)); ASSERT_EQ(isolate->builtins()->InterruptCheck()->entry(), - Assembler::target_address_at(call_target_address)); + Assembler::target_address_at(call_target_address, + unoptimized_code)); return INTERRUPT; } ASSERT_EQ(kNopByteOne, *jns_instr_address); ASSERT_EQ(kNopByteTwo, *(call_target_address - 2)); - if (Assembler::target_address_at(call_target_address) == + if (Assembler::target_address_at(call_target_address, + unoptimized_code) == isolate->builtins()->OnStackReplacement()->entry()) { return ON_STACK_REPLACEMENT; } ASSERT_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(), - Assembler::target_address_at(call_target_address)); + Assembler::target_address_at(call_target_address, + unoptimized_code)); return OSR_AFTER_STACK_CHECK; } -- 2.7.4