Home | History | Annotate | Download | only in src
      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_INL_H_
     29 #define V8_OBJECTS_VISITING_INL_H_
     30 
     31 
     32 namespace v8 {
     33 namespace internal {
     34 
     35 template<typename StaticVisitor>
     36 void StaticNewSpaceVisitor<StaticVisitor>::Initialize() {
     37   table_.Register(kVisitShortcutCandidate,
     38                   &FixedBodyVisitor<StaticVisitor,
     39                   ConsString::BodyDescriptor,
     40                   int>::Visit);
     41 
     42   table_.Register(kVisitConsString,
     43                   &FixedBodyVisitor<StaticVisitor,
     44                   ConsString::BodyDescriptor,
     45                   int>::Visit);
     46 
     47   table_.Register(kVisitSlicedString,
     48                   &FixedBodyVisitor<StaticVisitor,
     49                   SlicedString::BodyDescriptor,
     50                   int>::Visit);
     51 
     52   table_.Register(kVisitSymbol,
     53                   &FixedBodyVisitor<StaticVisitor,
     54                   Symbol::BodyDescriptor,
     55                   int>::Visit);
     56 
     57   table_.Register(kVisitFixedArray,
     58                   &FlexibleBodyVisitor<StaticVisitor,
     59                   FixedArray::BodyDescriptor,
     60                   int>::Visit);
     61 
     62   table_.Register(kVisitFixedDoubleArray, &VisitFixedDoubleArray);
     63 
     64   table_.Register(kVisitNativeContext,
     65                   &FixedBodyVisitor<StaticVisitor,
     66                   Context::ScavengeBodyDescriptor,
     67                   int>::Visit);
     68 
     69   table_.Register(kVisitByteArray, &VisitByteArray);
     70 
     71   table_.Register(kVisitSharedFunctionInfo,
     72                   &FixedBodyVisitor<StaticVisitor,
     73                   SharedFunctionInfo::BodyDescriptor,
     74                   int>::Visit);
     75 
     76   table_.Register(kVisitSeqOneByteString, &VisitSeqOneByteString);
     77 
     78   table_.Register(kVisitSeqTwoByteString, &VisitSeqTwoByteString);
     79 
     80   table_.Register(kVisitJSFunction, &VisitJSFunction);
     81 
     82   table_.Register(kVisitJSArrayBuffer, &VisitJSArrayBuffer);
     83 
     84   table_.Register(kVisitJSTypedArray, &VisitJSTypedArray);
     85 
     86   table_.Register(kVisitJSDataView, &VisitJSDataView);
     87 
     88   table_.Register(kVisitFreeSpace, &VisitFreeSpace);
     89 
     90   table_.Register(kVisitJSWeakMap, &JSObjectVisitor::Visit);
     91 
     92   table_.Register(kVisitJSWeakSet, &JSObjectVisitor::Visit);
     93 
     94   table_.Register(kVisitJSRegExp, &JSObjectVisitor::Visit);
     95 
     96   table_.template RegisterSpecializations<DataObjectVisitor,
     97                                           kVisitDataObject,
     98                                           kVisitDataObjectGeneric>();
     99 
    100   table_.template RegisterSpecializations<JSObjectVisitor,
    101                                           kVisitJSObject,
    102                                           kVisitJSObjectGeneric>();
    103   table_.template RegisterSpecializations<StructVisitor,
    104                                           kVisitStruct,
    105                                           kVisitStructGeneric>();
    106 }
    107 
    108 
    109 template<typename StaticVisitor>
    110 int StaticNewSpaceVisitor<StaticVisitor>::VisitJSArrayBuffer(
    111     Map* map, HeapObject* object) {
    112   Heap* heap = map->GetHeap();
    113 
    114   STATIC_ASSERT(
    115       JSArrayBuffer::kWeakFirstViewOffset ==
    116       JSArrayBuffer::kWeakNextOffset + kPointerSize);
    117   VisitPointers(
    118       heap,
    119       HeapObject::RawField(object, JSArrayBuffer::BodyDescriptor::kStartOffset),
    120       HeapObject::RawField(object, JSArrayBuffer::kWeakNextOffset));
    121   VisitPointers(
    122       heap,
    123       HeapObject::RawField(object,
    124           JSArrayBuffer::kWeakNextOffset + 2 * kPointerSize),
    125       HeapObject::RawField(object, JSArrayBuffer::kSizeWithInternalFields));
    126   return JSArrayBuffer::kSizeWithInternalFields;
    127 }
    128 
    129 
    130 template<typename StaticVisitor>
    131 int StaticNewSpaceVisitor<StaticVisitor>::VisitJSTypedArray(
    132     Map* map, HeapObject* object) {
    133   VisitPointers(
    134       map->GetHeap(),
    135       HeapObject::RawField(object, JSTypedArray::BodyDescriptor::kStartOffset),
    136       HeapObject::RawField(object, JSTypedArray::kWeakNextOffset));
    137   VisitPointers(
    138       map->GetHeap(),
    139       HeapObject::RawField(object,
    140           JSTypedArray::kWeakNextOffset + kPointerSize),
    141       HeapObject::RawField(object, JSTypedArray::kSizeWithInternalFields));
    142   return JSTypedArray::kSizeWithInternalFields;
    143 }
    144 
    145 
    146 template<typename StaticVisitor>
    147 int StaticNewSpaceVisitor<StaticVisitor>::VisitJSDataView(
    148     Map* map, HeapObject* object) {
    149   VisitPointers(
    150       map->GetHeap(),
    151       HeapObject::RawField(object, JSDataView::BodyDescriptor::kStartOffset),
    152       HeapObject::RawField(object, JSDataView::kWeakNextOffset));
    153   VisitPointers(
    154       map->GetHeap(),
    155       HeapObject::RawField(object,
    156           JSDataView::kWeakNextOffset + kPointerSize),
    157       HeapObject::RawField(object, JSDataView::kSizeWithInternalFields));
    158   return JSDataView::kSizeWithInternalFields;
    159 }
    160 
    161 
    162 template<typename StaticVisitor>
    163 void StaticMarkingVisitor<StaticVisitor>::Initialize() {
    164   table_.Register(kVisitShortcutCandidate,
    165                   &FixedBodyVisitor<StaticVisitor,
    166                   ConsString::BodyDescriptor,
    167                   void>::Visit);
    168 
    169   table_.Register(kVisitConsString,
    170                   &FixedBodyVisitor<StaticVisitor,
    171                   ConsString::BodyDescriptor,
    172                   void>::Visit);
    173 
    174   table_.Register(kVisitSlicedString,
    175                   &FixedBodyVisitor<StaticVisitor,
    176                   SlicedString::BodyDescriptor,
    177                   void>::Visit);
    178 
    179   table_.Register(kVisitSymbol,
    180                   &FixedBodyVisitor<StaticVisitor,
    181                   Symbol::BodyDescriptor,
    182                   void>::Visit);
    183 
    184   table_.Register(kVisitFixedArray, &FixedArrayVisitor::Visit);
    185 
    186   table_.Register(kVisitFixedDoubleArray, &DataObjectVisitor::Visit);
    187 
    188   table_.Register(kVisitConstantPoolArray, &VisitConstantPoolArray);
    189 
    190   table_.Register(kVisitNativeContext, &VisitNativeContext);
    191 
    192   table_.Register(kVisitAllocationSite, &VisitAllocationSite);
    193 
    194   table_.Register(kVisitByteArray, &DataObjectVisitor::Visit);
    195 
    196   table_.Register(kVisitFreeSpace, &DataObjectVisitor::Visit);
    197 
    198   table_.Register(kVisitSeqOneByteString, &DataObjectVisitor::Visit);
    199 
    200   table_.Register(kVisitSeqTwoByteString, &DataObjectVisitor::Visit);
    201 
    202   table_.Register(kVisitJSWeakMap, &StaticVisitor::VisitWeakCollection);
    203 
    204   table_.Register(kVisitJSWeakSet, &StaticVisitor::VisitWeakCollection);
    205 
    206   table_.Register(kVisitOddball,
    207                   &FixedBodyVisitor<StaticVisitor,
    208                   Oddball::BodyDescriptor,
    209                   void>::Visit);
    210 
    211   table_.Register(kVisitMap, &VisitMap);
    212 
    213   table_.Register(kVisitCode, &VisitCode);
    214 
    215   table_.Register(kVisitSharedFunctionInfo, &VisitSharedFunctionInfo);
    216 
    217   table_.Register(kVisitJSFunction, &VisitJSFunction);
    218 
    219   table_.Register(kVisitJSArrayBuffer, &VisitJSArrayBuffer);
    220 
    221   table_.Register(kVisitJSTypedArray, &VisitJSTypedArray);
    222 
    223   table_.Register(kVisitJSDataView, &VisitJSDataView);
    224 
    225   // Registration for kVisitJSRegExp is done by StaticVisitor.
    226 
    227   table_.Register(kVisitCell,
    228                   &FixedBodyVisitor<StaticVisitor,
    229                   Cell::BodyDescriptor,
    230                   void>::Visit);
    231 
    232   table_.Register(kVisitPropertyCell, &VisitPropertyCell);
    233 
    234   table_.template RegisterSpecializations<DataObjectVisitor,
    235                                           kVisitDataObject,
    236                                           kVisitDataObjectGeneric>();
    237 
    238   table_.template RegisterSpecializations<JSObjectVisitor,
    239                                           kVisitJSObject,
    240                                           kVisitJSObjectGeneric>();
    241 
    242   table_.template RegisterSpecializations<StructObjectVisitor,
    243                                           kVisitStruct,
    244                                           kVisitStructGeneric>();
    245 }
    246 
    247 
    248 template<typename StaticVisitor>
    249 void StaticMarkingVisitor<StaticVisitor>::VisitCodeEntry(
    250     Heap* heap, Address entry_address) {
    251   Code* code = Code::cast(Code::GetObjectFromEntryAddress(entry_address));
    252   heap->mark_compact_collector()->RecordCodeEntrySlot(entry_address, code);
    253   StaticVisitor::MarkObject(heap, code);
    254 }
    255 
    256 
    257 template<typename StaticVisitor>
    258 void StaticMarkingVisitor<StaticVisitor>::VisitEmbeddedPointer(
    259     Heap* heap, RelocInfo* rinfo) {
    260   ASSERT(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT);
    261   ASSERT(!rinfo->target_object()->IsConsString());
    262   HeapObject* object = HeapObject::cast(rinfo->target_object());
    263   heap->mark_compact_collector()->RecordRelocSlot(rinfo, object);
    264   if (!Code::IsWeakEmbeddedObject(rinfo->host()->kind(), object)) {
    265     StaticVisitor::MarkObject(heap, object);
    266   }
    267 }
    268 
    269 
    270 template<typename StaticVisitor>
    271 void StaticMarkingVisitor<StaticVisitor>::VisitCell(
    272     Heap* heap, RelocInfo* rinfo) {
    273   ASSERT(rinfo->rmode() == RelocInfo::CELL);
    274   Cell* cell = rinfo->target_cell();
    275   StaticVisitor::MarkObject(heap, cell);
    276 }
    277 
    278 
    279 template<typename StaticVisitor>
    280 void StaticMarkingVisitor<StaticVisitor>::VisitDebugTarget(
    281     Heap* heap, RelocInfo* rinfo) {
    282   ASSERT((RelocInfo::IsJSReturn(rinfo->rmode()) &&
    283           rinfo->IsPatchedReturnSequence()) ||
    284          (RelocInfo::IsDebugBreakSlot(rinfo->rmode()) &&
    285           rinfo->IsPatchedDebugBreakSlotSequence()));
    286   Code* target = Code::GetCodeFromTargetAddress(rinfo->call_address());
    287   heap->mark_compact_collector()->RecordRelocSlot(rinfo, target);
    288   StaticVisitor::MarkObject(heap, target);
    289 }
    290 
    291 
    292 template<typename StaticVisitor>
    293 void StaticMarkingVisitor<StaticVisitor>::VisitCodeTarget(
    294     Heap* heap, RelocInfo* rinfo) {
    295   ASSERT(RelocInfo::IsCodeTarget(rinfo->rmode()));
    296   Code* target = Code::GetCodeFromTargetAddress(rinfo->target_address());
    297   // Monomorphic ICs are preserved when possible, but need to be flushed
    298   // when they might be keeping a Context alive, or when the heap is about
    299   // to be serialized.
    300   if (FLAG_cleanup_code_caches_at_gc && target->is_inline_cache_stub()
    301       && (target->ic_state() == MEGAMORPHIC || target->ic_state() == GENERIC ||
    302           target->ic_state() == POLYMORPHIC || heap->flush_monomorphic_ics() ||
    303           Serializer::enabled() || target->ic_age() != heap->global_ic_age())) {
    304     IC::Clear(target->GetIsolate(), rinfo->pc());
    305     target = Code::GetCodeFromTargetAddress(rinfo->target_address());
    306   }
    307   heap->mark_compact_collector()->RecordRelocSlot(rinfo, target);
    308   StaticVisitor::MarkObject(heap, target);
    309 }
    310 
    311 
    312 template<typename StaticVisitor>
    313 void StaticMarkingVisitor<StaticVisitor>::VisitCodeAgeSequence(
    314     Heap* heap, RelocInfo* rinfo) {
    315   ASSERT(RelocInfo::IsCodeAgeSequence(rinfo->rmode()));
    316   Code* target = rinfo->code_age_stub();
    317   ASSERT(target != NULL);
    318   heap->mark_compact_collector()->RecordRelocSlot(rinfo, target);
    319   StaticVisitor::MarkObject(heap, target);
    320 }
    321 
    322 
    323 template<typename StaticVisitor>
    324 void StaticMarkingVisitor<StaticVisitor>::VisitNativeContext(
    325     Map* map, HeapObject* object) {
    326   FixedBodyVisitor<StaticVisitor,
    327                    Context::MarkCompactBodyDescriptor,
    328                    void>::Visit(map, object);
    329 
    330   MarkCompactCollector* collector = map->GetHeap()->mark_compact_collector();
    331   for (int idx = Context::FIRST_WEAK_SLOT;
    332        idx < Context::NATIVE_CONTEXT_SLOTS;
    333        ++idx) {
    334     Object** slot =
    335         HeapObject::RawField(object, FixedArray::OffsetOfElementAt(idx));
    336     collector->RecordSlot(slot, slot, *slot);
    337   }
    338 }
    339 
    340 
    341 template<typename StaticVisitor>
    342 void StaticMarkingVisitor<StaticVisitor>::VisitMap(
    343     Map* map, HeapObject* object) {
    344   Heap* heap = map->GetHeap();
    345   Map* map_object = Map::cast(object);
    346 
    347   // Clears the cache of ICs related to this map.
    348   if (FLAG_cleanup_code_caches_at_gc) {
    349     map_object->ClearCodeCache(heap);
    350   }
    351 
    352   // When map collection is enabled we have to mark through map's transitions
    353   // and back pointers in a special way to make these links weak.
    354   if (FLAG_collect_maps && map_object->CanTransition()) {
    355     MarkMapContents(heap, map_object);
    356   } else {
    357     StaticVisitor::VisitPointers(heap,
    358         HeapObject::RawField(object, Map::kPointerFieldsBeginOffset),
    359         HeapObject::RawField(object, Map::kPointerFieldsEndOffset));
    360   }
    361 }
    362 
    363 
    364 template<typename StaticVisitor>
    365 void StaticMarkingVisitor<StaticVisitor>::VisitPropertyCell(
    366     Map* map, HeapObject* object) {
    367   Heap* heap = map->GetHeap();
    368 
    369   Object** slot =
    370       HeapObject::RawField(object, PropertyCell::kDependentCodeOffset);
    371   if (FLAG_collect_maps) {
    372     // Mark property cell dependent codes array but do not push it onto marking
    373     // stack, this will make references from it weak. We will clean dead
    374     // codes when we iterate over property cells in ClearNonLiveReferences.
    375     HeapObject* obj = HeapObject::cast(*slot);
    376     heap->mark_compact_collector()->RecordSlot(slot, slot, obj);
    377     StaticVisitor::MarkObjectWithoutPush(heap, obj);
    378   } else {
    379     StaticVisitor::VisitPointer(heap, slot);
    380   }
    381 
    382   StaticVisitor::VisitPointers(heap,
    383       HeapObject::RawField(object, PropertyCell::kPointerFieldsBeginOffset),
    384       HeapObject::RawField(object, PropertyCell::kPointerFieldsEndOffset));
    385 }
    386 
    387 
    388 template<typename StaticVisitor>
    389 void StaticMarkingVisitor<StaticVisitor>::VisitAllocationSite(
    390     Map* map, HeapObject* object) {
    391   Heap* heap = map->GetHeap();
    392 
    393   Object** slot =
    394       HeapObject::RawField(object, AllocationSite::kDependentCodeOffset);
    395   if (FLAG_collect_maps) {
    396     // Mark allocation site dependent codes array but do not push it onto
    397     // marking stack, this will make references from it weak. We will clean
    398     // dead codes when we iterate over allocation sites in
    399     // ClearNonLiveReferences.
    400     HeapObject* obj = HeapObject::cast(*slot);
    401     heap->mark_compact_collector()->RecordSlot(slot, slot, obj);
    402     StaticVisitor::MarkObjectWithoutPush(heap, obj);
    403   } else {
    404     StaticVisitor::VisitPointer(heap, slot);
    405   }
    406 
    407   StaticVisitor::VisitPointers(heap,
    408       HeapObject::RawField(object, AllocationSite::kPointerFieldsBeginOffset),
    409       HeapObject::RawField(object, AllocationSite::kPointerFieldsEndOffset));
    410 }
    411 
    412 
    413 template<typename StaticVisitor>
    414 void StaticMarkingVisitor<StaticVisitor>::VisitCode(
    415     Map* map, HeapObject* object) {
    416   Heap* heap = map->GetHeap();
    417   Code* code = Code::cast(object);
    418   if (FLAG_cleanup_code_caches_at_gc) {
    419     code->ClearTypeFeedbackCells(heap);
    420   }
    421   if (FLAG_age_code && !Serializer::enabled()) {
    422     code->MakeOlder(heap->mark_compact_collector()->marking_parity());
    423   }
    424   code->CodeIterateBody<StaticVisitor>(heap);
    425 }
    426 
    427 
    428 template<typename StaticVisitor>
    429 void StaticMarkingVisitor<StaticVisitor>::VisitSharedFunctionInfo(
    430     Map* map, HeapObject* object) {
    431   Heap* heap = map->GetHeap();
    432   SharedFunctionInfo* shared = SharedFunctionInfo::cast(object);
    433   if (shared->ic_age() != heap->global_ic_age()) {
    434     shared->ResetForNewContext(heap->global_ic_age());
    435   }
    436   if (FLAG_cache_optimized_code &&
    437       FLAG_flush_optimized_code_cache &&
    438       !shared->optimized_code_map()->IsSmi()) {
    439     // Always flush the optimized code map if requested by flag.
    440     shared->ClearOptimizedCodeMap();
    441   }
    442   MarkCompactCollector* collector = heap->mark_compact_collector();
    443   if (collector->is_code_flushing_enabled()) {
    444     if (FLAG_cache_optimized_code && !shared->optimized_code_map()->IsSmi()) {
    445       // Add the shared function info holding an optimized code map to
    446       // the code flusher for processing of code maps after marking.
    447       collector->code_flusher()->AddOptimizedCodeMap(shared);
    448       // Treat all references within the code map weakly by marking the
    449       // code map itself but not pushing it onto the marking deque.
    450       FixedArray* code_map = FixedArray::cast(shared->optimized_code_map());
    451       StaticVisitor::MarkObjectWithoutPush(heap, code_map);
    452     }
    453     if (IsFlushable(heap, shared)) {
    454       // This function's code looks flushable. But we have to postpone
    455       // the decision until we see all functions that point to the same
    456       // SharedFunctionInfo because some of them might be optimized.
    457       // That would also make the non-optimized version of the code
    458       // non-flushable, because it is required for bailing out from
    459       // optimized code.
    460       collector->code_flusher()->AddCandidate(shared);
    461       // Treat the reference to the code object weakly.
    462       VisitSharedFunctionInfoWeakCode(heap, object);
    463       return;
    464     }
    465   } else {
    466     if (FLAG_cache_optimized_code && !shared->optimized_code_map()->IsSmi()) {
    467       // Flush optimized code map on major GCs without code flushing,
    468       // needed because cached code doesn't contain breakpoints.
    469       shared->ClearOptimizedCodeMap();
    470     }
    471   }
    472   VisitSharedFunctionInfoStrongCode(heap, object);
    473 }
    474 
    475 
    476 template<typename StaticVisitor>
    477 void StaticMarkingVisitor<StaticVisitor>::VisitConstantPoolArray(
    478     Map* map, HeapObject* object) {
    479   Heap* heap = map->GetHeap();
    480   ConstantPoolArray* constant_pool = ConstantPoolArray::cast(object);
    481   int first_ptr_offset = constant_pool->OffsetOfElementAt(
    482       constant_pool->first_ptr_index());
    483   int last_ptr_offset = constant_pool->OffsetOfElementAt(
    484       constant_pool->first_ptr_index() + constant_pool->count_of_ptr_entries());
    485   StaticVisitor::VisitPointers(
    486       heap,
    487       HeapObject::RawField(object, first_ptr_offset),
    488       HeapObject::RawField(object, last_ptr_offset));
    489 }
    490 
    491 
    492 template<typename StaticVisitor>
    493 void StaticMarkingVisitor<StaticVisitor>::VisitJSFunction(
    494     Map* map, HeapObject* object) {
    495   Heap* heap = map->GetHeap();
    496   JSFunction* function = JSFunction::cast(object);
    497   MarkCompactCollector* collector = heap->mark_compact_collector();
    498   if (collector->is_code_flushing_enabled()) {
    499     if (IsFlushable(heap, function)) {
    500       // This function's code looks flushable. But we have to postpone
    501       // the decision until we see all functions that point to the same
    502       // SharedFunctionInfo because some of them might be optimized.
    503       // That would also make the non-optimized version of the code
    504       // non-flushable, because it is required for bailing out from
    505       // optimized code.
    506       collector->code_flusher()->AddCandidate(function);
    507       // Visit shared function info immediately to avoid double checking
    508       // of its flushability later. This is just an optimization because
    509       // the shared function info would eventually be visited.
    510       SharedFunctionInfo* shared = function->shared();
    511       if (StaticVisitor::MarkObjectWithoutPush(heap, shared)) {
    512         StaticVisitor::MarkObject(heap, shared->map());
    513         VisitSharedFunctionInfoWeakCode(heap, shared);
    514       }
    515       // Treat the reference to the code object weakly.
    516       VisitJSFunctionWeakCode(heap, object);
    517       return;
    518     } else {
    519       // Visit all unoptimized code objects to prevent flushing them.
    520       StaticVisitor::MarkObject(heap, function->shared()->code());
    521       if (function->code()->kind() == Code::OPTIMIZED_FUNCTION) {
    522         MarkInlinedFunctionsCode(heap, function->code());
    523       }
    524     }
    525   }
    526   VisitJSFunctionStrongCode(heap, object);
    527 }
    528 
    529 
    530 template<typename StaticVisitor>
    531 void StaticMarkingVisitor<StaticVisitor>::VisitJSRegExp(
    532     Map* map, HeapObject* object) {
    533   int last_property_offset =
    534       JSRegExp::kSize + kPointerSize * map->inobject_properties();
    535   StaticVisitor::VisitPointers(map->GetHeap(),
    536       HeapObject::RawField(object, JSRegExp::kPropertiesOffset),
    537       HeapObject::RawField(object, last_property_offset));
    538 }
    539 
    540 
    541 template<typename StaticVisitor>
    542 void StaticMarkingVisitor<StaticVisitor>::VisitJSArrayBuffer(
    543     Map* map, HeapObject* object) {
    544   Heap* heap = map->GetHeap();
    545 
    546   STATIC_ASSERT(
    547       JSArrayBuffer::kWeakFirstViewOffset ==
    548       JSArrayBuffer::kWeakNextOffset + kPointerSize);
    549   StaticVisitor::VisitPointers(
    550       heap,
    551       HeapObject::RawField(object, JSArrayBuffer::BodyDescriptor::kStartOffset),
    552       HeapObject::RawField(object, JSArrayBuffer::kWeakNextOffset));
    553   StaticVisitor::VisitPointers(
    554       heap,
    555       HeapObject::RawField(object,
    556           JSArrayBuffer::kWeakNextOffset + 2 * kPointerSize),
    557       HeapObject::RawField(object, JSArrayBuffer::kSizeWithInternalFields));
    558 }
    559 
    560 
    561 template<typename StaticVisitor>
    562 void StaticMarkingVisitor<StaticVisitor>::VisitJSTypedArray(
    563     Map* map, HeapObject* object) {
    564   StaticVisitor::VisitPointers(
    565       map->GetHeap(),
    566       HeapObject::RawField(object, JSTypedArray::BodyDescriptor::kStartOffset),
    567       HeapObject::RawField(object, JSTypedArray::kWeakNextOffset));
    568   StaticVisitor::VisitPointers(
    569       map->GetHeap(),
    570       HeapObject::RawField(object,
    571         JSTypedArray::kWeakNextOffset + kPointerSize),
    572       HeapObject::RawField(object, JSTypedArray::kSizeWithInternalFields));
    573 }
    574 
    575 
    576 template<typename StaticVisitor>
    577 void StaticMarkingVisitor<StaticVisitor>::VisitJSDataView(
    578     Map* map, HeapObject* object) {
    579   StaticVisitor::VisitPointers(
    580       map->GetHeap(),
    581       HeapObject::RawField(object, JSDataView::BodyDescriptor::kStartOffset),
    582       HeapObject::RawField(object, JSDataView::kWeakNextOffset));
    583   StaticVisitor::VisitPointers(
    584       map->GetHeap(),
    585       HeapObject::RawField(object,
    586         JSDataView::kWeakNextOffset + kPointerSize),
    587       HeapObject::RawField(object, JSDataView::kSizeWithInternalFields));
    588 }
    589 
    590 
    591 template<typename StaticVisitor>
    592 void StaticMarkingVisitor<StaticVisitor>::MarkMapContents(
    593     Heap* heap, Map* map) {
    594   // Make sure that the back pointer stored either in the map itself or
    595   // inside its transitions array is marked. Skip recording the back
    596   // pointer slot since map space is not compacted.
    597   StaticVisitor::MarkObject(heap, HeapObject::cast(map->GetBackPointer()));
    598 
    599   // Treat pointers in the transitions array as weak and also mark that
    600   // array to prevent visiting it later. Skip recording the transition
    601   // array slot, since it will be implicitly recorded when the pointer
    602   // fields of this map are visited.
    603   TransitionArray* transitions = map->unchecked_transition_array();
    604   if (transitions->IsTransitionArray()) {
    605     MarkTransitionArray(heap, transitions);
    606   } else {
    607     // Already marked by marking map->GetBackPointer() above.
    608     ASSERT(transitions->IsMap() || transitions->IsUndefined());
    609   }
    610 
    611   // Since descriptor arrays are potentially shared, ensure that only the
    612   // descriptors that belong to this map are marked. The first time a
    613   // non-empty descriptor array is marked, its header is also visited. The slot
    614   // holding the descriptor array will be implicitly recorded when the pointer
    615   // fields of this map are visited.
    616   DescriptorArray* descriptors = map->instance_descriptors();
    617   if (StaticVisitor::MarkObjectWithoutPush(heap, descriptors) &&
    618       descriptors->length() > 0) {
    619     StaticVisitor::VisitPointers(heap,
    620         descriptors->GetFirstElementAddress(),
    621         descriptors->GetDescriptorEndSlot(0));
    622   }
    623   int start = 0;
    624   int end = map->NumberOfOwnDescriptors();
    625   if (start < end) {
    626     StaticVisitor::VisitPointers(heap,
    627         descriptors->GetDescriptorStartSlot(start),
    628         descriptors->GetDescriptorEndSlot(end));
    629   }
    630 
    631   // Mark prototype dependent codes array but do not push it onto marking
    632   // stack, this will make references from it weak. We will clean dead
    633   // codes when we iterate over maps in ClearNonLiveTransitions.
    634   Object** slot = HeapObject::RawField(map, Map::kDependentCodeOffset);
    635   HeapObject* obj = HeapObject::cast(*slot);
    636   heap->mark_compact_collector()->RecordSlot(slot, slot, obj);
    637   StaticVisitor::MarkObjectWithoutPush(heap, obj);
    638 
    639   // Mark the pointer fields of the Map. Since the transitions array has
    640   // been marked already, it is fine that one of these fields contains a
    641   // pointer to it.
    642   StaticVisitor::VisitPointers(heap,
    643       HeapObject::RawField(map, Map::kPointerFieldsBeginOffset),
    644       HeapObject::RawField(map, Map::kPointerFieldsEndOffset));
    645 }
    646 
    647 
    648 template<typename StaticVisitor>
    649 void StaticMarkingVisitor<StaticVisitor>::MarkTransitionArray(
    650     Heap* heap, TransitionArray* transitions) {
    651   if (!StaticVisitor::MarkObjectWithoutPush(heap, transitions)) return;
    652 
    653   // Simple transitions do not have keys nor prototype transitions.
    654   if (transitions->IsSimpleTransition()) return;
    655 
    656   if (transitions->HasPrototypeTransitions()) {
    657     // Mark prototype transitions array but do not push it onto marking
    658     // stack, this will make references from it weak. We will clean dead
    659     // prototype transitions in ClearNonLiveTransitions.
    660     Object** slot = transitions->GetPrototypeTransitionsSlot();
    661     HeapObject* obj = HeapObject::cast(*slot);
    662     heap->mark_compact_collector()->RecordSlot(slot, slot, obj);
    663     StaticVisitor::MarkObjectWithoutPush(heap, obj);
    664   }
    665 
    666   for (int i = 0; i < transitions->number_of_transitions(); ++i) {
    667     StaticVisitor::VisitPointer(heap, transitions->GetKeySlot(i));
    668   }
    669 }
    670 
    671 
    672 template<typename StaticVisitor>
    673 void StaticMarkingVisitor<StaticVisitor>::MarkInlinedFunctionsCode(
    674     Heap* heap, Code* code) {
    675   // For optimized functions we should retain both non-optimized version
    676   // of its code and non-optimized version of all inlined functions.
    677   // This is required to support bailing out from inlined code.
    678   DeoptimizationInputData* data =
    679       DeoptimizationInputData::cast(code->deoptimization_data());
    680   FixedArray* literals = data->LiteralArray();
    681   for (int i = 0, count = data->InlinedFunctionCount()->value();
    682        i < count;
    683        i++) {
    684     JSFunction* inlined = JSFunction::cast(literals->get(i));
    685     StaticVisitor::MarkObject(heap, inlined->shared()->code());
    686   }
    687 }
    688 
    689 
    690 inline static bool IsValidNonBuiltinContext(Object* context) {
    691   return context->IsContext() &&
    692       !Context::cast(context)->global_object()->IsJSBuiltinsObject();
    693 }
    694 
    695 
    696 inline static bool HasSourceCode(Heap* heap, SharedFunctionInfo* info) {
    697   Object* undefined = heap->undefined_value();
    698   return (info->script() != undefined) &&
    699       (reinterpret_cast<Script*>(info->script())->source() != undefined);
    700 }
    701 
    702 
    703 template<typename StaticVisitor>
    704 bool StaticMarkingVisitor<StaticVisitor>::IsFlushable(
    705     Heap* heap, JSFunction* function) {
    706   SharedFunctionInfo* shared_info = function->shared();
    707 
    708   // Code is either on stack, in compilation cache or referenced
    709   // by optimized version of function.
    710   MarkBit code_mark = Marking::MarkBitFrom(function->code());
    711   if (code_mark.Get()) {
    712     return false;
    713   }
    714 
    715   // The function must have a valid context and not be a builtin.
    716   if (!IsValidNonBuiltinContext(function->context())) {
    717     return false;
    718   }
    719 
    720   // We do not (yet) flush code for optimized functions.
    721   if (function->code() != shared_info->code()) {
    722     return false;
    723   }
    724 
    725   // Check age of optimized code.
    726   if (FLAG_age_code && !function->code()->IsOld()) {
    727     return false;
    728   }
    729 
    730   return IsFlushable(heap, shared_info);
    731 }
    732 
    733 
    734 template<typename StaticVisitor>
    735 bool StaticMarkingVisitor<StaticVisitor>::IsFlushable(
    736     Heap* heap, SharedFunctionInfo* shared_info) {
    737   // Code is either on stack, in compilation cache or referenced
    738   // by optimized version of function.
    739   MarkBit code_mark = Marking::MarkBitFrom(shared_info->code());
    740   if (code_mark.Get()) {
    741     return false;
    742   }
    743 
    744   // The function must be compiled and have the source code available,
    745   // to be able to recompile it in case we need the function again.
    746   if (!(shared_info->is_compiled() && HasSourceCode(heap, shared_info))) {
    747     return false;
    748   }
    749 
    750   // We never flush code for API functions.
    751   Object* function_data = shared_info->function_data();
    752   if (function_data->IsFunctionTemplateInfo()) {
    753     return false;
    754   }
    755 
    756   // Only flush code for functions.
    757   if (shared_info->code()->kind() != Code::FUNCTION) {
    758     return false;
    759   }
    760 
    761   // Function must be lazy compilable.
    762   if (!shared_info->allows_lazy_compilation()) {
    763     return false;
    764   }
    765 
    766   // We do not (yet?) flush code for generator functions, because we don't know
    767   // if there are still live activations (generator objects) on the heap.
    768   if (shared_info->is_generator()) {
    769     return false;
    770   }
    771 
    772   // If this is a full script wrapped in a function we do not flush the code.
    773   if (shared_info->is_toplevel()) {
    774     return false;
    775   }
    776 
    777   // If this is a function initialized with %SetCode then the one-to-one
    778   // relation between SharedFunctionInfo and Code is broken.
    779   if (shared_info->dont_flush()) {
    780     return false;
    781   }
    782 
    783   // Check age of code. If code aging is disabled we never flush.
    784   if (!FLAG_age_code || !shared_info->code()->IsOld()) {
    785     return false;
    786   }
    787 
    788   return true;
    789 }
    790 
    791 
    792 template<typename StaticVisitor>
    793 void StaticMarkingVisitor<StaticVisitor>::VisitSharedFunctionInfoStrongCode(
    794     Heap* heap, HeapObject* object) {
    795   StaticVisitor::BeforeVisitingSharedFunctionInfo(object);
    796   Object** start_slot =
    797       HeapObject::RawField(object,
    798                            SharedFunctionInfo::BodyDescriptor::kStartOffset);
    799   Object** end_slot =
    800       HeapObject::RawField(object,
    801                            SharedFunctionInfo::BodyDescriptor::kEndOffset);
    802   StaticVisitor::VisitPointers(heap, start_slot, end_slot);
    803 }
    804 
    805 
    806 template<typename StaticVisitor>
    807 void StaticMarkingVisitor<StaticVisitor>::VisitSharedFunctionInfoWeakCode(
    808     Heap* heap, HeapObject* object) {
    809   StaticVisitor::BeforeVisitingSharedFunctionInfo(object);
    810   Object** name_slot =
    811       HeapObject::RawField(object, SharedFunctionInfo::kNameOffset);
    812   StaticVisitor::VisitPointer(heap, name_slot);
    813 
    814   // Skip visiting kCodeOffset as it is treated weakly here.
    815   STATIC_ASSERT(SharedFunctionInfo::kNameOffset + kPointerSize ==
    816       SharedFunctionInfo::kCodeOffset);
    817   STATIC_ASSERT(SharedFunctionInfo::kCodeOffset + kPointerSize ==
    818       SharedFunctionInfo::kOptimizedCodeMapOffset);
    819 
    820   Object** start_slot =
    821       HeapObject::RawField(object,
    822                            SharedFunctionInfo::kOptimizedCodeMapOffset);
    823   Object** end_slot =
    824       HeapObject::RawField(object,
    825                            SharedFunctionInfo::BodyDescriptor::kEndOffset);
    826   StaticVisitor::VisitPointers(heap, start_slot, end_slot);
    827 }
    828 
    829 
    830 template<typename StaticVisitor>
    831 void StaticMarkingVisitor<StaticVisitor>::VisitJSFunctionStrongCode(
    832     Heap* heap, HeapObject* object) {
    833   Object** start_slot =
    834       HeapObject::RawField(object, JSFunction::kPropertiesOffset);
    835   Object** end_slot =
    836       HeapObject::RawField(object, JSFunction::kCodeEntryOffset);
    837   StaticVisitor::VisitPointers(heap, start_slot, end_slot);
    838 
    839   VisitCodeEntry(heap, object->address() + JSFunction::kCodeEntryOffset);
    840   STATIC_ASSERT(JSFunction::kCodeEntryOffset + kPointerSize ==
    841       JSFunction::kPrototypeOrInitialMapOffset);
    842 
    843   start_slot =
    844       HeapObject::RawField(object, JSFunction::kPrototypeOrInitialMapOffset);
    845   end_slot =
    846       HeapObject::RawField(object, JSFunction::kNonWeakFieldsEndOffset);
    847   StaticVisitor::VisitPointers(heap, start_slot, end_slot);
    848 }
    849 
    850 
    851 template<typename StaticVisitor>
    852 void StaticMarkingVisitor<StaticVisitor>::VisitJSFunctionWeakCode(
    853     Heap* heap, HeapObject* object) {
    854   Object** start_slot =
    855       HeapObject::RawField(object, JSFunction::kPropertiesOffset);
    856   Object** end_slot =
    857       HeapObject::RawField(object, JSFunction::kCodeEntryOffset);
    858   StaticVisitor::VisitPointers(heap, start_slot, end_slot);
    859 
    860   // Skip visiting kCodeEntryOffset as it is treated weakly here.
    861   STATIC_ASSERT(JSFunction::kCodeEntryOffset + kPointerSize ==
    862       JSFunction::kPrototypeOrInitialMapOffset);
    863 
    864   start_slot =
    865       HeapObject::RawField(object, JSFunction::kPrototypeOrInitialMapOffset);
    866   end_slot =
    867       HeapObject::RawField(object, JSFunction::kNonWeakFieldsEndOffset);
    868   StaticVisitor::VisitPointers(heap, start_slot, end_slot);
    869 }
    870 
    871 
    872 void Code::CodeIterateBody(ObjectVisitor* v) {
    873   int mode_mask = RelocInfo::kCodeTargetMask |
    874                   RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
    875                   RelocInfo::ModeMask(RelocInfo::CELL) |
    876                   RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) |
    877                   RelocInfo::ModeMask(RelocInfo::JS_RETURN) |
    878                   RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT) |
    879                   RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY);
    880 
    881   // There are two places where we iterate code bodies: here and the
    882   // templated CodeIterateBody (below). They should be kept in sync.
    883   IteratePointer(v, kRelocationInfoOffset);
    884   IteratePointer(v, kHandlerTableOffset);
    885   IteratePointer(v, kDeoptimizationDataOffset);
    886   IteratePointer(v, kTypeFeedbackInfoOffset);
    887 
    888   RelocIterator it(this, mode_mask);
    889   Isolate* isolate = this->GetIsolate();
    890   for (; !it.done(); it.next()) {
    891     it.rinfo()->Visit(isolate, v);
    892   }
    893 }
    894 
    895 
    896 template<typename StaticVisitor>
    897 void Code::CodeIterateBody(Heap* heap) {
    898   int mode_mask = RelocInfo::kCodeTargetMask |
    899                   RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
    900                   RelocInfo::ModeMask(RelocInfo::CELL) |
    901                   RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) |
    902                   RelocInfo::ModeMask(RelocInfo::JS_RETURN) |
    903                   RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT) |
    904                   RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY);
    905 
    906   // There are two places where we iterate code bodies: here and the non-
    907   // templated CodeIterateBody (above). They should be kept in sync.
    908   StaticVisitor::VisitPointer(
    909       heap,
    910       reinterpret_cast<Object**>(this->address() + kRelocationInfoOffset));
    911   StaticVisitor::VisitPointer(
    912       heap,
    913       reinterpret_cast<Object**>(this->address() + kHandlerTableOffset));
    914   StaticVisitor::VisitPointer(
    915       heap,
    916       reinterpret_cast<Object**>(this->address() + kDeoptimizationDataOffset));
    917   StaticVisitor::VisitPointer(
    918       heap,
    919       reinterpret_cast<Object**>(this->address() + kTypeFeedbackInfoOffset));
    920 
    921   RelocIterator it(this, mode_mask);
    922   for (; !it.done(); it.next()) {
    923     it.rinfo()->template Visit<StaticVisitor>(heap);
    924   }
    925 }
    926 
    927 
    928 } }  // namespace v8::internal
    929 
    930 #endif  // V8_OBJECTS_VISITING_INL_H_
    931