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 |