The data contained in this repository can be downloaded to your computer using one of several clients.
Please see the documentation of your version control software client for more information.

Please select the desired protocol below to get the URL.

This URL has Read-Only access.

Statistics
| Branch: | Revision:

main_repo / deps / v8 / src / objects-visiting.h @ f230a1cf

History | View | Annotate | Download (17.8 KB)

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(SeqOneByteString)           \
51
  V(SeqTwoByteString)         \
52
  V(ShortcutCandidate)        \
53
  V(ByteArray)                \
54
  V(FreeSpace)                \
55
  V(FixedArray)               \
56
  V(FixedDoubleArray)         \
57
  V(ConstantPoolArray)        \
58
  V(NativeContext)            \
59
  V(AllocationSite)           \
60
  V(DataObject2)              \
61
  V(DataObject3)              \
62
  V(DataObject4)              \
63
  V(DataObject5)              \
64
  V(DataObject6)              \
65
  V(DataObject7)              \
66
  V(DataObject8)              \
67
  V(DataObject9)              \
68
  V(DataObjectGeneric)        \
69
  V(JSObject2)                \
70
  V(JSObject3)                \
71
  V(JSObject4)                \
72
  V(JSObject5)                \
73
  V(JSObject6)                \
74
  V(JSObject7)                \
75
  V(JSObject8)                \
76
  V(JSObject9)                \
77
  V(JSObjectGeneric)          \
78
  V(Struct2)                  \
79
  V(Struct3)                  \
80
  V(Struct4)                  \
81
  V(Struct5)                  \
82
  V(Struct6)                  \
83
  V(Struct7)                  \
84
  V(Struct8)                  \
85
  V(Struct9)                  \
86
  V(StructGeneric)            \
87
  V(ConsString)               \
88
  V(SlicedString)             \
89
  V(Symbol)                   \
90
  V(Oddball)                  \
91
  V(Code)                     \
92
  V(Map)                      \
93
  V(Cell)                     \
94
  V(PropertyCell)             \
95
  V(SharedFunctionInfo)       \
96
  V(JSFunction)               \
97
  V(JSWeakMap)                \
98
  V(JSWeakSet)                \
99
  V(JSArrayBuffer)            \
100
  V(JSTypedArray)             \
101
  V(JSDataView)               \
102
  V(JSRegExp)
103

    
104
  // For data objects, JS objects and structs along with generic visitor which
105
  // can visit object of any size we provide visitors specialized by
106
  // object size in words.
107
  // Ids of specialized visitors are declared in a linear order (without
108
  // holes) starting from the id of visitor specialized for 2 words objects
109
  // (base visitor id) and ending with the id of generic visitor.
110
  // Method GetVisitorIdForSize depends on this ordering to calculate visitor
111
  // id of specialized visitor from given instance size, base visitor id and
112
  // generic visitor's id.
113
  enum VisitorId {
114
#define VISITOR_ID_ENUM_DECL(id)  kVisit##id,
115
    VISITOR_ID_LIST(VISITOR_ID_ENUM_DECL)
116
#undef VISITOR_ID_ENUM_DECL
117
    kVisitorIdCount,
118
    kVisitDataObject = kVisitDataObject2,
119
    kVisitJSObject = kVisitJSObject2,
120
    kVisitStruct = kVisitStruct2,
121
    kMinObjectSizeInWords = 2
122
  };
123

    
124
  // Visitor ID should fit in one byte.
125
  STATIC_ASSERT(kVisitorIdCount <= 256);
126

    
127
  // Determine which specialized visitor should be used for given instance type
128
  // and instance type.
129
  static VisitorId GetVisitorId(int instance_type, int instance_size);
130

    
131
  static VisitorId GetVisitorId(Map* map) {
132
    return GetVisitorId(map->instance_type(), map->instance_size());
133
  }
134

    
135
  // For visitors that allow specialization by size calculate VisitorId based
136
  // on size, base visitor id and generic visitor id.
