Files
sdk/runtime/vm/raw_object.cc
T
cshapiro@google.com 569ef3c044 Add ByteArray interface and provide internal and external implementations.
The new ByteArray interface supersedes the ByteBuffer type which allowed
only external data storage.  This type has been removed and replaced by
the more flexible ByteArray with a default implementation that stores its
elements on the managed heap.

Review URL: https://chromiumcodereview.appspot.com//9195031

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@3613 260f80e4-7a28-3924-810f-c04153c831b5
2012-01-26 02:42:08 +00:00

641 lines
22 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/freelist.h"
#include "vm/isolate.h"
#include "vm/object.h"
#include "vm/visitor.h"
namespace dart {
void RawObject::Validate() 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 class_ field is sensible.
RawClass* raw_class = ptr()->class_;
ASSERT(raw_class->IsHeapObject());
RawClass* raw_class_class = raw_class->ptr()->class_;
ASSERT(raw_class_class->IsHeapObject());
ASSERT(raw_class_class->ptr()->instance_kind_ == kClass);
// Validate that the tags_ field is sensible.
intptr_t tags = ptr()->tags_;
ASSERT((tags & 0xffff00f0) == 0);
}
intptr_t RawObject::SizeFromClass() const {
NoHandleScope no_handles(Isolate::Current());
// Only reasonable to be called on heap objects.
ASSERT(IsHeapObject());
RawClass* raw_class = ptr()->class_;
intptr_t instance_size = raw_class->ptr()->instance_size_;
ObjectKind instance_kind = raw_class->ptr()->instance_kind_;
if (instance_size == 0) {
switch (instance_kind) {
case kTokenStream: {
const RawTokenStream* raw_tokens =
reinterpret_cast<const RawTokenStream*>(this);
intptr_t tokens_length = Smi::Value(raw_tokens->ptr()->length_);
instance_size = TokenStream::InstanceSize(tokens_length);
break;
}
case kCode: {
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 kInstructions: {
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 kContext: {
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 kContextScope: {
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 kBigint: {
const RawBigint* raw_bgi = reinterpret_cast<const RawBigint*>(this);
const BIGNUM* bn_ptr = &raw_bgi->ptr()->bn_;
instance_size = Bigint::InstanceSize(bn_ptr);
break;
}
case kOneByteString: {
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 kTwoByteString: {
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 kFourByteString: {
const RawFourByteString* raw_string =
reinterpret_cast<const RawFourByteString*>(this);
intptr_t string_length = Smi::Value(raw_string->ptr()->length_);
instance_size = FourByteString::InstanceSize(string_length);
break;
}
case kArray:
case kImmutableArray: {
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 kInternalByteArray: {
const RawInternalByteArray* raw_byte_array =
reinterpret_cast<const RawInternalByteArray*>(this);
intptr_t byte_array_length = Smi::Value(raw_byte_array->ptr()->length_);
instance_size = InternalByteArray::InstanceSize(byte_array_length);
break;
}
case kTypeArguments: {
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 kPcDescriptors: {
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 kLocalVarDescriptors: {
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 kExceptionHandlers: {
const RawExceptionHandlers* raw_handlers =
reinterpret_cast<const RawExceptionHandlers*>(this);
intptr_t num_handlers = Smi::Value(raw_handlers->ptr()->length_);
instance_size = ExceptionHandlers::InstanceSize(num_handlers);
break;
}
case kJSRegExp: {
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);
intptr_t tags = ptr()->tags_;
ASSERT((instance_size == SizeTag::decode(tags)) ||
(SizeTag::decode(tags) == 0) ||
FreeBit::decode(tags));
return instance_size;
}
intptr_t RawObject::VisitPointers(ObjectPointerVisitor* visitor) {
intptr_t size = 0;
NoHandleScope no_handles(Isolate::Current());
// Only reasonable to be called on heap objects.
ASSERT(IsHeapObject());
// Read the necessary data out of the class before visting the class itself.
RawClass* raw_class = ptr()->class_;
ObjectKind kind = raw_class->ptr()->instance_kind_;
// Visit the class before visting the fields.
visitor->VisitPointer(reinterpret_cast<RawObject**>(&ptr()->class_));
switch (kind) {
#define RAW_VISITPOINTERS(clazz) \
case clazz::kInstanceKind: { \
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
case kFreeListElement: {
ASSERT(FreeBit::decode(ptr()->tags_));
// Nothing to visit for free list elements.
uword addr = RawObject::ToAddr(this);
FreeListElement* element = reinterpret_cast<FreeListElement*>(addr);
size = element->Size();
break;
}
default:
OS::Print("Kind: %d\n", kind);
UNREACHABLE();
break;
}
ASSERT(size != 0);
ASSERT(size == Size());
return size;
}
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->VisitPointer(reinterpret_cast<RawObject**>(&raw_obj->ptr()->name_));
return TypeParameter::InstanceSize();
}
intptr_t RawInstantiatedType::VisitInstantiatedTypePointers(
RawInstantiatedType* raw_obj, ObjectPointerVisitor* visitor) {
visitor->VisitPointers(raw_obj->from(), raw_obj->to());
return InstantiatedType::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 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 RawTokenStream::VisitTokenStreamPointers(
RawTokenStream* raw_obj, ObjectPointerVisitor* visitor) {
intptr_t length = Smi::Value(raw_obj->ptr()->length_);
visitor->VisitPointers(raw_obj->from(), raw_obj->to(length));
return TokenStream::InstanceSize(length);
}
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 RawCode::VisitCodePointers(RawCode* raw_obj,
ObjectPointerVisitor* visitor) {
visitor->VisitPointers(raw_obj->from(), raw_obj->to());
// Also visit all the embedded pointers in the corresponding instructions.
RawCode* obj = raw_obj->ptr();
intptr_t length = obj->pointer_offsets_length_;
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->VisitPointer(reinterpret_cast<RawObject**>(&obj->code_));
return Instructions::InstanceSize(obj->size_);
}
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 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 length = Smi::Value(obj->length_);
visitor->VisitPointer(reinterpret_cast<RawObject**>(&obj->length_));
return ExceptionHandlers::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 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());
RawInstance* obj = raw_obj->ptr();
intptr_t instance_size = obj->class_->ptr()->instance_size_;
intptr_t num_native_fields = obj->class_->ptr()->num_native_fields_;
// Calculate the first and last raw object pointer fields.
uword obj_addr = RawObject::ToAddr(raw_obj);
uword from = obj_addr + sizeof(RawObject) + num_native_fields * kWordSize;
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();
return Bigint::InstanceSize(&obj->bn_);
}
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) {
intptr_t length = Smi::Value(raw_obj->ptr()->length_);
visitor->VisitPointers(raw_obj->from(), raw_obj->to());
return OneByteString::InstanceSize(length);
}
intptr_t RawTwoByteString::VisitTwoByteStringPointers(
RawTwoByteString* raw_obj, ObjectPointerVisitor* visitor) {
intptr_t length = Smi::Value(raw_obj->ptr()->length_);
visitor->VisitPointers(raw_obj->from(), raw_obj->to());
return TwoByteString::InstanceSize(length);
}
intptr_t RawFourByteString::VisitFourByteStringPointers(
RawFourByteString* raw_obj, ObjectPointerVisitor* visitor) {
intptr_t length = Smi::Value(raw_obj->ptr()->length_);
visitor->VisitPointers(raw_obj->from(), raw_obj->to());
return FourByteString::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 RawExternalFourByteString::VisitExternalFourByteStringPointers(
RawExternalFourByteString* 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 ExternalFourByteString::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 RawByteArray::VisitByteArrayPointers(RawByteArray* raw_obj,
ObjectPointerVisitor* visitor) {
// ByteArray is an abstract class.
UNREACHABLE();
return 0;
}
intptr_t RawInternalByteArray::VisitInternalByteArrayPointers(
RawInternalByteArray* 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()->length_);
visitor->VisitPointers(raw_obj->from(), raw_obj->to());
return InternalByteArray::InstanceSize(length);
}
intptr_t RawExternalByteArray::VisitExternalByteArrayPointers(
RawExternalByteArray* 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 ExternalByteArray::InstanceSize();
}
intptr_t RawClosure::VisitClosurePointers(RawClosure* 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 Closure::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);
}
} // namespace dart