Line data Source code
1 : // Copyright 2012 the V8 project authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #ifndef V8_X64_ASSEMBLER_X64_INL_H_
6 : #define V8_X64_ASSEMBLER_X64_INL_H_
7 :
8 : #include "src/x64/assembler-x64.h"
9 :
10 : #include "src/base/cpu.h"
11 : #include "src/debug/debug.h"
12 : #include "src/objects-inl.h"
13 : #include "src/v8memory.h"
14 :
15 : namespace v8 {
16 : namespace internal {
17 :
18 : bool CpuFeatures::SupportsCrankshaft() { return true; }
19 :
20 : bool CpuFeatures::SupportsWasmSimd128() { return IsSupported(SSE4_1); }
21 :
22 : // -----------------------------------------------------------------------------
23 : // Implementation of Assembler
24 :
25 :
26 : static const byte kCallOpcode = 0xE8;
27 :
28 :
29 : void Assembler::emitl(uint32_t x) {
30 84929151 : Memory::uint32_at(pc_) = x;
31 84929151 : pc_ += sizeof(uint32_t);
32 : }
33 :
34 :
35 37378780 : void Assembler::emitp(void* x, RelocInfo::Mode rmode) {
36 37378780 : uintptr_t value = reinterpret_cast<uintptr_t>(x);
37 37378780 : Memory::uintptr_at(pc_) = value;
38 37378780 : if (!RelocInfo::IsNone(rmode)) {
39 21872279 : RecordRelocInfo(rmode, value);
40 : }
41 37378771 : pc_ += sizeof(uintptr_t);
42 37378771 : }
43 :
44 :
45 : void Assembler::emitq(uint64_t x) {
46 789158 : Memory::uint64_at(pc_) = x;
47 789158 : pc_ += sizeof(uint64_t);
48 : }
49 :
50 :
51 : void Assembler::emitw(uint16_t x) {
52 138507 : Memory::uint16_at(pc_) = x;
53 138507 : pc_ += sizeof(uint16_t);
54 : }
55 :
56 :
57 17880250 : void Assembler::emit_code_target(Handle<Code> target,
58 : RelocInfo::Mode rmode,
59 : TypeFeedbackId ast_id) {
60 : DCHECK(RelocInfo::IsCodeTarget(rmode) ||
61 : rmode == RelocInfo::CODE_AGE_SEQUENCE);
62 17880250 : if (rmode == RelocInfo::CODE_TARGET && !ast_id.IsNone()) {
63 1530903 : RecordRelocInfo(RelocInfo::CODE_TARGET_WITH_ID, ast_id.ToInt());
64 : } else {
65 16349347 : RecordRelocInfo(rmode);
66 : }
67 17880264 : int current = code_targets_.length();
68 33608680 : if (current > 0 && code_targets_.last().address() == target.address()) {
69 : // Optimization if we keep jumping to the same code target.
70 1503582 : emitl(current - 1);
71 : } else {
72 16376682 : code_targets_.Add(target);
73 16376682 : emitl(current);
74 : }
75 17880264 : }
76 :
77 :
78 : void Assembler::emit_runtime_entry(Address entry, RelocInfo::Mode rmode) {
79 : DCHECK(RelocInfo::IsRuntimeEntry(rmode));
80 889889 : RecordRelocInfo(rmode);
81 1779778 : emitl(static_cast<uint32_t>(entry - isolate_data().code_range_start_));
82 : }
83 :
84 12080008 : void Assembler::emit(Immediate x) {
85 12080008 : if (!RelocInfo::IsNone(x.rmode_)) {
86 246868 : RecordRelocInfo(x.rmode_);
87 : }
88 12080008 : emitl(x.value_);
89 12080008 : }
90 :
91 : void Assembler::emit_rex_64(Register reg, Register rm_reg) {
92 45653128 : emit(0x48 | reg.high_bit() << 2 | rm_reg.high_bit());
93 : }
94 :
95 :
96 : void Assembler::emit_rex_64(XMMRegister reg, Register rm_reg) {
97 396 : emit(0x48 | (reg.code() & 0x8) >> 1 | rm_reg.code() >> 3);
98 : }
99 :
100 :
101 : void Assembler::emit_rex_64(Register reg, XMMRegister rm_reg) {
102 132 : emit(0x48 | (reg.code() & 0x8) >> 1 | rm_reg.code() >> 3);
103 : }
104 :
105 :
106 : void Assembler::emit_rex_64(Register reg, const Operand& op) {
107 59023755 : emit(0x48 | reg.high_bit() << 2 | op.rex_);
108 : }
109 :
110 :
111 : void Assembler::emit_rex_64(XMMRegister reg, const Operand& op) {
112 544 : emit(0x48 | (reg.code() & 0x8) >> 1 | op.rex_);
113 : }
114 :
115 :
116 : void Assembler::emit_rex_64(Register rm_reg) {
117 : DCHECK_EQ(rm_reg.code() & 0xf, rm_reg.code());
118 50581727 : emit(0x48 | rm_reg.high_bit());
119 : }
120 :
121 :
122 : void Assembler::emit_rex_64(const Operand& op) {
123 310862 : emit(0x48 | op.rex_);
124 : }
125 :
126 :
127 : void Assembler::emit_rex_32(Register reg, Register rm_reg) {
128 21114 : emit(0x40 | reg.high_bit() << 2 | rm_reg.high_bit());
129 : }
130 :
131 :
132 : void Assembler::emit_rex_32(Register reg, const Operand& op) {
133 5999 : emit(0x40 | reg.high_bit() << 2 | op.rex_);
134 : }
135 :
136 :
137 : void Assembler::emit_rex_32(Register rm_reg) {
138 428541 : emit(0x40 | rm_reg.high_bit());
139 : }
140 :
141 :
142 : void Assembler::emit_rex_32(const Operand& op) {
143 : emit(0x40 | op.rex_);
144 : }
145 :
146 :
147 : void Assembler::emit_optional_rex_32(Register reg, Register rm_reg) {
148 7213474 : byte rex_bits = reg.high_bit() << 2 | rm_reg.high_bit();
149 3606737 : if (rex_bits != 0) emit(0x40 | rex_bits);
150 : }
151 :
152 :
153 : void Assembler::emit_optional_rex_32(Register reg, const Operand& op) {
154 9039808 : byte rex_bits = reg.high_bit() << 2 | op.rex_;
155 9039808 : if (rex_bits != 0) emit(0x40 | rex_bits);
156 : }
157 :
158 :
159 : void Assembler::emit_optional_rex_32(XMMRegister reg, const Operand& op) {
160 34668 : byte rex_bits = (reg.code() & 0x8) >> 1 | op.rex_;
161 34668 : if (rex_bits != 0) emit(0x40 | rex_bits);
162 : }
163 :
164 :
165 : void Assembler::emit_optional_rex_32(XMMRegister reg, XMMRegister base) {
166 6301 : byte rex_bits = (reg.code() & 0x8) >> 1 | (base.code() & 0x8) >> 3;
167 6301 : if (rex_bits != 0) emit(0x40 | rex_bits);
168 : }
169 :
170 :
171 : void Assembler::emit_optional_rex_32(XMMRegister reg, Register base) {
172 18441 : byte rex_bits = (reg.code() & 0x8) >> 1 | (base.code() & 0x8) >> 3;
173 18441 : if (rex_bits != 0) emit(0x40 | rex_bits);
174 : }
175 :
176 :
177 : void Assembler::emit_optional_rex_32(Register reg, XMMRegister base) {
178 122 : byte rex_bits = (reg.code() & 0x8) >> 1 | (base.code() & 0x8) >> 3;
179 122 : if (rex_bits != 0) emit(0x40 | rex_bits);
180 : }
181 :
182 :
183 : void Assembler::emit_optional_rex_32(Register rm_reg) {
184 52598234 : if (rm_reg.high_bit()) emit(0x41);
185 : }
186 :
187 : void Assembler::emit_optional_rex_32(XMMRegister rm_reg) {
188 169 : if (rm_reg.high_bit()) emit(0x41);
189 : }
190 :
191 : void Assembler::emit_optional_rex_32(const Operand& op) {
192 15070887 : if (op.rex_ != 0) emit(0x40 | op.rex_);
193 : }
194 :
195 :
196 : // byte 1 of 3-byte VEX
197 : void Assembler::emit_vex3_byte1(XMMRegister reg, XMMRegister rm,
198 : LeadingOpcode m) {
199 720547 : byte rxb = ~((reg.high_bit() << 2) | rm.high_bit()) << 5;
200 720547 : emit(rxb | m);
201 : }
202 :
203 :
204 : // byte 1 of 3-byte VEX
205 : void Assembler::emit_vex3_byte1(XMMRegister reg, const Operand& rm,
206 : LeadingOpcode m) {
207 49157 : byte rxb = ~((reg.high_bit() << 2) | rm.rex_) << 5;
208 49157 : emit(rxb | m);
209 : }
210 :
211 :
212 : // byte 1 of 2-byte VEX
213 : void Assembler::emit_vex2_byte1(XMMRegister reg, XMMRegister v, VectorLength l,
214 : SIMDPrefix pp) {
215 8770198 : byte rv = ~((reg.high_bit() << 4) | v.code()) << 3;
216 8770198 : emit(rv | l | pp);
217 : }
218 :
219 :
220 : // byte 2 of 3-byte VEX
221 : void Assembler::emit_vex3_byte2(VexW w, XMMRegister v, VectorLength l,
222 : SIMDPrefix pp) {
223 769704 : emit(w | ((~v.code() & 0xf) << 3) | l | pp);
224 : }
225 :
226 :
227 2371271 : void Assembler::emit_vex_prefix(XMMRegister reg, XMMRegister vreg,
228 : XMMRegister rm, VectorLength l, SIMDPrefix pp,
229 : LeadingOpcode mm, VexW w) {
230 2371271 : if (rm.high_bit() || mm != k0F || w != kW0) {
231 : emit_vex3_byte0();
232 : emit_vex3_byte1(reg, rm, mm);
233 : emit_vex3_byte2(w, vreg, l, pp);
234 : } else {
235 : emit_vex2_byte0();
236 : emit_vex2_byte1(reg, vreg, l, pp);
237 : }
238 2371271 : }
239 :
240 :
241 : void Assembler::emit_vex_prefix(Register reg, Register vreg, Register rm,
242 : VectorLength l, SIMDPrefix pp, LeadingOpcode mm,
243 : VexW w) {
244 364 : XMMRegister ireg = {reg.code()};
245 364 : XMMRegister ivreg = {vreg.code()};
246 364 : XMMRegister irm = {rm.code()};
247 364 : emit_vex_prefix(ireg, ivreg, irm, l, pp, mm, w);
248 : }
249 :
250 :
251 7168631 : void Assembler::emit_vex_prefix(XMMRegister reg, XMMRegister vreg,
252 49157 : const Operand& rm, VectorLength l,
253 : SIMDPrefix pp, LeadingOpcode mm, VexW w) {
254 7168631 : if (rm.rex_ || mm != k0F || w != kW0) {
255 : emit_vex3_byte0();
256 : emit_vex3_byte1(reg, rm, mm);
257 : emit_vex3_byte2(w, vreg, l, pp);
258 : } else {
259 : emit_vex2_byte0();
260 : emit_vex2_byte1(reg, vreg, l, pp);
261 : }
262 7168631 : }
263 :
264 :
265 : void Assembler::emit_vex_prefix(Register reg, Register vreg, const Operand& rm,
266 : VectorLength l, SIMDPrefix pp, LeadingOpcode mm,
267 : VexW w) {
268 364 : XMMRegister ireg = {reg.code()};
269 364 : XMMRegister ivreg = {vreg.code()};
270 364 : emit_vex_prefix(ireg, ivreg, rm, l, pp, mm, w);
271 : }
272 :
273 :
274 : Address Assembler::target_address_at(Address pc, Address constant_pool) {
275 349888323 : return Memory::int32_at(pc) + pc + 4;
276 : }
277 :
278 :
279 : void Assembler::set_target_address_at(Isolate* isolate, Address pc,
280 : Address constant_pool, Address target,
281 : ICacheFlushMode icache_flush_mode) {
282 : DCHECK_IMPLIES(isolate == nullptr, icache_flush_mode == SKIP_ICACHE_FLUSH);
283 347747970 : Memory::int32_at(pc) = static_cast<int32_t>(target - pc - 4);
284 19008269 : if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
285 328745100 : Assembler::FlushICache(isolate, pc, sizeof(int32_t));
286 : }
287 : }
288 :
289 347370148 : Address Assembler::target_address_at(Address pc, Code* code) {
290 : Address constant_pool = code ? code->constant_pool() : NULL;
291 347370148 : return target_address_at(pc, constant_pool);
292 : }
293 :
294 5413 : void Assembler::set_target_address_at(Isolate* isolate, Address pc, Code* code,
295 : Address target,
296 : ICacheFlushMode icache_flush_mode) {
297 : Address constant_pool = code ? code->constant_pool() : NULL;
298 : set_target_address_at(isolate, pc, constant_pool, target, icache_flush_mode);
299 5413 : }
300 :
301 : void Assembler::deserialization_set_target_internal_reference_at(
302 : Isolate* isolate, Address pc, Address target, RelocInfo::Mode mode) {
303 90135114 : Memory::Address_at(pc) = target;
304 : }
305 :
306 :
307 : Address Assembler::target_address_from_return_address(Address pc) {
308 : return pc - kCallTargetAddressOffset;
309 : }
310 :
311 : void Assembler::deserialization_set_special_target_at(
312 : Isolate* isolate, Address instruction_payload, Code* code, Address target) {
313 : set_target_address_at(isolate, instruction_payload, code, target);
314 : }
315 :
316 17875886 : Handle<Code> Assembler::code_target_object_handle_at(Address pc) {
317 35751772 : return code_targets_[Memory::int32_at(pc)];
318 : }
319 :
320 :
321 889879 : Address Assembler::runtime_entry_at(Address pc) {
322 889879 : return Memory::int32_at(pc) + isolate_data().code_range_start_;
323 : }
324 :
325 : // -----------------------------------------------------------------------------
326 : // Implementation of RelocInfo
327 :
328 : // The modes possibly affected by apply must be in kApplyMask.
329 : void RelocInfo::apply(intptr_t delta) {
330 635777 : if (IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)) {
331 505609 : Memory::int32_at(pc_) -= static_cast<int32_t>(delta);
332 130168 : } else if (IsCodeAgeSequence(rmode_)) {
333 5257 : if (*pc_ == kCallOpcode) {
334 : int32_t* p = reinterpret_cast<int32_t*>(pc_ + 1);
335 5257 : *p -= static_cast<int32_t>(delta); // Relocate entry.
336 : }
337 124910 : } else if (IsInternalReference(rmode_)) {
338 : // absolute code pointer inside code object moves with the code object.
339 124910 : Memory::Address_at(pc_) += delta;
340 : }
341 : }
342 :
343 :
344 : Address RelocInfo::target_address() {
345 : DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_));
346 347370119 : return Assembler::target_address_at(pc_, host_);
347 : }
348 :
349 : Address RelocInfo::target_address_address() {
350 : DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)
351 : || rmode_ == EMBEDDED_OBJECT
352 : || rmode_ == EXTERNAL_REFERENCE);
353 : return reinterpret_cast<Address>(pc_);
354 : }
355 :
356 :
357 : Address RelocInfo::constant_pool_entry_address() {
358 0 : UNREACHABLE();
359 : return NULL;
360 : }
361 :
362 :
363 : int RelocInfo::target_address_size() {
364 1843733 : if (IsCodedSpecially()) {
365 : return Assembler::kSpecialTargetSize;
366 : } else {
367 : return kPointerSize;
368 : }
369 : }
370 :
371 : HeapObject* RelocInfo::target_object() {
372 : DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
373 42847671 : return HeapObject::cast(Memory::Object_at(pc_));
374 : }
375 :
376 : Handle<HeapObject> RelocInfo::target_object_handle(Assembler* origin) {
377 : DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
378 34072331 : if (rmode_ == EMBEDDED_OBJECT) {
379 16196461 : return Handle<HeapObject>::cast(Memory::Object_Handle_at(pc_));
380 : } else {
381 17875870 : return origin->code_target_object_handle_at(pc_);
382 : }
383 : }
384 :
385 :
386 : Address RelocInfo::target_external_reference() {
387 : DCHECK(rmode_ == RelocInfo::EXTERNAL_REFERENCE);
388 990758 : return Memory::Address_at(pc_);
389 : }
390 :
391 :
392 : Address RelocInfo::target_internal_reference() {
393 : DCHECK(rmode_ == INTERNAL_REFERENCE);
394 224084 : return Memory::Address_at(pc_);
395 : }
396 :
397 :
398 : Address RelocInfo::target_internal_reference_address() {
399 : DCHECK(rmode_ == INTERNAL_REFERENCE);
400 : return reinterpret_cast<Address>(pc_);
401 : }
402 :
403 : void RelocInfo::set_target_object(HeapObject* target,
404 : WriteBarrierMode write_barrier_mode,
405 33329837 : ICacheFlushMode icache_flush_mode) {
406 : DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
407 21588736 : Memory::Object_at(pc_) = target;
408 4852 : if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
409 5387702 : Assembler::FlushICache(target->GetIsolate(), pc_, sizeof(Address));
410 : }
411 17081684 : if (write_barrier_mode == UPDATE_WRITE_BARRIER && host() != NULL) {
412 : host()->GetHeap()->incremental_marking()->RecordWriteIntoCode(host(), this,
413 16248155 : target);
414 16248153 : host()->GetHeap()->RecordWriteIntoCode(host(), this, target);
415 : }
416 : }
417 :
418 :
419 : Address RelocInfo::target_runtime_entry(Assembler* origin) {
420 : DCHECK(IsRuntimeEntry(rmode_));
421 889879 : return origin->runtime_entry_at(pc_);
422 : }
423 :
424 : void RelocInfo::set_target_runtime_entry(Isolate* isolate, Address target,
425 : WriteBarrierMode write_barrier_mode,
426 : ICacheFlushMode icache_flush_mode) {
427 : DCHECK(IsRuntimeEntry(rmode_));
428 889879 : if (target_address() != target) {
429 889879 : set_target_address(isolate, target, write_barrier_mode, icache_flush_mode);
430 : }
431 : }
432 :
433 :
434 : Handle<Cell> RelocInfo::target_cell_handle() {
435 : DCHECK(rmode_ == RelocInfo::CELL);
436 38676 : Address address = Memory::Address_at(pc_);
437 : return Handle<Cell>(reinterpret_cast<Cell**>(address));
438 : }
439 :
440 :
441 : Cell* RelocInfo::target_cell() {
442 : DCHECK(rmode_ == RelocInfo::CELL);
443 65501 : return Cell::FromValueAddress(Memory::Address_at(pc_));
444 : }
445 :
446 :
447 : void RelocInfo::set_target_cell(Cell* cell,
448 : WriteBarrierMode write_barrier_mode,
449 38975 : ICacheFlushMode icache_flush_mode) {
450 : DCHECK(rmode_ == RelocInfo::CELL);
451 38975 : Address address = cell->address() + Cell::kValueOffset;
452 38975 : Memory::Address_at(pc_) = address;
453 : if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
454 299 : Assembler::FlushICache(cell->GetIsolate(), pc_, sizeof(Address));
455 : }
456 38975 : if (write_barrier_mode == UPDATE_WRITE_BARRIER &&
457 38975 : host() != NULL) {
458 : host()->GetHeap()->incremental_marking()->RecordWriteIntoCode(host(), this,
459 38676 : cell);
460 : }
461 : }
462 :
463 : void RelocInfo::WipeOut(Isolate* isolate) {
464 20494 : if (IsEmbeddedObject(rmode_) || IsExternalReference(rmode_) ||
465 6883 : IsInternalReference(rmode_)) {
466 8212 : Memory::Address_at(pc_) = NULL;
467 5399 : } else if (IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)) {
468 : // Effectively write zero into the relocation.
469 : Assembler::set_target_address_at(isolate, pc_, host_,
470 5399 : pc_ + sizeof(int32_t));
471 : } else {
472 0 : UNREACHABLE();
473 : }
474 : }
475 :
476 : Handle<Code> RelocInfo::code_age_stub_handle(Assembler* origin) {
477 : DCHECK(rmode_ == RelocInfo::CODE_AGE_SEQUENCE);
478 : DCHECK(*pc_ == kCallOpcode);
479 14 : return origin->code_target_object_handle_at(pc_ + 1);
480 : }
481 :
482 :
483 : Code* RelocInfo::code_age_stub() {
484 : DCHECK(rmode_ == RelocInfo::CODE_AGE_SEQUENCE);
485 : DCHECK(*pc_ == kCallOpcode);
486 : return Code::GetCodeFromTargetAddress(
487 0 : Assembler::target_address_at(pc_ + 1, host_));
488 : }
489 :
490 :
491 : void RelocInfo::set_code_age_stub(Code* stub,
492 : ICacheFlushMode icache_flush_mode) {
493 : DCHECK(*pc_ == kCallOpcode);
494 : DCHECK(rmode_ == RelocInfo::CODE_AGE_SEQUENCE);
495 : Assembler::set_target_address_at(stub->GetIsolate(), pc_ + 1, host_,
496 : stub->instruction_start(),
497 14 : icache_flush_mode);
498 : }
499 :
500 :
501 : Address RelocInfo::debug_call_address() {
502 : DCHECK(IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence());
503 12039 : return Memory::Address_at(pc_ + Assembler::kPatchDebugBreakSlotAddressOffset);
504 : }
505 :
506 0 : void RelocInfo::set_debug_call_address(Isolate* isolate, Address target) {
507 : DCHECK(IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence());
508 0 : Memory::Address_at(pc_ + Assembler::kPatchDebugBreakSlotAddressOffset) =
509 0 : target;
510 : Assembler::FlushICache(isolate,
511 0 : pc_ + Assembler::kPatchDebugBreakSlotAddressOffset,
512 0 : sizeof(Address));
513 0 : if (host() != NULL) {
514 0 : Code* target_code = Code::GetCodeFromTargetAddress(target);
515 : host()->GetHeap()->incremental_marking()->RecordWriteIntoCode(host(), this,
516 0 : target_code);
517 : }
518 : }
519 :
520 : template <typename ObjectVisitor>
521 73685002 : void RelocInfo::Visit(Isolate* isolate, ObjectVisitor* visitor) {
522 : RelocInfo::Mode mode = rmode();
523 36875787 : if (mode == RelocInfo::EMBEDDED_OBJECT) {
524 4464800 : visitor->VisitEmbeddedPointer(host(), this);
525 2232400 : Assembler::FlushICache(isolate, pc_, sizeof(Address));
526 34643387 : } else if (RelocInfo::IsCodeTarget(mode)) {
527 30498642 : visitor->VisitCodeTarget(host(), this);
528 19394066 : } else if (mode == RelocInfo::CELL) {
529 7304 : visitor->VisitCellPointer(host(), this);
530 19390414 : } else if (mode == RelocInfo::EXTERNAL_REFERENCE) {
531 31439622 : visitor->VisitExternalReference(host(), this);
532 3642569 : } else if (mode == RelocInfo::INTERNAL_REFERENCE) {
533 7090360 : visitor->VisitInternalReference(host(), this);
534 97389 : } else if (RelocInfo::IsCodeAgeSequence(mode)) {
535 0 : visitor->VisitCodeAgeSequence(host(), this);
536 120365 : } else if (RelocInfo::IsDebugBreakSlot(mode) &&
537 22976 : IsPatchedDebugBreakSlotSequence()) {
538 24 : visitor->VisitDebugTarget(host(), this);
539 81803 : } else if (RelocInfo::IsRuntimeEntry(mode)) {
540 117678 : visitor->VisitRuntimeEntry(host(), this);
541 : }
542 36875787 : }
543 :
544 :
545 : template<typename StaticVisitor>
546 776988535 : void RelocInfo::Visit(Heap* heap) {
547 : RelocInfo::Mode mode = rmode();
548 776988535 : if (mode == RelocInfo::EMBEDDED_OBJECT) {
549 : StaticVisitor::VisitEmbeddedPointer(heap, this);
550 61635708 : Assembler::FlushICache(heap->isolate(), pc_, sizeof(Address));
551 746170682 : } else if (RelocInfo::IsCodeTarget(mode)) {
552 : StaticVisitor::VisitCodeTarget(heap, this);
553 431821434 : } else if (mode == RelocInfo::CELL) {
554 : StaticVisitor::VisitCell(heap, this);
555 431759884 : } else if (mode == RelocInfo::EXTERNAL_REFERENCE) {
556 : StaticVisitor::VisitExternalReference(this);
557 80509921 : } else if (mode == RelocInfo::INTERNAL_REFERENCE) {
558 : StaticVisitor::VisitInternalReference(this);
559 1264282 : } else if (RelocInfo::IsCodeAgeSequence(mode)) {
560 : StaticVisitor::VisitCodeAgeSequence(heap, this);
561 1328782 : } else if (RelocInfo::IsDebugBreakSlot(mode) &&
562 64500 : IsPatchedDebugBreakSlotSequence()) {
563 : StaticVisitor::VisitDebugTarget(heap, this);
564 : } else if (RelocInfo::IsRuntimeEntry(mode)) {
565 : StaticVisitor::VisitRuntimeEntry(this);
566 : }
567 776987928 : }
568 :
569 :
570 : // -----------------------------------------------------------------------------
571 : // Implementation of Operand
572 :
573 : void Operand::set_modrm(int mod, Register rm_reg) {
574 : DCHECK(is_uint2(mod));
575 90292425 : buf_[0] = mod << 6 | rm_reg.low_bits();
576 : // Set REX.B to the high bit of rm.code().
577 90235514 : rex_ |= rm_reg.high_bit();
578 : }
579 :
580 :
581 : void Operand::set_sib(ScaleFactor scale, Register index, Register base) {
582 : DCHECK(len_ == 1);
583 : DCHECK(is_uint2(scale));
584 : // Use SIB with no index register only for base rsp or r12. Otherwise we
585 : // would skip the SIB byte entirely.
586 : DCHECK(!index.is(rsp) || base.is(rsp) || base.is(r12));
587 21108281 : buf_[1] = (scale << 6) | (index.low_bits() << 3) | base.low_bits();
588 18490301 : rex_ |= index.high_bit() << 1 | base.high_bit();
589 15923146 : len_ = 2;
590 : }
591 :
592 : void Operand::set_disp8(int disp) {
593 : DCHECK(is_int8(disp));
594 : DCHECK(len_ == 1 || len_ == 2);
595 67420229 : int8_t* p = reinterpret_cast<int8_t*>(&buf_[len_]);
596 67420229 : *p = disp;
597 67420229 : len_ += sizeof(int8_t);
598 : }
599 :
600 : void Operand::set_disp32(int disp) {
601 : DCHECK(len_ == 1 || len_ == 2);
602 14299495 : int32_t* p = reinterpret_cast<int32_t*>(&buf_[len_]);
603 14299495 : *p = disp;
604 14299495 : len_ += sizeof(int32_t);
605 : }
606 :
607 : void Operand::set_disp64(int64_t disp) {
608 : DCHECK_EQ(1, len_);
609 6086 : int64_t* p = reinterpret_cast<int64_t*>(&buf_[len_]);
610 6086 : *p = disp;
611 6086 : len_ += sizeof(disp);
612 : }
613 : } // namespace internal
614 : } // namespace v8
615 :
616 : #endif // V8_X64_ASSEMBLER_X64_INL_H_
|