137
  static VisitorId GetVisitorIdForSize(VisitorId base,
138
                                       VisitorId generic,
139
                                       int object_size) {
140
    ASSERT((base == kVisitDataObject) ||
141
           (base == kVisitStruct) ||
142
           (base == kVisitJSObject));
143
    ASSERT(IsAligned(object_size, kPointerSize));
144
    ASSERT(kMinObjectSizeInWords * kPointerSize <= object_size);
145
    ASSERT(object_size <= Page::kMaxNonCodeHeapObjectSize);
146

    
147
    const VisitorId specialization = static_cast<VisitorId>(
148
        base + (object_size >> kPointerSizeLog2) - kMinObjectSizeInWords);
149

    
150
    return Min(specialization, generic);
151
  }
152
};
153

    
154

    
155
template<typename Callback>
156
class VisitorDispatchTable {
157
 public:
158
  void CopyFrom(VisitorDispatchTable* other) {
159
    // We are not using memcpy to guarantee that during update
160
    // every element of callbacks_ array will remain correct
161
    // pointer (memcpy might be implemented as a byte copying loop).
162
    for (int i = 0; i < StaticVisitorBase::kVisitorIdCount; i++) {
163
      NoBarrier_Store(&callbacks_[i], other->callbacks_[i]);
164
    }
165
  }
166

    
167
  inline Callback GetVisitorById(StaticVisitorBase::VisitorId id) {
168
    return reinterpret_cast<Callback>(callbacks_[id]);
169
  }
170

    
171
  inline Callback GetVisitor(Map* map) {
172
    return reinterpret_cast<Callback>(callbacks_[map->visitor_id()]);
173
  }
174

    
175
  void Register(StaticVisitorBase::VisitorId id, Callback callback) {
176
    ASSERT(id < StaticVisitorBase::kVisitorIdCount);  // id is unsigned.
177
    callbacks_[id] = reinterpret_cast<AtomicWord>(callback);
178
  }
179

    
180
  template<typename Visitor,
181
           StaticVisitorBase::VisitorId base,
182
           StaticVisitorBase::VisitorId generic,
183
           int object_size_in_words>
184
  void RegisterSpecialization() {
185
    static const int size = object_size_in_words * kPointerSize;
186
    Register(StaticVisitorBase::GetVisitorIdForSize(base, generic, size),
187
             &Visitor::template VisitSpecialized<size>);
188
  }
189

    
190

    
191
  template<typename Visitor,
192
           StaticVisitorBase::VisitorId base,
193
           StaticVisitorBase::VisitorId generic>
194
  void RegisterSpecializations() {
195
    STATIC_ASSERT(
196
        (generic - base + StaticVisitorBase::kMinObjectSizeInWords) == 10);
197
    RegisterSpecialization<Visitor, base, generic, 2>();
198
    RegisterSpecialization<Visitor, base, generic, 3>();
199
    RegisterSpecialization<Visitor, base, generic, 4>();
200
    RegisterSpecialization<Visitor, base, generic, 5>();
201
    RegisterSpecialization<Visitor, base, generic, 6>();
202
    RegisterSpecialization<Visitor, base, generic, 7>();
203
    RegisterSpecialization<Visitor, base, generic, 8>();
204
    RegisterSpecialization<Visitor, base, generic, 9>();
205
    Register(generic, &Visitor::Visit);
206
  }
207

    
208
 private:
209
  AtomicWord callbacks_[StaticVisitorBase::kVisitorIdCount];
210
};
211

    
212

    
213
template<typename StaticVisitor>
214
class BodyVisitorBase : public AllStatic {
215
 public:
216
  INLINE(static void IteratePointers(Heap* heap,
217
                                     HeapObject* object,
218
                                     int start_offset,
219
                                     int end_offset)) {
220
    Object** start_slot = reinterpret_cast<Object**>(object->address() +
221
                                                     start_offset);
222
    Object** end_slot = reinterpret_cast<Object**>(object->address() +
223
                                                   end_offset);
224
    StaticVisitor::VisitPointers(heap, start_slot, end_slot);
225
  }
226
};
227

    
228

    
229
template<typename StaticVisitor, typename BodyDescriptor, typename ReturnType>
230
class FlexibleBodyVisitor : public BodyVisitorBase<StaticVisitor> {
231
 public:
232
  INLINE(static ReturnType Visit(Map* map, HeapObject* object)) {
233
    int object_size = BodyDescriptor::SizeOf(map, object);
234
    BodyVisitorBase<StaticVisitor>::IteratePointers(
235
        map->GetHeap(),
236
        object,
237
        BodyDescriptor::kStartOffset,
238
        object_size);
239
    return static_cast<ReturnType>(object_size);
240
  }
241

    
242
  template<int object_size>
243
  static inline ReturnType VisitSpecialized(Map* map, HeapObject* object) {
244
    ASSERT(BodyDescriptor::SizeOf(map, object) == object_size);
245
    BodyVisitorBase<StaticVisitor>::IteratePointers(
246
        map->GetHeap(),
247
        object,
248
        BodyDescriptor::kStartOffset,
249
        object_size);
250
    return static_cast<ReturnType>(object_size);
251
  }
252
};
253

    
254

    
255
template<typename StaticVisitor, typename BodyDescriptor, typename ReturnType>
256
class FixedBodyVisitor : public BodyVisitorBase<StaticVisitor> {
257
 public:
258
  INLINE(static ReturnType Visit(Map* map, HeapObject* object)) {
259
    BodyVisitorBase<StaticVisitor>::IteratePointers(
260
        map->GetHeap(),
261
        object,
262
        BodyDescriptor::kStartOffset,
263
        BodyDescriptor::kEndOffset);
264
    return static_cast<ReturnType>(BodyDescriptor::kSize);
265
  }
266
};
267

    
268

    
269
// Base class for visitors used for a linear new space iteration.
270
// IterateBody returns size of visited object.
271
// Certain types of objects (i.e. Code objects) are not handled
272
// by dispatch table of this visitor because they cannot appear
273
// in the new space.
274
//
275
// This class is intended to be used in the following way:
276
//
277
//   class SomeVisitor : public StaticNewSpaceVisitor<SomeVisitor> {
278
//     ...
279
//   }
280
//
281
// This is an example of Curiously recurring template pattern
282
// (see http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern).
283
// We use CRTP to guarantee aggressive compile time optimizations (i.e.
284
// inlining and specialization of StaticVisitor::VisitPointers methods).
285
template<typename StaticVisitor>
286
class StaticNewSpaceVisitor : public StaticVisitorBase {
287
 public:
288
  static void Initialize();
289

    
290
  INLINE(static int IterateBody(Map* map, HeapObject* obj)) {
291
    return table_.GetVisitor(map)(map, obj);
292
  }
293

    
294
  INLINE(static void VisitPointers(Heap* heap, Object** start, Object** end)) {
295
    for (Object** p = start; p < end; p++) StaticVisitor::VisitPointer(heap, p);
296
  }
297

    
298
 private:
299
  INLINE(static int VisitJSFunction(Map* map, HeapObject* object)) {
300
    Heap* heap = map->GetHeap();
301
    VisitPointers(heap,
302
                  HeapObject::RawField(object, JSFunction::kPropertiesOffset),
303
                  HeapObject::RawField(object, JSFunction::kCodeEntryOffset));
304

    
305
    // Don't visit code entry. We are using this visitor only during scavenges.
306

    
307
    VisitPointers(
308
        heap,
309
        HeapObject::RawField(object,
310
                             JSFunction::kCodeEntryOffset + kPointerSize),
311
        HeapObject::RawField(object,
312
                             JSFunction::kNonWeakFieldsEndOffset));
313
    return JSFunction::kSize;
314
  }
315

    
316
  INLINE(static int VisitByteArray(Map* map, HeapObject* object)) {
317
    return reinterpret_cast<ByteArray*>(object)->ByteArraySize();
318
  }
319

    
320
  INLINE(static int VisitFixedDoubleArray(Map* map, HeapObject* object)) {
321
    int length = reinterpret_cast<FixedDoubleArray*>(object)->length();
322
    return FixedDoubleArray::SizeFor(length);
323
  }
324

    
325
  INLINE(static int VisitJSObject(Map* map, HeapObject* object)) {
326
    return JSObjectVisitor::Visit(map, object);
327
  }
328

    
329
  INLINE(static int VisitSeqOneByteString(Map* map, HeapObject* object)) {
330
    return SeqOneByteString::cast(object)->
331
        SeqOneByteStringSize(map->instance_type());
332
  }
333

    
334
  INLINE(static int VisitSeqTwoByteString(Map* map, HeapObject* object)) {
335
    return SeqTwoByteString::cast(object)->
336
        SeqTwoByteStringSize(map->instance_type());
337
  }
338

    
339
  INLINE(static int VisitFreeSpace(Map* map, HeapObject* object)) {
340
    return FreeSpace::cast(object)->Size();
341
  }
342

    
343
  INLINE(static int VisitJSArrayBuffer(Map* map, HeapObject* object));
344
  INLINE(static int VisitJSTypedArray(Map* map, HeapObject* object));
345
  INLINE(static int VisitJSDataView(Map* map, HeapObject* object));
346

    
347
  class DataObjectVisitor {
348
   public:
349
    template<int object_size>
350
    static inline int VisitSpecialized(Map* map, HeapObject* object) {
351
      return object_size;
352
    }
353

    
354
    INLINE(static int Visit(Map* map, HeapObject* object)) {
355
      return map->instance_size();
356
    }
357
  };
358

    
359
  typedef FlexibleBodyVisitor<StaticVisitor,
360
                              StructBodyDescriptor,
361
                              int> StructVisitor;
362

    
363
  typedef FlexibleBodyVisitor<StaticVisitor,
364
                              JSObject::BodyDescriptor,
365
                              int> JSObjectVisitor;
366

    
367
  typedef int (*Callback)(Map* map, HeapObject* object);
368

    
369
  static VisitorDispatchTable<Callback> table_;
370
};
371

    
372

    
373
template<typename StaticVisitor>
374
VisitorDispatchTable<typename StaticNewSpaceVisitor<StaticVisitor>::Callback>
375
    StaticNewSpaceVisitor<StaticVisitor>::table_;
