| 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 21 matching lines...) Expand all Loading... |
| 32 // modified significantly by Google Inc. | 32 // modified significantly by Google Inc. |
| 33 // Copyright 2012 the V8 project authors. All rights reserved. | 33 // Copyright 2012 the V8 project authors. All rights reserved. |
| 34 | 34 |
| 35 // A light-weight IA32 Assembler. | 35 // A light-weight IA32 Assembler. |
| 36 | 36 |
| 37 #ifndef V8_IA32_ASSEMBLER_IA32_INL_H_ | 37 #ifndef V8_IA32_ASSEMBLER_IA32_INL_H_ |
| 38 #define V8_IA32_ASSEMBLER_IA32_INL_H_ | 38 #define V8_IA32_ASSEMBLER_IA32_INL_H_ |
| 39 | 39 |
| 40 #include "src/ia32/assembler-ia32.h" | 40 #include "src/ia32/assembler-ia32.h" |
| 41 | 41 |
| 42 #include "src/cpu.h" | 42 #include "src/assembler.h" |
| 43 #include "src/debug.h" | 43 #include "src/debug.h" |
| 44 | 44 |
| 45 namespace v8 { | 45 namespace v8 { |
| 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, ICacheFlushMode icache_flush_mode) { | 56 void RelocInfo::apply(intptr_t delta, ICacheFlushMode icache_flush_mode) { |
| 57 bool flush_icache = icache_flush_mode != SKIP_ICACHE_FLUSH; | 57 bool flush_icache = icache_flush_mode != SKIP_ICACHE_FLUSH; |
| 58 if (IsRuntimeEntry(rmode_) || IsCodeTarget(rmode_)) { | 58 if (IsRuntimeEntry(rmode_) || IsCodeTarget(rmode_)) { |
| 59 int32_t* p = reinterpret_cast<int32_t*>(pc_); | 59 int32_t* p = reinterpret_cast<int32_t*>(pc_); |
| 60 *p -= delta; // Relocate entry. | 60 *p -= delta; // Relocate entry. |
| 61 if (flush_icache) CPU::FlushICache(p, sizeof(uint32_t)); | 61 if (flush_icache) CpuFeatures::FlushICache(p, sizeof(uint32_t)); |
| 62 } else if (rmode_ == CODE_AGE_SEQUENCE) { | 62 } else if (rmode_ == CODE_AGE_SEQUENCE) { |
| 63 if (*pc_ == kCallOpcode) { | 63 if (*pc_ == kCallOpcode) { |
| 64 int32_t* p = reinterpret_cast<int32_t*>(pc_ + 1); | 64 int32_t* p = reinterpret_cast<int32_t*>(pc_ + 1); |
| 65 *p -= delta; // Relocate entry. | 65 *p -= delta; // Relocate entry. |
| 66 if (flush_icache) CPU::FlushICache(p, sizeof(uint32_t)); | 66 if (flush_icache) CpuFeatures::FlushICache(p, sizeof(uint32_t)); |
| 67 } | 67 } |
| 68 } else if (rmode_ == JS_RETURN && IsPatchedReturnSequence()) { | 68 } else if (rmode_ == JS_RETURN && IsPatchedReturnSequence()) { |
| 69 // 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 |
| 70 // instruction has been inserted). | 70 // instruction has been inserted). |
| 71 int32_t* p = reinterpret_cast<int32_t*>(pc_ + 1); | 71 int32_t* p = reinterpret_cast<int32_t*>(pc_ + 1); |
| 72 *p -= delta; // Relocate entry. | 72 *p -= delta; // Relocate entry. |
| 73 if (flush_icache) CPU::FlushICache(p, sizeof(uint32_t)); | 73 if (flush_icache) CpuFeatures::FlushICache(p, sizeof(uint32_t)); |
| 74 } else if (rmode_ == DEBUG_BREAK_SLOT && IsPatchedDebugBreakSlotSequence()) { | 74 } else if (rmode_ == DEBUG_BREAK_SLOT && IsPatchedDebugBreakSlotSequence()) { |
| 75 // 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 |
| 76 // instruction has been inserted). | 76 // instruction has been inserted). |
| 77 int32_t* p = reinterpret_cast<int32_t*>(pc_ + 1); | 77 int32_t* p = reinterpret_cast<int32_t*>(pc_ + 1); |
| 78 *p -= delta; // Relocate entry. | 78 *p -= delta; // Relocate entry. |
| 79 if (flush_icache) CPU::FlushICache(p, sizeof(uint32_t)); | 79 if (flush_icache) CpuFeatures::FlushICache(p, sizeof(uint32_t)); |
| 80 } else if (IsInternalReference(rmode_)) { | 80 } else if (IsInternalReference(rmode_)) { |
| 81 // absolute code pointer inside code object moves with the code object. | 81 // absolute code pointer inside code object moves with the code object. |
| 82 int32_t* p = reinterpret_cast<int32_t*>(pc_); | 82 int32_t* p = reinterpret_cast<int32_t*>(pc_); |
| 83 *p += delta; // Relocate entry. | 83 *p += delta; // Relocate entry. |
| 84 if (flush_icache) CPU::FlushICache(p, sizeof(uint32_t)); | 84 if (flush_icache) CpuFeatures::FlushICache(p, sizeof(uint32_t)); |
| 85 } | 85 } |
| 86 } | 86 } |
| 87 | 87 |
| 88 | 88 |
| 89 Address RelocInfo::target_address() { | 89 Address RelocInfo::target_address() { |
| 90 ASSERT(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)); | 90 ASSERT(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)); |
| 91 return Assembler::target_address_at(pc_, host_); | 91 return Assembler::target_address_at(pc_, host_); |
| 92 } | 92 } |
| 93 | 93 |
| 94 | 94 |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 137 } | 137 } |
| 138 | 138 |
| 139 | 139 |
| 140 void RelocInfo::set_target_object(Object* target, | 140 void RelocInfo::set_target_object(Object* target, |
| 141 WriteBarrierMode write_barrier_mode, | 141 WriteBarrierMode write_barrier_mode, |
| 142 ICacheFlushMode icache_flush_mode) { | 142 ICacheFlushMode icache_flush_mode) { |
| 143 ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); | 143 ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); |
| 144 ASSERT(!target->IsConsString()); | 144 ASSERT(!target->IsConsString()); |
| 145 Memory::Object_at(pc_) = target; | 145 Memory::Object_at(pc_) = target; |
| 146 if (icache_flush_mode != SKIP_ICACHE_FLUSH) { | 146 if (icache_flush_mode != SKIP_ICACHE_FLUSH) { |
| 147 CPU::FlushICache(pc_, sizeof(Address)); | 147 CpuFeatures::FlushICache(pc_, sizeof(Address)); |
| 148 } | 148 } |
| 149 if (write_barrier_mode == UPDATE_WRITE_BARRIER && | 149 if (write_barrier_mode == UPDATE_WRITE_BARRIER && |
| 150 host() != NULL && | 150 host() != NULL && |
| 151 target->IsHeapObject()) { | 151 target->IsHeapObject()) { |
| 152 host()->GetHeap()->incremental_marking()->RecordWrite( | 152 host()->GetHeap()->incremental_marking()->RecordWrite( |
| 153 host(), &Memory::Object_at(pc_), HeapObject::cast(target)); | 153 host(), &Memory::Object_at(pc_), HeapObject::cast(target)); |
| 154 } | 154 } |
| 155 } | 155 } |
| 156 | 156 |
| 157 | 157 |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 190 } | 190 } |
| 191 | 191 |
| 192 | 192 |
| 193 void RelocInfo::set_target_cell(Cell* cell, | 193 void RelocInfo::set_target_cell(Cell* cell, |
| 194 WriteBarrierMode write_barrier_mode, | 194 WriteBarrierMode write_barrier_mode, |
| 195 ICacheFlushMode icache_flush_mode) { | 195 ICacheFlushMode icache_flush_mode) { |
| 196 ASSERT(rmode_ == RelocInfo::CELL); | 196 ASSERT(rmode_ == RelocInfo::CELL); |
| 197 Address address = cell->address() + Cell::kValueOffset; | 197 Address address = cell->address() + Cell::kValueOffset; |
| 198 Memory::Address_at(pc_) = address; | 198 Memory::Address_at(pc_) = address; |
| 199 if (icache_flush_mode != SKIP_ICACHE_FLUSH) { | 199 if (icache_flush_mode != SKIP_ICACHE_FLUSH) { |
| 200 CPU::FlushICache(pc_, sizeof(Address)); | 200 CpuFeatures::FlushICache(pc_, sizeof(Address)); |
| 201 } | 201 } |
| 202 if (write_barrier_mode == UPDATE_WRITE_BARRIER && host() != NULL) { | 202 if (write_barrier_mode == UPDATE_WRITE_BARRIER && host() != NULL) { |
| 203 // 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 |
| 204 // evacuation candidate. | 204 // evacuation candidate. |
| 205 host()->GetHeap()->incremental_marking()->RecordWrite( | 205 host()->GetHeap()->incremental_marking()->RecordWrite( |
| 206 host(), NULL, cell); | 206 host(), NULL, cell); |
| 207 } | 207 } |
| 208 } | 208 } |
| 209 | 209 |
| 210 | 210 |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 287 | 287 |
| 288 bool RelocInfo::IsPatchedDebugBreakSlotSequence() { | 288 bool RelocInfo::IsPatchedDebugBreakSlotSequence() { |
| 289 return !Assembler::IsNop(pc()); | 289 return !Assembler::IsNop(pc()); |
| 290 } | 290 } |
| 291 | 291 |
| 292 | 292 |
| 293 void RelocInfo::Visit(Isolate* isolate, ObjectVisitor* visitor) { | 293 void RelocInfo::Visit(Isolate* isolate, ObjectVisitor* visitor) { |
| 294 RelocInfo::Mode mode = rmode(); | 294 RelocInfo::Mode mode = rmode(); |
| 295 if (mode == RelocInfo::EMBEDDED_OBJECT) { | 295 if (mode == RelocInfo::EMBEDDED_OBJECT) { |
| 296 visitor->VisitEmbeddedPointer(this); | 296 visitor->VisitEmbeddedPointer(this); |
| 297 CPU::FlushICache(pc_, sizeof(Address)); | 297 CpuFeatures::FlushICache(pc_, sizeof(Address)); |
| 298 } else if (RelocInfo::IsCodeTarget(mode)) { | 298 } else if (RelocInfo::IsCodeTarget(mode)) { |
| 299 visitor->VisitCodeTarget(this); | 299 visitor->VisitCodeTarget(this); |
| 300 } else if (mode == RelocInfo::CELL) { | 300 } else if (mode == RelocInfo::CELL) { |
| 301 visitor->VisitCell(this); | 301 visitor->VisitCell(this); |
| 302 } else if (mode == RelocInfo::EXTERNAL_REFERENCE) { | 302 } else if (mode == RelocInfo::EXTERNAL_REFERENCE) { |
| 303 visitor->VisitExternalReference(this); | 303 visitor->VisitExternalReference(this); |
| 304 CPU::FlushICache(pc_, sizeof(Address)); | 304 CpuFeatures::FlushICache(pc_, sizeof(Address)); |
| 305 } else if (RelocInfo::IsCodeAgeSequence(mode)) { | 305 } else if (RelocInfo::IsCodeAgeSequence(mode)) { |
| 306 visitor->VisitCodeAgeSequence(this); | 306 visitor->VisitCodeAgeSequence(this); |
| 307 } else if (((RelocInfo::IsJSReturn(mode) && | 307 } else if (((RelocInfo::IsJSReturn(mode) && |
| 308 IsPatchedReturnSequence()) || | 308 IsPatchedReturnSequence()) || |
| 309 (RelocInfo::IsDebugBreakSlot(mode) && | 309 (RelocInfo::IsDebugBreakSlot(mode) && |
| 310 IsPatchedDebugBreakSlotSequence())) && | 310 IsPatchedDebugBreakSlotSequence())) && |
| 311 isolate->debug()->has_break_points()) { | 311 isolate->debug()->has_break_points()) { |
| 312 visitor->VisitDebugTarget(this); | 312 visitor->VisitDebugTarget(this); |
| 313 } else if (IsRuntimeEntry(mode)) { | 313 } else if (IsRuntimeEntry(mode)) { |
| 314 visitor->VisitRuntimeEntry(this); | 314 visitor->VisitRuntimeEntry(this); |
| 315 } | 315 } |
| 316 } | 316 } |
| 317 | 317 |
| 318 | 318 |
| 319 template<typename StaticVisitor> | 319 template<typename StaticVisitor> |
| 320 void RelocInfo::Visit(Heap* heap) { | 320 void RelocInfo::Visit(Heap* heap) { |
| 321 RelocInfo::Mode mode = rmode(); | 321 RelocInfo::Mode mode = rmode(); |
| 322 if (mode == RelocInfo::EMBEDDED_OBJECT) { | 322 if (mode == RelocInfo::EMBEDDED_OBJECT) { |
| 323 StaticVisitor::VisitEmbeddedPointer(heap, this); | 323 StaticVisitor::VisitEmbeddedPointer(heap, this); |
| 324 CPU::FlushICache(pc_, sizeof(Address)); | 324 CpuFeatures::FlushICache(pc_, sizeof(Address)); |
| 325 } else if (RelocInfo::IsCodeTarget(mode)) { | 325 } else if (RelocInfo::IsCodeTarget(mode)) { |
| 326 StaticVisitor::VisitCodeTarget(heap, this); | 326 StaticVisitor::VisitCodeTarget(heap, this); |
| 327 } else if (mode == RelocInfo::CELL) { | 327 } else if (mode == RelocInfo::CELL) { |
| 328 StaticVisitor::VisitCell(heap, this); | 328 StaticVisitor::VisitCell(heap, this); |
| 329 } else if (mode == RelocInfo::EXTERNAL_REFERENCE) { | 329 } else if (mode == RelocInfo::EXTERNAL_REFERENCE) { |
| 330 StaticVisitor::VisitExternalReference(this); | 330 StaticVisitor::VisitExternalReference(this); |
| 331 CPU::FlushICache(pc_, sizeof(Address)); | 331 CpuFeatures::FlushICache(pc_, sizeof(Address)); |
| 332 } else if (RelocInfo::IsCodeAgeSequence(mode)) { | 332 } else if (RelocInfo::IsCodeAgeSequence(mode)) { |
| 333 StaticVisitor::VisitCodeAgeSequence(heap, this); | 333 StaticVisitor::VisitCodeAgeSequence(heap, this); |
| 334 } else if (heap->isolate()->debug()->has_break_points() && | 334 } else if (heap->isolate()->debug()->has_break_points() && |
| 335 ((RelocInfo::IsJSReturn(mode) && | 335 ((RelocInfo::IsJSReturn(mode) && |
| 336 IsPatchedReturnSequence()) || | 336 IsPatchedReturnSequence()) || |
| 337 (RelocInfo::IsDebugBreakSlot(mode) && | 337 (RelocInfo::IsDebugBreakSlot(mode) && |
| 338 IsPatchedDebugBreakSlotSequence()))) { | 338 IsPatchedDebugBreakSlotSequence()))) { |
| 339 StaticVisitor::VisitDebugTarget(heap, this); | 339 StaticVisitor::VisitDebugTarget(heap, this); |
| 340 } else if (IsRuntimeEntry(mode)) { | 340 } else if (IsRuntimeEntry(mode)) { |
| 341 StaticVisitor::VisitRuntimeEntry(this); | 341 StaticVisitor::VisitRuntimeEntry(this); |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 466 } | 466 } |
| 467 | 467 |
| 468 | 468 |
| 469 void Assembler::set_target_address_at(Address pc, | 469 void Assembler::set_target_address_at(Address pc, |
| 470 ConstantPoolArray* constant_pool, | 470 ConstantPoolArray* constant_pool, |
| 471 Address target, | 471 Address target, |
| 472 ICacheFlushMode icache_flush_mode) { | 472 ICacheFlushMode icache_flush_mode) { |
| 473 int32_t* p = reinterpret_cast<int32_t*>(pc); | 473 int32_t* p = reinterpret_cast<int32_t*>(pc); |
| 474 *p = target - (pc + sizeof(int32_t)); | 474 *p = target - (pc + sizeof(int32_t)); |
| 475 if (icache_flush_mode != SKIP_ICACHE_FLUSH) { | 475 if (icache_flush_mode != SKIP_ICACHE_FLUSH) { |
| 476 CPU::FlushICache(p, sizeof(int32_t)); | 476 CpuFeatures::FlushICache(p, sizeof(int32_t)); |
| 477 } | 477 } |
| 478 } | 478 } |
| 479 | 479 |
| 480 | 480 |
| 481 Address Assembler::target_address_from_return_address(Address pc) { | 481 Address Assembler::target_address_from_return_address(Address pc) { |
| 482 return pc - kCallTargetAddressOffset; | 482 return pc - kCallTargetAddressOffset; |
| 483 } | 483 } |
| 484 | 484 |
| 485 | 485 |
| 486 Displacement Assembler::disp_at(Label* L) { | 486 Displacement Assembler::disp_at(Label* L) { |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 557 | 557 |
| 558 Operand::Operand(int32_t disp, RelocInfo::Mode rmode) { | 558 Operand::Operand(int32_t disp, RelocInfo::Mode rmode) { |
| 559 // [disp/r] | 559 // [disp/r] |
| 560 set_modrm(0, ebp); | 560 set_modrm(0, ebp); |
| 561 set_dispr(disp, rmode); | 561 set_dispr(disp, rmode); |
| 562 } | 562 } |
| 563 | 563 |
| 564 } } // namespace v8::internal | 564 } } // namespace v8::internal |
| 565 | 565 |
| 566 #endif // V8_IA32_ASSEMBLER_IA32_INL_H_ | 566 #endif // V8_IA32_ASSEMBLER_IA32_INL_H_ |
| OLD | NEW |