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
objects-visiting.h
Go to the documentation of this file.
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28 #ifndef V8_OBJECTS_VISITING_H_
29 #define V8_OBJECTS_VISITING_H_
30 
31 #include "allocation.h"
32 
33 // This file provides base classes and auxiliary methods for defining
34 // static object visitors used during GC.
35 // Visiting HeapObject body with a normal ObjectVisitor requires performing
36 // two switches on object's instance type to determine object size and layout
37 // and one or more virtual method calls on visitor itself.
38 // Static visitor is different: it provides a dispatch table which contains
39 // pointers to specialized visit functions. Each map has the visitor_id
40 // field which contains an index of specialized visitor to use.
41 
42 namespace v8 {
43 namespace internal {
44 
45 
46 // Base class for all static visitors.
47 class StaticVisitorBase : public AllStatic {
48  public:
49 #define VISITOR_ID_LIST(V) \
50  V(SeqAsciiString) \
51  V(SeqTwoByteString) \
52  V(ShortcutCandidate) \
53  V(ByteArray) \
54  V(FreeSpace) \
55  V(FixedArray) \
56  V(FixedDoubleArray) \
57  V(NativeContext) \
58  V(DataObject2) \
59  V(DataObject3) \
60  V(DataObject4) \
61  V(DataObject5) \
62  V(DataObject6) \
63  V(DataObject7) \
64  V(DataObject8) \
65  V(DataObject9) \
66  V(DataObjectGeneric) \
67  V(JSObject2) \
68  V(JSObject3) \
69  V(JSObject4) \
70  V(JSObject5) \
71  V(JSObject6) \
72  V(JSObject7) \
73  V(JSObject8) \
74  V(JSObject9) \
75  V(JSObjectGeneric) \
76  V(Struct2) \
77  V(Struct3) \
78  V(Struct4) \
79  V(Struct5) \
80  V(Struct6) \
81  V(Struct7) \
82  V(Struct8) \
83  V(Struct9) \
84  V(StructGeneric) \
85  V(ConsString) \
86  V(SlicedString) \
87  V(Oddball) \
88  V(Code) \
89  V(Map) \
90  V(PropertyCell) \
91  V(SharedFunctionInfo) \
92  V(JSFunction) \
93  V(JSWeakMap) \
94  V(JSRegExp)
95 
96  // For data objects, JS objects and structs along with generic visitor which
97  // can visit object of any size we provide visitors specialized by
98  // object size in words.
99  // Ids of specialized visitors are declared in a linear order (without
100  // holes) starting from the id of visitor specialized for 2 words objects
101  // (base visitor id) and ending with the id of generic visitor.
102  // Method GetVisitorIdForSize depends on this ordering to calculate visitor
103  // id of specialized visitor from given instance size, base visitor id and
104  // generic visitor's id.
105  enum VisitorId {
106 #define VISITOR_ID_ENUM_DECL(id) kVisit##id,
108 #undef VISITOR_ID_ENUM_DECL
110  kVisitDataObject = kVisitDataObject2,
111  kVisitJSObject = kVisitJSObject2,
112  kVisitStruct = kVisitStruct2,
114  };
115 
116  // Visitor ID should fit in one byte.
118 
119  // Determine which specialized visitor should be used for given instance type
120  // and instance type.
121  static VisitorId GetVisitorId(int instance_type, int instance_size);
122 
123  static VisitorId GetVisitorId(Map* map) {
124  return GetVisitorId(map->instance_type(), map->instance_size());
125  }
126 
127  // For visitors that allow specialization by size calculate VisitorId based
128  // on size, base visitor id and generic visitor id.
130  VisitorId generic,
131  int object_size) {
132  ASSERT((base == kVisitDataObject) ||
133  (base == kVisitStruct) ||
134  (base == kVisitJSObject));
135  ASSERT(IsAligned(object_size, kPointerSize));
136  ASSERT(kMinObjectSizeInWords * kPointerSize <= object_size);
138 
139  const VisitorId specialization = static_cast<VisitorId>(
140  base + (object_size >> kPointerSizeLog2) - kMinObjectSizeInWords);
141 
142  return Min(specialization, generic);
143  }
144 };
145 
146 
147 template<typename Callback>
149  public:
151  // We are not using memcpy to guarantee that during update
152  // every element of callbacks_ array will remain correct
153  // pointer (memcpy might be implemented as a byte copying loop).
154  for (int i = 0; i < StaticVisitorBase::kVisitorIdCount; i++) {
155  NoBarrier_Store(&callbacks_[i], other->callbacks_[i]);
156  }
157  }
158 
160  return reinterpret_cast<Callback>(callbacks_[id]);
161  }
162 
163  inline Callback GetVisitor(Map* map) {
164  return reinterpret_cast<Callback>(callbacks_[map->visitor_id()]);
165  }
166 
167  void Register(StaticVisitorBase::VisitorId id, Callback callback) {
168  ASSERT(id < StaticVisitorBase::kVisitorIdCount); // id is unsigned.
169  callbacks_[id] = reinterpret_cast<AtomicWord>(callback);
170  }
171 
172  template<typename Visitor,
175  int object_size_in_words>
177  static const int size = object_size_in_words * kPointerSize;
179  &Visitor::template VisitSpecialized<size>);
180  }
181 
182 
183  template<typename Visitor,
188  (generic - base + StaticVisitorBase::kMinObjectSizeInWords) == 10);
189  RegisterSpecialization<Visitor, base, generic, 2>();
190  RegisterSpecialization<Visitor, base, generic, 3>();
191  RegisterSpecialization<Visitor, base, generic, 4>();
192  RegisterSpecialization<Visitor, base, generic, 5>();
193  RegisterSpecialization<Visitor, base, generic, 6>();
194  RegisterSpecialization<Visitor, base, generic, 7>();
195  RegisterSpecialization<Visitor, base, generic, 8>();
196  RegisterSpecialization<Visitor, base, generic, 9>();
197  Register(generic, &Visitor::Visit);
198  }
199 
200  private:
202 };
203 
204 
205 template<typename StaticVisitor>
206 class BodyVisitorBase : public AllStatic {
207  public:
208  INLINE(static void IteratePointers(Heap* heap,
209  HeapObject* object,
210  int start_offset,
211  int end_offset)) {
212  Object** start_slot = reinterpret_cast<Object**>(object->address() +
213  start_offset);
214  Object** end_slot = reinterpret_cast<Object**>(object->address() +
215  end_offset);
216  StaticVisitor::VisitPointers(heap, start_slot, end_slot);
217  }
218 };
219 
220 
221 template<typename StaticVisitor, typename BodyDescriptor, typename ReturnType>
222 class FlexibleBodyVisitor : public BodyVisitorBase<StaticVisitor> {
223  public:
224  static inline ReturnType Visit(Map* map, HeapObject* object) {
225  int object_size = BodyDescriptor::SizeOf(map, object);
227  map->GetHeap(),
228  object,
229  BodyDescriptor::kStartOffset,
230  object_size);
231  return static_cast<ReturnType>(object_size);
232  }
233 
234  template<int object_size>
235  static inline ReturnType VisitSpecialized(Map* map, HeapObject* object) {
236  ASSERT(BodyDescriptor::SizeOf(map, object) == object_size);
238  map->GetHeap(),
239  object,
240  BodyDescriptor::kStartOffset,
241  object_size);
242  return static_cast<ReturnType>(object_size);
243  }
244 };
245 
246 
247 template<typename StaticVisitor, typename BodyDescriptor, typename ReturnType>
248 class FixedBodyVisitor : public BodyVisitorBase<StaticVisitor> {
249  public:
250  static inline ReturnType Visit(Map* map, HeapObject* object) {
252  map->GetHeap(),
253  object,
254  BodyDescriptor::kStartOffset,
255  BodyDescriptor::kEndOffset);
256  return static_cast<ReturnType>(BodyDescriptor::kSize);
257  }
258 };
259 
260 
261 // Base class for visitors used for a linear new space iteration.
262 // IterateBody returns size of visited object.
263 // Certain types of objects (i.e. Code objects) are not handled
264 // by dispatch table of this visitor because they cannot appear
265 // in the new space.
266 //
267 // This class is intended to be used in the following way:
268 //
269 // class SomeVisitor : public StaticNewSpaceVisitor<SomeVisitor> {
270 // ...
271 // }
272 //
273 // This is an example of Curiously recurring template pattern
274 // (see http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern).
275 // We use CRTP to guarantee aggressive compile time optimizations (i.e.
276 // inlining and specialization of StaticVisitor::VisitPointers methods).
277 template<typename StaticVisitor>
279  public:
280  static void Initialize();
281 
282  static inline int IterateBody(Map* map, HeapObject* obj) {
283  return table_.GetVisitor(map)(map, obj);
284  }
285 
286  static inline void VisitPointers(Heap* heap, Object** start, Object** end) {
287  for (Object** p = start; p < end; p++) StaticVisitor::VisitPointer(heap, p);
288  }
289 
290  private:
291  static inline int VisitJSFunction(Map* map, HeapObject* object) {
292  Heap* heap = map->GetHeap();
293  VisitPointers(heap,
296 
297  // Don't visit code entry. We are using this visitor only during scavenges.
298 
300  heap,
301  HeapObject::RawField(object,
303  HeapObject::RawField(object,
305  return JSFunction::kSize;
306  }
307 
308  static inline int VisitByteArray(Map* map, HeapObject* object) {
309  return reinterpret_cast<ByteArray*>(object)->ByteArraySize();
310  }
311 
312  static inline int VisitFixedDoubleArray(Map* map, HeapObject* object) {
313  int length = reinterpret_cast<FixedDoubleArray*>(object)->length();
314  return FixedDoubleArray::SizeFor(length);
315  }
316 
317  static inline int VisitJSObject(Map* map, HeapObject* object) {
318  return JSObjectVisitor::Visit(map, object);
319  }
320 
321  static inline int VisitSeqAsciiString(Map* map, HeapObject* object) {
322  return SeqAsciiString::cast(object)->
323  SeqAsciiStringSize(map->instance_type());
324  }
325 
326  static inline int VisitSeqTwoByteString(Map* map, HeapObject* object) {
327  return SeqTwoByteString::cast(object)->
328  SeqTwoByteStringSize(map->instance_type());
329  }
330 
331  static inline int VisitFreeSpace(Map* map, HeapObject* object) {
332  return FreeSpace::cast(object)->Size();
333  }
334 
335  class DataObjectVisitor {
336  public:
337  template<int object_size>
338  static inline int VisitSpecialized(Map* map, HeapObject* object) {
339  return object_size;
340  }
341 
342  static inline int Visit(Map* map, HeapObject* object) {
343  return map->instance_size();
344  }
345  };
346 
347  typedef FlexibleBodyVisitor<StaticVisitor,
348  StructBodyDescriptor,
349  int> StructVisitor;
350 
351  typedef FlexibleBodyVisitor<StaticVisitor,
352  JSObject::BodyDescriptor,
353  int> JSObjectVisitor;
354 
355  typedef int (*Callback)(Map* map, HeapObject* object);
356 
357  static VisitorDispatchTable<Callback> table_;
358 };
359 
360 
361 template<typename StaticVisitor>
362 VisitorDispatchTable<typename StaticNewSpaceVisitor<StaticVisitor>::Callback>
363  StaticNewSpaceVisitor<StaticVisitor>::table_;
364 
365 
366 // Base class for visitors used to transitively mark the entire heap.
367 // IterateBody returns nothing.
368 // Certain types of objects might not be handled by this base class and
369 // no visitor function is registered by the generic initialization. A
370 // specialized visitor function needs to be provided by the inheriting
371 // class itself for those cases.
372 //
373 // This class is intended to be used in the following way:
374 //
375 // class SomeVisitor : public StaticMarkingVisitor<SomeVisitor> {
376 // ...
377 // }
378 //
379 // This is an example of Curiously recurring template pattern.
380 template<typename StaticVisitor>
382  public:
383  static void Initialize();
384 
385  static inline void IterateBody(Map* map, HeapObject* obj) {
386  table_.GetVisitor(map)(map, obj);
387  }
388 
389  static inline void VisitCodeEntry(Heap* heap, Address entry_address);
390  static inline void VisitEmbeddedPointer(Heap* heap, RelocInfo* rinfo);
391  static inline void VisitGlobalPropertyCell(Heap* heap, RelocInfo* rinfo);
392  static inline void VisitDebugTarget(Heap* heap, RelocInfo* rinfo);
393  static inline void VisitCodeTarget(Heap* heap, RelocInfo* rinfo);
394  static inline void VisitExternalReference(RelocInfo* rinfo) { }
395  static inline void VisitRuntimeEntry(RelocInfo* rinfo) { }
396 
397  // TODO(mstarzinger): This should be made protected once refactoring is done.
398  static inline void VisitNativeContext(Map* map, HeapObject* object);
399 
400  // TODO(mstarzinger): This should be made protected once refactoring is done.
401  // Mark non-optimize code for functions inlined into the given optimized
402  // code. This will prevent it from being flushed.
403  static void MarkInlinedFunctionsCode(Heap* heap, Code* code);
404 
405  protected:
406  static inline void VisitMap(Map* map, HeapObject* object);
407  static inline void VisitCode(Map* map, HeapObject* object);
408  static inline void VisitSharedFunctionInfo(Map* map, HeapObject* object);
409  static inline void VisitJSFunction(Map* map, HeapObject* object);
410  static inline void VisitJSRegExp(Map* map, HeapObject* object);
411 
412  // Mark pointers in a Map and its TransitionArray together, possibly
413  // treating transitions or back pointers weak.
414  static void MarkMapContents(Heap* heap, Map* map);
415  static void MarkTransitionArray(Heap* heap, TransitionArray* transitions);
416 
417  // Code flushing support.
418  static inline bool IsFlushable(Heap* heap, JSFunction* function);
419  static inline bool IsFlushable(Heap* heap, SharedFunctionInfo* shared_info);
420 
421  // Helpers used by code flushing support that visit pointer fields and treat
422  // references to code objects either strongly or weakly.
423  static void VisitSharedFunctionInfoStrongCode(Heap* heap, HeapObject* object);
424  static void VisitSharedFunctionInfoWeakCode(Heap* heap, HeapObject* object);
425  static void VisitJSFunctionStrongCode(Heap* heap, HeapObject* object);
426  static void VisitJSFunctionWeakCode(Heap* heap, HeapObject* object);
427 
429  public:
430  template<int size>
431  static inline void VisitSpecialized(Map* map, HeapObject* object) {
432  }
433 
434  static inline void Visit(Map* map, HeapObject* object) {
435  }
436  };
437 
438  typedef FlexibleBodyVisitor<StaticVisitor,
441 
442  typedef FlexibleBodyVisitor<StaticVisitor,
445 
446  typedef void (*Callback)(Map* map, HeapObject* object);
447 
449 };
450 
451 
452 template<typename StaticVisitor>
455 
456 
457 } } // namespace v8::internal
458 
459 #endif // V8_OBJECTS_VISITING_H_
byte * Address
Definition: globals.h:157
static void VisitCodeEntry(Heap *heap, Address entry_address)
static void VisitCodeTarget(Heap *heap, RelocInfo *rinfo)
STATIC_ASSERT(kVisitorIdCount<=256)
static const int kCodeEntryOffset
Definition: objects.h:6182
static VisitorDispatchTable< Callback > table_
static void VisitJSFunction(Map *map, HeapObject *object)
static void VisitJSRegExp(Map *map, HeapObject *object)
static void MarkInlinedFunctionsCode(Heap *heap, Code *code)
static void VisitPointers(Heap *heap, Object **start, Object **end)
static void MarkMapContents(Heap *heap, Map *map)
static void VisitDebugTarget(Heap *heap, RelocInfo *rinfo)
static VisitorId GetVisitorIdForSize(VisitorId base, VisitorId generic, int object_size)
static VisitorId GetVisitorId(Map *map)
static FreeSpace * cast(Object *obj)
static void VisitSpecialized(Map *map, HeapObject *object)
#define ASSERT(condition)
Definition: checks.h:270
static bool IsFlushable(Heap *heap, JSFunction *function)
static void VisitExternalReference(RelocInfo *rinfo)
const int kPointerSizeLog2
Definition: globals.h:232
#define VISITOR_ID_LIST(V)
static void VisitGlobalPropertyCell(Heap *heap, RelocInfo *rinfo)
void NoBarrier_Store(volatile Atomic32 *ptr, Atomic32 value)
static ReturnType Visit(Map *map, HeapObject *object)
static Object ** RawField(HeapObject *obj, int offset)
Definition: objects-inl.h:971
void(* Callback)(Map *map, HeapObject *object)
FlexibleBodyVisitor< StaticVisitor, StructBodyDescriptor, void > StructObjectVisitor
STATIC_ASSERT((FixedDoubleArray::kHeaderSize &kDoubleAlignmentMask)==0)
void Register(StaticVisitorBase::VisitorId id, Callback callback)
INLINE(static void IteratePointers(Heap *heap, HeapObject *object, int start_offset, int end_offset))
const int kPointerSize
Definition: globals.h:220
bool IsAligned(T value, U alignment)
Definition: utils.h:206
static SeqAsciiString * cast(Object *obj)
static ReturnType Visit(Map *map, HeapObject *object)
static void VisitRuntimeEntry(RelocInfo *rinfo)
intptr_t AtomicWord
Definition: atomicops.h:75
static void IterateBody(Map *map, HeapObject *obj)
static const int kPropertiesOffset
Definition: objects.h:2171
static void VisitSharedFunctionInfoStrongCode(Heap *heap, HeapObject *object)
static const int kMaxNonCodeHeapObjectSize
Definition: spaces.h:717
static void VisitCode(Map *map, HeapObject *object)
static int SizeFor(int length)
Definition: objects.h:2434
static int IterateBody(Map *map, HeapObject *obj)
static void VisitSharedFunctionInfoWeakCode(Heap *heap, HeapObject *object)
Callback GetVisitorById(StaticVisitorBase::VisitorId id)
static const int kNonWeakFieldsEndOffset
Definition: objects.h:6189
static SeqTwoByteString * cast(Object *obj)
#define VISITOR_ID_ENUM_DECL(id)
FlexibleBodyVisitor< StaticVisitor, JSObject::BodyDescriptor, void > JSObjectVisitor
InstanceType instance_type()
Definition: objects-inl.h:3009
static void VisitSharedFunctionInfo(Map *map, HeapObject *object)
static void VisitJSFunctionWeakCode(Heap *heap, HeapObject *object)
static void Visit(Map *map, HeapObject *object)
static void VisitMap(Map *map, HeapObject *object)
static VisitorId GetVisitorId(int instance_type, int instance_size)
static const int kSize
Definition: objects.h:6191
static void MarkTransitionArray(Heap *heap, TransitionArray *transitions)
void CopyFrom(VisitorDispatchTable *other)
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 code(assertions) for debugging") DEFINE_bool(code_comments
static void VisitNativeContext(Map *map, HeapObject *object)
T Min(T a, T b)
Definition: utils.h:229
static void VisitJSFunctionStrongCode(Heap *heap, HeapObject *object)
static ReturnType VisitSpecialized(Map *map, HeapObject *object)
static void VisitEmbeddedPointer(Heap *heap, RelocInfo *rinfo)