Home | History | Annotate | Download | only in src
      1 // Copyright 2011 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "src/v8.h"
      6 
      7 #include "src/ic-inl.h"
      8 #include "src/objects-visiting.h"
      9 
     10 namespace v8 {
     11 namespace internal {
     12 
     13 
     14 static inline bool IsShortcutCandidate(int type) {
     15   return ((type & kShortcutTypeMask) == kShortcutTypeTag);
     16 }
     17 
     18 
     19 StaticVisitorBase::VisitorId StaticVisitorBase::GetVisitorId(
     20     int instance_type,
     21     int instance_size) {
     22   if (instance_type < FIRST_NONSTRING_TYPE) {
     23     switch (instance_type & kStringRepresentationMask) {
     24       case kSeqStringTag:
     25         if ((instance_type & kStringEncodingMask) == kOneByteStringTag) {
     26           return kVisitSeqOneByteString;
     27         } else {
     28           return kVisitSeqTwoByteString;
     29         }
     30 
     31       case kConsStringTag:
     32         if (IsShortcutCandidate(instance_type)) {
     33           return kVisitShortcutCandidate;
     34         } else {
     35           return kVisitConsString;
     36         }
     37 
     38       case kSlicedStringTag:
     39         return kVisitSlicedString;
     40 
     41       case kExternalStringTag:
     42         return GetVisitorIdForSize(kVisitDataObject,
     43                                    kVisitDataObjectGeneric,
     44                                    instance_size);
     45     }
     46     UNREACHABLE();
     47   }
     48 
     49   switch (instance_type) {
     50     case BYTE_ARRAY_TYPE:
     51       return kVisitByteArray;
     52 
     53     case FREE_SPACE_TYPE:
     54       return kVisitFreeSpace;
     55 
     56     case FIXED_ARRAY_TYPE:
     57       return kVisitFixedArray;
     58 
     59     case FIXED_DOUBLE_ARRAY_TYPE:
     60       return kVisitFixedDoubleArray;
     61 
     62     case CONSTANT_POOL_ARRAY_TYPE:
     63       return kVisitConstantPoolArray;
     64 
     65     case ODDBALL_TYPE:
     66       return kVisitOddball;
     67 
     68     case MAP_TYPE:
     69       return kVisitMap;
     70 
     71     case CODE_TYPE:
     72       return kVisitCode;
     73 
     74     case CELL_TYPE:
     75       return kVisitCell;
     76 
     77     case PROPERTY_CELL_TYPE:
     78       return kVisitPropertyCell;
     79 
     80     case JS_SET_TYPE:
     81       return GetVisitorIdForSize(kVisitStruct,
     82                                  kVisitStructGeneric,
     83                                  JSSet::kSize);
     84 
     85     case JS_MAP_TYPE:
     86       return GetVisitorIdForSize(kVisitStruct,
     87                                  kVisitStructGeneric,
     88                                  JSMap::kSize);
     89 
     90     case JS_WEAK_MAP_TYPE:
     91     case JS_WEAK_SET_TYPE:
     92       return kVisitJSWeakCollection;
     93 
     94     case JS_REGEXP_TYPE:
     95       return kVisitJSRegExp;
     96 
     97     case SHARED_FUNCTION_INFO_TYPE:
     98       return kVisitSharedFunctionInfo;
     99 
    100     case JS_PROXY_TYPE:
    101       return GetVisitorIdForSize(kVisitStruct,
    102                                  kVisitStructGeneric,
    103                                  JSProxy::kSize);
    104 
    105     case JS_FUNCTION_PROXY_TYPE:
    106       return GetVisitorIdForSize(kVisitStruct,
    107                                  kVisitStructGeneric,
    108                                  JSFunctionProxy::kSize);
    109 
    110     case FOREIGN_TYPE:
    111       return GetVisitorIdForSize(kVisitDataObject,
    112                                  kVisitDataObjectGeneric,
    113                                  Foreign::kSize);
    114 
    115     case SYMBOL_TYPE:
    116       return kVisitSymbol;
    117 
    118     case FILLER_TYPE:
    119       return kVisitDataObjectGeneric;
    120 
    121     case JS_ARRAY_BUFFER_TYPE:
    122       return kVisitJSArrayBuffer;
    123 
    124     case JS_TYPED_ARRAY_TYPE:
    125       return kVisitJSTypedArray;
    126 
    127     case JS_DATA_VIEW_TYPE:
    128       return kVisitJSDataView;
    129 
    130     case JS_OBJECT_TYPE:
    131     case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
    132     case JS_GENERATOR_OBJECT_TYPE:
    133     case JS_MODULE_TYPE:
    134     case JS_VALUE_TYPE:
    135     case JS_DATE_TYPE:
    136     case JS_ARRAY_TYPE:
    137     case JS_GLOBAL_PROXY_TYPE:
    138     case JS_GLOBAL_OBJECT_TYPE:
    139     case JS_BUILTINS_OBJECT_TYPE:
    140     case JS_MESSAGE_OBJECT_TYPE:
    141     case JS_SET_ITERATOR_TYPE:
    142     case JS_MAP_ITERATOR_TYPE:
    143       return GetVisitorIdForSize(kVisitJSObject,
    144                                  kVisitJSObjectGeneric,
    145                                  instance_size);
    146 
    147     case JS_FUNCTION_TYPE:
    148       return kVisitJSFunction;
    149 
    150     case HEAP_NUMBER_TYPE:
    151 #define EXTERNAL_ARRAY_CASE(Type, type, TYPE, ctype, size)                     \
    152     case EXTERNAL_##TYPE##_ARRAY_TYPE:
    153 
    154     TYPED_ARRAYS(EXTERNAL_ARRAY_CASE)
    155       return GetVisitorIdForSize(kVisitDataObject,
    156                                  kVisitDataObjectGeneric,
    157                                  instance_size);
    158 #undef EXTERNAL_ARRAY_CASE
    159 
    160     case FIXED_UINT8_ARRAY_TYPE:
    161     case FIXED_INT8_ARRAY_TYPE:
    162     case FIXED_UINT16_ARRAY_TYPE:
    163     case FIXED_INT16_ARRAY_TYPE:
    164     case FIXED_UINT32_ARRAY_TYPE:
    165     case FIXED_INT32_ARRAY_TYPE:
    166     case FIXED_FLOAT32_ARRAY_TYPE:
    167     case FIXED_UINT8_CLAMPED_ARRAY_TYPE:
    168       return kVisitFixedTypedArray;
    169 
    170     case FIXED_FLOAT64_ARRAY_TYPE:
    171       return kVisitFixedFloat64Array;
    172 
    173 #define MAKE_STRUCT_CASE(NAME, Name, name) \
    174         case NAME##_TYPE:
    175       STRUCT_LIST(MAKE_STRUCT_CASE)
    176 #undef MAKE_STRUCT_CASE
    177           if (instance_type == ALLOCATION_SITE_TYPE) {
    178             return kVisitAllocationSite;
    179           }
    180 
    181           return GetVisitorIdForSize(kVisitStruct,
    182                                      kVisitStructGeneric,
    183                                      instance_size);
    184 
    185     default:
    186       UNREACHABLE();
    187       return kVisitorIdCount;
    188   }
    189 }
    190 
    191 
    192 // We don't record weak slots during marking or scavenges. Instead we do it
    193 // once when we complete mark-compact cycle.  Note that write barrier has no
    194 // effect if we are already in the middle of compacting mark-sweep cycle and we
    195 // have to record slots manually.
    196 static bool MustRecordSlots(Heap* heap) {
    197   return heap->gc_state() == Heap::MARK_COMPACT &&
    198       heap->mark_compact_collector()->is_compacting();
    199 }
    200 
    201 
    202 template <class T>
    203 struct WeakListVisitor;
    204 
    205 
    206 template <class T>
    207 Object* VisitWeakList(Heap* heap,
    208                       Object* list,
    209                       WeakObjectRetainer* retainer) {
    210   Object* undefined = heap->undefined_value();
    211   Object* head = undefined;
    212   T* tail = NULL;
    213   MarkCompactCollector* collector = heap->mark_compact_collector();
    214   bool record_slots = MustRecordSlots(heap);
    215   while (list != undefined) {
    216     // Check whether to keep the candidate in the list.
    217     T* candidate = reinterpret_cast<T*>(list);
    218     Object* retained = retainer->RetainAs(list);
    219     if (retained != NULL) {
    220       if (head == undefined) {
    221         // First element in the list.
    222         head = retained;
    223       } else {
    224         // Subsequent elements in the list.
    225         ASSERT(tail != NULL);
    226         WeakListVisitor<T>::SetWeakNext(tail, retained);
    227         if (record_slots) {
    228           Object** next_slot =
    229             HeapObject::RawField(tail, WeakListVisitor<T>::WeakNextOffset());
    230           collector->RecordSlot(next_slot, next_slot, retained);
    231         }
    232       }
    233       // Retained object is new tail.
    234       ASSERT(!retained->IsUndefined());
    235       candidate = reinterpret_cast<T*>(retained);
    236       tail = candidate;
    237 
    238 
    239       // tail is a live object, visit it.
    240       WeakListVisitor<T>::VisitLiveObject(heap, tail, retainer);
    241     } else {
    242       WeakListVisitor<T>::VisitPhantomObject(heap, candidate);
    243     }
    244 
    245     // Move to next element in the list.
    246     list = WeakListVisitor<T>::WeakNext(candidate);
    247   }
    248 
    249   // Terminate the list if there is one or more elements.
    250   if (tail != NULL) {
    251     WeakListVisitor<T>::SetWeakNext(tail, undefined);
    252   }
    253   return head;
    254 }
    255 
    256 
    257 template <class T>
    258 static void ClearWeakList(Heap* heap,
    259                           Object* list) {
    260   Object* undefined = heap->undefined_value();
    261   while (list != undefined) {
    262     T* candidate = reinterpret_cast<T*>(list);
    263     list = WeakListVisitor<T>::WeakNext(candidate);
    264     WeakListVisitor<T>::SetWeakNext(candidate, undefined);
    265   }
    266 }
    267 
    268 
    269 template<>
    270 struct WeakListVisitor<JSFunction> {
    271   static void SetWeakNext(JSFunction* function, Object* next) {
    272     function->set_next_function_link(next);
    273   }
    274 
    275   static Object* WeakNext(JSFunction* function) {
    276     return function->next_function_link();
    277   }
    278 
    279   static int WeakNextOffset() {
    280     return JSFunction::kNextFunctionLinkOffset;
    281   }
    282 
    283   static void VisitLiveObject(Heap*, JSFunction*, WeakObjectRetainer*) {}
    284 
    285   static void VisitPhantomObject(Heap*, JSFunction*) {}
    286 };
    287 
    288 
    289 template<>
    290 struct WeakListVisitor<Code> {
    291   static void SetWeakNext(Code* code, Object* next) {
    292     code->set_next_code_link(next);
    293   }
    294 
    295   static Object* WeakNext(Code* code) {
    296     return code->next_code_link();
    297   }
    298 
    299   static int WeakNextOffset() {
    300     return Code::kNextCodeLinkOffset;
    301   }
    302 
    303   static void VisitLiveObject(Heap*, Code*, WeakObjectRetainer*) {}
    304 
    305   static void VisitPhantomObject(Heap*, Code*) {}
    306 };
    307 
    308 
    309 template<>
    310 struct WeakListVisitor<Context> {
    311   static void SetWeakNext(Context* context, Object* next) {
    312     context->set(Context::NEXT_CONTEXT_LINK,
    313                  next,
    314                  UPDATE_WRITE_BARRIER);
    315   }
    316 
    317   static Object* WeakNext(Context* context) {
    318     return context->get(Context::NEXT_CONTEXT_LINK);
    319   }
    320 
    321   static int WeakNextOffset() {
    322     return FixedArray::SizeFor(Context::NEXT_CONTEXT_LINK);
    323   }
    324 
    325   static void VisitLiveObject(Heap* heap,
    326                               Context* context,
    327                               WeakObjectRetainer* retainer) {
    328     // Process the three weak lists linked off the context.
    329     DoWeakList<JSFunction>(heap, context, retainer,
    330         Context::OPTIMIZED_FUNCTIONS_LIST);
    331     DoWeakList<Code>(heap, context, retainer, Context::OPTIMIZED_CODE_LIST);
    332     DoWeakList<Code>(heap, context, retainer, Context::DEOPTIMIZED_CODE_LIST);
    333   }
    334 
    335   template<class T>
    336   static void DoWeakList(Heap* heap,
    337                          Context* context,
    338                          WeakObjectRetainer* retainer,
    339                          int index) {
    340     // Visit the weak list, removing dead intermediate elements.
    341     Object* list_head = VisitWeakList<T>(heap, context->get(index), retainer);
    342 
    343     // Update the list head.
    344     context->set(index, list_head, UPDATE_WRITE_BARRIER);
    345 
    346     if (MustRecordSlots(heap)) {
    347       // Record the updated slot if necessary.
    348       Object** head_slot = HeapObject::RawField(
    349           context, FixedArray::SizeFor(index));
    350       heap->mark_compact_collector()->RecordSlot(
    351           head_slot, head_slot, list_head);
    352     }
    353   }
    354 
    355   static void VisitPhantomObject(Heap* heap, Context* context) {
    356     ClearWeakList<JSFunction>(heap,
    357         context->get(Context::OPTIMIZED_FUNCTIONS_LIST));
    358     ClearWeakList<Code>(heap, context->get(Context::OPTIMIZED_CODE_LIST));
    359     ClearWeakList<Code>(heap, context->get(Context::DEOPTIMIZED_CODE_LIST));
    360   }
    361 };
    362 
    363 
    364 template<>
    365 struct WeakListVisitor<JSArrayBufferView> {
    366   static void SetWeakNext(JSArrayBufferView* obj, Object* next) {
    367     obj->set_weak_next(next);
    368   }
    369 
    370   static Object* WeakNext(JSArrayBufferView* obj) {
    371     return obj->weak_next();
    372   }
    373 
    374   static int WeakNextOffset() {
    375     return JSArrayBufferView::kWeakNextOffset;
    376   }
    377 
    378   static void VisitLiveObject(Heap*, JSArrayBufferView*, WeakObjectRetainer*) {}
    379 
    380   static void VisitPhantomObject(Heap*, JSArrayBufferView*) {}
    381 };
    382 
    383 
    384 template<>
    385 struct WeakListVisitor<JSArrayBuffer> {
    386   static void SetWeakNext(JSArrayBuffer* obj, Object* next) {
    387     obj->set_weak_next(next);
    388   }
    389 
    390   static Object* WeakNext(JSArrayBuffer* obj) {
    391     return obj->weak_next();
    392   }
    393 
    394   static int WeakNextOffset() {
    395     return JSArrayBuffer::kWeakNextOffset;
    396   }
    397 
    398   static void VisitLiveObject(Heap* heap,
    399                               JSArrayBuffer* array_buffer,
    400                               WeakObjectRetainer* retainer) {
    401     Object* typed_array_obj =
    402         VisitWeakList<JSArrayBufferView>(
    403             heap,
    404             array_buffer->weak_first_view(),
    405             retainer);
    406     array_buffer->set_weak_first_view(typed_array_obj);
    407     if (typed_array_obj != heap->undefined_value() && MustRecordSlots(heap)) {
    408       Object** slot = HeapObject::RawField(
    409           array_buffer, JSArrayBuffer::kWeakFirstViewOffset);
    410       heap->mark_compact_collector()->RecordSlot(slot, slot, typed_array_obj);
    411     }
    412   }
    413 
    414   static void VisitPhantomObject(Heap* heap, JSArrayBuffer* phantom) {
    415     Runtime::FreeArrayBuffer(heap->isolate(), phantom);
    416   }
    417 };
    418 
    419 
    420 template<>
    421 struct WeakListVisitor<AllocationSite> {
    422   static void SetWeakNext(AllocationSite* obj, Object* next) {
    423     obj->set_weak_next(next);
    424   }
    425 
    426   static Object* WeakNext(AllocationSite* obj) {
    427     return obj->weak_next();
    428   }
    429 
    430   static int WeakNextOffset() {
    431     return AllocationSite::kWeakNextOffset;
    432   }
    433 
    434   static void VisitLiveObject(Heap*, AllocationSite*, WeakObjectRetainer*) {}
    435 
    436   static void VisitPhantomObject(Heap*, AllocationSite*) {}
    437 };
    438 
    439 
    440 template Object* VisitWeakList<Code>(
    441     Heap* heap, Object* list, WeakObjectRetainer* retainer);
    442 
    443 
    444 template Object* VisitWeakList<JSFunction>(
    445     Heap* heap, Object* list, WeakObjectRetainer* retainer);
    446 
    447 
    448 template Object* VisitWeakList<Context>(
    449     Heap* heap, Object* list, WeakObjectRetainer* retainer);
    450 
    451 
    452 template Object* VisitWeakList<JSArrayBuffer>(
    453     Heap* heap, Object* list, WeakObjectRetainer* retainer);
    454 
    455 
    456 template Object* VisitWeakList<AllocationSite>(
    457     Heap* heap, Object* list, WeakObjectRetainer* retainer);
    458 
    459 } }  // namespace v8::internal
    460