v8  3.11.10(node0.8.26)
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);
153  Address address = Memory::Address_at(pc_);
156  return reinterpret_cast<JSGlobalPropertyCell*>(object);
157 }
158 
159 
160 void RelocInfo::set_target_cell(JSGlobalPropertyCell* cell,
161  WriteBarrierMode mode) {
162  ASSERT(rmode_ == RelocInfo::GLOBAL_PROPERTY_CELL);
163  Address address = cell->address() + JSGlobalPropertyCell::kValueOffset;
164  Memory::Address_at(pc_) = address;
165  CPU::FlushICache(pc_, sizeof(Address));
166  if (mode == UPDATE_WRITE_BARRIER && host() != NULL) {
167  // TODO(1550) We are passing NULL as a slot because cell can never be on
168  // evacuation candidate.
169  host()->GetHeap()->incremental_marking()->RecordWrite(
170  host(), NULL, cell);
171  }
172 }
173 
174 
175 Address RelocInfo::call_address() {
176  ASSERT((IsJSReturn(rmode()) && IsPatchedReturnSequence()) ||
177  (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence()));
178  return Assembler::target_address_at(pc_ + 1);
179 }
180 
181 
182 void RelocInfo::set_call_address(Address target) {
183  ASSERT((IsJSReturn(rmode()) && IsPatchedReturnSequence()) ||
184  (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence()));
185  Assembler::set_target_address_at(pc_ + 1, target);
186  if (host() != NULL) {
187  Object* target_code = Code::GetCodeFromTargetAddress(target);
188  host()->GetHeap()->incremental_marking()->RecordWriteIntoCode(
189  host(), this, HeapObject::cast(target_code));
190  }
191 }
192 
193 
194 Object* RelocInfo::call_object() {
195  return *call_object_address();
196 }
197 
198 
199 void RelocInfo::set_call_object(Object* target) {
200  *call_object_address() = target;
201 }
202 
203 
204 Object** RelocInfo::call_object_address() {
205  ASSERT((IsJSReturn(rmode()) && IsPatchedReturnSequence()) ||
206  (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence()));
207  return reinterpret_cast<Object**>(pc_ + 1);
208 }
209 
210 
211 bool RelocInfo::IsPatchedReturnSequence() {
212  return *pc_ == 0xE8;
213 }
214 
215 
216 bool RelocInfo::IsPatchedDebugBreakSlotSequence() {
217  return !Assembler::IsNop(pc());
218 }
219 
220 
221 void RelocInfo::Visit(ObjectVisitor* visitor) {
222  RelocInfo::Mode mode = rmode();
223  if (mode == RelocInfo::EMBEDDED_OBJECT) {
224  visitor->VisitEmbeddedPointer(this);
225  CPU::FlushICache(pc_, sizeof(Address));
226  } else if (RelocInfo::IsCodeTarget(mode)) {
227  visitor->VisitCodeTarget(this);
228  } else if (mode == RelocInfo::GLOBAL_PROPERTY_CELL) {
229  visitor->VisitGlobalPropertyCell(this);
230  } else if (mode == RelocInfo::EXTERNAL_REFERENCE) {
231  visitor->VisitExternalReference(this);
232  CPU::FlushICache(pc_, sizeof(Address));
233 #ifdef ENABLE_DEBUGGER_SUPPORT
234  // TODO(isolates): Get a cached isolate below.
235  } else if (((RelocInfo::IsJSReturn(mode) &&
236  IsPatchedReturnSequence()) ||
237  (RelocInfo::IsDebugBreakSlot(mode) &&
238  IsPatchedDebugBreakSlotSequence())) &&
239  Isolate::Current()->debug()->has_break_points()) {
240  visitor->VisitDebugTarget(this);
241 #endif
242  } else if (mode == RelocInfo::RUNTIME_ENTRY) {
243  visitor->VisitRuntimeEntry(this);
244  }
245 }
246 
247 
248 template<typename StaticVisitor>
249 void RelocInfo::Visit(Heap* heap) {
250  RelocInfo::Mode mode = rmode();
251  if (mode == RelocInfo::EMBEDDED_OBJECT) {
252  StaticVisitor::VisitEmbeddedPointer(heap, this);
253  CPU::FlushICache(pc_, sizeof(Address));
254  } else if (RelocInfo::IsCodeTarget(mode)) {
255  StaticVisitor::VisitCodeTarget(heap, this);
256  } else if (mode == RelocInfo::GLOBAL_PROPERTY_CELL) {
257  StaticVisitor::VisitGlobalPropertyCell(heap, this);
258  } else if (mode == RelocInfo::EXTERNAL_REFERENCE) {
259  StaticVisitor::VisitExternalReference(this);
260  CPU::FlushICache(pc_, sizeof(Address));
261 #ifdef ENABLE_DEBUGGER_SUPPORT
262  } else if (heap->isolate()->debug()->has_break_points() &&
263  ((RelocInfo::IsJSReturn(mode) &&
264  IsPatchedReturnSequence()) ||
265  (RelocInfo::IsDebugBreakSlot(mode) &&
266  IsPatchedDebugBreakSlotSequence()))) {
267  StaticVisitor::VisitDebugTarget(heap, this);
268 #endif
269  } else if (mode == RelocInfo::RUNTIME_ENTRY) {
270  StaticVisitor::VisitRuntimeEntry(this);
271  }
272 }
273 
274 
275 
276 Immediate::Immediate(int x) {
277  x_ = x;
278  rmode_ = RelocInfo::NONE;
279 }
280 
281 
282 Immediate::Immediate(const ExternalReference& ext) {
283  x_ = reinterpret_cast<int32_t>(ext.address());
284  rmode_ = RelocInfo::EXTERNAL_REFERENCE;
285 }
286 
287 
288 Immediate::Immediate(Label* internal_offset) {
289  x_ = reinterpret_cast<int32_t>(internal_offset);
290  rmode_ = RelocInfo::INTERNAL_REFERENCE;
291 }
292 
293 
294 Immediate::Immediate(Handle<Object> handle) {
295  // Verify all Objects referred by code are NOT in new space.
296  Object* obj = *handle;
297  ASSERT(!HEAP->InNewSpace(obj));
298  if (obj->IsHeapObject()) {
299  x_ = reinterpret_cast<intptr_t>(handle.location());
300  rmode_ = RelocInfo::EMBEDDED_OBJECT;
301  } else {
302  // no relocation needed
303  x_ = reinterpret_cast<intptr_t>(obj);
304  rmode_ = RelocInfo::NONE;
305  }
306 }
307 
308 
309 Immediate::Immediate(Smi* value) {
310  x_ = reinterpret_cast<intptr_t>(value);
311  rmode_ = RelocInfo::NONE;
312 }
313 
314 
315 Immediate::Immediate(Address addr) {
316  x_ = reinterpret_cast<int32_t>(addr);
317  rmode_ = RelocInfo::NONE;
318 }
319 
320 
321 void Assembler::emit(uint32_t x) {
322  *reinterpret_cast<uint32_t*>(pc_) = x;
323  pc_ += sizeof(uint32_t);
324 }
325 
326 
327 void Assembler::emit(Handle<Object> handle) {
328  // Verify all Objects referred by code are NOT in new space.
329  Object* obj = *handle;
330  ASSERT(!isolate()->heap()->InNewSpace(obj));
331  if (obj->IsHeapObject()) {
332  emit(reinterpret_cast<intptr_t>(handle.location()),
333  RelocInfo::EMBEDDED_OBJECT);
334  } else {
335  // no relocation needed
336  emit(reinterpret_cast<intptr_t>(obj));
337  }
338 }
339 
340 
341 void Assembler::emit(uint32_t x, RelocInfo::Mode rmode, unsigned id) {
342  if (rmode == RelocInfo::CODE_TARGET && id != kNoASTId) {
343  RecordRelocInfo(RelocInfo::CODE_TARGET_WITH_ID, static_cast<intptr_t>(id));
344  } else if (rmode != RelocInfo::NONE) {
345  RecordRelocInfo(rmode);
346  }
347  emit(x);
348 }
349 
350 
351 void Assembler::emit(const Immediate& x) {
352  if (x.rmode_ == RelocInfo::INTERNAL_REFERENCE) {
353  Label* label = reinterpret_cast<Label*>(x.x_);
354  emit_code_relative_offset(label);
355  return;
356  }
357  if (x.rmode_ != RelocInfo::NONE) RecordRelocInfo(x.rmode_);
358  emit(x.x_);
359 }
360 
361 
362 void Assembler::emit_code_relative_offset(Label* label) {
363  if (label->is_bound()) {
364  int32_t pos;
365  pos = label->pos() + Code::kHeaderSize - kHeapObjectTag;
366  emit(pos);
367  } else {
368  emit_disp(label, Displacement::CODE_RELATIVE);
369  }
370 }
371 
372 
373 void Assembler::emit_w(const Immediate& x) {
374  ASSERT(x.rmode_ == RelocInfo::NONE);
375  uint16_t value = static_cast<uint16_t>(x.x_);
376  reinterpret_cast<uint16_t*>(pc_)[0] = value;
377  pc_ += sizeof(uint16_t);
378 }
379 
380 
382  return pc + sizeof(int32_t) + *reinterpret_cast<int32_t*>(pc);
383 }
384 
385 
387  int32_t* p = reinterpret_cast<int32_t*>(pc);
388  *p = target - (pc + sizeof(int32_t));
389  CPU::FlushICache(p, sizeof(int32_t));
390 }
391 
392 
393 Displacement Assembler::disp_at(Label* L) {
394  return Displacement(long_at(L->pos()));
395 }
396 
397 
398 void Assembler::disp_at_put(Label* L, Displacement disp) {
399  long_at_put(L->pos(), disp.data());
400 }
401 
402 
403 void Assembler::emit_disp(Label* L, Displacement::Type type) {
404  Displacement disp(L, type);
405  L->link_to(pc_offset());
406  emit(static_cast<int>(disp.data()));
407 }
408 
409 
410 void Assembler::emit_near_disp(Label* L) {
411  byte disp = 0x00;
412  if (L->is_near_linked()) {
413  int offset = L->near_link_pos() - pc_offset();
414  ASSERT(is_int8(offset));
415  disp = static_cast<byte>(offset & 0xFF);
416  }
417  L->link_to(pc_offset(), Label::kNear);
418  *pc_++ = disp;
419 }
420 
421 
422 void Operand::set_modrm(int mod, Register rm) {
423  ASSERT((mod & -4) == 0);
424  buf_[0] = mod << 6 | rm.code();
425  len_ = 1;
426 }
427 
428 
429 void Operand::set_sib(ScaleFactor scale, Register index, Register base) {
430  ASSERT(len_ == 1);
431  ASSERT((scale & -4) == 0);
432  // Use SIB with no index register only for base esp.
433  ASSERT(!index.is(esp) || base.is(esp));
434  buf_[1] = scale << 6 | index.code() << 3 | base.code();
435  len_ = 2;
436 }
437 
438 
439 void Operand::set_disp8(int8_t disp) {
440  ASSERT(len_ == 1 || len_ == 2);
441  *reinterpret_cast<int8_t*>(&buf_[len_++]) = disp;
442 }
443 
444 
445 void Operand::set_dispr(int32_t disp, RelocInfo::Mode rmode) {
446  ASSERT(len_ == 1 || len_ == 2);
447  int32_t* p = reinterpret_cast<int32_t*>(&buf_[len_]);
448  *p = disp;
449  len_ += sizeof(int32_t);
450  rmode_ = rmode;
451 }
452 
453 Operand::Operand(Register reg) {
454  // reg
455  set_modrm(3, reg);
456 }
457 
458 
459 Operand::Operand(XMMRegister xmm_reg) {
460  Register reg = { xmm_reg.code() };
461  set_modrm(3, reg);
462 }
463 
464 
465 Operand::Operand(int32_t disp, RelocInfo::Mode rmode) {
466  // [disp/r]
467  set_modrm(0, ebp);
468  set_dispr(disp, rmode);
469 }
470 
471 } } // namespace v8::internal
472 
473 #endif // V8_IA32_ASSEMBLER_IA32_INL_H_
byte * Address
Definition: globals.h:172
Isolate * isolate() const
Definition: assembler.h:62
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:830
#define ASSERT(condition)
Definition: checks.h:270
unsigned short uint16_t
Definition: unicode.cc:46
uint8_t byte
Definition: globals.h:171
const unsigned kNoASTId
Definition: assembler.h:54
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:3848
const Register pc
static Code * GetCodeFromTargetAddress(Address address)
Definition: objects-inl.h:3380
static bool IsNop(Instr instr, int type=NON_MARKING_NOP)
static Address target_address_at(Address pc)
static const int kHeaderSize
Definition: objects.h:4513
#define HEAP
Definition: isolate.h:1408
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 trace on stack replacement optimize closures functions with arguments object optimize functions containing for in loops profiler considers IC stability primitive functions trigger their own optimization re try self optimization if it failed insert an interrupt check at function exit execution budget before interrupt is triggered call count before self optimization self_optimization count_based_interrupts weighted_back_edges trace_opt 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 enable use of ARMv7 instructions if enable use of MIPS FPU instructions if NULL
Definition: flags.cc:274
static HeapObject * FromAddress(Address address)
Definition: objects-inl.h:1163
#define RUNTIME_ENTRY(name, nargs, ressize)
static void FlushICache(void *start, size_t size)
FlagType type() const
Definition: flags.cc:1358