Files
sdk/runtime/vm/raw_object.cc
T
Florian Schneider 265a54411a Object pool with support for untagged entries.
This adds meta-information to object pool entries to allow storing
untagged immediates or code addresses (ExternalLabel) directly.

This eliminates the need to generate extra code to preserve the LSB
when storing immediates as smis (x64, arm64).

BUG=

Review URL: https://codereview.chromium.org//1175523002.
2015-06-10 11:41:22 +02:00

947 lines
32 KiB
C++

// 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/dart.h"
#include "vm/freelist.h"
#include "vm/isolate.h"
#include "vm/object.h"
#include "vm/visitor.h"
namespace dart {
#if defined(DEBUG)
DEFINE_FLAG(bool, validate_overwrite, true, "Verify overwritten fields.");
#endif // DEBUG
bool RawObject::IsVMHeapObject() const {
return Dart::vm_isolate()->heap()->Contains(ToAddr(this));
}
void RawObject::Validate(Isolate* isolate) const {
if (Object::void_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;
}
// Slightly more readable than a segfault.
if (this == reinterpret_cast<RawObject*>(kHeapObjectTag)) {
FATAL("RAW_NULL encountered");
}
// 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);
}
if ((class_id == kNullCid) &&
(isolate->class_table()->At(class_id) == NULL)) {
// Null class not yet initialized; skip.
return;
}
intptr_t size = SizeTag::decode(tags);
if (size != 0 && size != SizeFromClass()) {
FATAL1("Inconsistent class size encountered %" Pd "\n", size);
}
}
intptr_t RawObject::SizeFromClass() const {
// Only reasonable to be called on heap objects.
ASSERT(IsHeapObject());
intptr_t class_id = GetClassId();
intptr_t instance_size = 0;
switch (class_id) {
case kCodeCid: {
const RawCode* raw_code = reinterpret_cast<const RawCode*>(this);
intptr_t pointer_offsets_length =
Code::PtrOffBits::decode(raw_code->ptr()->state_bits_);
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 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;
}
case kObjectPoolCid: {
const RawObjectPool* raw_object_pool =
reinterpret_cast<const RawObjectPool*>(this);
intptr_t len = raw_object_pool->ptr()->length_;
instance_size = ObjectPool::InstanceSize(len);
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 length = raw_descriptors->ptr()->length_;
instance_size = PcDescriptors::InstanceSize(length);
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()->num_entries_;
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()->num_entries_;
instance_size = ExceptionHandlers::InstanceSize(num_handlers);
break;
}
case kFreeListElement: {
uword addr = RawObject::ToAddr(const_cast<RawObject*>(this));
FreeListElement* element = reinterpret_cast<FreeListElement*>(addr);
instance_size = element->Size();
break;
}
default: {
// Get the (constant) instance size out of the class object.
// TODO(koda): Add Size(ClassTable*) interface to allow caching in loops.
Isolate* isolate = Isolate::Current();
ClassTable* class_table = isolate->class_table();
#if defined(DEBUG)
if (!class_table->IsValidIndex(class_id) ||
!class_table->HasValidClassAt(class_id)) {
FATAL2("Invalid class id: %" Pd " from tags %" Px "\n",
class_id, ptr()->tags_);
}
#endif // DEBUG
RawClass* raw_class = class_table->At(class_id);
ASSERT(raw_class->ptr()->id_ == class_id);
instance_size =
raw_class->ptr()->instance_size_in_words_ << kWordSizeLog2;
}
}
ASSERT(instance_size != 0);
#if defined(DEBUG)
uword tags = ptr()->tags_;
intptr_t tags_size = SizeTag::decode(tags);
if ((class_id == kArrayCid) && (instance_size > tags_size && tags_size > 0)) {
// TODO(22501): Array::MakeArray could be in the process of shrinking
// the array (see comment therein), having already updated the tags but not
// yet set the new length. Wait a millisecond and try again.
int retries_remaining = 1000; // ... but not forever.
do {
OS::Sleep(1);
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);
} while ((instance_size > tags_size) && (--retries_remaining > 0));
}
if ((instance_size != tags_size) && (tags_size != 0)) {
FATAL3("Size mismatch: %" Pd " from class vs %" Pd " from tags %" Px "\n",
instance_size, tags_size, tags);
}
#endif // DEBUG
return instance_size;
}
#if defined(DEBUG)
void RawObject::ValidateOverwrittenPointer(RawObject* raw) {
if (FLAG_validate_overwrite) {
raw->Validate(Isolate::Current());
}
}
void RawObject::ValidateOverwrittenSmi(RawSmi* raw) {
if (FLAG_validate_overwrite && raw->IsHeapObject() && raw != Object::null()) {
FATAL1("Expected smi/null, found: %" Px "\n", reinterpret_cast<uword>(raw));
}
}
#endif // DEBUG
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 k##clazz##Cid: { \
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:
case kByteBufferCid: {
RawInstance* raw_obj = reinterpret_cast<RawInstance*>(this);
size = RawInstance::VisitInstancePointers(raw_obj, visitor);
break;
}
#undef RAW_VISITPOINTERS
case kFreeListElement: {
uword addr = RawObject::ToAddr(const_cast<RawObject*>(this));
FreeListElement* element = reinterpret_cast<FreeListElement*>(addr);
size = element->Size();
break;
}
case kNullCid:
size = 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 RawTypeRef::VisitTypeRefPointers(
RawTypeRef* raw_obj, ObjectPointerVisitor* visitor) {
visitor->VisitPointers(raw_obj->from(), raw_obj->to());
return TypeRef::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 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 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();
}
bool RawFunction::CheckUsageCounter(RawFunction* raw_fun) {
// NOTE: This code runs while GC is in progress and runs within
// a NoHandleScope block. Hence it is not okay to use regular Zone or
// Scope handles. We use direct stack handles, and so the raw pointers in
// these handles are not traversed. The use of handles is mainly to
// be able to reuse the handle based code and avoid having to add
// helper functions to the raw object interface.
Function fn;
fn = raw_fun;
// The function may not have code.
if (!fn.HasCode()) return false;
// These may not increment the usage counter.
if (fn.is_intrinsic()) return false;
if (fn.usage_counter() >= 0) {
fn.set_usage_counter(fn.usage_counter() / 2);
}
return FLAG_always_drop_code || (fn.usage_counter() == 0);
}
bool RawFunction::ShouldVisitCode(RawCode* raw_code) {
// NOTE: This code runs while GC is in progress and runs within
// a NoHandleScope block. Hence it is not okay to use regular Zone or
// Scope handles. We use direct stack handles, and so the raw pointers in
// these handles are not traversed. The use of handles is mainly to
// be able to reuse the handle based code and avoid having to add
// helper functions to the raw object interface.
Code code;
code = raw_code;
if (code.IsNull()) return true;
if (code.is_optimized()) return true;
if (code.HasBreakpoint()) return true;
return false;
}
intptr_t RawFunction::VisitFunctionPointers(RawFunction* raw_obj,
ObjectPointerVisitor* visitor) {
if (visitor->visit_function_code() || !CheckUsageCounter(raw_obj)) {
visitor->VisitPointers(raw_obj->from(), raw_obj->to());
return Function::InstanceSize();
}
visitor->VisitPointers(raw_obj->from(), raw_obj->to_no_code());
if (ShouldVisitCode(raw_obj->ptr()->instructions_->ptr()->code_)) {
visitor->VisitPointer(
reinterpret_cast<RawObject**>(&raw_obj->ptr()->instructions_));
} else {
visitor->skipped_code_functions()->Add(raw_obj);
}
if (ShouldVisitCode(raw_obj->ptr()->unoptimized_code_)) {
visitor->VisitPointer(
reinterpret_cast<RawObject**>(&raw_obj->ptr()->unoptimized_code_));
} else {
visitor->skipped_code_functions()->Add(raw_obj);
}
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 = Code::PtrOffBits::decode(obj->state_bits_);
if (Code::AliveBit::decode(obj->state_bits_)) {
// 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 RawObjectPool::VisitObjectPoolPointers(
RawObjectPool* raw_obj, ObjectPointerVisitor* visitor) {
visitor->VisitPointer(
reinterpret_cast<RawObject**>(&raw_obj->ptr()->info_array_));
const intptr_t len = raw_obj->ptr()->length_;
RawTypedData* info_array = raw_obj->ptr()->info_array_->ptr();
Entry* first = raw_obj->first_entry();
for (intptr_t i = 0; i < len; ++i) {
ObjectPool::EntryType entry_type =
static_cast<ObjectPool::EntryType>(info_array->data()[i]);
if (entry_type == ObjectPool::kTaggedObject) {
visitor->VisitPointer(&(first + i)->raw_obj_);
}
}
return ObjectPool::InstanceSize(raw_obj->ptr()->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) {
return PcDescriptors::InstanceSize(raw_obj->ptr()->length_);
}
intptr_t RawStackmap::VisitStackmapPointers(RawStackmap* raw_obj,
ObjectPointerVisitor* visitor) {
return Stackmap::InstanceSize(raw_obj->ptr()->length_);
}
intptr_t RawLocalVarDescriptors::VisitLocalVarDescriptorsPointers(
RawLocalVarDescriptors* raw_obj, ObjectPointerVisitor* visitor) {
intptr_t num_entries = raw_obj->ptr()->num_entries_;
visitor->VisitPointers(raw_obj->from(), raw_obj->to(num_entries));
return LocalVarDescriptors::InstanceSize(num_entries);
}
intptr_t RawExceptionHandlers::VisitExceptionHandlersPointers(
RawExceptionHandlers* raw_obj, ObjectPointerVisitor* visitor) {
RawExceptionHandlers* obj = raw_obj->ptr();
intptr_t len = obj->num_entries_;
visitor->VisitPointer(
reinterpret_cast<RawObject**>(&obj->handled_types_data_));
return ExceptionHandlers::InstanceSize(len);
}
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());
visitor->VisitPointers(raw_obj->from(), raw_obj->to());
return Bigint::InstanceSize();
}
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 RawLinkedHashMap::VisitLinkedHashMapPointers(
RawLinkedHashMap* raw_obj, ObjectPointerVisitor* visitor) {
visitor->VisitPointers(raw_obj->from(), raw_obj->to());
return LinkedHashMap::InstanceSize();
}
intptr_t RawFloat32x4::VisitFloat32x4Pointers(
RawFloat32x4* raw_obj,
ObjectPointerVisitor* visitor) {
ASSERT(raw_obj->IsHeapObject());
return Float32x4::InstanceSize();
}
intptr_t RawInt32x4::VisitInt32x4Pointers(
RawInt32x4* raw_obj,
ObjectPointerVisitor* visitor) {
ASSERT(raw_obj->IsHeapObject());
return Int32x4::InstanceSize();
}
intptr_t RawFloat64x2::VisitFloat64x2Pointers(
RawFloat64x2* raw_obj,
ObjectPointerVisitor* visitor) {
ASSERT(raw_obj->IsHeapObject());
return Float64x2::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 RawCapability::VisitCapabilityPointers(RawCapability* raw_obj,
ObjectPointerVisitor* visitor) {
// Make sure that we got here with the tagged pointer as this.
ASSERT(raw_obj->IsHeapObject());
return Capability::InstanceSize();
}
intptr_t RawReceivePort::VisitReceivePortPointers(
RawReceivePort* 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 ReceivePort::InstanceSize();
}
intptr_t RawSendPort::VisitSendPortPointers(RawSendPort* raw_obj,
ObjectPointerVisitor* visitor) {
// Make sure that we got here with the tagged pointer as this.
ASSERT(raw_obj->IsHeapObject());
return SendPort::InstanceSize();
}
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());
visitor->VisitPointers(raw_obj->from(), raw_obj->to());
return JSRegExp::InstanceSize();
}
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();
}
intptr_t RawMirrorReference::VisitMirrorReferencePointers(
RawMirrorReference* 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 MirrorReference::InstanceSize();
}
intptr_t RawUserTag::VisitUserTagPointers(
RawUserTag* 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 UserTag::InstanceSize();
}
} // namespace dart