| OLD | NEW |
| 1 // Copyright (c) 1994-2006 Sun Microsystems Inc. | 1 // Copyright (c) 1994-2006 Sun Microsystems Inc. |
| 2 // All Rights Reserved. | 2 // All Rights Reserved. |
| 3 // | 3 // |
| 4 // Redistribution and use in source and binary forms, with or without | 4 // Redistribution and use in source and binary forms, with or without |
| 5 // modification, are permitted provided that the following conditions are | 5 // modification, are permitted provided that the following conditions are |
| 6 // met: | 6 // met: |
| 7 // | 7 // |
| 8 // - Redistributions of source code must retain the above copyright notice, | 8 // - Redistributions of source code must retain the above copyright notice, |
| 9 // this list of conditions and the following disclaimer. | 9 // this list of conditions and the following disclaimer. |
| 10 // | 10 // |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 46 namespace internal { | 46 namespace internal { |
| 47 | 47 |
| 48 bool CpuFeatures::SupportsCrankshaft() { return true; } | 48 bool CpuFeatures::SupportsCrankshaft() { return true; } |
| 49 | 49 |
| 50 | 50 |
| 51 static const byte kCallOpcode = 0xE8; | 51 static const byte kCallOpcode = 0xE8; |
| 52 static const int kNoCodeAgeSequenceLength = 5; | 52 static const int kNoCodeAgeSequenceLength = 5; |
| 53 | 53 |
| 54 | 54 |
| 55 // The modes possibly affected by apply must be in kApplyMask. | 55 // The modes possibly affected by apply must be in kApplyMask. |
| 56 void RelocInfo::apply(intptr_t delta) { | 56 void RelocInfo::apply(intptr_t delta, ICacheFlushMode icache_flush_mode) { |
| 57 bool flush_icache = icache_flush_mode != SKIP_ICACHE_FLUSH; |
| 57 if (IsRuntimeEntry(rmode_) || IsCodeTarget(rmode_)) { | 58 if (IsRuntimeEntry(rmode_) || IsCodeTarget(rmode_)) { |
| 58 int32_t* p = reinterpret_cast<int32_t*>(pc_); | 59 int32_t* p = reinterpret_cast<int32_t*>(pc_); |
| 59 *p -= delta; // Relocate entry. | 60 *p -= delta; // Relocate entry. |
| 60 CPU::FlushICache(p, sizeof(uint32_t)); | 61 if (flush_icache) CPU::FlushICache(p, sizeof(uint32_t)); |
| 61 } else if (rmode_ == CODE_AGE_SEQUENCE) { | 62 } else if (rmode_ == CODE_AGE_SEQUENCE) { |
| 62 if (*pc_ == kCallOpcode) { | 63 if (*pc_ == kCallOpcode) { |
| 63 int32_t* p = reinterpret_cast<int32_t*>(pc_ + 1); | 64 int32_t* p = reinterpret_cast<int32_t*>(pc_ + 1); |
| 64 *p -= delta; // Relocate entry. | 65 *p -= delta; // Relocate entry. |
| 65 CPU::FlushICache(p, sizeof(uint32_t)); | 66 if (flush_icache) CPU::FlushICache(p, sizeof(uint32_t)); |
| 66 } | 67 } |
| 67 } else if (rmode_ == JS_RETURN && IsPatchedReturnSequence()) { | 68 } else if (rmode_ == JS_RETURN && IsPatchedReturnSequence()) { |
| 68 // Special handling of js_return when a break point is set (call | 69 // Special handling of js_return when a break point is set (call |
| 69 // instruction has been inserted). | 70 // instruction has been inserted). |
| 70 int32_t* p = reinterpret_cast<int32_t*>(pc_ + 1); | 71 int32_t* p = reinterpret_cast<int32_t*>(pc_ + 1); |
| 71 *p -= delta; // Relocate entry. | 72 *p -= delta; // Relocate entry. |
| 72 CPU::FlushICache(p, sizeof(uint32_t)); | 73 if (flush_icache) CPU::FlushICache(p, sizeof(uint32_t)); |
| 73 } else if (rmode_ == DEBUG_BREAK_SLOT && IsPatchedDebugBreakSlotSequence()) { | 74 } else if (rmode_ == DEBUG_BREAK_SLOT && IsPatchedDebugBreakSlotSequence()) { |
| 74 // Special handling of a debug break slot when a break point is set (call | 75 // Special handling of a debug break slot when a break point is set (call |
| 75 // instruction has been inserted). | 76 // instruction has been inserted). |
| 76 int32_t* p = reinterpret_cast<int32_t*>(pc_ + 1); | 77 int32_t* p = reinterpret_cast<int32_t*>(pc_ + 1); |
| 77 *p -= delta; // Relocate entry. | 78 *p -= delta; // Relocate entry. |
| 78 CPU::FlushICache(p, sizeof(uint32_t)); | 79 if (flush_icache) CPU::FlushICache(p, sizeof(uint32_t)); |
| 79 } else if (IsInternalReference(rmode_)) { | 80 } else if (IsInternalReference(rmode_)) { |
| 80 // absolute code pointer inside code object moves with the code object. | 81 // absolute code pointer inside code object moves with the code object. |
| 81 int32_t* p = reinterpret_cast<int32_t*>(pc_); | 82 int32_t* p = reinterpret_cast<int32_t*>(pc_); |
| 82 *p += delta; // Relocate entry. | 83 *p += delta; // Relocate entry. |
| 83 CPU::FlushICache(p, sizeof(uint32_t)); | 84 if (flush_icache) CPU::FlushICache(p, sizeof(uint32_t)); |
| 84 } | 85 } |
| 85 } | 86 } |
| 86 | 87 |
| 87 | 88 |
| 88 Address RelocInfo::target_address() { | 89 Address RelocInfo::target_address() { |
| 89 ASSERT(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)); | 90 ASSERT(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)); |
| 90 return Assembler::target_address_at(pc_, host_); | 91 return Assembler::target_address_at(pc_, host_); |
| 91 } | 92 } |
| 92 | 93 |
| 93 | 94 |
| 94 Address RelocInfo::target_address_address() { | 95 Address RelocInfo::target_address_address() { |
| 95 ASSERT(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_) | 96 ASSERT(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_) |
| 96 || rmode_ == EMBEDDED_OBJECT | 97 || rmode_ == EMBEDDED_OBJECT |
| 97 || rmode_ == EXTERNAL_REFERENCE); | 98 || rmode_ == EXTERNAL_REFERENCE); |
| 98 return reinterpret_cast<Address>(pc_); | 99 return reinterpret_cast<Address>(pc_); |
| 99 } | 100 } |
| 100 | 101 |
| 101 | 102 |
| 102 Address RelocInfo::constant_pool_entry_address() { | 103 Address RelocInfo::constant_pool_entry_address() { |
| 103 UNREACHABLE(); | 104 UNREACHABLE(); |
| 104 return NULL; | 105 return NULL; |
| 105 } | 106 } |
| 106 | 107 |
| 107 | 108 |
| 108 int RelocInfo::target_address_size() { | 109 int RelocInfo::target_address_size() { |
| 109 return Assembler::kSpecialTargetSize; | 110 return Assembler::kSpecialTargetSize; |
| 110 } | 111 } |
| 111 | 112 |
| 112 | 113 |
| 113 void RelocInfo::set_target_address(Address target, WriteBarrierMode mode) { | 114 void RelocInfo::set_target_address(Address target, |
| 114 Assembler::set_target_address_at(pc_, host_, target); | 115 WriteBarrierMode write_barrier_mode, |
| 116 ICacheFlushMode icache_flush_mode) { |
| 117 Assembler::set_target_address_at(pc_, host_, target, icache_flush_mode); |
| 115 ASSERT(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)); | 118 ASSERT(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)); |
| 116 if (mode == UPDATE_WRITE_BARRIER && host() != NULL && IsCodeTarget(rmode_)) { | 119 if (write_barrier_mode == UPDATE_WRITE_BARRIER && host() != NULL && |
| 120 IsCodeTarget(rmode_)) { |
| 117 Object* target_code = Code::GetCodeFromTargetAddress(target); | 121 Object* target_code = Code::GetCodeFromTargetAddress(target); |
| 118 host()->GetHeap()->incremental_marking()->RecordWriteIntoCode( | 122 host()->GetHeap()->incremental_marking()->RecordWriteIntoCode( |
| 119 host(), this, HeapObject::cast(target_code)); | 123 host(), this, HeapObject::cast(target_code)); |
| 120 } | 124 } |
| 121 } | 125 } |
| 122 | 126 |
| 123 | 127 |
| 124 Object* RelocInfo::target_object() { | 128 Object* RelocInfo::target_object() { |
| 125 ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); | 129 ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); |
| 126 return Memory::Object_at(pc_); | 130 return Memory::Object_at(pc_); |
| 127 } | 131 } |
| 128 | 132 |
| 129 | 133 |
| 130 Handle<Object> RelocInfo::target_object_handle(Assembler* origin) { | 134 Handle<Object> RelocInfo::target_object_handle(Assembler* origin) { |
| 131 ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); | 135 ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); |
| 132 return Memory::Object_Handle_at(pc_); | 136 return Memory::Object_Handle_at(pc_); |
| 133 } | 137 } |
| 134 | 138 |
| 135 | 139 |
| 136 void RelocInfo::set_target_object(Object* target, WriteBarrierMode mode) { | 140 void RelocInfo::set_target_object(Object* target, |
| 141 WriteBarrierMode write_barrier_mode, |
| 142 ICacheFlushMode icache_flush_mode) { |
| 137 ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); | 143 ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); |
| 138 ASSERT(!target->IsConsString()); | 144 ASSERT(!target->IsConsString()); |
| 139 Memory::Object_at(pc_) = target; | 145 Memory::Object_at(pc_) = target; |
| 140 CPU::FlushICache(pc_, sizeof(Address)); | 146 if (icache_flush_mode != SKIP_ICACHE_FLUSH) { |
| 141 if (mode == UPDATE_WRITE_BARRIER && | 147 CPU::FlushICache(pc_, sizeof(Address)); |
| 148 } |
| 149 if (write_barrier_mode == UPDATE_WRITE_BARRIER && |
| 142 host() != NULL && | 150 host() != NULL && |
| 143 target->IsHeapObject()) { | 151 target->IsHeapObject()) { |
| 144 host()->GetHeap()->incremental_marking()->RecordWrite( | 152 host()->GetHeap()->incremental_marking()->RecordWrite( |
| 145 host(), &Memory::Object_at(pc_), HeapObject::cast(target)); | 153 host(), &Memory::Object_at(pc_), HeapObject::cast(target)); |
| 146 } | 154 } |
| 147 } | 155 } |
| 148 | 156 |
| 149 | 157 |
| 150 Address RelocInfo::target_reference() { | 158 Address RelocInfo::target_reference() { |
| 151 ASSERT(rmode_ == RelocInfo::EXTERNAL_REFERENCE); | 159 ASSERT(rmode_ == RelocInfo::EXTERNAL_REFERENCE); |
| 152 return Memory::Address_at(pc_); | 160 return Memory::Address_at(pc_); |
| 153 } | 161 } |
| 154 | 162 |
| 155 | 163 |
| 156 Address RelocInfo::target_runtime_entry(Assembler* origin) { | 164 Address RelocInfo::target_runtime_entry(Assembler* origin) { |
| 157 ASSERT(IsRuntimeEntry(rmode_)); | 165 ASSERT(IsRuntimeEntry(rmode_)); |
| 158 return reinterpret_cast<Address>(*reinterpret_cast<int32_t*>(pc_)); | 166 return reinterpret_cast<Address>(*reinterpret_cast<int32_t*>(pc_)); |
| 159 } | 167 } |
| 160 | 168 |
| 161 | 169 |
| 162 void RelocInfo::set_target_runtime_entry(Address target, | 170 void RelocInfo::set_target_runtime_entry(Address target, |
| 163 WriteBarrierMode mode) { | 171 WriteBarrierMode write_barrier_mode, |
| 172 ICacheFlushMode icache_flush_mode) { |
| 164 ASSERT(IsRuntimeEntry(rmode_)); | 173 ASSERT(IsRuntimeEntry(rmode_)); |
| 165 if (target_address() != target) set_target_address(target, mode); | 174 if (target_address() != target) { |
| 175 set_target_address(target, write_barrier_mode, icache_flush_mode); |
| 176 } |
| 166 } | 177 } |
| 167 | 178 |
| 168 | 179 |
| 169 Handle<Cell> RelocInfo::target_cell_handle() { | 180 Handle<Cell> RelocInfo::target_cell_handle() { |
| 170 ASSERT(rmode_ == RelocInfo::CELL); | 181 ASSERT(rmode_ == RelocInfo::CELL); |
| 171 Address address = Memory::Address_at(pc_); | 182 Address address = Memory::Address_at(pc_); |
| 172 return Handle<Cell>(reinterpret_cast<Cell**>(address)); | 183 return Handle<Cell>(reinterpret_cast<Cell**>(address)); |
| 173 } | 184 } |
| 174 | 185 |
| 175 | 186 |
| 176 Cell* RelocInfo::target_cell() { | 187 Cell* RelocInfo::target_cell() { |
| 177 ASSERT(rmode_ == RelocInfo::CELL); | 188 ASSERT(rmode_ == RelocInfo::CELL); |
| 178 return Cell::FromValueAddress(Memory::Address_at(pc_)); | 189 return Cell::FromValueAddress(Memory::Address_at(pc_)); |
| 179 } | 190 } |
| 180 | 191 |
| 181 | 192 |
| 182 void RelocInfo::set_target_cell(Cell* cell, WriteBarrierMode mode) { | 193 void RelocInfo::set_target_cell(Cell* cell, |
| 194 WriteBarrierMode write_barrier_mode, |
| 195 ICacheFlushMode icache_flush_mode) { |
| 183 ASSERT(rmode_ == RelocInfo::CELL); | 196 ASSERT(rmode_ == RelocInfo::CELL); |
| 184 Address address = cell->address() + Cell::kValueOffset; | 197 Address address = cell->address() + Cell::kValueOffset; |
| 185 Memory::Address_at(pc_) = address; | 198 Memory::Address_at(pc_) = address; |
| 186 CPU::FlushICache(pc_, sizeof(Address)); | 199 if (icache_flush_mode != SKIP_ICACHE_FLUSH) { |
| 187 if (mode == UPDATE_WRITE_BARRIER && host() != NULL) { | 200 CPU::FlushICache(pc_, sizeof(Address)); |
| 201 } |
| 202 if (write_barrier_mode == UPDATE_WRITE_BARRIER && host() != NULL) { |
| 188 // TODO(1550) We are passing NULL as a slot because cell can never be on | 203 // TODO(1550) We are passing NULL as a slot because cell can never be on |
| 189 // evacuation candidate. | 204 // evacuation candidate. |
| 190 host()->GetHeap()->incremental_marking()->RecordWrite( | 205 host()->GetHeap()->incremental_marking()->RecordWrite( |
| 191 host(), NULL, cell); | 206 host(), NULL, cell); |
| 192 } | 207 } |
| 193 } | 208 } |
| 194 | 209 |
| 195 | 210 |
| 196 Handle<Object> RelocInfo::code_age_stub_handle(Assembler* origin) { | 211 Handle<Object> RelocInfo::code_age_stub_handle(Assembler* origin) { |
| 197 ASSERT(rmode_ == RelocInfo::CODE_AGE_SEQUENCE); | 212 ASSERT(rmode_ == RelocInfo::CODE_AGE_SEQUENCE); |
| 198 ASSERT(*pc_ == kCallOpcode); | 213 ASSERT(*pc_ == kCallOpcode); |
| 199 return Memory::Object_Handle_at(pc_ + 1); | 214 return Memory::Object_Handle_at(pc_ + 1); |
| 200 } | 215 } |
| 201 | 216 |
| 202 | 217 |
| 203 Code* RelocInfo::code_age_stub() { | 218 Code* RelocInfo::code_age_stub() { |
| 204 ASSERT(rmode_ == RelocInfo::CODE_AGE_SEQUENCE); | 219 ASSERT(rmode_ == RelocInfo::CODE_AGE_SEQUENCE); |
| 205 ASSERT(*pc_ == kCallOpcode); | 220 ASSERT(*pc_ == kCallOpcode); |
| 206 return Code::GetCodeFromTargetAddress( | 221 return Code::GetCodeFromTargetAddress( |
| 207 Assembler::target_address_at(pc_ + 1, host_)); | 222 Assembler::target_address_at(pc_ + 1, host_)); |
| 208 } | 223 } |
| 209 | 224 |
| 210 | 225 |
| 211 void RelocInfo::set_code_age_stub(Code* stub) { | 226 void RelocInfo::set_code_age_stub(Code* stub, |
| 227 ICacheFlushMode icache_flush_mode) { |
| 212 ASSERT(*pc_ == kCallOpcode); | 228 ASSERT(*pc_ == kCallOpcode); |
| 213 ASSERT(rmode_ == RelocInfo::CODE_AGE_SEQUENCE); | 229 ASSERT(rmode_ == RelocInfo::CODE_AGE_SEQUENCE); |
| 214 Assembler::set_target_address_at(pc_ + 1, host_, stub->instruction_start()); | 230 Assembler::set_target_address_at(pc_ + 1, host_, stub->instruction_start(), |
| 231 icache_flush_mode); |
| 215 } | 232 } |
| 216 | 233 |
| 217 | 234 |
| 218 Address RelocInfo::call_address() { | 235 Address RelocInfo::call_address() { |
| 219 ASSERT((IsJSReturn(rmode()) && IsPatchedReturnSequence()) || | 236 ASSERT((IsJSReturn(rmode()) && IsPatchedReturnSequence()) || |
| 220 (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence())); | 237 (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence())); |
| 221 return Assembler::target_address_at(pc_ + 1, host_); | 238 return Assembler::target_address_at(pc_ + 1, host_); |
| 222 } | 239 } |
| 223 | 240 |
| 224 | 241 |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 444 | 461 |
| 445 | 462 |
| 446 Address Assembler::target_address_at(Address pc, | 463 Address Assembler::target_address_at(Address pc, |
| 447 ConstantPoolArray* constant_pool) { | 464 ConstantPoolArray* constant_pool) { |
| 448 return pc + sizeof(int32_t) + *reinterpret_cast<int32_t*>(pc); | 465 return pc + sizeof(int32_t) + *reinterpret_cast<int32_t*>(pc); |
| 449 } | 466 } |
| 450 | 467 |
| 451 | 468 |
| 452 void Assembler::set_target_address_at(Address pc, | 469 void Assembler::set_target_address_at(Address pc, |
| 453 ConstantPoolArray* constant_pool, | 470 ConstantPoolArray* constant_pool, |
| 454 Address target) { | 471 Address target, |
| 472 ICacheFlushMode icache_flush_mode) { |
| 455 int32_t* p = reinterpret_cast<int32_t*>(pc); | 473 int32_t* p = reinterpret_cast<int32_t*>(pc); |
| 456 *p = target - (pc + sizeof(int32_t)); | 474 *p = target - (pc + sizeof(int32_t)); |
| 457 CPU::FlushICache(p, sizeof(int32_t)); | 475 if (icache_flush_mode != SKIP_ICACHE_FLUSH) { |
| 476 CPU::FlushICache(p, sizeof(int32_t)); |
| 477 } |
| 458 } | 478 } |
| 459 | 479 |
| 460 | 480 |
| 461 Address Assembler::target_address_from_return_address(Address pc) { | 481 Address Assembler::target_address_from_return_address(Address pc) { |
| 462 return pc - kCallTargetAddressOffset; | 482 return pc - kCallTargetAddressOffset; |
| 463 } | 483 } |
| 464 | 484 |
| 465 | 485 |
| 466 Displacement Assembler::disp_at(Label* L) { | 486 Displacement Assembler::disp_at(Label* L) { |
| 467 return Displacement(long_at(L->pos())); | 487 return Displacement(long_at(L->pos())); |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 537 | 557 |
| 538 Operand::Operand(int32_t disp, RelocInfo::Mode rmode) { | 558 Operand::Operand(int32_t disp, RelocInfo::Mode rmode) { |
| 539 // [disp/r] | 559 // [disp/r] |
| 540 set_modrm(0, ebp); | 560 set_modrm(0, ebp); |
| 541 set_dispr(disp, rmode); | 561 set_dispr(disp, rmode); |
| 542 } | 562 } |
| 543 | 563 |
| 544 } } // namespace v8::internal | 564 } } // namespace v8::internal |
| 545 | 565 |
| 546 #endif // V8_IA32_ASSEMBLER_IA32_INL_H_ | 566 #endif // V8_IA32_ASSEMBLER_IA32_INL_H_ |
| OLD | NEW |