v8  3.14.5(node0.10.28)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
assembler-ia32-inl.h
Go to the documentation of this file.
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 "ia32/assembler-ia32.h"
41 
42 #include "cpu.h"
43 #include "debug.h"
44 
45 namespace v8 {
46 namespace internal {
47 
48 
49 // The modes possibly affected by apply must be in kApplyMask.
50 void RelocInfo::apply(intptr_t delta) {
51  if (rmode_ == RUNTIME_ENTRY || IsCodeTarget(rmode_)) {
52  int32_t* p = reinterpret_cast<int32_t*>(pc_);
53  *p -= delta; // Relocate entry.
54  CPU::FlushICache(p, sizeof(uint32_t));
55  } else if (rmode_ == JS_RETURN && IsPatchedReturnSequence()) {
56  // Special handling of js_return when a break point is set (call
57  // instruction has been inserted).
58  int32_t* p = reinterpret_cast<int32_t*>(pc_ + 1);
59  *p -= delta; // Relocate entry.
60  CPU::FlushICache(p, sizeof(uint32_t));
61  } else if (rmode_ == DEBUG_BREAK_SLOT && IsPatchedDebugBreakSlotSequence()) {
62  // Special handling of a debug break slot when a break point is set (call
63  // instruction has been inserted).
64  int32_t* p = reinterpret_cast<int32_t*>(pc_ + 1);
65  *p -= delta; // Relocate entry.
66  CPU::FlushICache(p, sizeof(uint32_t));
67  } else if (IsInternalReference(rmode_)) {
68  // absolute code pointer inside code object moves with the code object.
69  int32_t* p = reinterpret_cast<int32_t*>(pc_);
70  *p += delta; // Relocate entry.
71  CPU::FlushICache(p, sizeof(uint32_t));
72  }
73 }
74 
75 
76 Address RelocInfo::target_address() {
77  ASSERT(IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY);
78  return Assembler::target_address_at(pc_);
79 }
80 
81 
82 Address RelocInfo::target_address_address() {
83  ASSERT(IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY
84  || rmode_ == EMBEDDED_OBJECT
85  || rmode_ == EXTERNAL_REFERENCE);
86  return reinterpret_cast<Address>(pc_);
87 }
88 
89 
90 int RelocInfo::target_address_size() {
92 }
93 
94 
95 void RelocInfo::set_target_address(Address target, WriteBarrierMode mode) {
97  ASSERT(IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY);
98  if (mode == UPDATE_WRITE_BARRIER && host() != NULL && IsCodeTarget(rmode_)) {
99  Object* target_code = Code::GetCodeFromTargetAddress(target);
100  host()->GetHeap()->incremental_marking()->RecordWriteIntoCode(
101  host(), this, HeapObject::cast(target_code));
102  }
103 }
104 
105 
106 Object* RelocInfo::target_object() {
107  ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
108  return Memory::Object_at(pc_);
109 }
110 
111 
112 Handle<Object> RelocInfo::target_object_handle(Assembler* origin) {
113  ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
114  return Memory::Object_Handle_at(pc_);
115 }
116 
117 
118 Object** RelocInfo::target_object_address() {
119  ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
120  return &Memory::Object_at(pc_);
121 }
122 
123 
124 void RelocInfo::set_target_object(Object* target, WriteBarrierMode mode) {
125  ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
126  Memory::Object_at(pc_) = target;
127  CPU::FlushICache(pc_, sizeof(Address));
128  if (mode == UPDATE_WRITE_BARRIER &&
129  host() != NULL &&
130  target->IsHeapObject()) {
131  host()->GetHeap()->incremental_marking()->RecordWrite(
132  host(), &Memory::Object_at(pc_), HeapObject::cast(target));
133  }
134 }
135 
136 
137 Address* RelocInfo::target_reference_address() {
138  ASSERT(rmode_ == RelocInfo::EXTERNAL_REFERENCE);
139  return reinterpret_cast<Address*>(pc_);
140 }
141 
142 
143 Handle<JSGlobalPropertyCell> RelocInfo::target_cell_handle() {
144  ASSERT(rmode_ == RelocInfo::GLOBAL_PROPERTY_CELL);
145  Address address = Memory::Address_at(pc_);
146  return Handle<JSGlobalPropertyCell>(
147  reinterpret_cast<JSGlobalPropertyCell**>(address));
148 }
149 
150 
151 JSGlobalPropertyCell* RelocInfo::target_cell() {
152  ASSERT(rmode_ == RelocInfo::GLOBAL_PROPERTY_CELL);
154 }
155 
156 
157 void RelocInfo::set_target_cell(JSGlobalPropertyCell* cell,
158  WriteBarrierMode mode) {
159  ASSERT(rmode_ == RelocInfo::GLOBAL_PROPERTY_CELL);
160  Address address = cell->address() + JSGlobalPropertyCell::kValueOffset;
161  Memory::Address_at(pc_) = address;
162  CPU::FlushICache(pc_, sizeof(Address));
163  if (mode == UPDATE_WRITE_BARRIER && host() != NULL) {
164  // TODO(1550) We are passing NULL as a slot because cell can never be on
165  // evacuation candidate.
166  host()->GetHeap()->incremental_marking()->RecordWrite(
167  host(), NULL, cell);
168  }
169 }
170 
171 
172 Address RelocInfo::call_address() {
173  ASSERT((IsJSReturn(rmode()) && IsPatchedReturnSequence()) ||
174  (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence()));
175  return Assembler::target_address_at(pc_ + 1);
176 }
177 
178 
179 void RelocInfo::set_call_address(Address target) {
180  ASSERT((IsJSReturn(rmode()) && IsPatchedReturnSequence()) ||
181  (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence()));
182  Assembler::set_target_address_at(pc_ + 1, target);
183  if (host() != NULL) {
184  Object* target_code = Code::GetCodeFromTargetAddress(target);
185  host()->GetHeap()->incremental_marking()->RecordWriteIntoCode(
186  host(), this, HeapObject::cast(target_code));
187  }
188 }
189 
190 
191 Object* RelocInfo::call_object() {
192  return *call_object_address();
193 }
194 
195 
196 void RelocInfo::set_call_object(Object* target) {
197  *call_object_address() = target;
198 }
199 
200 
201 Object** RelocInfo::call_object_address() {
202  ASSERT((IsJSReturn(rmode()) && IsPatchedReturnSequence()) ||
203  (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence()));
204  return reinterpret_cast<Object**>(pc_ + 1);
205 }
206 
207 
208 bool RelocInfo::IsPatchedReturnSequence() {
209  return *pc_ == 0xE8;
210 }
211 
212 
213 bool RelocInfo::IsPatchedDebugBreakSlotSequence() {
214  return !Assembler::IsNop(pc());
215 }
216 
217 
218 void RelocInfo::Visit(ObjectVisitor* visitor) {
219  RelocInfo::Mode mode = rmode();
220  if (mode == RelocInfo::EMBEDDED_OBJECT) {
221  visitor->VisitEmbeddedPointer(this);
222  CPU::FlushICache(pc_, sizeof(Address));
223  } else if (RelocInfo::IsCodeTarget(mode)) {
224  visitor->VisitCodeTarget(this);
225  } else if (mode == RelocInfo::GLOBAL_PROPERTY_CELL) {
226  visitor->VisitGlobalPropertyCell(this);
227  } else if (mode == RelocInfo::EXTERNAL_REFERENCE) {
228  visitor->VisitExternalReference(this);
229  CPU::FlushICache(pc_, sizeof(Address));
230 #ifdef ENABLE_DEBUGGER_SUPPORT
231  // TODO(isolates): Get a cached isolate below.
232  } else if (((RelocInfo::IsJSReturn(mode) &&
233  IsPatchedReturnSequence()) ||
234  (RelocInfo::IsDebugBreakSlot(mode) &&
235  IsPatchedDebugBreakSlotSequence())) &&
236  Isolate::Current()->debug()->has_break_points()) {
237  visitor->VisitDebugTarget(this);
238 #endif
239  } else if (mode == RelocInfo::RUNTIME_ENTRY) {
240  visitor->VisitRuntimeEntry(this);
241  }
242 }
243 
244 
245 template<typename StaticVisitor>
246 void RelocInfo::Visit(Heap* heap) {
247  RelocInfo::Mode mode = rmode();
248  if (mode == RelocInfo::EMBEDDED_OBJECT) {
249  StaticVisitor::VisitEmbeddedPointer(heap, this);
250  CPU::FlushICache(pc_, sizeof(Address));
251  } else if (RelocInfo::IsCodeTarget(mode)) {
252  StaticVisitor::VisitCodeTarget(heap, this);
253  } else if (mode == RelocInfo::GLOBAL_PROPERTY_CELL) {
254  StaticVisitor::VisitGlobalPropertyCell(heap, this);
255  } else if (mode == RelocInfo::EXTERNAL_REFERENCE) {
256  StaticVisitor::VisitExternalReference(this);
257  CPU::FlushICache(pc_, sizeof(Address));
258 #ifdef ENABLE_DEBUGGER_SUPPORT
259  } else if (heap->isolate()->debug()->has_break_points() &&
260  ((RelocInfo::IsJSReturn(mode) &&
261  IsPatchedReturnSequence()) ||
262  (RelocInfo::IsDebugBreakSlot(mode) &&
263  IsPatchedDebugBreakSlotSequence()))) {
264  StaticVisitor::VisitDebugTarget(heap, this);
265 #endif
266  } else if (mode == RelocInfo::RUNTIME_ENTRY) {
267  StaticVisitor::VisitRuntimeEntry(this);
268  }
269 }
270 
271 
272 
273 Immediate::Immediate(int x) {
274  x_ = x;
275  rmode_ = RelocInfo::NONE;
276 }
277 
278 
279 Immediate::Immediate(const ExternalReference& ext) {
280  x_ = reinterpret_cast<int32_t>(ext.address());
281  rmode_ = RelocInfo::EXTERNAL_REFERENCE;
282 }
283 
284 
285 Immediate::Immediate(Label* internal_offset) {
286  x_ = reinterpret_cast<int32_t>(internal_offset);
287  rmode_ = RelocInfo::INTERNAL_REFERENCE;
288 }
289 
290 
291 Immediate::Immediate(Handle<Object> handle) {
292  // Verify all Objects referred by code are NOT in new space.
293  Object* obj = *handle;
294  ASSERT(!HEAP->InNewSpace(obj));
295  if (obj->IsHeapObject()) {
296  x_ = reinterpret_cast<intptr_t>(handle.location());
297  rmode_ = RelocInfo::EMBEDDED_OBJECT;
298  } else {
299  // no relocation needed
300  x_ = reinterpret_cast<intptr_t>(obj);
301  rmode_ = RelocInfo::NONE;
302  }
303 }
304 
305 
306 Immediate::Immediate(Smi* value) {
307  x_ = reinterpret_cast<intptr_t>(value);
308  rmode_ = RelocInfo::NONE;
309 }
310 
311 
312 Immediate::Immediate(Address addr) {
313  x_ = reinterpret_cast<int32_t>(addr);
314  rmode_ = RelocInfo::NONE;
315 }
316 
317 
318 void Assembler::emit(uint32_t x) {
319  *reinterpret_cast<uint32_t*>(pc_) = x;
320  pc_ += sizeof(uint32_t);
321 }
322 
323 
324 void Assembler::emit(Handle<Object> handle) {
325  // Verify all Objects referred by code are NOT in new space.
326  Object* obj = *handle;
327  ASSERT(!isolate()->heap()->InNewSpace(obj));
328  if (obj->IsHeapObject()) {
329  emit(reinterpret_cast<intptr_t>(handle.location()),
330  RelocInfo::EMBEDDED_OBJECT);
331  } else {
332  // no relocation needed
333  emit(reinterpret_cast<intptr_t>(obj));
334  }
335 }
336 
337 
338 void Assembler::emit(uint32_t x, RelocInfo::Mode rmode, TypeFeedbackId id) {
339  if (rmode == RelocInfo::CODE_TARGET && !id.IsNone()) {
340  RecordRelocInfo(RelocInfo::CODE_TARGET_WITH_ID, id.ToInt());
341  } else if (rmode != RelocInfo::NONE) {
342  RecordRelocInfo(rmode);
343  }
344  emit(x);
345 }
346 
347 
348 void Assembler::emit(const Immediate& x) {
349  if (x.rmode_ == RelocInfo::INTERNAL_REFERENCE) {
350  Label* label = reinterpret_cast<Label*>(x.x_);
351  emit_code_relative_offset(label);
352  return;
353  }
354  if (x.rmode_ != RelocInfo::NONE) RecordRelocInfo(x.rmode_);
355  emit(x.x_);
356 }
357 
358 
359 void Assembler::emit_code_relative_offset(Label* label) {
360  if (label->is_bound()) {
361  int32_t pos;
362  pos = label->pos() + Code::kHeaderSize - kHeapObjectTag;
363  emit(pos);
364  } else {
365  emit_disp(label, Displacement::CODE_RELATIVE);
366  }
367 }
368 
369 
370 void Assembler::emit_w(const Immediate& x) {
371  ASSERT(x.rmode_ == RelocInfo::NONE);
372  uint16_t value = static_cast<uint16_t>(x.x_);
373  reinterpret_cast<uint16_t*>(pc_)[0] = value;
374  pc_ += sizeof(uint16_t);
375 }
376 
377 
379  return pc + sizeof(int32_t) + *reinterpret_cast<int32_t*>(pc);
380 }
381 
382 
384  int32_t* p = reinterpret_cast<int32_t*>(pc);
385  *p = target - (pc + sizeof(int32_t));
386  CPU::FlushICache(p, sizeof(int32_t));
387 }
388 
389 
391  return pc - kCallTargetAddressOffset;
392 }
393 
394 
395 Displacement Assembler::disp_at(Label* L) {
396  return Displacement(long_at(L->pos()));
397 }
398 
399 
400 void Assembler::disp_at_put(Label* L, Displacement disp) {
401  long_at_put(L->pos(), disp.data());
402 }
403 
404 
405 void Assembler::emit_disp(Label* L, Displacement::Type type) {
406  Displacement disp(L, type);
407  L->link_to(pc_offset());
408  emit(static_cast<int>(disp.data()));
409 }
410 
411 
412 void Assembler::emit_near_disp(Label* L) {
413  byte disp = 0x00;
414  if (L->is_near_linked()) {
415  int offset = L->near_link_pos() - pc_offset();
416  ASSERT(is_int8(offset));
417  disp = static_cast<byte>(offset & 0xFF);
418  }
419  L->link_to(pc_offset(), Label::kNear);
420  *pc_++ = disp;
421 }
422 
423 
424 void Operand::set_modrm(int mod, Register rm) {
425  ASSERT((mod & -4) == 0);
426  buf_[0] = mod << 6 | rm.code();
427  len_ = 1;
428 }
429 
430 
431 void Operand::set_sib(ScaleFactor scale, Register index, Register base) {
432  ASSERT(len_ == 1);
433  ASSERT((scale & -4) == 0);
434  // Use SIB with no index register only for base esp.
435  ASSERT(!index.is(esp) || base.is(esp));
436  buf_[1] = scale << 6 | index.code() << 3 | base.code();
437  len_ = 2;
438 }
439 
440 
441 void Operand::set_disp8(int8_t disp) {
442  ASSERT(len_ == 1 || len_ == 2);
443  *reinterpret_cast<int8_t*>(&buf_[len_++]) = disp;
444 }
445 
446 
447 void Operand::set_dispr(int32_t disp, RelocInfo::Mode rmode) {
448  ASSERT(len_ == 1 || len_ == 2);
449  int32_t* p = reinterpret_cast<int32_t*>(&buf_[len_]);
450  *p = disp;
451  len_ += sizeof(int32_t);
452  rmode_ = rmode;
453 }
454 
455 Operand::Operand(Register reg) {
456  // reg
457  set_modrm(3, reg);
458 }
459 
460 
461 Operand::Operand(XMMRegister xmm_reg) {
462  Register reg = { xmm_reg.code() };
463  set_modrm(3, reg);
464 }
465 
466 
467 Operand::Operand(int32_t disp, RelocInfo::Mode rmode) {
468  // [disp/r]
469  set_modrm(0, ebp);
470  set_dispr(disp, rmode);
471 }
472 
473 } } // namespace v8::internal
474 
475 #endif // V8_IA32_ASSEMBLER_IA32_INL_H_
byte * Address
Definition: globals.h:157
Isolate * isolate() const
Definition: assembler.h:61
static Object *& Object_at(Address addr)
Definition: v8memory.h:75
static Handle< Object > & Object_Handle_at(Address addr)
Definition: v8memory.h:79
const Register esp
static HeapObject * cast(Object *obj)
int int32_t
Definition: unicode.cc:47
bool is_int8(int x)
Definition: assembler.h:836
#define ASSERT(condition)
Definition: checks.h:270
unsigned short uint16_t
Definition: unicode.cc:46
uint8_t byte
Definition: globals.h:156
const Register ebp
static const int kSpecialTargetSize
static Address & Address_at(Address addr)
Definition: v8memory.h:71
static void set_target_address_at(Address pc, Address target)
const int kHeapObjectTag
Definition: v8.h:4009
const Register pc
static Code * GetCodeFromTargetAddress(Address address)
Definition: objects-inl.h:3559
static const int kCallTargetAddressOffset
static bool IsNop(Instr instr, int type=NON_MARKING_NOP)
static Address target_address_at(Address pc)
static JSGlobalPropertyCell * FromValueAddress(Address value)
Definition: objects.h:7993
static Address target_address_from_return_address(Address pc)
static const int kHeaderSize
Definition: objects.h:4549
#define HEAP
Definition: isolate.h:1433
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 and VFP2 enable use of VFP2 instructions if available enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of MIPS FPU instructions if NULL
Definition: flags.cc:301
#define RUNTIME_ENTRY(name, nargs, ressize)
static void FlushICache(void *start, size_t size)