| // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| #include "vm/raw_object.h" |
| |
| #include "vm/class_table.h" |
| #include "vm/freelist.h" |
| #include "vm/isolate.h" |
| #include "vm/object.h" |
| #include "vm/visitor.h" |
| |
| |
| namespace dart { |
| |
| bool RawObject::IsVMHeapObject() const { |
| // TODO(asiva): Need a better way to represent VM heap objects, for |
| // now we use the premarked property for identifying objects in the |
| // VM heap. |
| ASSERT(IsHeapObject()); |
| ASSERT(!Isolate::Current()->heap()->gc_in_progress()); |
| return IsMarked(); |
| } |
| |
| |
| void RawObject::Validate(Isolate* isolate) const { |
| if (Object::null_class_ == reinterpret_cast<RawClass*>(kHeapObjectTag)) { |
| // Validation relies on properly initialized class classes. Skip if the |
| // VM is still being initialized. |
| return; |
| } |
| // All Smi values are valid. |
| if (!IsHeapObject()) { |
| return; |
| } |
| // Validate that the tags_ field is sensible. |
| uword tags = ptr()->tags_; |
| intptr_t reserved = ReservedBits::decode(tags); |
| if (reserved != 0) { |
| FATAL1("Invalid tags field encountered %#"Px"\n", tags); |
| } |
| intptr_t class_id = ClassIdTag::decode(tags); |
| if (!isolate->class_table()->IsValidIndex(class_id)) { |
| FATAL1("Invalid class id encountered %"Pd"\n", class_id); |
| } |
| intptr_t size = SizeTag::decode(tags); |
| if (size != 0 && size != SizeFromClass()) { |
| FATAL1("Inconsistent class size encountered %"Pd"\n", size); |
| } |
| } |
| |
| |
| intptr_t RawObject::SizeFromClass() const { |
| Isolate* isolate = Isolate::Current(); |
| NoHandleScope no_handles(isolate); |
| |
| // Only reasonable to be called on heap objects. |
| ASSERT(IsHeapObject()); |
| |
| RawClass* raw_class = isolate->class_table()->At(GetClassId()); |
| intptr_t instance_size = |
| raw_class->ptr()->instance_size_in_words_ << kWordSizeLog2; |
| intptr_t class_id = raw_class->ptr()->id_; |
| |
| if (instance_size == 0) { |
| switch (class_id) { |
| case kCodeCid: { |
| const RawCode* raw_code = reinterpret_cast<const RawCode*>(this); |
| intptr_t pointer_offsets_length = |
| raw_code->ptr()->pointer_offsets_length_; |
| instance_size = Code::InstanceSize(pointer_offsets_length); |
| break; |
| } |
| case kInstructionsCid: { |
| const RawInstructions* raw_instructions = |
| reinterpret_cast<const RawInstructions*>(this); |
| intptr_t instructions_size = raw_instructions->ptr()->size_; |
| instance_size = Instructions::InstanceSize(instructions_size); |
| break; |
| } |
| case kContextCid: { |
| const RawContext* raw_context = |
| reinterpret_cast<const RawContext*>(this); |
| intptr_t num_variables = raw_context->ptr()->num_variables_; |
| instance_size = Context::InstanceSize(num_variables); |
| break; |
| } |
| case kContextScopeCid: { |
| const RawContextScope* raw_context_scope = |
| reinterpret_cast<const RawContextScope*>(this); |
| intptr_t num_variables = raw_context_scope->ptr()->num_variables_; |
| instance_size = ContextScope::InstanceSize(num_variables); |
| break; |
| } |
| case kBigintCid: { |
| const RawBigint* raw_bgi = reinterpret_cast<const RawBigint*>(this); |
| intptr_t length = raw_bgi->ptr()->allocated_length_; |
| instance_size = Bigint::InstanceSize(length); |
| break; |
| } |
| case kOneByteStringCid: { |
| const RawOneByteString* raw_string = |
| reinterpret_cast<const RawOneByteString*>(this); |
| intptr_t string_length = Smi::Value(raw_string->ptr()->length_); |
| instance_size = OneByteString::InstanceSize(string_length); |
| break; |
| } |
| case kTwoByteStringCid: { |
| const RawTwoByteString* raw_string = |
| reinterpret_cast<const RawTwoByteString*>(this); |
| intptr_t string_length = Smi::Value(raw_string->ptr()->length_); |
| instance_size = TwoByteString::InstanceSize(string_length); |
| break; |
| } |
| case kArrayCid: |
| case kImmutableArrayCid: { |
| const RawArray* raw_array = reinterpret_cast<const RawArray*>(this); |
| intptr_t array_length = Smi::Value(raw_array->ptr()->length_); |
| instance_size = Array::InstanceSize(array_length); |
| break; |
| } |
| #define SIZE_FROM_CLASS(clazz) \ |
| case kTypedData##clazz##Cid: |
| CLASS_LIST_TYPED_DATA(SIZE_FROM_CLASS) { |
| const RawTypedData* raw_obj = |
| reinterpret_cast<const RawTypedData*>(this); |
| intptr_t cid = raw_obj->GetClassId(); |
| intptr_t array_len = Smi::Value(raw_obj->ptr()->length_); |
| intptr_t lengthInBytes = array_len * TypedData::ElementSizeInBytes(cid); |
| instance_size = TypedData::InstanceSize(lengthInBytes); |
| break; |
| } |
| #undef SIZE_FROM_CLASS |
| case kTypeArgumentsCid: { |
| const RawTypeArguments* raw_array = |
| reinterpret_cast<const RawTypeArguments*>(this); |
| intptr_t array_length = Smi::Value(raw_array->ptr()->length_); |
| instance_size = TypeArguments::InstanceSize(array_length); |
| break; |
| } |
| case kPcDescriptorsCid: { |
| const RawPcDescriptors* raw_descriptors = |
| reinterpret_cast<const RawPcDescriptors*>(this); |
| intptr_t num_descriptors = Smi::Value(raw_descriptors->ptr()->length_); |
| instance_size = PcDescriptors::InstanceSize(num_descriptors); |
| break; |
| } |
| case kStackmapCid: { |
| const RawStackmap* map = reinterpret_cast<const RawStackmap*>(this); |
| intptr_t length = map->ptr()->length_; |
| instance_size = Stackmap::InstanceSize(length); |
| break; |
| } |
| case kLocalVarDescriptorsCid: { |
| const RawLocalVarDescriptors* raw_descriptors = |
| reinterpret_cast<const RawLocalVarDescriptors*>(this); |
| intptr_t num_descriptors = raw_descriptors->ptr()->length_; |
| instance_size = LocalVarDescriptors::InstanceSize(num_descriptors); |
| break; |
| } |
| case kExceptionHandlersCid: { |
| const RawExceptionHandlers* raw_handlers = |
| reinterpret_cast<const RawExceptionHandlers*>(this); |
| intptr_t num_handlers = raw_handlers->ptr()->length_; |
| instance_size = ExceptionHandlers::InstanceSize(num_handlers); |
| break; |
| } |
| case kDeoptInfoCid: { |
| const RawDeoptInfo* raw_deopt_info = |
| reinterpret_cast<const RawDeoptInfo*>(this); |
| intptr_t num_entries = Smi::Value(raw_deopt_info->ptr()->length_); |
| instance_size = DeoptInfo::InstanceSize(num_entries); |
| break; |
| } |
| case kJSRegExpCid: { |
| const RawJSRegExp* raw_jsregexp = |
| reinterpret_cast<const RawJSRegExp*>(this); |
| intptr_t data_length = Smi::Value(raw_jsregexp->ptr()->data_length_); |
| instance_size = JSRegExp::InstanceSize(data_length); |
| break; |
| } |
| case kFreeListElement: { |
| ASSERT(FreeBit::decode(ptr()->tags_)); |
| uword addr = RawObject::ToAddr(const_cast<RawObject*>(this)); |
| FreeListElement* element = reinterpret_cast<FreeListElement*>(addr); |
| instance_size = element->Size(); |
| break; |
| } |
| default: |
| UNREACHABLE(); |
| break; |
| } |
| } |
| ASSERT(instance_size != 0); |
| uword tags = ptr()->tags_; |
| ASSERT((instance_size == SizeTag::decode(tags)) || |
| (SizeTag::decode(tags) == 0)); |
| return instance_size; |
| } |
| |
| |
| intptr_t RawObject::VisitPointers(ObjectPointerVisitor* visitor) { |
| intptr_t size = 0; |
| NoHandleScope no_handles(visitor->isolate()); |
| |
| // Only reasonable to be called on heap objects. |
| ASSERT(IsHeapObject()); |
| |
| // Read the necessary data out of the class before visting the class itself. |
| intptr_t class_id = GetClassId(); |
| |
| if (class_id < kNumPredefinedCids) { |
| switch (class_id) { |
| #define RAW_VISITPOINTERS(clazz) \ |
| case clazz::kClassId: { \ |
| Raw##clazz* raw_obj = reinterpret_cast<Raw##clazz*>(this); \ |
| size = Raw##clazz::Visit##clazz##Pointers(raw_obj, visitor); \ |
| break; \ |
| } |
| CLASS_LIST_NO_OBJECT(RAW_VISITPOINTERS) |
| #undef RAW_VISITPOINTERS |
| #define RAW_VISITPOINTERS(clazz) \ |
| case kTypedData##clazz##Cid: |
| CLASS_LIST_TYPED_DATA(RAW_VISITPOINTERS) { |
| RawTypedData* raw_obj = reinterpret_cast<RawTypedData*>(this); |
| size = RawTypedData::VisitTypedDataPointers(raw_obj, visitor); |
| break; |
| } |
| #undef RAW_VISITPOINTERS |
| #define RAW_VISITPOINTERS(clazz) \ |
| case kExternalTypedData##clazz##Cid: |
| CLASS_LIST_TYPED_DATA(RAW_VISITPOINTERS) { |
| RawExternalTypedData* raw_obj = |
| reinterpret_cast<RawExternalTypedData*>(this); |
| size = RawExternalTypedData::VisitExternalTypedDataPointers(raw_obj, |
| visitor); |
| break; |
| } |
| #undef RAW_VISITPOINTERS |
| #define RAW_VISITPOINTERS(clazz) \ |
| case kTypedData##clazz##ViewCid: |
| CLASS_LIST_TYPED_DATA(RAW_VISITPOINTERS) |
| case kByteDataViewCid: { |
| RawInstance* raw_obj = reinterpret_cast<RawInstance*>(this); |
| size = RawInstance::VisitInstancePointers(raw_obj, visitor); |
| break; |
| } |
| #undef RAW_VISITPOINTERS |
| case kFreeListElement: { |
| ASSERT(FreeBit::decode(ptr()->tags_)); |
| uword addr = RawObject::ToAddr(const_cast<RawObject*>(this)); |
| FreeListElement* element = reinterpret_cast<FreeListElement*>(addr); |
| size = element->Size(); |
| break; |
| } |
| default: |
| OS::Print("Class Id: %"Pd"\n", class_id); |
| UNREACHABLE(); |
| break; |
| } |
| } else { |
| RawInstance* raw_obj = reinterpret_cast<RawInstance*>(this); |
| size = RawInstance::VisitInstancePointers(raw_obj, visitor); |
| } |
| |
| ASSERT(size != 0); |
| ASSERT(size == Size()); |
| return size; |
| } |
| |
| |
| bool RawObject::FindObject(FindObjectVisitor* visitor) { |
| ASSERT(visitor != NULL); |
| return visitor->FindObject(const_cast<RawObject*>(this)); |
| } |
| |
| |
| intptr_t RawClass::VisitClassPointers(RawClass* raw_obj, |
| ObjectPointerVisitor* visitor) { |
| visitor->VisitPointers(raw_obj->from(), raw_obj->to()); |
| return Class::InstanceSize(); |
| } |
| |
| |
| intptr_t RawUnresolvedClass::VisitUnresolvedClassPointers( |
| RawUnresolvedClass* raw_obj, ObjectPointerVisitor* visitor) { |
| visitor->VisitPointers(raw_obj->from(), raw_obj->to()); |
| return UnresolvedClass::InstanceSize(); |
| } |
| |
| |
| intptr_t RawAbstractType::VisitAbstractTypePointers( |
| RawAbstractType* raw_obj, ObjectPointerVisitor* visitor) { |
| // RawAbstractType is an abstract class. |
| UNREACHABLE(); |
| return 0; |
| } |
| |
| |
| intptr_t RawType::VisitTypePointers( |
| RawType* raw_obj, ObjectPointerVisitor* visitor) { |
| visitor->VisitPointers(raw_obj->from(), raw_obj->to()); |
| return Type::InstanceSize(); |
| } |
| |
| |
| intptr_t RawTypeParameter::VisitTypeParameterPointers( |
| RawTypeParameter* raw_obj, ObjectPointerVisitor* visitor) { |
| visitor->VisitPointers(raw_obj->from(), raw_obj->to()); |
| return TypeParameter::InstanceSize(); |
| } |
| |
| |
| intptr_t RawBoundedType::VisitBoundedTypePointers( |
| RawBoundedType* raw_obj, ObjectPointerVisitor* visitor) { |
| visitor->VisitPointers(raw_obj->from(), raw_obj->to()); |
| return BoundedType::InstanceSize(); |
| } |
| |
| |
| intptr_t RawMixinAppType::VisitMixinAppTypePointers( |
| RawMixinAppType* raw_obj, ObjectPointerVisitor* visitor) { |
| visitor->VisitPointers(raw_obj->from(), raw_obj->to()); |
| return MixinAppType::InstanceSize(); |
| } |
| |
| |
| intptr_t RawAbstractTypeArguments::VisitAbstractTypeArgumentsPointers( |
| RawAbstractTypeArguments* raw_obj, ObjectPointerVisitor* visitor) { |
| // RawAbstractTypeArguments is an abstract class. |
| UNREACHABLE(); |
| return 0; |
| } |
| |
| |
| intptr_t RawTypeArguments::VisitTypeArgumentsPointers( |
| RawTypeArguments* raw_obj, ObjectPointerVisitor* visitor) { |
| intptr_t length = Smi::Value(raw_obj->ptr()->length_); |
| visitor->VisitPointers(raw_obj->from(), raw_obj->to(length)); |
| return TypeArguments::InstanceSize(length); |
| } |
| |
| |
| intptr_t RawInstantiatedTypeArguments::VisitInstantiatedTypeArgumentsPointers( |
| RawInstantiatedTypeArguments* raw_obj, ObjectPointerVisitor* visitor) { |
| visitor->VisitPointers(raw_obj->from(), raw_obj->to()); |
| return InstantiatedTypeArguments::InstanceSize(); |
| } |
| |
| |
| intptr_t RawPatchClass::VisitPatchClassPointers(RawPatchClass* raw_obj, |
| ObjectPointerVisitor* visitor) { |
| visitor->VisitPointers(raw_obj->from(), raw_obj->to()); |
| return PatchClass::InstanceSize(); |
| } |
| |
| |
| intptr_t RawClosureData::VisitClosureDataPointers( |
| RawClosureData* raw_obj, ObjectPointerVisitor* visitor) { |
| visitor->VisitPointers(raw_obj->from(), raw_obj->to()); |
| return ClosureData::InstanceSize(); |
| } |
| |
| |
| intptr_t RawRedirectionData::VisitRedirectionDataPointers( |
| RawRedirectionData* raw_obj, ObjectPointerVisitor* visitor) { |
| visitor->VisitPointers(raw_obj->from(), raw_obj->to()); |
| return RedirectionData::InstanceSize(); |
| } |
| |
| |
| intptr_t RawFunction::VisitFunctionPointers(RawFunction* raw_obj, |
| ObjectPointerVisitor* visitor) { |
| visitor->VisitPointers(raw_obj->from(), raw_obj->to()); |
| return Function::InstanceSize(); |
| } |
| |
| |
| intptr_t RawField::VisitFieldPointers(RawField* raw_obj, |
| ObjectPointerVisitor* visitor) { |
| visitor->VisitPointers(raw_obj->from(), raw_obj->to()); |
| return Field::InstanceSize(); |
| } |
| |
| |
| intptr_t RawLiteralToken::VisitLiteralTokenPointers( |
| RawLiteralToken* raw_obj, ObjectPointerVisitor* visitor) { |
| visitor->VisitPointers(raw_obj->from(), raw_obj->to()); |
| return LiteralToken::InstanceSize(); |
| } |
| |
| |
| intptr_t RawTokenStream::VisitTokenStreamPointers( |
| RawTokenStream* raw_obj, ObjectPointerVisitor* visitor) { |
| visitor->VisitPointers(raw_obj->from(), raw_obj->to()); |
| return TokenStream::InstanceSize(); |
| } |
| |
| |
| intptr_t RawScript::VisitScriptPointers(RawScript* raw_obj, |
| ObjectPointerVisitor* visitor) { |
| visitor->VisitPointers(raw_obj->from(), raw_obj->to()); |
| return Script::InstanceSize(); |
| } |
| |
| |
| intptr_t RawLibrary::VisitLibraryPointers(RawLibrary* raw_obj, |
| ObjectPointerVisitor* visitor) { |
| visitor->VisitPointers(raw_obj->from(), raw_obj->to()); |
| return Library::InstanceSize(); |
| } |
| |
| |
| intptr_t RawLibraryPrefix::VisitLibraryPrefixPointers( |
| RawLibraryPrefix* raw_obj, ObjectPointerVisitor* visitor) { |
| visitor->VisitPointers(raw_obj->from(), raw_obj->to()); |
| return LibraryPrefix::InstanceSize(); |
| } |
| |
| |
| intptr_t RawNamespace::VisitNamespacePointers( |
| RawNamespace* raw_obj, ObjectPointerVisitor* visitor) { |
| visitor->VisitPointers(raw_obj->from(), raw_obj->to()); |
| return Namespace::InstanceSize(); |
| } |
| |
| |
| intptr_t RawCode::VisitCodePointers(RawCode* raw_obj, |
| ObjectPointerVisitor* visitor) { |
| visitor->VisitPointers(raw_obj->from(), raw_obj->to()); |
| |
| RawCode* obj = raw_obj->ptr(); |
| intptr_t length = obj->pointer_offsets_length_; |
| if (obj->is_alive_ == 1) { |
| // Also visit all the embedded pointers in the corresponding instructions. |
| uword entry_point = reinterpret_cast<uword>(obj->instructions_->ptr()) + |
| Instructions::HeaderSize(); |
| for (intptr_t i = 0; i < length; i++) { |
| int32_t offset = obj->data_[i]; |
| visitor->VisitPointer( |
| reinterpret_cast<RawObject**>(entry_point + offset)); |
| } |
| } |
| return Code::InstanceSize(length); |
| } |
| |
| |
| intptr_t RawInstructions::VisitInstructionsPointers( |
| RawInstructions* raw_obj, ObjectPointerVisitor* visitor) { |
| RawInstructions* obj = raw_obj->ptr(); |
| visitor->VisitPointers(raw_obj->from(), raw_obj->to()); |
| return Instructions::InstanceSize(obj->size_); |
| } |
| |
| |
| bool RawInstructions::ContainsPC(RawObject* raw_obj, uword pc) { |
| uword tags = raw_obj->ptr()->tags_; |
| if (RawObject::ClassIdTag::decode(tags) == kInstructionsCid) { |
| RawInstructions* raw_instr = reinterpret_cast<RawInstructions*>(raw_obj); |
| uword start_pc = |
| reinterpret_cast<uword>(raw_instr->ptr()) + Instructions::HeaderSize(); |
| uword end_pc = start_pc + raw_instr->ptr()->size_; |
| ASSERT(end_pc > start_pc); |
| if ((pc >= start_pc) && (pc < end_pc)) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| |
| intptr_t RawPcDescriptors::VisitPcDescriptorsPointers( |
| RawPcDescriptors* raw_obj, ObjectPointerVisitor* visitor) { |
| RawPcDescriptors* obj = raw_obj->ptr(); |
| intptr_t length = Smi::Value(obj->length_); |
| visitor->VisitPointer(reinterpret_cast<RawObject**>(&obj->length_)); |
| return PcDescriptors::InstanceSize(length); |
| } |
| |
| |
| intptr_t RawStackmap::VisitStackmapPointers(RawStackmap* raw_obj, |
| ObjectPointerVisitor* visitor) { |
| RawStackmap* obj = raw_obj->ptr(); |
| intptr_t length = obj->length_; |
| visitor->VisitPointer(reinterpret_cast<RawObject**>(&obj->code_)); |
| return Stackmap::InstanceSize(length); |
| } |
| |
| |
| intptr_t RawLocalVarDescriptors::VisitLocalVarDescriptorsPointers( |
| RawLocalVarDescriptors* raw_obj, ObjectPointerVisitor* visitor) { |
| RawLocalVarDescriptors* obj = raw_obj->ptr(); |
| intptr_t len = obj->length_; |
| visitor->VisitPointer(reinterpret_cast<RawObject**>(&obj->names_)); |
| return LocalVarDescriptors::InstanceSize(len); |
| } |
| |
| |
| intptr_t RawExceptionHandlers::VisitExceptionHandlersPointers( |
| RawExceptionHandlers* raw_obj, ObjectPointerVisitor* visitor) { |
| RawExceptionHandlers* obj = raw_obj->ptr(); |
| intptr_t len = obj->length_; |
| visitor->VisitPointer( |
| reinterpret_cast<RawObject**>(&obj->handled_types_data_)); |
| return ExceptionHandlers::InstanceSize(len); |
| } |
| |
| |
| intptr_t RawDeoptInfo::VisitDeoptInfoPointers( |
| RawDeoptInfo* raw_obj, ObjectPointerVisitor* visitor) { |
| RawDeoptInfo* obj = raw_obj->ptr(); |
| intptr_t length = Smi::Value(obj->length_); |
| visitor->VisitPointer(reinterpret_cast<RawObject**>(&obj->length_)); |
| return DeoptInfo::InstanceSize(length); |
| } |
| |
| |
| intptr_t RawContext::VisitContextPointers(RawContext* raw_obj, |
| ObjectPointerVisitor* visitor) { |
| intptr_t num_variables = raw_obj->ptr()->num_variables_; |
| visitor->VisitPointers(raw_obj->from(), raw_obj->to(num_variables)); |
| return Context::InstanceSize(num_variables); |
| } |
| |
| |
| intptr_t RawContextScope::VisitContextScopePointers( |
| RawContextScope* raw_obj, ObjectPointerVisitor* visitor) { |
| intptr_t num_variables = raw_obj->ptr()->num_variables_; |
| visitor->VisitPointers(raw_obj->from(), raw_obj->to(num_variables)); |
| return ContextScope::InstanceSize(num_variables); |
| } |
| |
| |
| intptr_t RawICData::VisitICDataPointers(RawICData* raw_obj, |
| ObjectPointerVisitor* visitor) { |
| // Make sure that we got here with the tagged pointer as this. |
| visitor->VisitPointers(raw_obj->from(), raw_obj->to()); |
| return ICData::InstanceSize(); |
| } |
| |
| |
| intptr_t RawMegamorphicCache::VisitMegamorphicCachePointers( |
| RawMegamorphicCache* raw_obj, |
| ObjectPointerVisitor* visitor) { |
| visitor->VisitPointers(raw_obj->from(), raw_obj->to()); |
| return MegamorphicCache::InstanceSize(); |
| } |
| |
| |
| intptr_t RawSubtypeTestCache::VisitSubtypeTestCachePointers( |
| RawSubtypeTestCache* raw_obj, ObjectPointerVisitor* visitor) { |
| // Make sure that we got here with the tagged pointer as this. |
| RawSubtypeTestCache* obj = raw_obj->ptr(); |
| visitor->VisitPointer(reinterpret_cast<RawObject**>(&obj->cache_)); |
| return SubtypeTestCache::InstanceSize(); |
| } |
| |
| |
| intptr_t RawError::VisitErrorPointers(RawError* raw_obj, |
| ObjectPointerVisitor* visitor) { |
| // Error is an abstract class. |
| UNREACHABLE(); |
| return 0; |
| } |
| |
| |
| intptr_t RawApiError::VisitApiErrorPointers( |
| RawApiError* raw_obj, ObjectPointerVisitor* visitor) { |
| visitor->VisitPointers(raw_obj->from(), raw_obj->to()); |
| return ApiError::InstanceSize(); |
| } |
| |
| |
| intptr_t RawLanguageError::VisitLanguageErrorPointers( |
| RawLanguageError* raw_obj, ObjectPointerVisitor* visitor) { |
| visitor->VisitPointers(raw_obj->from(), raw_obj->to()); |
| return LanguageError::InstanceSize(); |
| } |
| |
| |
| intptr_t RawUnhandledException::VisitUnhandledExceptionPointers( |
| RawUnhandledException* raw_obj, ObjectPointerVisitor* visitor) { |
| visitor->VisitPointers(raw_obj->from(), raw_obj->to()); |
| return UnhandledException::InstanceSize(); |
| } |
| |
| |
| intptr_t RawUnwindError::VisitUnwindErrorPointers( |
| RawUnwindError* raw_obj, ObjectPointerVisitor* visitor) { |
| visitor->VisitPointers(raw_obj->from(), raw_obj->to()); |
| return UnwindError::InstanceSize(); |
| } |
| |
| |
| intptr_t RawInstance::VisitInstancePointers(RawInstance* raw_obj, |
| ObjectPointerVisitor* visitor) { |
| // Make sure that we got here with the tagged pointer as this. |
| ASSERT(raw_obj->IsHeapObject()); |
| uword tags = raw_obj->ptr()->tags_; |
| intptr_t instance_size = SizeTag::decode(tags); |
| if (instance_size == 0) { |
| RawClass* cls = |
| visitor->isolate()->class_table()->At(raw_obj->GetClassId()); |
| instance_size = cls->ptr()->instance_size_in_words_ << kWordSizeLog2; |
| } |
| |
| // Calculate the first and last raw object pointer fields. |
| uword obj_addr = RawObject::ToAddr(raw_obj); |
| uword from = obj_addr + sizeof(RawObject); |
| uword to = obj_addr + instance_size - kWordSize; |
| visitor->VisitPointers(reinterpret_cast<RawObject**>(from), |
| reinterpret_cast<RawObject**>(to)); |
| return instance_size; |
| } |
| |
| |
| intptr_t RawNumber::VisitNumberPointers(RawNumber* raw_obj, |
| ObjectPointerVisitor* visitor) { |
| // Number is an abstract class. |
| UNREACHABLE(); |
| return 0; |
| } |
| |
| |
| intptr_t RawInteger::VisitIntegerPointers(RawInteger* raw_obj, |
| ObjectPointerVisitor* visitor) { |
| // Integer is an abstract class. |
| UNREACHABLE(); |
| return 0; |
| } |
| |
| |
| intptr_t RawSmi::VisitSmiPointers(RawSmi* raw_obj, |
| ObjectPointerVisitor* visitor) { |
| // Smi does not have a heap representation. |
| UNREACHABLE(); |
| return 0; |
| } |
| |
| |
| intptr_t RawMint::VisitMintPointers(RawMint* raw_obj, |
| ObjectPointerVisitor* visitor) { |
| // Make sure that we got here with the tagged pointer as this. |
| ASSERT(raw_obj->IsHeapObject()); |
| return Mint::InstanceSize(); |
| } |
| |
| |
| intptr_t RawBigint::VisitBigintPointers(RawBigint* raw_obj, |
| ObjectPointerVisitor* visitor) { |
| // Make sure that we got here with the tagged pointer as this. |
| ASSERT(raw_obj->IsHeapObject()); |
| RawBigint* obj = raw_obj->ptr(); |
| intptr_t length = obj->allocated_length_; |
| return Bigint::InstanceSize(length); |
| } |
| |
| |
| intptr_t RawDouble::VisitDoublePointers(RawDouble* raw_obj, |
| ObjectPointerVisitor* visitor) { |
| // Make sure that we got here with the tagged pointer as this. |
| ASSERT(raw_obj->IsHeapObject()); |
| return Double::InstanceSize(); |
| } |
| |
| |
| intptr_t RawString::VisitStringPointers(RawString* raw_obj, |
| ObjectPointerVisitor* visitor) { |
| // String is an abstract class. |
| UNREACHABLE(); |
| return 0; |
| } |
| |
| |
| intptr_t RawOneByteString::VisitOneByteStringPointers( |
| RawOneByteString* raw_obj, ObjectPointerVisitor* visitor) { |
| ASSERT(!raw_obj->ptr()->length_->IsHeapObject()); |
| ASSERT(!raw_obj->ptr()->hash_->IsHeapObject()); |
| intptr_t length = Smi::Value(raw_obj->ptr()->length_); |
| return OneByteString::InstanceSize(length); |
| } |
| |
| |
| intptr_t RawTwoByteString::VisitTwoByteStringPointers( |
| RawTwoByteString* raw_obj, ObjectPointerVisitor* visitor) { |
| ASSERT(!raw_obj->ptr()->length_->IsHeapObject()); |
| ASSERT(!raw_obj->ptr()->hash_->IsHeapObject()); |
| intptr_t length = Smi::Value(raw_obj->ptr()->length_); |
| return TwoByteString::InstanceSize(length); |
| } |
| |
| |
| intptr_t RawExternalOneByteString::VisitExternalOneByteStringPointers( |
| RawExternalOneByteString* raw_obj, ObjectPointerVisitor* visitor) { |
| // Make sure that we got here with the tagged pointer as this. |
| ASSERT(raw_obj->IsHeapObject()); |
| visitor->VisitPointers(raw_obj->from(), raw_obj->to()); |
| return ExternalOneByteString::InstanceSize(); |
| } |
| |
| |
| intptr_t RawExternalTwoByteString::VisitExternalTwoByteStringPointers( |
| RawExternalTwoByteString* raw_obj, ObjectPointerVisitor* visitor) { |
| // Make sure that we got here with the tagged pointer as this. |
| ASSERT(raw_obj->IsHeapObject()); |
| visitor->VisitPointers(raw_obj->from(), raw_obj->to()); |
| return ExternalTwoByteString::InstanceSize(); |
| } |
| |
| |
| intptr_t RawBool::VisitBoolPointers(RawBool* raw_obj, |
| ObjectPointerVisitor* visitor) { |
| // Make sure that we got here with the tagged pointer as this. |
| ASSERT(raw_obj->IsHeapObject()); |
| return Bool::InstanceSize(); |
| } |
| |
| |
| intptr_t RawArray::VisitArrayPointers(RawArray* raw_obj, |
| ObjectPointerVisitor* visitor) { |
| intptr_t length = Smi::Value(raw_obj->ptr()->length_); |
| visitor->VisitPointers(raw_obj->from(), raw_obj->to(length)); |
| return Array::InstanceSize(length); |
| } |
| |
| |
| intptr_t RawImmutableArray::VisitImmutableArrayPointers( |
| RawImmutableArray* raw_obj, ObjectPointerVisitor* visitor) { |
| return RawArray::VisitArrayPointers(raw_obj, visitor); |
| } |
| |
| |
| intptr_t RawGrowableObjectArray::VisitGrowableObjectArrayPointers( |
| RawGrowableObjectArray* raw_obj, ObjectPointerVisitor* visitor) { |
| visitor->VisitPointers(raw_obj->from(), raw_obj->to()); |
| return GrowableObjectArray::InstanceSize(); |
| } |
| |
| |
| intptr_t RawFloat32x4::VisitFloat32x4Pointers( |
| RawFloat32x4* raw_obj, |
| ObjectPointerVisitor* visitor) { |
| ASSERT(raw_obj->IsHeapObject()); |
| return Float32x4::InstanceSize(); |
| } |
| |
| |
| intptr_t RawUint32x4::VisitUint32x4Pointers( |
| RawUint32x4* raw_obj, |
| ObjectPointerVisitor* visitor) { |
| ASSERT(raw_obj->IsHeapObject()); |
| return Uint32x4::InstanceSize(); |
| } |
| |
| |
| intptr_t RawTypedData::VisitTypedDataPointers( |
| RawTypedData* raw_obj, ObjectPointerVisitor* visitor) { |
| // Make sure that we got here with the tagged pointer as this. |
| ASSERT(raw_obj->IsHeapObject()); |
| intptr_t cid = raw_obj->GetClassId(); |
| intptr_t array_len = Smi::Value(raw_obj->ptr()->length_); |
| intptr_t lengthInBytes = array_len * TypedData::ElementSizeInBytes(cid); |
| visitor->VisitPointers(raw_obj->from(), raw_obj->to()); |
| return TypedData::InstanceSize(lengthInBytes); |
| } |
| |
| |
| intptr_t RawExternalTypedData::VisitExternalTypedDataPointers( |
| RawExternalTypedData* raw_obj, ObjectPointerVisitor* visitor) { |
| // Make sure that we got here with the tagged pointer as this. |
| ASSERT(raw_obj->IsHeapObject()); |
| visitor->VisitPointers(raw_obj->from(), raw_obj->to()); |
| return ExternalTypedData::InstanceSize(); |
| } |
| |
| |
| intptr_t RawDartFunction::VisitDartFunctionPointers( |
| RawDartFunction* raw_obj, ObjectPointerVisitor* visitor) { |
| // Function (defined in core library) is an abstract class. |
| UNREACHABLE(); |
| return 0; |
| } |
| |
| |
| intptr_t RawStacktrace::VisitStacktracePointers(RawStacktrace* raw_obj, |
| ObjectPointerVisitor* visitor) { |
| // Make sure that we got here with the tagged pointer as this. |
| ASSERT(raw_obj->IsHeapObject()); |
| visitor->VisitPointers(raw_obj->from(), raw_obj->to()); |
| return Stacktrace::InstanceSize(); |
| } |
| |
| |
| intptr_t RawJSRegExp::VisitJSRegExpPointers(RawJSRegExp* raw_obj, |
| ObjectPointerVisitor* visitor) { |
| // Make sure that we got here with the tagged pointer as this. |
| ASSERT(raw_obj->IsHeapObject()); |
| intptr_t length = Smi::Value(raw_obj->ptr()->data_length_); |
| visitor->VisitPointers(raw_obj->from(), raw_obj->to()); |
| return JSRegExp::InstanceSize(length); |
| } |
| |
| |
| intptr_t RawWeakProperty::VisitWeakPropertyPointers( |
| RawWeakProperty* raw_obj, ObjectPointerVisitor* visitor) { |
| // Make sure that we got here with the tagged pointer as this. |
| ASSERT(raw_obj->IsHeapObject()); |
| visitor->VisitPointers(raw_obj->from(), raw_obj->to()); |
| return WeakProperty::InstanceSize(); |
| } |
| |
| } // namespace dart |