Index: src/objects-visiting-inl.h |
diff --git a/src/objects-visiting-inl.h b/src/objects-visiting-inl.h |
deleted file mode 100644 |
index 19fe0c610a1226e4994a60fdfa0ce31eabad5a1d..0000000000000000000000000000000000000000 |
--- a/src/objects-visiting-inl.h |
+++ /dev/null |
@@ -1,971 +0,0 @@ |
-// Copyright 2012 the V8 project authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-#ifndef V8_OBJECTS_VISITING_INL_H_ |
-#define V8_OBJECTS_VISITING_INL_H_ |
- |
- |
-namespace v8 { |
-namespace internal { |
- |
-template<typename StaticVisitor> |
-void StaticNewSpaceVisitor<StaticVisitor>::Initialize() { |
- table_.Register(kVisitShortcutCandidate, |
- &FixedBodyVisitor<StaticVisitor, |
- ConsString::BodyDescriptor, |
- int>::Visit); |
- |
- table_.Register(kVisitConsString, |
- &FixedBodyVisitor<StaticVisitor, |
- ConsString::BodyDescriptor, |
- int>::Visit); |
- |
- table_.Register(kVisitSlicedString, |
- &FixedBodyVisitor<StaticVisitor, |
- SlicedString::BodyDescriptor, |
- int>::Visit); |
- |
- table_.Register(kVisitSymbol, |
- &FixedBodyVisitor<StaticVisitor, |
- Symbol::BodyDescriptor, |
- int>::Visit); |
- |
- table_.Register(kVisitFixedArray, |
- &FlexibleBodyVisitor<StaticVisitor, |
- FixedArray::BodyDescriptor, |
- int>::Visit); |
- |
- table_.Register(kVisitFixedDoubleArray, &VisitFixedDoubleArray); |
- table_.Register(kVisitFixedTypedArray, &VisitFixedTypedArray); |
- table_.Register(kVisitFixedFloat64Array, &VisitFixedTypedArray); |
- |
- table_.Register(kVisitNativeContext, |
- &FixedBodyVisitor<StaticVisitor, |
- Context::ScavengeBodyDescriptor, |
- int>::Visit); |
- |
- table_.Register(kVisitByteArray, &VisitByteArray); |
- |
- table_.Register(kVisitSharedFunctionInfo, |
- &FixedBodyVisitor<StaticVisitor, |
- SharedFunctionInfo::BodyDescriptor, |
- int>::Visit); |
- |
- table_.Register(kVisitSeqOneByteString, &VisitSeqOneByteString); |
- |
- table_.Register(kVisitSeqTwoByteString, &VisitSeqTwoByteString); |
- |
- table_.Register(kVisitJSFunction, &VisitJSFunction); |
- |
- table_.Register(kVisitJSArrayBuffer, &VisitJSArrayBuffer); |
- |
- table_.Register(kVisitJSTypedArray, &VisitJSTypedArray); |
- |
- table_.Register(kVisitJSDataView, &VisitJSDataView); |
- |
- table_.Register(kVisitFreeSpace, &VisitFreeSpace); |
- |
- table_.Register(kVisitJSWeakCollection, &JSObjectVisitor::Visit); |
- |
- table_.Register(kVisitJSRegExp, &JSObjectVisitor::Visit); |
- |
- table_.template RegisterSpecializations<DataObjectVisitor, |
- kVisitDataObject, |
- kVisitDataObjectGeneric>(); |
- |
- table_.template RegisterSpecializations<JSObjectVisitor, |
- kVisitJSObject, |
- kVisitJSObjectGeneric>(); |
- table_.template RegisterSpecializations<StructVisitor, |
- kVisitStruct, |
- kVisitStructGeneric>(); |
-} |
- |
- |
-template<typename StaticVisitor> |
-int StaticNewSpaceVisitor<StaticVisitor>::VisitJSArrayBuffer( |
- Map* map, HeapObject* object) { |
- Heap* heap = map->GetHeap(); |
- |
- STATIC_ASSERT( |
- JSArrayBuffer::kWeakFirstViewOffset == |
- JSArrayBuffer::kWeakNextOffset + kPointerSize); |
- VisitPointers( |
- heap, |
- HeapObject::RawField(object, JSArrayBuffer::BodyDescriptor::kStartOffset), |
- HeapObject::RawField(object, JSArrayBuffer::kWeakNextOffset)); |
- VisitPointers( |
- heap, |
- HeapObject::RawField(object, |
- JSArrayBuffer::kWeakNextOffset + 2 * kPointerSize), |
- HeapObject::RawField(object, JSArrayBuffer::kSizeWithInternalFields)); |
- return JSArrayBuffer::kSizeWithInternalFields; |
-} |
- |
- |
-template<typename StaticVisitor> |
-int StaticNewSpaceVisitor<StaticVisitor>::VisitJSTypedArray( |
- Map* map, HeapObject* object) { |
- VisitPointers( |
- map->GetHeap(), |
- HeapObject::RawField(object, JSTypedArray::BodyDescriptor::kStartOffset), |
- HeapObject::RawField(object, JSTypedArray::kWeakNextOffset)); |
- VisitPointers( |
- map->GetHeap(), |
- HeapObject::RawField(object, |
- JSTypedArray::kWeakNextOffset + kPointerSize), |
- HeapObject::RawField(object, JSTypedArray::kSizeWithInternalFields)); |
- return JSTypedArray::kSizeWithInternalFields; |
-} |
- |
- |
-template<typename StaticVisitor> |
-int StaticNewSpaceVisitor<StaticVisitor>::VisitJSDataView( |
- Map* map, HeapObject* object) { |
- VisitPointers( |
- map->GetHeap(), |
- HeapObject::RawField(object, JSDataView::BodyDescriptor::kStartOffset), |
- HeapObject::RawField(object, JSDataView::kWeakNextOffset)); |
- VisitPointers( |
- map->GetHeap(), |
- HeapObject::RawField(object, |
- JSDataView::kWeakNextOffset + kPointerSize), |
- HeapObject::RawField(object, JSDataView::kSizeWithInternalFields)); |
- return JSDataView::kSizeWithInternalFields; |
-} |
- |
- |
-template<typename StaticVisitor> |
-void StaticMarkingVisitor<StaticVisitor>::Initialize() { |
- table_.Register(kVisitShortcutCandidate, |
- &FixedBodyVisitor<StaticVisitor, |
- ConsString::BodyDescriptor, |
- void>::Visit); |
- |
- table_.Register(kVisitConsString, |
- &FixedBodyVisitor<StaticVisitor, |
- ConsString::BodyDescriptor, |
- void>::Visit); |
- |
- table_.Register(kVisitSlicedString, |
- &FixedBodyVisitor<StaticVisitor, |
- SlicedString::BodyDescriptor, |
- void>::Visit); |
- |
- table_.Register(kVisitSymbol, |
- &FixedBodyVisitor<StaticVisitor, |
- Symbol::BodyDescriptor, |
- void>::Visit); |
- |
- table_.Register(kVisitFixedArray, &FixedArrayVisitor::Visit); |
- |
- table_.Register(kVisitFixedDoubleArray, &DataObjectVisitor::Visit); |
- |
- table_.Register(kVisitFixedTypedArray, &DataObjectVisitor::Visit); |
- |
- table_.Register(kVisitFixedFloat64Array, &DataObjectVisitor::Visit); |
- |
- table_.Register(kVisitConstantPoolArray, &VisitConstantPoolArray); |
- |
- table_.Register(kVisitNativeContext, &VisitNativeContext); |
- |
- table_.Register(kVisitAllocationSite, &VisitAllocationSite); |
- |
- table_.Register(kVisitByteArray, &DataObjectVisitor::Visit); |
- |
- table_.Register(kVisitFreeSpace, &DataObjectVisitor::Visit); |
- |
- table_.Register(kVisitSeqOneByteString, &DataObjectVisitor::Visit); |
- |
- table_.Register(kVisitSeqTwoByteString, &DataObjectVisitor::Visit); |
- |
- table_.Register(kVisitJSWeakCollection, &VisitWeakCollection); |
- |
- table_.Register(kVisitOddball, |
- &FixedBodyVisitor<StaticVisitor, |
- Oddball::BodyDescriptor, |
- void>::Visit); |
- |
- table_.Register(kVisitMap, &VisitMap); |
- |
- table_.Register(kVisitCode, &VisitCode); |
- |
- table_.Register(kVisitSharedFunctionInfo, &VisitSharedFunctionInfo); |
- |
- table_.Register(kVisitJSFunction, &VisitJSFunction); |
- |
- table_.Register(kVisitJSArrayBuffer, &VisitJSArrayBuffer); |
- |
- table_.Register(kVisitJSTypedArray, &VisitJSTypedArray); |
- |
- table_.Register(kVisitJSDataView, &VisitJSDataView); |
- |
- // Registration for kVisitJSRegExp is done by StaticVisitor. |
- |
- table_.Register(kVisitCell, |
- &FixedBodyVisitor<StaticVisitor, |
- Cell::BodyDescriptor, |
- void>::Visit); |
- |
- table_.Register(kVisitPropertyCell, &VisitPropertyCell); |
- |
- table_.template RegisterSpecializations<DataObjectVisitor, |
- kVisitDataObject, |
- kVisitDataObjectGeneric>(); |
- |
- table_.template RegisterSpecializations<JSObjectVisitor, |
- kVisitJSObject, |
- kVisitJSObjectGeneric>(); |
- |
- table_.template RegisterSpecializations<StructObjectVisitor, |
- kVisitStruct, |
- kVisitStructGeneric>(); |
-} |
- |
- |
-template<typename StaticVisitor> |
-void StaticMarkingVisitor<StaticVisitor>::VisitCodeEntry( |
- Heap* heap, Address entry_address) { |
- Code* code = Code::cast(Code::GetObjectFromEntryAddress(entry_address)); |
- heap->mark_compact_collector()->RecordCodeEntrySlot(entry_address, code); |
- StaticVisitor::MarkObject(heap, code); |
-} |
- |
- |
-template<typename StaticVisitor> |
-void StaticMarkingVisitor<StaticVisitor>::VisitEmbeddedPointer( |
- Heap* heap, RelocInfo* rinfo) { |
- DCHECK(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT); |
- HeapObject* object = HeapObject::cast(rinfo->target_object()); |
- heap->mark_compact_collector()->RecordRelocSlot(rinfo, object); |
- // TODO(ulan): It could be better to record slots only for strongly embedded |
- // objects here and record slots for weakly embedded object during clearing |
- // of non-live references in mark-compact. |
- if (!rinfo->host()->IsWeakObject(object)) { |
- StaticVisitor::MarkObject(heap, object); |
- } |
-} |
- |
- |
-template<typename StaticVisitor> |
-void StaticMarkingVisitor<StaticVisitor>::VisitCell( |
- Heap* heap, RelocInfo* rinfo) { |
- DCHECK(rinfo->rmode() == RelocInfo::CELL); |
- Cell* cell = rinfo->target_cell(); |
- // No need to record slots because the cell space is not compacted during GC. |
- if (!rinfo->host()->IsWeakObject(cell)) { |
- StaticVisitor::MarkObject(heap, cell); |
- } |
-} |
- |
- |
-template<typename StaticVisitor> |
-void StaticMarkingVisitor<StaticVisitor>::VisitDebugTarget( |
- Heap* heap, RelocInfo* rinfo) { |
- DCHECK((RelocInfo::IsJSReturn(rinfo->rmode()) && |
- rinfo->IsPatchedReturnSequence()) || |
- (RelocInfo::IsDebugBreakSlot(rinfo->rmode()) && |
- rinfo->IsPatchedDebugBreakSlotSequence())); |
- Code* target = Code::GetCodeFromTargetAddress(rinfo->call_address()); |
- heap->mark_compact_collector()->RecordRelocSlot(rinfo, target); |
- StaticVisitor::MarkObject(heap, target); |
-} |
- |
- |
-template<typename StaticVisitor> |
-void StaticMarkingVisitor<StaticVisitor>::VisitCodeTarget( |
- Heap* heap, RelocInfo* rinfo) { |
- DCHECK(RelocInfo::IsCodeTarget(rinfo->rmode())); |
- Code* target = Code::GetCodeFromTargetAddress(rinfo->target_address()); |
- // Monomorphic ICs are preserved when possible, but need to be flushed |
- // when they might be keeping a Context alive, or when the heap is about |
- // to be serialized. |
- if (FLAG_cleanup_code_caches_at_gc && target->is_inline_cache_stub() |
- && (target->ic_state() == MEGAMORPHIC || target->ic_state() == GENERIC || |
- target->ic_state() == POLYMORPHIC || heap->flush_monomorphic_ics() || |
- heap->isolate()->serializer_enabled() || |
- target->ic_age() != heap->global_ic_age() || |
- target->is_invalidated_weak_stub())) { |
- IC::Clear(heap->isolate(), rinfo->pc(), rinfo->host()->constant_pool()); |
- target = Code::GetCodeFromTargetAddress(rinfo->target_address()); |
- } |
- heap->mark_compact_collector()->RecordRelocSlot(rinfo, target); |
- StaticVisitor::MarkObject(heap, target); |
-} |
- |
- |
-template<typename StaticVisitor> |
-void StaticMarkingVisitor<StaticVisitor>::VisitCodeAgeSequence( |
- Heap* heap, RelocInfo* rinfo) { |
- DCHECK(RelocInfo::IsCodeAgeSequence(rinfo->rmode())); |
- Code* target = rinfo->code_age_stub(); |
- DCHECK(target != NULL); |
- heap->mark_compact_collector()->RecordRelocSlot(rinfo, target); |
- StaticVisitor::MarkObject(heap, target); |
-} |
- |
- |
-template<typename StaticVisitor> |
-void StaticMarkingVisitor<StaticVisitor>::VisitNativeContext( |
- Map* map, HeapObject* object) { |
- FixedBodyVisitor<StaticVisitor, |
- Context::MarkCompactBodyDescriptor, |
- void>::Visit(map, object); |
- |
- MarkCompactCollector* collector = map->GetHeap()->mark_compact_collector(); |
- for (int idx = Context::FIRST_WEAK_SLOT; |
- idx < Context::NATIVE_CONTEXT_SLOTS; |
- ++idx) { |
- Object** slot = Context::cast(object)->RawFieldOfElementAt(idx); |
- collector->RecordSlot(slot, slot, *slot); |
- } |
-} |
- |
- |
-template<typename StaticVisitor> |
-void StaticMarkingVisitor<StaticVisitor>::VisitMap( |
- Map* map, HeapObject* object) { |
- Heap* heap = map->GetHeap(); |
- Map* map_object = Map::cast(object); |
- |
- // Clears the cache of ICs related to this map. |
- if (FLAG_cleanup_code_caches_at_gc) { |
- map_object->ClearCodeCache(heap); |
- } |
- |
- // When map collection is enabled we have to mark through map's transitions |
- // and back pointers in a special way to make these links weak. |
- if (FLAG_collect_maps && map_object->CanTransition()) { |
- MarkMapContents(heap, map_object); |
- } else { |
- StaticVisitor::VisitPointers(heap, |
- HeapObject::RawField(object, Map::kPointerFieldsBeginOffset), |
- HeapObject::RawField(object, Map::kPointerFieldsEndOffset)); |
- } |
-} |
- |
- |
-template<typename StaticVisitor> |
-void StaticMarkingVisitor<StaticVisitor>::VisitPropertyCell( |
- Map* map, HeapObject* object) { |
- Heap* heap = map->GetHeap(); |
- |
- Object** slot = |
- HeapObject::RawField(object, PropertyCell::kDependentCodeOffset); |
- if (FLAG_collect_maps) { |
- // Mark property cell dependent codes array but do not push it onto marking |
- // stack, this will make references from it weak. We will clean dead |
- // codes when we iterate over property cells in ClearNonLiveReferences. |
- HeapObject* obj = HeapObject::cast(*slot); |
- heap->mark_compact_collector()->RecordSlot(slot, slot, obj); |
- StaticVisitor::MarkObjectWithoutPush(heap, obj); |
- } else { |
- StaticVisitor::VisitPointer(heap, slot); |
- } |
- |
- StaticVisitor::VisitPointers(heap, |
- HeapObject::RawField(object, PropertyCell::kPointerFieldsBeginOffset), |
- HeapObject::RawField(object, PropertyCell::kPointerFieldsEndOffset)); |
-} |
- |
- |
-template<typename StaticVisitor> |
-void StaticMarkingVisitor<StaticVisitor>::VisitAllocationSite( |
- Map* map, HeapObject* object) { |
- Heap* heap = map->GetHeap(); |
- |
- Object** slot = |
- HeapObject::RawField(object, AllocationSite::kDependentCodeOffset); |
- if (FLAG_collect_maps) { |
- // Mark allocation site dependent codes array but do not push it onto |
- // marking stack, this will make references from it weak. We will clean |
- // dead codes when we iterate over allocation sites in |
- // ClearNonLiveReferences. |
- HeapObject* obj = HeapObject::cast(*slot); |
- heap->mark_compact_collector()->RecordSlot(slot, slot, obj); |
- StaticVisitor::MarkObjectWithoutPush(heap, obj); |
- } else { |
- StaticVisitor::VisitPointer(heap, slot); |
- } |
- |
- StaticVisitor::VisitPointers(heap, |
- HeapObject::RawField(object, AllocationSite::kPointerFieldsBeginOffset), |
- HeapObject::RawField(object, AllocationSite::kPointerFieldsEndOffset)); |
-} |
- |
- |
-template<typename StaticVisitor> |
-void StaticMarkingVisitor<StaticVisitor>::VisitWeakCollection( |
- Map* map, HeapObject* object) { |
- Heap* heap = map->GetHeap(); |
- JSWeakCollection* weak_collection = |
- reinterpret_cast<JSWeakCollection*>(object); |
- |
- // Enqueue weak collection in linked list of encountered weak collections. |
- if (weak_collection->next() == heap->undefined_value()) { |
- weak_collection->set_next(heap->encountered_weak_collections()); |
- heap->set_encountered_weak_collections(weak_collection); |
- } |
- |
- // Skip visiting the backing hash table containing the mappings and the |
- // pointer to the other enqueued weak collections, both are post-processed. |
- StaticVisitor::VisitPointers(heap, |
- HeapObject::RawField(object, JSWeakCollection::kPropertiesOffset), |
- HeapObject::RawField(object, JSWeakCollection::kTableOffset)); |
- STATIC_ASSERT(JSWeakCollection::kTableOffset + kPointerSize == |
- JSWeakCollection::kNextOffset); |
- STATIC_ASSERT(JSWeakCollection::kNextOffset + kPointerSize == |
- JSWeakCollection::kSize); |
- |
- // Partially initialized weak collection is enqueued, but table is ignored. |
- if (!weak_collection->table()->IsHashTable()) return; |
- |
- // Mark the backing hash table without pushing it on the marking stack. |
- Object** slot = HeapObject::RawField(object, JSWeakCollection::kTableOffset); |
- HeapObject* obj = HeapObject::cast(*slot); |
- heap->mark_compact_collector()->RecordSlot(slot, slot, obj); |
- StaticVisitor::MarkObjectWithoutPush(heap, obj); |
-} |
- |
- |
-template<typename StaticVisitor> |
-void StaticMarkingVisitor<StaticVisitor>::VisitCode( |
- Map* map, HeapObject* object) { |
- Heap* heap = map->GetHeap(); |
- Code* code = Code::cast(object); |
- if (FLAG_age_code && !heap->isolate()->serializer_enabled()) { |
- code->MakeOlder(heap->mark_compact_collector()->marking_parity()); |
- } |
- code->CodeIterateBody<StaticVisitor>(heap); |
-} |
- |
- |
-template<typename StaticVisitor> |
-void StaticMarkingVisitor<StaticVisitor>::VisitSharedFunctionInfo( |
- Map* map, HeapObject* object) { |
- Heap* heap = map->GetHeap(); |
- SharedFunctionInfo* shared = SharedFunctionInfo::cast(object); |
- if (shared->ic_age() != heap->global_ic_age()) { |
- shared->ResetForNewContext(heap->global_ic_age()); |
- } |
- if (FLAG_cleanup_code_caches_at_gc) { |
- shared->ClearTypeFeedbackInfo(); |
- } |
- if (FLAG_cache_optimized_code && |
- FLAG_flush_optimized_code_cache && |
- !shared->optimized_code_map()->IsSmi()) { |
- // Always flush the optimized code map if requested by flag. |
- shared->ClearOptimizedCodeMap(); |
- } |
- MarkCompactCollector* collector = heap->mark_compact_collector(); |
- if (collector->is_code_flushing_enabled()) { |
- if (FLAG_cache_optimized_code && !shared->optimized_code_map()->IsSmi()) { |
- // Add the shared function info holding an optimized code map to |
- // the code flusher for processing of code maps after marking. |
- collector->code_flusher()->AddOptimizedCodeMap(shared); |
- // Treat all references within the code map weakly by marking the |
- // code map itself but not pushing it onto the marking deque. |
- FixedArray* code_map = FixedArray::cast(shared->optimized_code_map()); |
- StaticVisitor::MarkObjectWithoutPush(heap, code_map); |
- } |
- if (IsFlushable(heap, shared)) { |
- // This function's code looks flushable. But we have to postpone |
- // the decision until we see all functions that point to the same |
- // SharedFunctionInfo because some of them might be optimized. |
- // That would also make the non-optimized version of the code |
- // non-flushable, because it is required for bailing out from |
- // optimized code. |
- collector->code_flusher()->AddCandidate(shared); |
- // Treat the reference to the code object weakly. |
- VisitSharedFunctionInfoWeakCode(heap, object); |
- return; |
- } |
- } else { |
- if (FLAG_cache_optimized_code && !shared->optimized_code_map()->IsSmi()) { |
- // Flush optimized code map on major GCs without code flushing, |
- // needed because cached code doesn't contain breakpoints. |
- shared->ClearOptimizedCodeMap(); |
- } |
- } |
- VisitSharedFunctionInfoStrongCode(heap, object); |
-} |
- |
- |
-template<typename StaticVisitor> |
-void StaticMarkingVisitor<StaticVisitor>::VisitConstantPoolArray( |
- Map* map, HeapObject* object) { |
- Heap* heap = map->GetHeap(); |
- ConstantPoolArray* array = ConstantPoolArray::cast(object); |
- ConstantPoolArray::Iterator code_iter(array, ConstantPoolArray::CODE_PTR); |
- while (!code_iter.is_finished()) { |
- Address code_entry = reinterpret_cast<Address>( |
- array->RawFieldOfElementAt(code_iter.next_index())); |
- StaticVisitor::VisitCodeEntry(heap, code_entry); |
- } |
- |
- ConstantPoolArray::Iterator heap_iter(array, ConstantPoolArray::HEAP_PTR); |
- while (!heap_iter.is_finished()) { |
- Object** slot = array->RawFieldOfElementAt(heap_iter.next_index()); |
- HeapObject* object = HeapObject::cast(*slot); |
- heap->mark_compact_collector()->RecordSlot(slot, slot, object); |
- bool is_weak_object = |
- (array->get_weak_object_state() == |
- ConstantPoolArray::WEAK_OBJECTS_IN_OPTIMIZED_CODE && |
- Code::IsWeakObjectInOptimizedCode(object)) || |
- (array->get_weak_object_state() == |
- ConstantPoolArray::WEAK_OBJECTS_IN_IC && |
- Code::IsWeakObjectInIC(object)); |
- if (!is_weak_object) { |
- StaticVisitor::MarkObject(heap, object); |
- } |
- } |
-} |
- |
- |
-template<typename StaticVisitor> |
-void StaticMarkingVisitor<StaticVisitor>::VisitJSFunction( |
- Map* map, HeapObject* object) { |
- Heap* heap = map->GetHeap(); |
- JSFunction* function = JSFunction::cast(object); |
- MarkCompactCollector* collector = heap->mark_compact_collector(); |
- if (collector->is_code_flushing_enabled()) { |
- if (IsFlushable(heap, function)) { |
- // This function's code looks flushable. But we have to postpone |
- // the decision until we see all functions that point to the same |
- // SharedFunctionInfo because some of them might be optimized. |
- // That would also make the non-optimized version of the code |
- // non-flushable, because it is required for bailing out from |
- // optimized code. |
- collector->code_flusher()->AddCandidate(function); |
- // Visit shared function info immediately to avoid double checking |
- // of its flushability later. This is just an optimization because |
- // the shared function info would eventually be visited. |
- SharedFunctionInfo* shared = function->shared(); |
- if (StaticVisitor::MarkObjectWithoutPush(heap, shared)) { |
- StaticVisitor::MarkObject(heap, shared->map()); |
- VisitSharedFunctionInfoWeakCode(heap, shared); |
- } |
- // Treat the reference to the code object weakly. |
- VisitJSFunctionWeakCode(heap, object); |
- return; |
- } else { |
- // Visit all unoptimized code objects to prevent flushing them. |
- StaticVisitor::MarkObject(heap, function->shared()->code()); |
- if (function->code()->kind() == Code::OPTIMIZED_FUNCTION) { |
- MarkInlinedFunctionsCode(heap, function->code()); |
- } |
- } |
- } |
- VisitJSFunctionStrongCode(heap, object); |
-} |
- |
- |
-template<typename StaticVisitor> |
-void StaticMarkingVisitor<StaticVisitor>::VisitJSRegExp( |
- Map* map, HeapObject* object) { |
- int last_property_offset = |
- JSRegExp::kSize + kPointerSize * map->inobject_properties(); |
- StaticVisitor::VisitPointers(map->GetHeap(), |
- HeapObject::RawField(object, JSRegExp::kPropertiesOffset), |
- HeapObject::RawField(object, last_property_offset)); |
-} |
- |
- |
-template<typename StaticVisitor> |
-void StaticMarkingVisitor<StaticVisitor>::VisitJSArrayBuffer( |
- Map* map, HeapObject* object) { |
- Heap* heap = map->GetHeap(); |
- |
- STATIC_ASSERT( |
- JSArrayBuffer::kWeakFirstViewOffset == |
- JSArrayBuffer::kWeakNextOffset + kPointerSize); |
- StaticVisitor::VisitPointers( |
- heap, |
- HeapObject::RawField(object, JSArrayBuffer::BodyDescriptor::kStartOffset), |
- HeapObject::RawField(object, JSArrayBuffer::kWeakNextOffset)); |
- StaticVisitor::VisitPointers( |
- heap, |
- HeapObject::RawField(object, |
- JSArrayBuffer::kWeakNextOffset + 2 * kPointerSize), |
- HeapObject::RawField(object, JSArrayBuffer::kSizeWithInternalFields)); |
-} |
- |
- |
-template<typename StaticVisitor> |
-void StaticMarkingVisitor<StaticVisitor>::VisitJSTypedArray( |
- Map* map, HeapObject* object) { |
- StaticVisitor::VisitPointers( |
- map->GetHeap(), |
- HeapObject::RawField(object, JSTypedArray::BodyDescriptor::kStartOffset), |
- HeapObject::RawField(object, JSTypedArray::kWeakNextOffset)); |
- StaticVisitor::VisitPointers( |
- map->GetHeap(), |
- HeapObject::RawField(object, |
- JSTypedArray::kWeakNextOffset + kPointerSize), |
- HeapObject::RawField(object, JSTypedArray::kSizeWithInternalFields)); |
-} |
- |
- |
-template<typename StaticVisitor> |
-void StaticMarkingVisitor<StaticVisitor>::VisitJSDataView( |
- Map* map, HeapObject* object) { |
- StaticVisitor::VisitPointers( |
- map->GetHeap(), |
- HeapObject::RawField(object, JSDataView::BodyDescriptor::kStartOffset), |
- HeapObject::RawField(object, JSDataView::kWeakNextOffset)); |
- StaticVisitor::VisitPointers( |
- map->GetHeap(), |
- HeapObject::RawField(object, |
- JSDataView::kWeakNextOffset + kPointerSize), |
- HeapObject::RawField(object, JSDataView::kSizeWithInternalFields)); |
-} |
- |
- |
-template<typename StaticVisitor> |
-void StaticMarkingVisitor<StaticVisitor>::MarkMapContents( |
- Heap* heap, Map* map) { |
- // Make sure that the back pointer stored either in the map itself or |
- // inside its transitions array is marked. Skip recording the back |
- // pointer slot since map space is not compacted. |
- StaticVisitor::MarkObject(heap, HeapObject::cast(map->GetBackPointer())); |
- |
- // Treat pointers in the transitions array as weak and also mark that |
- // array to prevent visiting it later. Skip recording the transition |
- // array slot, since it will be implicitly recorded when the pointer |
- // fields of this map are visited. |
- if (map->HasTransitionArray()) { |
- TransitionArray* transitions = map->transitions(); |
- MarkTransitionArray(heap, transitions); |
- } |
- |
- // Since descriptor arrays are potentially shared, ensure that only the |
- // descriptors that belong to this map are marked. The first time a |
- // non-empty descriptor array is marked, its header is also visited. The slot |
- // holding the descriptor array will be implicitly recorded when the pointer |
- // fields of this map are visited. |
- DescriptorArray* descriptors = map->instance_descriptors(); |
- if (StaticVisitor::MarkObjectWithoutPush(heap, descriptors) && |
- descriptors->length() > 0) { |
- StaticVisitor::VisitPointers(heap, |
- descriptors->GetFirstElementAddress(), |
- descriptors->GetDescriptorEndSlot(0)); |
- } |
- int start = 0; |
- int end = map->NumberOfOwnDescriptors(); |
- if (start < end) { |
- StaticVisitor::VisitPointers(heap, |
- descriptors->GetDescriptorStartSlot(start), |
- descriptors->GetDescriptorEndSlot(end)); |
- } |
- |
- // Mark prototype dependent codes array but do not push it onto marking |
- // stack, this will make references from it weak. We will clean dead |
- // codes when we iterate over maps in ClearNonLiveTransitions. |
- Object** slot = HeapObject::RawField(map, Map::kDependentCodeOffset); |
- HeapObject* obj = HeapObject::cast(*slot); |
- heap->mark_compact_collector()->RecordSlot(slot, slot, obj); |
- StaticVisitor::MarkObjectWithoutPush(heap, obj); |
- |
- // Mark the pointer fields of the Map. Since the transitions array has |
- // been marked already, it is fine that one of these fields contains a |
- // pointer to it. |
- StaticVisitor::VisitPointers(heap, |
- HeapObject::RawField(map, Map::kPointerFieldsBeginOffset), |
- HeapObject::RawField(map, Map::kPointerFieldsEndOffset)); |
-} |
- |
- |
-template<typename StaticVisitor> |
-void StaticMarkingVisitor<StaticVisitor>::MarkTransitionArray( |
- Heap* heap, TransitionArray* transitions) { |
- if (!StaticVisitor::MarkObjectWithoutPush(heap, transitions)) return; |
- |
- // Simple transitions do not have keys nor prototype transitions. |
- if (transitions->IsSimpleTransition()) return; |
- |
- if (transitions->HasPrototypeTransitions()) { |
- // Mark prototype transitions array but do not push it onto marking |
- // stack, this will make references from it weak. We will clean dead |
- // prototype transitions in ClearNonLiveTransitions. |
- Object** slot = transitions->GetPrototypeTransitionsSlot(); |
- HeapObject* obj = HeapObject::cast(*slot); |
- heap->mark_compact_collector()->RecordSlot(slot, slot, obj); |
- StaticVisitor::MarkObjectWithoutPush(heap, obj); |
- } |
- |
- for (int i = 0; i < transitions->number_of_transitions(); ++i) { |
- StaticVisitor::VisitPointer(heap, transitions->GetKeySlot(i)); |
- } |
-} |
- |
- |
-template<typename StaticVisitor> |
-void StaticMarkingVisitor<StaticVisitor>::MarkInlinedFunctionsCode( |
- Heap* heap, Code* code) { |
- // Skip in absence of inlining. |
- // TODO(turbofan): Revisit once we support inlining. |
- if (code->is_turbofanned()) return; |
- // For optimized functions we should retain both non-optimized version |
- // of its code and non-optimized version of all inlined functions. |
- // This is required to support bailing out from inlined code. |
- DeoptimizationInputData* data = |
- DeoptimizationInputData::cast(code->deoptimization_data()); |
- FixedArray* literals = data->LiteralArray(); |
- for (int i = 0, count = data->InlinedFunctionCount()->value(); |
- i < count; |
- i++) { |
- JSFunction* inlined = JSFunction::cast(literals->get(i)); |
- StaticVisitor::MarkObject(heap, inlined->shared()->code()); |
- } |
-} |
- |
- |
-inline static bool IsValidNonBuiltinContext(Object* context) { |
- return context->IsContext() && |
- !Context::cast(context)->global_object()->IsJSBuiltinsObject(); |
-} |
- |
- |
-inline static bool HasSourceCode(Heap* heap, SharedFunctionInfo* info) { |
- Object* undefined = heap->undefined_value(); |
- return (info->script() != undefined) && |
- (reinterpret_cast<Script*>(info->script())->source() != undefined); |
-} |
- |
- |
-template<typename StaticVisitor> |
-bool StaticMarkingVisitor<StaticVisitor>::IsFlushable( |
- Heap* heap, JSFunction* function) { |
- SharedFunctionInfo* shared_info = function->shared(); |
- |
- // Code is either on stack, in compilation cache or referenced |
- // by optimized version of function. |
- MarkBit code_mark = Marking::MarkBitFrom(function->code()); |
- if (code_mark.Get()) { |
- return false; |
- } |
- |
- // The function must have a valid context and not be a builtin. |
- if (!IsValidNonBuiltinContext(function->context())) { |
- return false; |
- } |
- |
- // We do not (yet) flush code for optimized functions. |
- if (function->code() != shared_info->code()) { |
- return false; |
- } |
- |
- // Check age of optimized code. |
- if (FLAG_age_code && !function->code()->IsOld()) { |
- return false; |
- } |
- |
- return IsFlushable(heap, shared_info); |
-} |
- |
- |
-template<typename StaticVisitor> |
-bool StaticMarkingVisitor<StaticVisitor>::IsFlushable( |
- Heap* heap, SharedFunctionInfo* shared_info) { |
- // Code is either on stack, in compilation cache or referenced |
- // by optimized version of function. |
- MarkBit code_mark = Marking::MarkBitFrom(shared_info->code()); |
- if (code_mark.Get()) { |
- return false; |
- } |
- |
- // The function must be compiled and have the source code available, |
- // to be able to recompile it in case we need the function again. |
- if (!(shared_info->is_compiled() && HasSourceCode(heap, shared_info))) { |
- return false; |
- } |
- |
- // We never flush code for API functions. |
- Object* function_data = shared_info->function_data(); |
- if (function_data->IsFunctionTemplateInfo()) { |
- return false; |
- } |
- |
- // Only flush code for functions. |
- if (shared_info->code()->kind() != Code::FUNCTION) { |
- return false; |
- } |
- |
- // Function must be lazy compilable. |
- if (!shared_info->allows_lazy_compilation()) { |
- return false; |
- } |
- |
- // We do not (yet?) flush code for generator functions, because we don't know |
- // if there are still live activations (generator objects) on the heap. |
- if (shared_info->is_generator()) { |
- return false; |
- } |
- |
- // If this is a full script wrapped in a function we do not flush the code. |
- if (shared_info->is_toplevel()) { |
- return false; |
- } |
- |
- // If this is a function initialized with %SetCode then the one-to-one |
- // relation between SharedFunctionInfo and Code is broken. |
- if (shared_info->dont_flush()) { |
- return false; |
- } |
- |
- // Check age of code. If code aging is disabled we never flush. |
- if (!FLAG_age_code || !shared_info->code()->IsOld()) { |
- return false; |
- } |
- |
- return true; |
-} |
- |
- |
-template<typename StaticVisitor> |
-void StaticMarkingVisitor<StaticVisitor>::VisitSharedFunctionInfoStrongCode( |
- Heap* heap, HeapObject* object) { |
- Object** start_slot = |
- HeapObject::RawField(object, |
- SharedFunctionInfo::BodyDescriptor::kStartOffset); |
- Object** end_slot = |
- HeapObject::RawField(object, |
- SharedFunctionInfo::BodyDescriptor::kEndOffset); |
- StaticVisitor::VisitPointers(heap, start_slot, end_slot); |
-} |
- |
- |
-template<typename StaticVisitor> |
-void StaticMarkingVisitor<StaticVisitor>::VisitSharedFunctionInfoWeakCode( |
- Heap* heap, HeapObject* object) { |
- Object** name_slot = |
- HeapObject::RawField(object, SharedFunctionInfo::kNameOffset); |
- StaticVisitor::VisitPointer(heap, name_slot); |
- |
- // Skip visiting kCodeOffset as it is treated weakly here. |
- STATIC_ASSERT(SharedFunctionInfo::kNameOffset + kPointerSize == |
- SharedFunctionInfo::kCodeOffset); |
- STATIC_ASSERT(SharedFunctionInfo::kCodeOffset + kPointerSize == |
- SharedFunctionInfo::kOptimizedCodeMapOffset); |
- |
- Object** start_slot = |
- HeapObject::RawField(object, |
- SharedFunctionInfo::kOptimizedCodeMapOffset); |
- Object** end_slot = |
- HeapObject::RawField(object, |
- SharedFunctionInfo::BodyDescriptor::kEndOffset); |
- StaticVisitor::VisitPointers(heap, start_slot, end_slot); |
-} |
- |
- |
-template<typename StaticVisitor> |
-void StaticMarkingVisitor<StaticVisitor>::VisitJSFunctionStrongCode( |
- Heap* heap, HeapObject* object) { |
- Object** start_slot = |
- HeapObject::RawField(object, JSFunction::kPropertiesOffset); |
- Object** end_slot = |
- HeapObject::RawField(object, JSFunction::kCodeEntryOffset); |
- StaticVisitor::VisitPointers(heap, start_slot, end_slot); |
- |
- VisitCodeEntry(heap, object->address() + JSFunction::kCodeEntryOffset); |
- STATIC_ASSERT(JSFunction::kCodeEntryOffset + kPointerSize == |
- JSFunction::kPrototypeOrInitialMapOffset); |
- |
- start_slot = |
- HeapObject::RawField(object, JSFunction::kPrototypeOrInitialMapOffset); |
- end_slot = |
- HeapObject::RawField(object, JSFunction::kNonWeakFieldsEndOffset); |
- StaticVisitor::VisitPointers(heap, start_slot, end_slot); |
-} |
- |
- |
-template<typename StaticVisitor> |
-void StaticMarkingVisitor<StaticVisitor>::VisitJSFunctionWeakCode( |
- Heap* heap, HeapObject* object) { |
- Object** start_slot = |
- HeapObject::RawField(object, JSFunction::kPropertiesOffset); |
- Object** end_slot = |
- HeapObject::RawField(object, JSFunction::kCodeEntryOffset); |
- StaticVisitor::VisitPointers(heap, start_slot, end_slot); |
- |
- // Skip visiting kCodeEntryOffset as it is treated weakly here. |
- STATIC_ASSERT(JSFunction::kCodeEntryOffset + kPointerSize == |
- JSFunction::kPrototypeOrInitialMapOffset); |
- |
- start_slot = |
- HeapObject::RawField(object, JSFunction::kPrototypeOrInitialMapOffset); |
- end_slot = |
- HeapObject::RawField(object, JSFunction::kNonWeakFieldsEndOffset); |
- StaticVisitor::VisitPointers(heap, start_slot, end_slot); |
-} |
- |
- |
-void Code::CodeIterateBody(ObjectVisitor* v) { |
- int mode_mask = RelocInfo::kCodeTargetMask | |
- RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) | |
- RelocInfo::ModeMask(RelocInfo::CELL) | |
- RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) | |
- RelocInfo::ModeMask(RelocInfo::JS_RETURN) | |
- RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT) | |
- RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY); |
- |
- // There are two places where we iterate code bodies: here and the |
- // templated CodeIterateBody (below). They should be kept in sync. |
- IteratePointer(v, kRelocationInfoOffset); |
- IteratePointer(v, kHandlerTableOffset); |
- IteratePointer(v, kDeoptimizationDataOffset); |
- IteratePointer(v, kTypeFeedbackInfoOffset); |
- IterateNextCodeLink(v, kNextCodeLinkOffset); |
- IteratePointer(v, kConstantPoolOffset); |
- |
- RelocIterator it(this, mode_mask); |
- Isolate* isolate = this->GetIsolate(); |
- for (; !it.done(); it.next()) { |
- it.rinfo()->Visit(isolate, v); |
- } |
-} |
- |
- |
-template<typename StaticVisitor> |
-void Code::CodeIterateBody(Heap* heap) { |
- int mode_mask = RelocInfo::kCodeTargetMask | |
- RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) | |
- RelocInfo::ModeMask(RelocInfo::CELL) | |
- RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) | |
- RelocInfo::ModeMask(RelocInfo::JS_RETURN) | |
- RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT) | |
- RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY); |
- |
- // There are two places where we iterate code bodies: here and the non- |
- // templated CodeIterateBody (above). They should be kept in sync. |
- StaticVisitor::VisitPointer( |
- heap, |
- reinterpret_cast<Object**>(this->address() + kRelocationInfoOffset)); |
- StaticVisitor::VisitPointer( |
- heap, |
- reinterpret_cast<Object**>(this->address() + kHandlerTableOffset)); |
- StaticVisitor::VisitPointer( |
- heap, |
- reinterpret_cast<Object**>(this->address() + kDeoptimizationDataOffset)); |
- StaticVisitor::VisitPointer( |
- heap, |
- reinterpret_cast<Object**>(this->address() + kTypeFeedbackInfoOffset)); |
- StaticVisitor::VisitNextCodeLink( |
- heap, |
- reinterpret_cast<Object**>(this->address() + kNextCodeLinkOffset)); |
- StaticVisitor::VisitPointer( |
- heap, |
- reinterpret_cast<Object**>(this->address() + kConstantPoolOffset)); |
- |
- |
- RelocIterator it(this, mode_mask); |
- for (; !it.done(); it.next()) { |
- it.rinfo()->template Visit<StaticVisitor>(heap); |
- } |
-} |
- |
- |
-} } // namespace v8::internal |
- |
-#endif // V8_OBJECTS_VISITING_INL_H_ |