1 // Copyright (c) 1994-2006 Sun Microsystems Inc.
2 // All Rights Reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 // - Redistributions of source code must retain the above copyright notice,
9 // this list of conditions and the following disclaimer.
10 //
11 // - Redistribution in binary form must reproduce the above copyright
12 // notice, this list of conditions and the following disclaimer in the
13 // documentation and/or other materials provided with the distribution.
14 //
15 // - Neither the name of Sun Microsystems or the names of contributors may
16 // be used to endorse or promote products derived from this software without
17 // specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
20 // IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 
31 // The original source code covered by the above license above has been
32 // modified significantly by Google Inc.
33 // Copyright 2012 the V8 project authors. All rights reserved.
34 
35 // A light-weight IA32 Assembler.
36 
37 #ifndef V8_IA32_ASSEMBLER_IA32_INL_H_
38 #define V8_IA32_ASSEMBLER_IA32_INL_H_
39 
40 #include "src/ia32/assembler-ia32.h"
41 
42 #include "src/assembler.h"
43 #include "src/debug/debug.h"
44 
45 namespace v8 {
46 namespace internal {
47 
SupportsCrankshaft()48 bool CpuFeatures::SupportsCrankshaft() { return true; }
49 
SupportsSimd128()50 bool CpuFeatures::SupportsSimd128() { return false; }
51 
52 static const byte kCallOpcode = 0xE8;
53 static const int kNoCodeAgeSequenceLength = 5;
54 
55 
56 // The modes possibly affected by apply must be in kApplyMask.
apply(intptr_t delta)57 void RelocInfo::apply(intptr_t delta) {
58   if (IsRuntimeEntry(rmode_) || IsCodeTarget(rmode_)) {
59     int32_t* p = reinterpret_cast<int32_t*>(pc_);
60     *p -= delta;  // Relocate entry.
61   } else if (IsCodeAgeSequence(rmode_)) {
62     if (*pc_ == kCallOpcode) {
63       int32_t* p = reinterpret_cast<int32_t*>(pc_ + 1);
64       *p -= delta;  // Relocate entry.
65     }
66   } else if (IsDebugBreakSlot(rmode_) && IsPatchedDebugBreakSlotSequence()) {
67     // Special handling of a debug break slot when a break point is set (call
68     // instruction has been inserted).
69     int32_t* p = reinterpret_cast<int32_t*>(
70         pc_ + Assembler::kPatchDebugBreakSlotAddressOffset);
71     *p -= delta;  // Relocate entry.
72   } else if (IsInternalReference(rmode_)) {
73     // absolute code pointer inside code object moves with the code object.
74     int32_t* p = reinterpret_cast<int32_t*>(pc_);
75     *p += delta;  // Relocate entry.
76   }
77 }
78 
79 
target_address()80 Address RelocInfo::target_address() {
81   DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_));
82   return Assembler::target_address_at(pc_, host_);
83 }
84 
target_address_address()85 Address RelocInfo::target_address_address() {
86   DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)
87                               || rmode_ == EMBEDDED_OBJECT
88                               || rmode_ == EXTERNAL_REFERENCE);
89   return reinterpret_cast<Address>(pc_);
90 }
91 
92 
constant_pool_entry_address()93 Address RelocInfo::constant_pool_entry_address() {
94   UNREACHABLE();
95   return NULL;
96 }
97 
98 
target_address_size()99 int RelocInfo::target_address_size() {
100   return Assembler::kSpecialTargetSize;
101 }
102 
103 
target_object()104 Object* RelocInfo::target_object() {
105   DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
106   return Memory::Object_at(pc_);
107 }
108 
109 
target_object_handle(Assembler * origin)110 Handle<Object> RelocInfo::target_object_handle(Assembler* origin) {
111   DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
112   return Memory::Object_Handle_at(pc_);
113 }
114 
115 
set_target_object(Object * target,WriteBarrierMode write_barrier_mode,ICacheFlushMode icache_flush_mode)116 void RelocInfo::set_target_object(Object* target,
117                                   WriteBarrierMode write_barrier_mode,
118                                   ICacheFlushMode icache_flush_mode) {
119   DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
120   Memory::Object_at(pc_) = target;
121   if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
122     Assembler::FlushICache(isolate_, pc_, sizeof(Address));
123   }
124   if (write_barrier_mode == UPDATE_WRITE_BARRIER &&
125       host() != NULL &&
126       target->IsHeapObject()) {
127     host()->GetHeap()->RecordWriteIntoCode(host(), this, target);
128     host()->GetHeap()->incremental_marking()->RecordWriteIntoCode(
129         host(), this, HeapObject::cast(target));
130   }
131 }
132 
133 
target_external_reference()134 Address RelocInfo::target_external_reference() {
135   DCHECK(rmode_ == RelocInfo::EXTERNAL_REFERENCE);
136   return Memory::Address_at(pc_);
137 }
138 
139 
target_internal_reference()140 Address RelocInfo::target_internal_reference() {
141   DCHECK(rmode_ == INTERNAL_REFERENCE);
142   return Memory::Address_at(pc_);
143 }
144 
145 
target_internal_reference_address()146 Address RelocInfo::target_internal_reference_address() {
147   DCHECK(rmode_ == INTERNAL_REFERENCE);
148   return reinterpret_cast<Address>(pc_);
149 }
150 
151 
target_runtime_entry(Assembler * origin)152 Address RelocInfo::target_runtime_entry(Assembler* origin) {
153   DCHECK(IsRuntimeEntry(rmode_));
154   return reinterpret_cast<Address>(*reinterpret_cast<int32_t*>(pc_));
155 }
156 
157 
set_target_runtime_entry(Address target,WriteBarrierMode write_barrier_mode,ICacheFlushMode icache_flush_mode)158 void RelocInfo::set_target_runtime_entry(Address target,
159                                          WriteBarrierMode write_barrier_mode,
160                                          ICacheFlushMode icache_flush_mode) {
161   DCHECK(IsRuntimeEntry(rmode_));
162   if (target_address() != target) {
163     set_target_address(target, write_barrier_mode, icache_flush_mode);
164   }
165 }
166 
167 
target_cell_handle()168 Handle<Cell> RelocInfo::target_cell_handle() {
169   DCHECK(rmode_ == RelocInfo::CELL);
170   Address address = Memory::Address_at(pc_);
171   return Handle<Cell>(reinterpret_cast<Cell**>(address));
172 }
173 
174 
target_cell()175 Cell* RelocInfo::target_cell() {
176   DCHECK(rmode_ == RelocInfo::CELL);
177   return Cell::FromValueAddress(Memory::Address_at(pc_));
178 }
179 
180 
set_target_cell(Cell * cell,WriteBarrierMode write_barrier_mode,ICacheFlushMode icache_flush_mode)181 void RelocInfo::set_target_cell(Cell* cell,
182                                 WriteBarrierMode write_barrier_mode,
183                                 ICacheFlushMode icache_flush_mode) {
184   DCHECK(cell->IsCell());
185   DCHECK(rmode_ == RelocInfo::CELL);
186   Address address = cell->address() + Cell::kValueOffset;
187   Memory::Address_at(pc_) = address;
188   if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
189     Assembler::FlushICache(isolate_, pc_, sizeof(Address));
190   }
191   if (write_barrier_mode == UPDATE_WRITE_BARRIER && host() != NULL) {
192     host()->GetHeap()->incremental_marking()->RecordWriteIntoCode(host(), this,
193                                                                   cell);
194   }
195 }
196 
197 
code_age_stub_handle(Assembler * origin)198 Handle<Object> RelocInfo::code_age_stub_handle(Assembler* origin) {
199   DCHECK(rmode_ == RelocInfo::CODE_AGE_SEQUENCE);
200   DCHECK(*pc_ == kCallOpcode);
201   return Memory::Object_Handle_at(pc_ + 1);
202 }
203 
204 
code_age_stub()205 Code* RelocInfo::code_age_stub() {
206   DCHECK(rmode_ == RelocInfo::CODE_AGE_SEQUENCE);
207   DCHECK(*pc_ == kCallOpcode);
208   return Code::GetCodeFromTargetAddress(
209       Assembler::target_address_at(pc_ + 1, host_));
210 }
211 
212 
set_code_age_stub(Code * stub,ICacheFlushMode icache_flush_mode)213 void RelocInfo::set_code_age_stub(Code* stub,
214                                   ICacheFlushMode icache_flush_mode) {
215   DCHECK(*pc_ == kCallOpcode);
216   DCHECK(rmode_ == RelocInfo::CODE_AGE_SEQUENCE);
217   Assembler::set_target_address_at(
218       isolate_, pc_ + 1, host_, stub->instruction_start(), icache_flush_mode);
219 }
220 
221 
debug_call_address()222 Address RelocInfo::debug_call_address() {
223   DCHECK(IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence());
224   Address location = pc_ + Assembler::kPatchDebugBreakSlotAddressOffset;
225   return Assembler::target_address_at(location, host_);
226 }
227 
228 
set_debug_call_address(Address target)229 void RelocInfo::set_debug_call_address(Address target) {
230   DCHECK(IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence());
231   Address location = pc_ + Assembler::kPatchDebugBreakSlotAddressOffset;
232   Assembler::set_target_address_at(isolate_, location, host_, target);
233   if (host() != NULL) {
234     Object* target_code = Code::GetCodeFromTargetAddress(target);
235     host()->GetHeap()->incremental_marking()->RecordWriteIntoCode(
236         host(), this, HeapObject::cast(target_code));
237   }
238 }
239 
240 
WipeOut()241 void RelocInfo::WipeOut() {
242   if (IsEmbeddedObject(rmode_) || IsExternalReference(rmode_) ||
243       IsInternalReference(rmode_)) {
244     Memory::Address_at(pc_) = NULL;
245   } else if (IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)) {
246     // Effectively write zero into the relocation.
247     Assembler::set_target_address_at(isolate_, pc_, host_,
248                                      pc_ + sizeof(int32_t));
249   } else {
250     UNREACHABLE();
251   }
252 }
253 
254 template <typename ObjectVisitor>
Visit(Isolate * isolate,ObjectVisitor * visitor)255 void RelocInfo::Visit(Isolate* isolate, ObjectVisitor* visitor) {
256   RelocInfo::Mode mode = rmode();
257   if (mode == RelocInfo::EMBEDDED_OBJECT) {
258     visitor->VisitEmbeddedPointer(this);
259     Assembler::FlushICache(isolate, pc_, sizeof(Address));
260   } else if (RelocInfo::IsCodeTarget(mode)) {
261     visitor->VisitCodeTarget(this);
262   } else if (mode == RelocInfo::CELL) {
263     visitor->VisitCell(this);
264   } else if (mode == RelocInfo::EXTERNAL_REFERENCE) {
265     visitor->VisitExternalReference(this);
266   } else if (mode == RelocInfo::INTERNAL_REFERENCE) {
267     visitor->VisitInternalReference(this);
268   } else if (RelocInfo::IsCodeAgeSequence(mode)) {
269     visitor->VisitCodeAgeSequence(this);
270   } else if (RelocInfo::IsDebugBreakSlot(mode) &&
271              IsPatchedDebugBreakSlotSequence()) {
272     visitor->VisitDebugTarget(this);
273   } else if (IsRuntimeEntry(mode)) {
274     visitor->VisitRuntimeEntry(this);
275   }
276 }
277 
278 
279 template<typename StaticVisitor>
Visit(Heap * heap)280 void RelocInfo::Visit(Heap* heap) {
281   RelocInfo::Mode mode = rmode();
282   if (mode == RelocInfo::EMBEDDED_OBJECT) {
283     StaticVisitor::VisitEmbeddedPointer(heap, this);
284     Assembler::FlushICache(heap->isolate(), pc_, sizeof(Address));
285   } else if (RelocInfo::IsCodeTarget(mode)) {
286     StaticVisitor::VisitCodeTarget(heap, this);
287   } else if (mode == RelocInfo::CELL) {
288     StaticVisitor::VisitCell(heap, this);
289   } else if (mode == RelocInfo::EXTERNAL_REFERENCE) {
290     StaticVisitor::VisitExternalReference(this);
291   } else if (mode == RelocInfo::INTERNAL_REFERENCE) {
292     StaticVisitor::VisitInternalReference(this);
293   } else if (RelocInfo::IsCodeAgeSequence(mode)) {
294     StaticVisitor::VisitCodeAgeSequence(heap, this);
295   } else if (RelocInfo::IsDebugBreakSlot(mode) &&
296              IsPatchedDebugBreakSlotSequence()) {
297     StaticVisitor::VisitDebugTarget(heap, this);
298   } else if (IsRuntimeEntry(mode)) {
299     StaticVisitor::VisitRuntimeEntry(this);
300   }
301 }
302 
303 
304 
Immediate(int x)305 Immediate::Immediate(int x)  {
306   x_ = x;
307   rmode_ = RelocInfo::NONE32;
308 }
309 
Immediate(Address x,RelocInfo::Mode rmode)310 Immediate::Immediate(Address x, RelocInfo::Mode rmode) {
311   x_ = reinterpret_cast<int32_t>(x);
312   rmode_ = rmode;
313 }
314 
Immediate(const ExternalReference & ext)315 Immediate::Immediate(const ExternalReference& ext) {
316   x_ = reinterpret_cast<int32_t>(ext.address());
317   rmode_ = RelocInfo::EXTERNAL_REFERENCE;
318 }
319 
320 
Immediate(Label * internal_offset)321 Immediate::Immediate(Label* internal_offset) {
322   x_ = reinterpret_cast<int32_t>(internal_offset);
323   rmode_ = RelocInfo::INTERNAL_REFERENCE;
324 }
325 
326 
Immediate(Handle<Object> handle)327 Immediate::Immediate(Handle<Object> handle) {
328   AllowDeferredHandleDereference using_raw_address;
329   // Verify all Objects referred by code are NOT in new space.
330   Object* obj = *handle;
331   if (obj->IsHeapObject()) {
332     x_ = reinterpret_cast<intptr_t>(handle.location());
333     rmode_ = RelocInfo::EMBEDDED_OBJECT;
334   } else {
335     // no relocation needed
336     x_ =  reinterpret_cast<intptr_t>(obj);
337     rmode_ = RelocInfo::NONE32;
338   }
339 }
340 
341 
Immediate(Smi * value)342 Immediate::Immediate(Smi* value) {
343   x_ = reinterpret_cast<intptr_t>(value);
344   rmode_ = RelocInfo::NONE32;
345 }
346 
347 
Immediate(Address addr)348 Immediate::Immediate(Address addr) {
349   x_ = reinterpret_cast<int32_t>(addr);
350   rmode_ = RelocInfo::NONE32;
351 }
352 
353 
emit(uint32_t x)354 void Assembler::emit(uint32_t x) {
355   *reinterpret_cast<uint32_t*>(pc_) = x;
356   pc_ += sizeof(uint32_t);
357 }
358 
359 
emit_q(uint64_t x)360 void Assembler::emit_q(uint64_t x) {
361   *reinterpret_cast<uint64_t*>(pc_) = x;
362   pc_ += sizeof(uint64_t);
363 }
364 
365 
emit(Handle<Object> handle)366 void Assembler::emit(Handle<Object> handle) {
367   AllowDeferredHandleDereference heap_object_check;
368   // Verify all Objects referred by code are NOT in new space.
369   Object* obj = *handle;
370   if (obj->IsHeapObject()) {
371     emit(reinterpret_cast<intptr_t>(handle.location()),
372          RelocInfo::EMBEDDED_OBJECT);
373   } else {
374     // no relocation needed
375     emit(reinterpret_cast<intptr_t>(obj));
376   }
377 }
378 
379 
emit(uint32_t x,RelocInfo::Mode rmode,TypeFeedbackId id)380 void Assembler::emit(uint32_t x, RelocInfo::Mode rmode, TypeFeedbackId id) {
381   if (rmode == RelocInfo::CODE_TARGET && !id.IsNone()) {
382     RecordRelocInfo(RelocInfo::CODE_TARGET_WITH_ID, id.ToInt());
383   } else if (!RelocInfo::IsNone(rmode)
384       && rmode != RelocInfo::CODE_AGE_SEQUENCE) {
385     RecordRelocInfo(rmode);
386   }
387   emit(x);
388 }
389 
390 
emit(Handle<Code> code,RelocInfo::Mode rmode,TypeFeedbackId id)391 void Assembler::emit(Handle<Code> code,
392                      RelocInfo::Mode rmode,
393                      TypeFeedbackId id) {
394   AllowDeferredHandleDereference embedding_raw_address;
395   emit(reinterpret_cast<intptr_t>(code.location()), rmode, id);
396 }
397 
398 
emit(const Immediate & x)399 void Assembler::emit(const Immediate& x) {
400   if (x.rmode_ == RelocInfo::INTERNAL_REFERENCE) {
401     Label* label = reinterpret_cast<Label*>(x.x_);
402     emit_code_relative_offset(label);
403     return;
404   }
405   if (!RelocInfo::IsNone(x.rmode_)) RecordRelocInfo(x.rmode_);
406   emit(x.x_);
407 }
408 
409 
emit_code_relative_offset(Label * label)410 void Assembler::emit_code_relative_offset(Label* label) {
411   if (label->is_bound()) {
412     int32_t pos;
413     pos = label->pos() + Code::kHeaderSize - kHeapObjectTag;
414     emit(pos);
415   } else {
416     emit_disp(label, Displacement::CODE_RELATIVE);
417   }
418 }
419 
emit_b(Immediate x)420 void Assembler::emit_b(Immediate x) {
421   DCHECK(x.is_int8() || x.is_uint8());
422   uint8_t value = static_cast<uint8_t>(x.x_);
423   *pc_++ = value;
424 }
425 
emit_w(const Immediate & x)426 void Assembler::emit_w(const Immediate& x) {
427   DCHECK(RelocInfo::IsNone(x.rmode_));
428   uint16_t value = static_cast<uint16_t>(x.x_);
429   reinterpret_cast<uint16_t*>(pc_)[0] = value;
430   pc_ += sizeof(uint16_t);
431 }
432 
433 
target_address_at(Address pc,Address constant_pool)434 Address Assembler::target_address_at(Address pc, Address constant_pool) {
435   return pc + sizeof(int32_t) + *reinterpret_cast<int32_t*>(pc);
436 }
437 
438 
set_target_address_at(Isolate * isolate,Address pc,Address constant_pool,Address target,ICacheFlushMode icache_flush_mode)439 void Assembler::set_target_address_at(Isolate* isolate, Address pc,
440                                       Address constant_pool, Address target,
441                                       ICacheFlushMode icache_flush_mode) {
442   int32_t* p = reinterpret_cast<int32_t*>(pc);
443   *p = target - (pc + sizeof(int32_t));
444   if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
445     Assembler::FlushICache(isolate, p, sizeof(int32_t));
446   }
447 }
448 
449 
target_address_from_return_address(Address pc)450 Address Assembler::target_address_from_return_address(Address pc) {
451   return pc - kCallTargetAddressOffset;
452 }
453 
454 
disp_at(Label * L)455 Displacement Assembler::disp_at(Label* L) {
456   return Displacement(long_at(L->pos()));
457 }
458 
459 
disp_at_put(Label * L,Displacement disp)460 void Assembler::disp_at_put(Label* L, Displacement disp) {
461   long_at_put(L->pos(), disp.data());
462 }
463 
464 
emit_disp(Label * L,Displacement::Type type)465 void Assembler::emit_disp(Label* L, Displacement::Type type) {
466   Displacement disp(L, type);
467   L->link_to(pc_offset());
468   emit(static_cast<int>(disp.data()));
469 }
470 
471 
emit_near_disp(Label * L)472 void Assembler::emit_near_disp(Label* L) {
473   byte disp = 0x00;
474   if (L->is_near_linked()) {
475     int offset = L->near_link_pos() - pc_offset();
476     DCHECK(is_int8(offset));
477     disp = static_cast<byte>(offset & 0xFF);
478   }
479   L->link_to(pc_offset(), Label::kNear);
480   *pc_++ = disp;
481 }
482 
483 
deserialization_set_target_internal_reference_at(Isolate * isolate,Address pc,Address target,RelocInfo::Mode mode)484 void Assembler::deserialization_set_target_internal_reference_at(
485     Isolate* isolate, Address pc, Address target, RelocInfo::Mode mode) {
486   Memory::Address_at(pc) = target;
487 }
488 
489 
set_modrm(int mod,Register rm)490 void Operand::set_modrm(int mod, Register rm) {
491   DCHECK((mod & -4) == 0);
492   buf_[0] = mod << 6 | rm.code();
493   len_ = 1;
494 }
495 
496 
set_sib(ScaleFactor scale,Register index,Register base)497 void Operand::set_sib(ScaleFactor scale, Register index, Register base) {
498   DCHECK(len_ == 1);
499   DCHECK((scale & -4) == 0);
500   // Use SIB with no index register only for base esp.
501   DCHECK(!index.is(esp) || base.is(esp));
502   buf_[1] = scale << 6 | index.code() << 3 | base.code();
503   len_ = 2;
504 }
505 
506 
set_disp8(int8_t disp)507 void Operand::set_disp8(int8_t disp) {
508   DCHECK(len_ == 1 || len_ == 2);
509   *reinterpret_cast<int8_t*>(&buf_[len_++]) = disp;
510 }
511 
512 
set_dispr(int32_t disp,RelocInfo::Mode rmode)513 void Operand::set_dispr(int32_t disp, RelocInfo::Mode rmode) {
514   DCHECK(len_ == 1 || len_ == 2);
515   int32_t* p = reinterpret_cast<int32_t*>(&buf_[len_]);
516   *p = disp;
517   len_ += sizeof(int32_t);
518   rmode_ = rmode;
519 }
520 
Operand(Register reg)521 Operand::Operand(Register reg) {
522   // reg
523   set_modrm(3, reg);
524 }
525 
526 
Operand(XMMRegister xmm_reg)527 Operand::Operand(XMMRegister xmm_reg) {
528   Register reg = { xmm_reg.code() };
529   set_modrm(3, reg);
530 }
531 
532 
Operand(int32_t disp,RelocInfo::Mode rmode)533 Operand::Operand(int32_t disp, RelocInfo::Mode rmode) {
534   // [disp/r]
535   set_modrm(0, ebp);
536   set_dispr(disp, rmode);
537 }
538 
539 
Operand(Immediate imm)540 Operand::Operand(Immediate imm) {
541   // [disp/r]
542   set_modrm(0, ebp);
543   set_dispr(imm.x_, imm.rmode_);
544 }
545 }  // namespace internal
546 }  // namespace v8
547 
548 #endif  // V8_IA32_ASSEMBLER_IA32_INL_H_
549