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(). R=ulan@chromium.org Review URL: https://codereview.chromium.org/183803022 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@19825 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
ab2493e428
commit
38732785dd
@ -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<Object*>(Assembler::target_address_at(pc_));
|
||||
return reinterpret_cast<Object*>(Assembler::target_address_at(pc_, host_));
|
||||
}
|
||||
|
||||
|
||||
Handle<Object> RelocInfo::target_object_handle(Assembler* origin) {
|
||||
ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
|
||||
return Handle<Object>(reinterpret_cast<Object**>(
|
||||
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<Address>(target));
|
||||
Assembler::set_target_address_at(pc_, host_,
|
||||
reinterpret_cast<Address>(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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -780,8 +780,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.
|
||||
@ -794,7 +801,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;
|
||||
|
@ -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
|
||||
};
|
||||
|
||||
|
||||
|
@ -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<Object*>(Assembler::target_address_at(pc_));
|
||||
return reinterpret_cast<Object*>(Assembler::target_address_at(pc_, host_));
|
||||
}
|
||||
|
||||
|
||||
Handle<Object> RelocInfo::target_object_handle(Assembler* origin) {
|
||||
ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
|
||||
return Handle<Object>(reinterpret_cast<Object**>(
|
||||
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<Address>(target));
|
||||
Assembler::set_target_address_at(pc_, host_,
|
||||
reinterpret_cast<Address>(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<uint32_t*>(pc);
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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<int32_t*>(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<int32_t*>(pc);
|
||||
*p = target - (pc + sizeof(int32_t));
|
||||
CPU::FlushICache(p, sizeof(int32_t));
|
||||
|
@ -624,8 +624,19 @@ 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) {
|
||||
return target_address_at(pc, code->constant_pool());
|
||||
}
|
||||
static inline void set_target_address_at(Address pc,
|
||||
Code* code,
|
||||
Address target) {
|
||||
set_target_address_at(pc, code->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 +645,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;
|
||||
|
@ -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
|
||||
};
|
||||
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
61
src/ic-inl.h
61
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<ConstantPoolArray> 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 {
|
||||
|
106
src/ic.cc
106
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<Address*>(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<Address*>(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<Object*>(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<SharedFunctionInfo> shared(function->shared(), isolate());
|
||||
return function->shared();
|
||||
}
|
||||
|
||||
|
||||
Code* IC::GetCode() const {
|
||||
HandleScope scope(isolate());
|
||||
Handle<SharedFunctionInfo> shared(GetSharedFunctionInfo(), isolate());
|
||||
Code* code = shared->code();
|
||||
return code;
|
||||
}
|
||||
|
||||
|
||||
Code* IC::GetOriginalCode() const {
|
||||
HandleScope scope(isolate());
|
||||
Handle<SharedFunctionInfo> 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);
|
||||
}
|
||||
|
||||
|
||||
|
61
src/ic.h
61
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<String> 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<ConstantPoolArray> raw_constant_pool_;
|
||||
|
||||
// The original code target that missed.
|
||||
Handle<Code> 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<JSObject> receiver,
|
||||
Handle<Object> 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<Code> 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> object);
|
||||
|
@ -313,7 +313,8 @@ void StaticMarkingVisitor<StaticVisitor>::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);
|
||||
|
@ -10635,7 +10635,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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -983,6 +983,7 @@ void Deserializer::ReadChunk(Object** current,
|
||||
reinterpret_cast<Address>(current); \
|
||||
Assembler::deserialization_set_special_target_at( \
|
||||
location_of_branch_data, \
|
||||
Code::cast(HeapObject::FromAddress(current_object_address)), \
|
||||
reinterpret_cast<Address>(new_object)); \
|
||||
location_of_branch_data += Assembler::kSpecialTargetSize; \
|
||||
current = reinterpret_cast<Object**>(location_of_branch_data); \
|
||||
|
@ -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<int32_t>(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());
|
||||
}
|
||||
|
||||
|
||||
|
@ -555,8 +555,19 @@ 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) {
|
||||
return target_address_at(pc, code->constant_pool());
|
||||
}
|
||||
static inline void set_target_address_at(Address pc,
|
||||
Code* code,
|
||||
Address target) {
|
||||
set_target_address_at(pc, code->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 +576,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() {
|
||||
|
@ -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
|
||||
};
|
||||
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user