V8 Project
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 
41 
42 #include "src/assembler.h"
43 #include "src/debug.h"
44 
45 namespace v8 {
46 namespace internal {
47 
48 bool CpuFeatures::SupportsCrankshaft() { return true; }
49 
50 
51 static const byte kCallOpcode = 0xE8;
52 static const int kNoCodeAgeSequenceLength = 5;
53 
54 
55 // The modes possibly affected by apply must be in kApplyMask.
56 void RelocInfo::apply(intptr_t delta, ICacheFlushMode icache_flush_mode) {
57  bool flush_icache = icache_flush_mode != SKIP_ICACHE_FLUSH;
59  int32_t* p = reinterpret_cast<int32_t*>(pc_);
60  *p -= delta; // Relocate entry.
61  if (flush_icache) CpuFeatures::FlushICache(p, sizeof(uint32_t));
62  } else if (rmode_ == CODE_AGE_SEQUENCE) {
63  if (*pc_ == kCallOpcode) {
64  int32_t* p = reinterpret_cast<int32_t*>(pc_ + 1);
65  *p -= delta; // Relocate entry.
66  if (flush_icache) CpuFeatures::FlushICache(p, sizeof(uint32_t));
67  }
68  } else if (rmode_ == JS_RETURN && IsPatchedReturnSequence()) {
69  // Special handling of js_return when a break point is set (call
70  // instruction has been inserted).
71  int32_t* p = reinterpret_cast<int32_t*>(pc_ + 1);
72  *p -= delta; // Relocate entry.
73  if (flush_icache) CpuFeatures::FlushICache(p, sizeof(uint32_t));
74  } else if (rmode_ == DEBUG_BREAK_SLOT && IsPatchedDebugBreakSlotSequence()) {
75  // Special handling of a debug break slot when a break point is set (call
76  // instruction has been inserted).
77  int32_t* p = reinterpret_cast<int32_t*>(pc_ + 1);
78  *p -= delta; // Relocate entry.
79  if (flush_icache) CpuFeatures::FlushICache(p, sizeof(uint32_t));
80  } else if (IsInternalReference(rmode_)) {
81  // absolute code pointer inside code object moves with the code object.
82  int32_t* p = reinterpret_cast<int32_t*>(pc_);
83  *p += delta; // Relocate entry.
84  if (flush_icache) CpuFeatures::FlushICache(p, sizeof(uint32_t));
85  }
86 }
87 
88 
89 Address RelocInfo::target_address() {
92 }
93 
94 
95 Address RelocInfo::target_address_address() {
99  return reinterpret_cast<Address>(pc_);
100 }
101 
102 
103 Address RelocInfo::constant_pool_entry_address() {
104  UNREACHABLE();
105  return NULL;
106 }
107 
108 
109 int RelocInfo::target_address_size() {
111 }
112 
113 
114 void RelocInfo::set_target_address(Address target,
115  WriteBarrierMode write_barrier_mode,
116  ICacheFlushMode icache_flush_mode) {
117  Assembler::set_target_address_at(pc_, host_, target, icache_flush_mode);
119  if (write_barrier_mode == UPDATE_WRITE_BARRIER && host() != NULL &&
120  IsCodeTarget(rmode_)) {
121  Object* target_code = Code::GetCodeFromTargetAddress(target);
122  host()->GetHeap()->incremental_marking()->RecordWriteIntoCode(
123  host(), this, HeapObject::cast(target_code));
124  }
125 }
126 
127 
128 Object* RelocInfo::target_object() {
130  return Memory::Object_at(pc_);
131 }
132 
133 
134 Handle<Object> RelocInfo::target_object_handle(Assembler* origin) {
137 }
138 
139 
140 void RelocInfo::set_target_object(Object* target,
141  WriteBarrierMode write_barrier_mode,
142  ICacheFlushMode icache_flush_mode) {
144  Memory::Object_at(pc_) = target;
145  if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
147  }
148  if (write_barrier_mode == UPDATE_WRITE_BARRIER &&
149  host() != NULL &&
150  target->IsHeapObject()) {
151  host()->GetHeap()->incremental_marking()->RecordWrite(
152  host(), &Memory::Object_at(pc_), HeapObject::cast(target));
153  }
154 }
155 
156 
157 Address RelocInfo::target_reference() {
159  return Memory::Address_at(pc_);
160 }
161 
162 
163 Address RelocInfo::target_runtime_entry(Assembler* origin) {
165  return reinterpret_cast<Address>(*reinterpret_cast<int32_t*>(pc_));
166 }
167 
168 
169 void RelocInfo::set_target_runtime_entry(Address target,
170  WriteBarrierMode write_barrier_mode,
171  ICacheFlushMode icache_flush_mode) {
173  if (target_address() != target) {
174  set_target_address(target, write_barrier_mode, icache_flush_mode);
175  }
176 }
177 
178 
179 Handle<Cell> RelocInfo::target_cell_handle() {
181  Address address = Memory::Address_at(pc_);
182  return Handle<Cell>(reinterpret_cast<Cell**>(address));
183 }
184 
185 
186 Cell* RelocInfo::target_cell() {
189 }
190 
191 
192 void RelocInfo::set_target_cell(Cell* cell,
193  WriteBarrierMode write_barrier_mode,
194  ICacheFlushMode icache_flush_mode) {
196  Address address = cell->address() + Cell::kValueOffset;
197  Memory::Address_at(pc_) = address;
198  if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
200  }
201  if (write_barrier_mode == UPDATE_WRITE_BARRIER && host() != NULL) {
202  // TODO(1550) We are passing NULL as a slot because cell can never be on
203  // evacuation candidate.
204  host()->GetHeap()->incremental_marking()->RecordWrite(
205  host(), NULL, cell);
206  }
207 }
208 
209 
210 Handle<Object> RelocInfo::code_age_stub_handle(Assembler* origin) {
212  DCHECK(*pc_ == kCallOpcode);
213  return Memory::Object_Handle_at(pc_ + 1);
214 }
215 
216 
217 Code* RelocInfo::code_age_stub() {
219  DCHECK(*pc_ == kCallOpcode);
222 }
223 
224 
225 void RelocInfo::set_code_age_stub(Code* stub,
226  ICacheFlushMode icache_flush_mode) {
227  DCHECK(*pc_ == kCallOpcode);
230  icache_flush_mode);
231 }
232 
233 
234 Address RelocInfo::call_address() {
235  DCHECK((IsJSReturn(rmode()) && IsPatchedReturnSequence()) ||
236  (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence()));
238 }
239 
240 
241 void RelocInfo::set_call_address(Address target) {
242  DCHECK((IsJSReturn(rmode()) && IsPatchedReturnSequence()) ||
243  (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence()));
245  if (host() != NULL) {
246  Object* target_code = Code::GetCodeFromTargetAddress(target);
247  host()->GetHeap()->incremental_marking()->RecordWriteIntoCode(
248  host(), this, HeapObject::cast(target_code));
249  }
250 }
251 
252 
253 Object* RelocInfo::call_object() {
254  return *call_object_address();
255 }
256 
257 
258 void RelocInfo::set_call_object(Object* target) {
259  *call_object_address() = target;
260 }
261 
262 
263 Object** RelocInfo::call_object_address() {
264  DCHECK((IsJSReturn(rmode()) && IsPatchedReturnSequence()) ||
265  (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence()));
266  return reinterpret_cast<Object**>(pc_ + 1);
267 }
268 
269 
270 void RelocInfo::WipeOut() {
273  } else if (IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)) {
274  // Effectively write zero into the relocation.
276  } else {
277  UNREACHABLE();
278  }
279 }
280 
281 
282 bool RelocInfo::IsPatchedReturnSequence() {
283  return *pc_ == kCallOpcode;
284 }
285 
286 
287 bool RelocInfo::IsPatchedDebugBreakSlotSequence() {
288  return !Assembler::IsNop(pc());
289 }
290 
291 
292 void RelocInfo::Visit(Isolate* isolate, ObjectVisitor* visitor) {
295  visitor->VisitEmbeddedPointer(this);
297  } else if (RelocInfo::IsCodeTarget(mode)) {
298  visitor->VisitCodeTarget(this);
299  } else if (mode == RelocInfo::CELL) {
300  visitor->VisitCell(this);
301  } else if (mode == RelocInfo::EXTERNAL_REFERENCE) {
302  visitor->VisitExternalReference(this);
304  } else if (RelocInfo::IsCodeAgeSequence(mode)) {
305  visitor->VisitCodeAgeSequence(this);
306  } else if (((RelocInfo::IsJSReturn(mode) &&
307  IsPatchedReturnSequence()) ||
309  IsPatchedDebugBreakSlotSequence())) &&
310  isolate->debug()->has_break_points()) {
311  visitor->VisitDebugTarget(this);
312  } else if (IsRuntimeEntry(mode)) {
313  visitor->VisitRuntimeEntry(this);
314  }
315 }
316 
317 
318 template<typename StaticVisitor>
319 void RelocInfo::Visit(Heap* heap) {
322  StaticVisitor::VisitEmbeddedPointer(heap, this);
324  } else if (RelocInfo::IsCodeTarget(mode)) {
325  StaticVisitor::VisitCodeTarget(heap, this);
326  } else if (mode == RelocInfo::CELL) {
327  StaticVisitor::VisitCell(heap, this);
328  } else if (mode == RelocInfo::EXTERNAL_REFERENCE) {
329  StaticVisitor::VisitExternalReference(this);
331  } else if (RelocInfo::IsCodeAgeSequence(mode)) {
332  StaticVisitor::VisitCodeAgeSequence(heap, this);
333  } else if (heap->isolate()->debug()->has_break_points() &&
335  IsPatchedReturnSequence()) ||
337  IsPatchedDebugBreakSlotSequence()))) {
338  StaticVisitor::VisitDebugTarget(heap, this);
339  } else if (IsRuntimeEntry(mode)) {
340  StaticVisitor::VisitRuntimeEntry(this);
341  }
342 }
343 
344 
345 
346 Immediate::Immediate(int x) {
347  x_ = x;
349 }
350 
351 
352 Immediate::Immediate(const ExternalReference& ext) {
353  x_ = reinterpret_cast<int32_t>(ext.address());
355 }
356 
357 
358 Immediate::Immediate(Label* internal_offset) {
359  x_ = reinterpret_cast<int32_t>(internal_offset);
361 }
362 
363 
364 Immediate::Immediate(Handle<Object> handle) {
365  AllowDeferredHandleDereference using_raw_address;
366  // Verify all Objects referred by code are NOT in new space.
367  Object* obj = *handle;
368  if (obj->IsHeapObject()) {
369  DCHECK(!HeapObject::cast(obj)->GetHeap()->InNewSpace(obj));
370  x_ = reinterpret_cast<intptr_t>(handle.location());
372  } else {
373  // no relocation needed
374  x_ = reinterpret_cast<intptr_t>(obj);
376  }
377 }
378 
379 
380 Immediate::Immediate(Smi* value) {
381  x_ = reinterpret_cast<intptr_t>(value);
383 }
384 
385 
387  x_ = reinterpret_cast<int32_t>(addr);
389 }
390 
391 
393  *reinterpret_cast<uint32_t*>(pc_) = x;
394  pc_ += sizeof(uint32_t);
395 }
396 
397 
399  AllowDeferredHandleDereference heap_object_check;
400  // Verify all Objects referred by code are NOT in new space.
401  Object* obj = *handle;
402  DCHECK(!isolate()->heap()->InNewSpace(obj));
403  if (obj->IsHeapObject()) {
404  emit(reinterpret_cast<intptr_t>(handle.location()),
406  } else {
407  // no relocation needed
408  emit(reinterpret_cast<intptr_t>(obj));
409  }
410 }
411 
412 
414  if (rmode == RelocInfo::CODE_TARGET && !id.IsNone()) {
416  } else if (!RelocInfo::IsNone(rmode)
417  && rmode != RelocInfo::CODE_AGE_SEQUENCE) {
418  RecordRelocInfo(rmode);
419  }
420  emit(x);
421 }
422 
423 
425  RelocInfo::Mode rmode,
426  TypeFeedbackId id) {
427  AllowDeferredHandleDereference embedding_raw_address;
428  emit(reinterpret_cast<intptr_t>(code.location()), rmode, id);
429 }
430 
431 
432 void Assembler::emit(const Immediate& x) {
434  Label* label = reinterpret_cast<Label*>(x.x_);
436  return;
437  }
439  emit(x.x_);
440 }
441 
442 
444  if (label->is_bound()) {
445  int32_t pos;
446  pos = label->pos() + Code::kHeaderSize - kHeapObjectTag;
447  emit(pos);
448  } else {
449  emit_disp(label, Displacement::CODE_RELATIVE);
450  }
451 }
452 
453 
454 void Assembler::emit_w(const Immediate& x) {
456  uint16_t value = static_cast<uint16_t>(x.x_);
457  reinterpret_cast<uint16_t*>(pc_)[0] = value;
458  pc_ += sizeof(uint16_t);
459 }
460 
461 
463  ConstantPoolArray* constant_pool) {
464  return pc + sizeof(int32_t) + *reinterpret_cast<int32_t*>(pc);
465 }
466 
467 
469  ConstantPoolArray* constant_pool,
470  Address target,
471  ICacheFlushMode icache_flush_mode) {
472  int32_t* p = reinterpret_cast<int32_t*>(pc);
473  *p = target - (pc + sizeof(int32_t));
474  if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
475  CpuFeatures::FlushICache(p, sizeof(int32_t));
476  }
477 }
478 
479 
481  return pc - kCallTargetAddressOffset;
482 }
483 
484 
487 }
488 
489 
490 Displacement Assembler::disp_at(Label* L) {
491  return Displacement(long_at(L->pos()));
492 }
493 
494 
495 void Assembler::disp_at_put(Label* L, Displacement disp) {
496  long_at_put(L->pos(), disp.data());
497 }
498 
499 
501  Displacement disp(L, type);
502  L->link_to(pc_offset());
503  emit(static_cast<int>(disp.data()));
504 }
505 
506 
508  byte disp = 0x00;
509  if (L->is_near_linked()) {
510  int offset = L->near_link_pos() - pc_offset();
511  DCHECK(is_int8(offset));
512  disp = static_cast<byte>(offset & 0xFF);
513  }
514  L->link_to(pc_offset(), Label::kNear);
515  *pc_++ = disp;
516 }
517 
518 
519 void Operand::set_modrm(int mod, Register rm) {
520  DCHECK((mod & -4) == 0);
521  buf_[0] = mod << 6 | rm.code();
522  len_ = 1;
523 }
524 
525 
526 void Operand::set_sib(ScaleFactor scale, Register index, Register base) {
527  DCHECK(len_ == 1);
528  DCHECK((scale & -4) == 0);
529  // Use SIB with no index register only for base esp.
530  DCHECK(!index.is(esp) || base.is(esp));
531  buf_[1] = scale << 6 | index.code() << 3 | base.code();
532  len_ = 2;
533 }
534 
535 
536 void Operand::set_disp8(int8_t disp) {
537  DCHECK(len_ == 1 || len_ == 2);
538  *reinterpret_cast<int8_t*>(&buf_[len_++]) = disp;
539 }
540 
541 
542 void Operand::set_dispr(int32_t disp, RelocInfo::Mode rmode) {
543  DCHECK(len_ == 1 || len_ == 2);
544  int32_t* p = reinterpret_cast<int32_t*>(&buf_[len_]);
545  *p = disp;
546  len_ += sizeof(int32_t);
547  rmode_ = rmode;
548 }
549 
550 Operand::Operand(Register reg) {
551  // reg
552  set_modrm(3, reg);
553 }
554 
555 
556 Operand::Operand(XMMRegister xmm_reg) {
557  Register reg = { xmm_reg.code() };
558  set_modrm(3, reg);
559 }
560 
561 
563  // [disp/r]
564  set_modrm(0, ebp);
565  set_dispr(disp, rmode);
566 }
567 
568 
569 Operand::Operand(Immediate imm) {
570  // [disp/r]
571  set_modrm(0, ebp);
572  set_dispr(imm.x_, imm.rmode_);
573 }
574 } } // namespace v8::internal
575 
576 #endif // V8_IA32_ASSEMBLER_IA32_INL_H_
Isolate * isolate() const
Definition: assembler.h:62
static const int kSpecialTargetSize
void emit_w(const Immediate &x)
Instruction * pc() const
static Address target_address_at(Address pc, ConstantPoolArray *constant_pool)
void disp_at_put(Label *L, Displacement disp)
void emit_code_relative_offset(Label *label)
void emit_disp(Label *L, Displacement::Type type)
static bool IsNop(Instr instr, int type=NON_MARKING_NOP)
void long_at_put(int pos, uint32_t x)
static const int kPatchDebugBreakSlotReturnOffset
static Address break_address_from_return_address(Address pc)
Displacement disp_at(Label *L)
void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data=0)
uint32_t long_at(int pos)
static void set_target_address_at(Address pc, ConstantPoolArray *constant_pool, Address target, ICacheFlushMode icache_flush_mode=FLUSH_ICACHE_IF_NEEDED)
static Address target_address_from_return_address(Address pc)
static const int kCallTargetAddressOffset
static const int kValueOffset
Definition: objects.h:9446
static Cell * FromValueAddress(Address value)
Definition: objects.h:9431
static Code * GetCodeFromTargetAddress(Address address)
Definition: objects-inl.h:5018
byte * instruction_start()
Definition: objects-inl.h:6176
static const int kHeaderSize
Definition: objects.h:5373
static void FlushICache(void *start, size_t size)
Heap * GetHeap() const
Definition: objects-inl.h:1379
IncrementalMarking * incremental_marking()
Definition: heap.h:1205
Immediate(Handle< T > handle)
static Object *& Object_at(Address addr)
Definition: v8memory.h:60
static Address & Address_at(Address addr)
Definition: v8memory.h:56
static Handle< Object > & Object_Handle_at(Address addr)
Definition: v8memory.h:64
Operand(Register reg, Shift shift=LSL, unsigned shift_amount=0)
static bool IsDebugBreakSlot(Mode mode)
Definition: assembler.h:436
static bool IsJSReturn(Mode mode)
Definition: assembler.h:412
static bool IsEmbeddedObject(Mode mode)
Definition: assembler.h:402
static bool IsRuntimeEntry(Mode mode)
Definition: assembler.h:405
static bool IsCodeTarget(Mode mode)
Definition: assembler.h:399
static bool IsNone(Mode mode)
Definition: assembler.h:439
static bool IsExternalReference(Mode mode)
Definition: assembler.h:430
byte * pc() const
Definition: assembler.h:457
Code * host() const
Definition: assembler.h:463
Mode rmode() const
Definition: assembler.h:459
static bool IsInternalReference(Mode mode)
Definition: assembler.h:433
static bool IsCodeAgeSequence(Mode mode)
Definition: assembler.h:442
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long mode(MIPS only)") DEFINE_BOOL(enable_always_align_csp
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be NULL
#define UNREACHABLE()
Definition: logging.h:30
#define DCHECK(condition)
Definition: logging.h:205
unsigned short uint16_t
Definition: unicode.cc:23
int int32_t
Definition: unicode.cc:24
@ UPDATE_WRITE_BARRIER
Definition: objects.h:235
const Register esp
TypeImpl< ZoneTypeConfig > Type
kSerializedDataOffset Object
Definition: objects-inl.h:5322
Handle< T > handle(T *t, Isolate *isolate)
Definition: handles.h:146
const Register pc
byte * Address
Definition: globals.h:101
const int kHeapObjectTag
Definition: v8.h:5737
static const byte kCallOpcode
@ SKIP_ICACHE_FLUSH
Definition: assembler.h:293
const Register ebp
static const int kNoCodeAgeSequenceLength
PerThreadAssertScopeDebugOnly< DEFERRED_HANDLE_DEREFERENCE_ASSERT, true > AllowDeferredHandleDereference
Definition: assert-scope.h:130
Debugger support for the V8 JavaScript engine.
Definition: accessors.cc:20