376

    
377

    
378
// Base class for visitors used to transitively mark the entire heap.
379
// IterateBody returns nothing.
380
// Certain types of objects might not be handled by this base class and
381
// no visitor function is registered by the generic initialization. A
382
// specialized visitor function needs to be provided by the inheriting
383
// class itself for those cases.
384
//
385
// This class is intended to be used in the following way:
386
//
387
//   class SomeVisitor : public StaticMarkingVisitor<SomeVisitor> {
388
//     ...
389
//   }
390
//
391
// This is an example of Curiously recurring template pattern.
392
template<typename StaticVisitor>
393
class StaticMarkingVisitor : public StaticVisitorBase {
394
 public:
395
  static void Initialize();
396

    
397
  INLINE(static void IterateBody(Map* map, HeapObject* obj)) {
398
    table_.GetVisitor(map)(map, obj);
399
  }
400

    
401
  INLINE(static void VisitPropertyCell(Map* map, HeapObject* object));
402
  INLINE(static void VisitCodeEntry(Heap* heap, Address entry_address));
403
  INLINE(static void VisitEmbeddedPointer(Heap* heap, RelocInfo* rinfo));
404
  INLINE(static void VisitCell(Heap* heap, RelocInfo* rinfo));
405
  INLINE(static void VisitDebugTarget(Heap* heap, RelocInfo* rinfo));
406
  INLINE(static void VisitCodeTarget(Heap* heap, RelocInfo* rinfo));
407
  INLINE(static void VisitCodeAgeSequence(Heap* heap, RelocInfo* rinfo));
408
  INLINE(static void VisitExternalReference(RelocInfo* rinfo)) { }
409
  INLINE(static void VisitRuntimeEntry(RelocInfo* rinfo)) { }
410

    
411
  // TODO(mstarzinger): This should be made protected once refactoring is done.
412
  // Mark non-optimize code for functions inlined into the given optimized
413
  // code. This will prevent it from being flushed.
414
  static void MarkInlinedFunctionsCode(Heap* heap, Code* code);
415

    
416
 protected:
417
  INLINE(static void VisitMap(Map* map, HeapObject* object));
418
  INLINE(static void VisitCode(Map* map, HeapObject* object));
419
  INLINE(static void VisitSharedFunctionInfo(Map* map, HeapObject* object));
420
  INLINE(static void VisitConstantPoolArray(Map* map, HeapObject* object));
421
  INLINE(static void VisitJSFunction(Map* map, HeapObject* object));
422
  INLINE(static void VisitJSRegExp(Map* map, HeapObject* object));
423
  INLINE(static void VisitJSArrayBuffer(Map* map, HeapObject* object));
424
  INLINE(static void VisitJSTypedArray(Map* map, HeapObject* object));
425
  INLINE(static void VisitJSDataView(Map* map, HeapObject* object));
426
  INLINE(static void VisitNativeContext(Map* map, HeapObject* object));
427

    
428
  // Mark pointers in a Map and its TransitionArray together, possibly
429
  // treating transitions or back pointers weak.
430
  static void MarkMapContents(Heap* heap, Map* map);
431
  static void MarkTransitionArray(Heap* heap, TransitionArray* transitions);
432

    
433
  // Code flushing support.
434
  INLINE(static bool IsFlushable(Heap* heap, JSFunction* function));
435
  INLINE(static bool IsFlushable(Heap* heap, SharedFunctionInfo* shared_info));
436

    
437
  // Helpers used by code flushing support that visit pointer fields and treat
438
  // references to code objects either strongly or weakly.
439
  static void VisitSharedFunctionInfoStrongCode(Heap* heap, HeapObject* object);
440
  static void VisitSharedFunctionInfoWeakCode(Heap* heap, HeapObject* object);
441
  static void VisitJSFunctionStrongCode(Heap* heap, HeapObject* object);
442
  static void VisitJSFunctionWeakCode(Heap* heap, HeapObject* object);
443

    
444
  class DataObjectVisitor {
445
   public:
446
    template<int size>
447
    static inline void VisitSpecialized(Map* map, HeapObject* object) {
448
    }
449

    
450
    INLINE(static void Visit(Map* map, HeapObject* object)) {
451
    }
452
  };
453

    
454
  typedef FlexibleBodyVisitor<StaticVisitor,
455
                              FixedArray::BodyDescriptor,
456
                              void> FixedArrayVisitor;
457

    
458
  typedef FlexibleBodyVisitor<StaticVisitor,
459
                              JSObject::BodyDescriptor,
460
                              void> JSObjectVisitor;
461

    
462
  typedef FlexibleBodyVisitor<StaticVisitor,
463
                              StructBodyDescriptor,
464
                              void> StructObjectVisitor;
465

    
466
  typedef void (*Callback)(Map* map, HeapObject* object);
467

    
468
  static VisitorDispatchTable<Callback> table_;
469
};
470

    
471

    
472
template<typename StaticVisitor>
473
VisitorDispatchTable<typename StaticMarkingVisitor<StaticVisitor>::Callback>
474
    StaticMarkingVisitor<StaticVisitor>::table_;
475

    
476

    
477
} }  // namespace v8::internal
478

    
479
#endif  // V8_OBJECTS_VISITING_H_