fb6d24945f
Fix issues 15244, 15148, 14869, 14000, and 13688 (was closed, but fragile). Note that the current solution is not final as it may not be correct in more complex cases not yet covered by language tests. The final solution will require a 'trail' instead of a simple mark bit to prevent operations involving recursive types to diverge. R=asiva@google.com Review URL: https://codereview.chromium.org//103913005 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@31087 260f80e4-7a28-3924-810f-c04153c831b5
853 lines
29 KiB
C++
853 lines
29 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 {
|
|
|
|
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;
|
|
}
|
|
// 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: {
|
|
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 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: {
|
|
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 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();
|
|
}
|
|
|
|
|
|
bool RawFunction::SkipCode(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;
|
|
|
|
Code code;
|
|
code = fn.CurrentCode();
|
|
|
|
if (!code.IsNull() && // The function may not have code.
|
|
!code.is_optimized() &&
|
|
(fn.CurrentCode() == fn.unoptimized_code()) &&
|
|
!fn.HasBreakpoint() &&
|
|
(fn.usage_counter() >= 0)) {
|
|
fn.set_usage_counter(fn.usage_counter() / 2);
|
|
if (FLAG_always_drop_code || (fn.usage_counter() == 0)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
intptr_t RawFunction::VisitFunctionPointers(RawFunction* raw_obj,
|
|
ObjectPointerVisitor* visitor) {
|
|
if (visitor->visit_function_code() ||
|
|
!RawFunction::SkipCode(raw_obj)) {
|
|
visitor->VisitPointers(raw_obj->from(), raw_obj->to());
|
|
} else {
|
|
GrowableArray<RawFunction*>* sfga = visitor->skipped_code_functions();
|
|
ASSERT(sfga != NULL);
|
|
sfga->Add(raw_obj);
|
|
visitor->VisitPointers(raw_obj->from(), raw_obj->to_no_code());
|
|
}
|
|
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 (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 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 RawInt32x4::VisitInt32x4Pointers(
|
|
RawInt32x4* raw_obj,
|
|
ObjectPointerVisitor* visitor) {
|
|
ASSERT(raw_obj->IsHeapObject());
|
|
return Int32x4::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 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();
|
|
}
|
|
|
|
|
|
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();
|
|
}
|
|
|
|
} // namespace dart
|