Files
sdk/runtime/vm/raw_object.h
T
asiva@google.com 5fd180cdfc 1. Register canonical names for internal VM classes and get rid of the method GetSingletonClassName
2. Create the empty_array object as a singleton in the VM isolate and remove it from the object store
3. Remove eager population of the functions_cache entry in the class. This results in a pretty impressive reduction of the initial isolate heap size:
    - on IA32 it goes from 1331k to 1071k
    - on X64 it goes from 2431k to 1911k
    - snapshot size also is reduced from 859219 bytes to 789147 bytes.
    (as a follow up change I will consider completely removing functions cache)
Review URL: https://chromiumcodereview.appspot.com//10827249

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@10535 260f80e4-7a28-3924-810f-c04153c831b5
2012-08-10 21:43:00 +00:00

1544 lines
48 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.
#ifndef VM_RAW_OBJECT_H_
#define VM_RAW_OBJECT_H_
#include "platform/assert.h"
#include "vm/globals.h"
#include "vm/token.h"
#include "vm/snapshot.h"
#include "include/dart_api.h"
namespace dart {
// Macrobatics to define the Object hierarchy of VM implementation classes.
#define CLASS_LIST_NO_OBJECT(V) \
V(Class) \
V(UnresolvedClass) \
V(AbstractType) \
V(Type) \
V(TypeParameter) \
V(AbstractTypeArguments) \
V(TypeArguments) \
V(InstantiatedTypeArguments) \
V(Function) \
V(Field) \
V(LiteralToken) \
V(TokenStream) \
V(Script) \
V(Library) \
V(LibraryPrefix) \
V(Code) \
V(Instructions) \
V(PcDescriptors) \
V(Stackmap) \
V(LocalVarDescriptors) \
V(ExceptionHandlers) \
V(DeoptInfo) \
V(Context) \
V(ContextScope) \
V(ICData) \
V(SubtypeTestCache) \
V(Error) \
V(ApiError) \
V(LanguageError) \
V(UnhandledException) \
V(UnwindError) \
V(Instance) \
V(Number) \
V(Integer) \
V(Smi) \
V(Mint) \
V(Bigint) \
V(Double) \
V(String) \
V(OneByteString) \
V(TwoByteString) \
V(FourByteString) \
V(ExternalOneByteString) \
V(ExternalTwoByteString) \
V(ExternalFourByteString) \
V(Bool) \
V(Array) \
V(ImmutableArray) \
V(GrowableObjectArray) \
V(ByteArray) \
V(Int8Array) \
V(Uint8Array) \
V(Int16Array) \
V(Uint16Array) \
V(Int32Array) \
V(Uint32Array) \
V(Int64Array) \
V(Uint64Array) \
V(Float32Array) \
V(Float64Array) \
V(ExternalInt8Array) \
V(ExternalUint8Array) \
V(ExternalInt16Array) \
V(ExternalUint16Array) \
V(ExternalInt32Array) \
V(ExternalUint32Array) \
V(ExternalInt64Array) \
V(ExternalUint64Array) \
V(ExternalFloat32Array) \
V(ExternalFloat64Array) \
V(Stacktrace) \
V(JSRegExp) \
V(Closure) \
#define CLASS_LIST(V) \
V(Object) \
CLASS_LIST_NO_OBJECT(V)
// Forward declarations.
class Isolate;
#define DEFINE_FORWARD_DECLARATION(clazz) \
class Raw##clazz;
CLASS_LIST(DEFINE_FORWARD_DECLARATION)
#undef DEFINE_FORWARD_DECLARATION
enum ClassId {
// Illegal class id.
kIllegalCid = 0,
// List of Ids for predefined classes.
#define DEFINE_OBJECT_KIND(clazz) \
k##clazz##Cid,
CLASS_LIST(DEFINE_OBJECT_KIND)
#undef DEFINE_OBJECT_KIND
// The following entries do not describe a predefined class, but instead
// are class indexes for pre-allocated instance (Null, Dynamic and Void).
kNullCid,
kDynamicCid,
kVoidCid,
// The following entry does not describe a real class, but instead it is an
// id which is used to identify free list elements in the heap.
kFreeListElement,
kNumPredefinedCids,
};
enum ObjectAlignment {
// Alignment offsets are used to determine object age.
kNewObjectAlignmentOffset = kWordSize,
kOldObjectAlignmentOffset = 0,
// Object sizes are aligned to kObjectAlignment.
kObjectAlignment = 2 * kWordSize,
kObjectAlignmentLog2 = kWordSizeLog2 + 1,
kObjectAlignmentMask = kObjectAlignment - 1,
};
enum {
kSmiTag = 0,
kHeapObjectTag = 1,
kSmiTagSize = 1,
kSmiTagMask = 1,
kSmiTagShift = 1,
};
#define SNAPSHOT_WRITER_SUPPORT() \
void WriteTo( \
SnapshotWriter* writer, intptr_t object_id, Snapshot::Kind kind); \
friend class SnapshotWriter; \
#define VISITOR_SUPPORT(object) \
static intptr_t Visit##object##Pointers(Raw##object* raw_obj, \
ObjectPointerVisitor* visitor);
#define HEAP_PROFILER_SUPPORT() \
friend class HeapProfiler; \
#define RAW_OBJECT_IMPLEMENTATION(object) \
private: /* NOLINT */ \
VISITOR_SUPPORT(object) \
friend class object; \
friend class RawObject; \
friend class Heap; \
DISALLOW_ALLOCATION(); \
DISALLOW_IMPLICIT_CONSTRUCTORS(Raw##object)
#define RAW_HEAP_OBJECT_IMPLEMENTATION(object) \
private: \
RAW_OBJECT_IMPLEMENTATION(object); \
Raw##object* ptr() const { \
ASSERT(IsHeapObject()); \
return reinterpret_cast<Raw##object*>( \
reinterpret_cast<uword>(this) - kHeapObjectTag); \
} \
SNAPSHOT_WRITER_SUPPORT() \
HEAP_PROFILER_SUPPORT() \
// RawObject is the base class of all raw objects, even though it carries the
// class_ field not all raw objects are allocated in the heap and thus cannot
// be dereferenced (e.g. RawSmi).
class RawObject {
public:
// The tags field which is a part of the object header uses the following
// bit fields for storing tags.
enum TagBits {
kFreeBit = 0,
kMarkBit = 1,
kCanonicalBit = 2,
kFromSnapshotBit = 3,
kReservedTagBit = 4, // kReservedBit{10K,100K,1M,10M}
kReservedTagSize = 4,
kSizeTagBit = 8,
kSizeTagSize = 8,
kClassIdTagBit = kSizeTagBit + kSizeTagSize,
kClassIdTagSize = 16
};
// Encodes the object size in the tag in units of object alignment.
class SizeTag {
public:
static const intptr_t kMaxSizeTag =
((1 << RawObject::kSizeTagSize) - 1) << kObjectAlignmentLog2;
static uword encode(intptr_t size) {
return SizeBits::encode(SizeToTagValue(size));
}
static intptr_t decode(uword tag) {
return TagValueToSize(SizeBits::decode(tag));
}
static uword update(intptr_t size, uword tag) {
return SizeBits::update(SizeToTagValue(size), tag);
}
private:
// The actual unscaled bit field used within the tag field.
class SizeBits : public BitField<intptr_t, kSizeTagBit, kSizeTagSize> {};
static intptr_t SizeToTagValue(intptr_t size) {
ASSERT(Utils::IsAligned(size, kObjectAlignment));
return (size > kMaxSizeTag) ? 0 : (size >> kObjectAlignmentLog2);
}
static intptr_t TagValueToSize(intptr_t value) {
return value << kObjectAlignmentLog2;
}
};
class ClassIdTag : public BitField<intptr_t,
kClassIdTagBit,
kClassIdTagSize> {}; // NOLINT
bool IsHeapObject() const {
uword value = reinterpret_cast<uword>(this);
return (value & kSmiTagMask) == kHeapObjectTag;
}
bool IsNewObject() const {
uword addr = reinterpret_cast<uword>(this);
return (addr & kNewObjectAlignmentOffset) == kNewObjectAlignmentOffset;
}
bool IsOldObject() const {
uword addr = reinterpret_cast<uword>(this);
return (addr & kNewObjectAlignmentOffset) == kOldObjectAlignmentOffset;
}
// Support for GC marking bit.
bool IsMarked() const {
return MarkBit::decode(ptr()->tags_);
}
void SetMarkBit() {
ASSERT(!IsMarked());
uword tags = ptr()->tags_;
ptr()->tags_ = MarkBit::update(true, tags);
}
void ClearMarkBit() {
ASSERT(IsMarked());
uword tags = ptr()->tags_;
ptr()->tags_ = MarkBit::update(false, tags);
}
// Support for object tags.
bool IsCanonical() const {
return CanonicalObjectTag::decode(ptr()->tags_);
}
void SetCanonical() {
uword tags = ptr()->tags_;
ptr()->tags_ = CanonicalObjectTag::update(true, tags);
}
bool IsCreatedFromSnapshot() const {
return CreatedFromSnapshotTag::decode(ptr()->tags_);
}
void SetCreatedFromSnapshot() {
uword tags = ptr()->tags_;
ptr()->tags_ = CreatedFromSnapshotTag::update(true, tags);
}
intptr_t Size() const {
uword tags = ptr()->tags_;
intptr_t result = SizeTag::decode(tags);
if (result != 0) {
ASSERT(result == SizeFromClass());
return result;
}
result = SizeFromClass();
ASSERT(result > SizeTag::kMaxSizeTag);
return result;
}
void Validate(Isolate* isolate) const;
intptr_t VisitPointers(ObjectPointerVisitor* visitor);
bool FindObject(FindObjectVisitor* visitor);
static RawObject* FromAddr(uword addr) {
// We expect the untagged address here.
ASSERT((addr & kSmiTagMask) != kHeapObjectTag);
return reinterpret_cast<RawObject*>(addr + kHeapObjectTag);
}
static uword ToAddr(RawObject* raw_obj) {
return reinterpret_cast<uword>(raw_obj->ptr());
}
static bool IsCreatedFromSnapshot(intptr_t value) {
return CreatedFromSnapshotTag::decode(value);
}
static bool IsCanonical(intptr_t value) {
return CanonicalObjectTag::decode(value);
}
// Class Id predicates.
static bool IsErrorClassId(intptr_t index);
static bool IsNumberClassId(intptr_t index);
static bool IsIntegerClassId(intptr_t index);
static bool IsStringClassId(intptr_t index);
static bool IsOneByteStringClassId(intptr_t index);
static bool IsTwoByteStringClassId(intptr_t index);
static bool IsExternalStringClassId(intptr_t index);
static bool IsBuiltinListClassId(intptr_t index);
static bool IsByteArrayClassId(intptr_t index);
protected:
uword tags_; // Various object tags (bits).
private:
class FreeBit : public BitField<bool, kFreeBit, 1> {};
class MarkBit : public BitField<bool, kMarkBit, 1> {};
class CanonicalObjectTag : public BitField<bool, kCanonicalBit, 1> {};
class CreatedFromSnapshotTag : public BitField<bool, kFromSnapshotBit, 1> {};
class ReservedBits : public BitField<intptr_t,
kReservedTagBit,
kReservedTagSize> {}; // NOLINT
RawObject* ptr() const {
ASSERT(IsHeapObject());
return reinterpret_cast<RawObject*>(
reinterpret_cast<uword>(this) - kHeapObjectTag);
}
intptr_t SizeFromClass() const;
intptr_t GetClassId() const {
uword tags = ptr()->tags_;
return ClassIdTag::decode(tags);
}
friend class Api;
friend class Array;
friend class FreeListElement;
friend class Heap;
friend class HeapProfiler;
friend class HeapProfilerRootVisitor;
friend class MarkingVisitor;
friend class Object;
friend class RawInstructions;
friend class RawInstance;
friend class SnapshotReader;
friend class SnapshotWriter;
DISALLOW_ALLOCATION();
DISALLOW_IMPLICIT_CONSTRUCTORS(RawObject);
};
class RawClass : public RawObject {
public:
enum ClassState {
kAllocated, // Initial state.
kPreFinalized, // VM classes: size precomputed, but no checks done.
kFinalized, // All checks completed, class ready for use.
};
private:
RAW_HEAP_OBJECT_IMPLEMENTATION(Class);
RawObject** from() { return reinterpret_cast<RawObject**>(&ptr()->name_); }
RawString* name_;
RawArray* functions_;
RawArray* fields_;
RawGrowableObjectArray* closure_functions_; // Local functions and literals.
RawArray* interfaces_; // Array of AbstractType.
RawScript* script_;
RawLibrary* library_;
RawTypeArguments* type_parameters_; // Array of TypeParameter.
RawType* super_type_;
RawObject* factory_class_; // UnresolvedClass (until finalization) or Class.
RawFunction* signature_function_; // Associated function for signature class.
RawArray* functions_cache_; // See class FunctionsCache.
RawArray* constants_; // Canonicalized values of this class.
RawArray* canonical_types_; // Canonicalized types of this class.
RawCode* allocation_stub_; // Stub code for allocation of instances.
RawObject** to() {
return reinterpret_cast<RawObject**>(&ptr()->allocation_stub_);
}
cpp_vtable handle_vtable_;
intptr_t instance_size_; // Size if fixed length or 0 if variable length.
intptr_t id_; // Class Id, also index in the class table.
intptr_t type_arguments_instance_field_offset_; // May be kNoTypeArguments.
intptr_t next_field_offset_; // Offset of the next instance field.
intptr_t num_native_fields_; // Number of native fields in class.
intptr_t token_pos_;
int8_t class_state_; // Of type ClassState.
bool is_const_;
bool is_interface_;
friend class Object;
friend class RawInstance;
friend class RawInstructions;
friend class SnapshotReader;
};
class RawUnresolvedClass : public RawObject {
RAW_HEAP_OBJECT_IMPLEMENTATION(UnresolvedClass);
RawObject** from() {
return reinterpret_cast<RawObject**>(&ptr()->library_prefix_);
}
RawLibraryPrefix* library_prefix_; // Library prefix qualifier for the ident.
RawString* ident_; // Name of the unresolved identifier.
RawClass* factory_signature_class_; // Expected type parameters for factory.
RawObject** to() {
return reinterpret_cast<RawObject**>(&ptr()->factory_signature_class_);
}
intptr_t token_pos_;
};
class RawAbstractType : public RawObject {
protected:
enum TypeState {
kAllocated, // Initial state.
kBeingFinalized, // In the process of being finalized.
kFinalizedInstantiated, // Instantiated type ready for use.
kFinalizedUninstantiated, // Uninstantiated type ready for use.
};
private:
RAW_HEAP_OBJECT_IMPLEMENTATION(AbstractType);
friend class ObjectStore;
};
class RawType : public RawAbstractType {
private:
RAW_HEAP_OBJECT_IMPLEMENTATION(Type);
RawObject** from() {
return reinterpret_cast<RawObject**>(&ptr()->type_class_);
}
RawObject* type_class_; // Either resolved class or unresolved class.
RawAbstractTypeArguments* arguments_;
RawError* malformed_error_; // Error object if type is malformed.
RawObject** to() {
return reinterpret_cast<RawObject**>(&ptr()->malformed_error_);
}
intptr_t token_pos_;
int8_t type_state_;
};
class RawTypeParameter : public RawAbstractType {
private:
RAW_HEAP_OBJECT_IMPLEMENTATION(TypeParameter);
RawObject** from() {
return reinterpret_cast<RawObject**>(&ptr()->parameterized_class_);
}
RawClass* parameterized_class_;
RawString* name_;
RawAbstractType* bound_; // DynamicType if no explicit bound specified.
RawObject** to() { return reinterpret_cast<RawObject**>(&ptr()->bound_); }
intptr_t index_;
intptr_t token_pos_;
int8_t type_state_;
};
class RawInstantiatedType : public RawAbstractType {
private:
RAW_HEAP_OBJECT_IMPLEMENTATION(InstantiatedType);
RawObject** from() {
return reinterpret_cast<RawObject**>(&ptr()->uninstantiated_type_);
}
RawAbstractType* uninstantiated_type_;
RawAbstractTypeArguments* instantiator_type_arguments_;
RawObject** to() {
return reinterpret_cast<RawObject**>(&ptr()->instantiator_type_arguments_);
}
};
class RawAbstractTypeArguments : public RawObject {
private:
RAW_HEAP_OBJECT_IMPLEMENTATION(AbstractTypeArguments);
};
class RawTypeArguments : public RawAbstractTypeArguments {
private:
RAW_HEAP_OBJECT_IMPLEMENTATION(TypeArguments);
RawObject** from() {
return reinterpret_cast<RawObject**>(&ptr()->length_);
}
RawSmi* length_;
// Variable length data follows here.
RawAbstractType* types_[0];
RawObject** to(intptr_t length) {
return reinterpret_cast<RawObject**>(&ptr()->types_[length - 1]);
}
friend class SnapshotReader;
};
class RawInstantiatedTypeArguments : public RawAbstractTypeArguments {
private:
RAW_HEAP_OBJECT_IMPLEMENTATION(InstantiatedTypeArguments);
RawObject** from() {
return reinterpret_cast<RawObject**>(
&ptr()->uninstantiated_type_arguments_);
}
RawAbstractTypeArguments* uninstantiated_type_arguments_;
RawAbstractTypeArguments* instantiator_type_arguments_;
RawObject** to() {
return reinterpret_cast<RawObject**>(&ptr()->instantiator_type_arguments_);
}
};
class RawFunction : public RawObject {
public:
enum Kind {
kRegularFunction,
kClosureFunction,
kSignatureFunction, // represents a signature only without actual code.
kGetterFunction, // represents getter functions e.g: get foo() { .. }.
kSetterFunction, // represents setter functions e.g: set foo(..) { .. }.
kConstructor,
kImplicitGetter, // represents an implicit getter for fields.
kImplicitSetter, // represents an implicit setter for fields.
kConstImplicitGetter, // represents an implicit const getter for fields.
};
private:
RAW_HEAP_OBJECT_IMPLEMENTATION(Function);
RawObject** from() { return reinterpret_cast<RawObject**>(&ptr()->name_); }
RawString* name_;
RawClass* owner_;
RawAbstractType* result_type_;
RawArray* parameter_types_;
RawArray* parameter_names_;
RawCode* code_; // Compiled code for the function.
RawCode* unoptimized_code_; // Unoptimized code, keep it after optimization.
RawContextScope* context_scope_;
RawFunction* parent_function_; // Enclosing function of this local function.
RawClass* signature_class_; // Only for closure or signature function.
RawCode* closure_allocation_stub_; // Stub code for allocation of closures.
RawFunction* implicit_closure_function_; // Implicit closure function.
RawObject** to() {
return reinterpret_cast<RawObject**>(&ptr()->implicit_closure_function_);
}
intptr_t token_pos_;
intptr_t end_token_pos_;
intptr_t num_fixed_parameters_;
intptr_t num_optional_parameters_;
intptr_t usage_counter_; // Incremented while function is running.
intptr_t deoptimization_counter_;
intptr_t kind_tag_;
};
class RawField : public RawObject {
RAW_HEAP_OBJECT_IMPLEMENTATION(Field);
RawObject** from() { return reinterpret_cast<RawObject**>(&ptr()->name_); }
RawString* name_;
RawClass* owner_;
RawAbstractType* type_;
RawInstance* value_; // Offset for instance and value for static fields.
RawObject** to() { return reinterpret_cast<RawObject**>(&ptr()->value_); }
intptr_t token_pos_;
bool is_static_;
bool is_final_;
bool is_const_;
bool has_initializer_;
};
class RawLiteralToken : public RawObject {
RAW_HEAP_OBJECT_IMPLEMENTATION(LiteralToken);
RawObject** from() {
return reinterpret_cast<RawObject**>(&ptr()->literal_);
}
RawString* literal_; // Literal characters as they appear in source text.
RawObject* value_; // The actual object corresponding to the token.
RawObject** to() {
return reinterpret_cast<RawObject**>(&ptr()->value_);
}
Token::Kind kind_; // The literal kind (string, integer, double).
friend class SnapshotReader;
};
class RawTokenStream : public RawObject {
RAW_HEAP_OBJECT_IMPLEMENTATION(TokenStream);
RawObject** from() {
return reinterpret_cast<RawObject**>(&ptr()->private_key_);
}
RawString* private_key_; // Key used for private identifiers.
RawSmi* length_; // Length of token stream.
RawArray* token_objects_;
RawObject** to() {
return reinterpret_cast<RawObject**>(&ptr()->token_objects_);
}
// Variable length data follows here.
uint8_t data_[0];
friend class SnapshotReader;
};
class RawScript : public RawObject {
public:
enum Kind {
kScriptTag = 0,
kLibraryTag,
kSourceTag,
kPatchTag,
};
private:
RAW_HEAP_OBJECT_IMPLEMENTATION(Script);
RawObject** from() { return reinterpret_cast<RawObject**>(&ptr()->url_); }
RawString* url_;
RawString* source_;
RawTokenStream* tokens_;
RawObject** to() { return reinterpret_cast<RawObject**>(&ptr()->tokens_); }
Kind kind_;
};
class RawLibrary : public RawObject {
enum LibraryState {
kAllocated, // Initial state.
kLoadInProgress, // Library is in the process of being loaded.
kLoaded, // Library is loaded.
kLoadError, // Error occurred during load of the Library.
};
RAW_HEAP_OBJECT_IMPLEMENTATION(Library);
RawObject** from() { return reinterpret_cast<RawObject**>(&ptr()->name_); }
RawString* name_;
RawString* url_;
RawScript* script_;
RawString* private_key_;
RawArray* dictionary_; // Top-level names in this library.
RawArray* anonymous_classes_; // Classes containing top-level elements.
RawArray* imports_; // List of libraries imported without prefix.
RawArray* imported_into_; // List of libraries where this library
// is imported into without a prefix.
RawArray* loaded_scripts_; // Array of scripts loaded in this library.
RawObject** to() {
return reinterpret_cast<RawObject**>(&ptr()->loaded_scripts_);
}
intptr_t index_; // Library id number.
intptr_t num_imports_; // Number of entries in imports_.
intptr_t num_imported_into_; // Number of entries in imported_into_.
intptr_t num_anonymous_; // Number of entries in anonymous_classes_.
Dart_NativeEntryResolver native_entry_resolver_; // Resolves natives.
bool corelib_imported_;
bool debuggable_; // True if debugger can stop in library.
int8_t load_state_; // Of type LibraryState.
friend class Isolate;
};
class RawLibraryPrefix : public RawObject {
RAW_HEAP_OBJECT_IMPLEMENTATION(LibraryPrefix);
RawObject** from() { return reinterpret_cast<RawObject**>(&ptr()->name_); }
RawString* name_; // library prefix name.
RawArray* libraries_; // libraries imported with this prefix.
RawObject** to() {
return reinterpret_cast<RawObject**>(&ptr()->libraries_);
}
intptr_t num_libs_; // Number of library entries in libraries_.
};
class RawCode : public RawObject {
RAW_HEAP_OBJECT_IMPLEMENTATION(Code);
RawObject** from() {
return reinterpret_cast<RawObject**>(&ptr()->instructions_);
}
RawInstructions* instructions_;
RawFunction* function_;
RawExceptionHandlers* exception_handlers_;
RawPcDescriptors* pc_descriptors_;
RawArray* deopt_info_array_;
RawArray* object_table_;
RawArray* stackmaps_;
RawLocalVarDescriptors* var_descriptors_;
RawArray* comments_;
RawObject** to() {
return reinterpret_cast<RawObject**>(&ptr()->comments_);
}
intptr_t pointer_offsets_length_;
// This cannot be boolean because of alignment issues on x64 architectures.
intptr_t is_optimized_;
// Variable length data follows here.
int32_t data_[0];
friend class StackFrame;
};
class RawInstructions : public RawObject {
RAW_HEAP_OBJECT_IMPLEMENTATION(Instructions);
RawCode* code_;
intptr_t size_;
// Variable length data follows here.
uint8_t data_[0];
// Private helper function used while visiting stack frames. The
// code which iterates over dart frames is also called during GC and
// is not allowed to create handles.
static bool ContainsPC(RawObject* raw_obj, uword pc);
friend class RawCode;
friend class Code;
friend class StackFrame;
};
class RawPcDescriptors : public RawObject {
RAW_HEAP_OBJECT_IMPLEMENTATION(PcDescriptors);
RawSmi* length_; // Number of descriptors.
// Variable length data follows here.
intptr_t data_[0];
};
// Stackmap is an immutable representation of the layout of the stack at
// a PC. The stack map representation consists of a bit map which marks
// each stack slot index starting from the FP (frame pointer) as an object
// or regular untagged value.
// The Stackmap also consists of a link to code object corresponding to
// the frame which the stack map is describing.
// The bit map representation is optimized for dense and small bit maps,
// without any upper bound.
class RawStackmap : public RawObject {
RAW_HEAP_OBJECT_IMPLEMENTATION(Stackmap);
RawObject** from() {
return reinterpret_cast<RawObject**>(&ptr()->code_);
}
RawCode* code_; // Code object corresponding to the frame described.
RawSmi* bitmap_size_in_bytes_; // Size of the bit map in bytes.
RawObject** to() {
return reinterpret_cast<RawObject**>(&ptr()->bitmap_size_in_bytes_);
}
uword pc_; // PC corresponding to this stack map representation.
intptr_t min_set_bit_index_; // Minimum bit offset which is set.
intptr_t max_set_bit_index_; // Maximum bit offset which is set.
// Variable length data follows here (bitmap of the stack layout).
uint8_t data_[0];
};
class RawLocalVarDescriptors : public RawObject {
public:
enum VarInfoKind {
kStackVar = 1,
kContextVar,
kContextLevel,
kContextChain
};
struct VarInfo {
intptr_t index; // Slot index on stack or in context.
int8_t kind; // Entry kind of type VarInfoKind.
int16_t scope_id; // Scope to which the variable belongs.
intptr_t begin_pos; // Token position of scope start.
intptr_t end_pos; // Token position of scope end.
};
private:
RAW_HEAP_OBJECT_IMPLEMENTATION(LocalVarDescriptors);
intptr_t length_; // Number of descriptors.
RawArray* names_; // Array of [length_] variable names.
VarInfo data_[0]; // Variable info with [length_] entries.
};
class RawExceptionHandlers : public RawObject {
RAW_HEAP_OBJECT_IMPLEMENTATION(ExceptionHandlers);
RawSmi* length_; // Number of exception handler entries.
// Variable length data follows here.
intptr_t data_[0];
};
// Contains an array of deoptimization commands, e.g., move a specific register
// into a specific slot of unoptimized frame.
class RawDeoptInfo : public RawObject {
RAW_HEAP_OBJECT_IMPLEMENTATION(DeoptInfo);
RawSmi* length_; // Number of deoptimization commands
// Variable length data follows here.
intptr_t data_[0];
};
class RawContext : public RawObject {
RAW_HEAP_OBJECT_IMPLEMENTATION(Context);
intptr_t num_variables_;
Isolate* isolate_;
RawObject** from() { return reinterpret_cast<RawObject**>(&ptr()->parent_); }
RawContext* parent_;
// Variable length data follows here.
RawInstance* data_[0];
RawObject** to(intptr_t num_vars) {
return reinterpret_cast<RawObject**>(&ptr()->data_[num_vars - 1]);
}
friend class SnapshotReader;
};
class RawContextScope : public RawObject {
RAW_HEAP_OBJECT_IMPLEMENTATION(ContextScope);
// TODO(iposva): Switch to convential enum offset based structure to avoid
// alignment mishaps.
struct VariableDesc {
RawSmi* token_pos;
RawString* name;
RawBool* is_final;
RawAbstractType* type;
RawSmi* context_index;
RawSmi* context_level;
};
intptr_t num_variables_;
// Variable length data follows here.
RawObject** from() { return reinterpret_cast<RawObject**>(&ptr()->data_[0]); }
RawObject* data_[0];
RawObject** to(intptr_t num_vars) {
intptr_t data_length = num_vars * (sizeof(VariableDesc)/kWordSize);
return reinterpret_cast<RawObject**>(&ptr()->data_[data_length - 1]);
}
};
class RawICData : public RawObject {
RAW_HEAP_OBJECT_IMPLEMENTATION(ICData);
RawObject** from() {
return reinterpret_cast<RawObject**>(&ptr()->function_);
}
RawFunction* function_; // Parent/calling function of this IC.
RawString* target_name_; // Name of target function.
RawArray* ic_data_; // Contains test class-ids and target functions.
RawObject** to() {
return reinterpret_cast<RawObject**>(&ptr()->ic_data_);
}
intptr_t deopt_id_; // Deoptimization id corresponding to this IC.
intptr_t num_args_tested_; // Number of arguments tested in IC.
};
class RawSubtypeTestCache : public RawObject {
RAW_HEAP_OBJECT_IMPLEMENTATION(SubtypeTestCache);
RawArray* cache_;
};
class RawError : public RawObject {
RAW_HEAP_OBJECT_IMPLEMENTATION(Error);
};
class RawApiError : public RawError {
RAW_HEAP_OBJECT_IMPLEMENTATION(ApiError);
RawObject** from() {
return reinterpret_cast<RawObject**>(&ptr()->message_);
}
RawString* message_;
RawObject** to() {
return reinterpret_cast<RawObject**>(&ptr()->message_);
}
};
class RawLanguageError : public RawError {
RAW_HEAP_OBJECT_IMPLEMENTATION(LanguageError);
RawObject** from() {
return reinterpret_cast<RawObject**>(&ptr()->message_);
}
RawString* message_;
RawObject** to() {
return reinterpret_cast<RawObject**>(&ptr()->message_);
}
};
class RawUnhandledException : public RawError {
RAW_HEAP_OBJECT_IMPLEMENTATION(UnhandledException);
RawObject** from() {
return reinterpret_cast<RawObject**>(&ptr()->exception_);
}
RawInstance* exception_;
RawInstance* stacktrace_;
RawObject** to() {
return reinterpret_cast<RawObject**>(&ptr()->stacktrace_);
}
};
class RawUnwindError : public RawError {
RAW_HEAP_OBJECT_IMPLEMENTATION(UnwindError);
RawObject** from() {
return reinterpret_cast<RawObject**>(&ptr()->message_);
}
RawString* message_;
RawObject** to() {
return reinterpret_cast<RawObject**>(&ptr()->message_);
}
};
class RawInstance : public RawObject {
RAW_HEAP_OBJECT_IMPLEMENTATION(Instance);
};
class RawNumber : public RawInstance {
RAW_OBJECT_IMPLEMENTATION(Number);
};
class RawInteger : public RawNumber {
RAW_OBJECT_IMPLEMENTATION(Integer);
};
class RawSmi : public RawInteger {
RAW_OBJECT_IMPLEMENTATION(Smi);
};
class RawMint : public RawInteger {
RAW_HEAP_OBJECT_IMPLEMENTATION(Mint);
int64_t value_;
friend class SnapshotReader;
};
class RawBigint : public RawInteger {
RAW_HEAP_OBJECT_IMPLEMENTATION(Bigint);
// Actual length in chunks at the time of allocation (later we may
// clamp the operational length but we need to maintain a consistent
// object length so that the object can be traversed during GC).
intptr_t allocated_length_;
// Operational length in chunks of the bigint object, clamping can
// cause this length to be reduced. If the signed_length_ is
// negative then the number is negative.
intptr_t signed_length_;
// A sequence of Chunks (typedef in Bignum) representing bignum digits.
// Bignum::Chunk chunks_[Utils::Abs(signed_length_)];
uint8_t data_[0];
friend class SnapshotReader;
};
class RawDouble : public RawNumber {
RAW_HEAP_OBJECT_IMPLEMENTATION(Double);
double value_;
friend class SnapshotReader;
};
class RawString : public RawInstance {
RAW_HEAP_OBJECT_IMPLEMENTATION(String);
protected:
RawObject** from() { return reinterpret_cast<RawObject**>(&ptr()->length_); }
RawSmi* length_;
RawSmi* hash_;
RawObject** to() { return reinterpret_cast<RawObject**>(&ptr()->hash_); }
};
class RawOneByteString : public RawString {
RAW_HEAP_OBJECT_IMPLEMENTATION(OneByteString);
// Variable length data follows here.
uint8_t data_[0];
friend class SnapshotReader;
friend class ApiMessageReader;
};
class RawTwoByteString : public RawString {
RAW_HEAP_OBJECT_IMPLEMENTATION(TwoByteString);
// Variable length data follows here.
uint16_t data_[0];
friend class SnapshotReader;
};
class RawFourByteString : public RawString {
RAW_HEAP_OBJECT_IMPLEMENTATION(FourByteString);
// Variable length data follows here.
uint32_t data_[0];
friend class SnapshotReader;
};
template<typename T>
class ExternalStringData {
public:
ExternalStringData(const T* data, void* peer, Dart_PeerFinalizer callback) :
data_(data), peer_(peer), callback_(callback) {
}
~ExternalStringData() {
if (callback_ != NULL) (*callback_)(peer_);
}
const T* data() {
return data_;
}
void* peer() {
return peer_;
}
private:
const T* data_;
void* peer_;
Dart_PeerFinalizer callback_;
};
class RawExternalOneByteString : public RawString {
RAW_HEAP_OBJECT_IMPLEMENTATION(ExternalOneByteString);
ExternalStringData<uint8_t>* external_data_;
};
class RawExternalTwoByteString : public RawString {
RAW_HEAP_OBJECT_IMPLEMENTATION(ExternalTwoByteString);
ExternalStringData<uint16_t>* external_data_;
};
class RawExternalFourByteString : public RawString {
RAW_HEAP_OBJECT_IMPLEMENTATION(ExternalFourByteString);
ExternalStringData<uint32_t>* external_data_;
};
class RawBool : public RawInstance {
RAW_HEAP_OBJECT_IMPLEMENTATION(Bool);
bool value_;
};
class RawArray : public RawInstance {
RAW_HEAP_OBJECT_IMPLEMENTATION(Array);
RawObject** from() {
return reinterpret_cast<RawObject**>(&ptr()->type_arguments_);
}
RawAbstractTypeArguments* type_arguments_;
RawSmi* length_;
// Variable length data follows here.
RawObject** data() {
uword address_of_length = reinterpret_cast<uword>(&length_);
return reinterpret_cast<RawObject**>(address_of_length + kWordSize);
}
RawObject** to(intptr_t length) {
return reinterpret_cast<RawObject**>(&ptr()->data()[length - 1]);
}
friend class RawCode;
friend class RawImmutableArray;
friend class SnapshotReader;
friend class GrowableObjectArray;
friend class Object;
};
class RawImmutableArray : public RawArray {
RAW_HEAP_OBJECT_IMPLEMENTATION(ImmutableArray);
friend class SnapshotReader;
};
class RawGrowableObjectArray : public RawInstance {
RAW_HEAP_OBJECT_IMPLEMENTATION(GrowableObjectArray);
RawObject** from() {
return reinterpret_cast<RawObject**>(&ptr()->type_arguments_);
}
RawAbstractTypeArguments* type_arguments_;
RawSmi* length_;
RawArray* data_;
RawObject** to() {
return reinterpret_cast<RawObject**>(&ptr()->data_);
}
friend class SnapshotReader;
};
class RawByteArray : public RawInstance {
RAW_HEAP_OBJECT_IMPLEMENTATION(ByteArray);
protected:
RawObject** from() { return reinterpret_cast<RawObject**>(&ptr()->length_); }
RawSmi* length_;
RawObject** to() { return reinterpret_cast<RawObject**>(&ptr()->length_); }
};
class RawInt8Array : public RawByteArray {
RAW_HEAP_OBJECT_IMPLEMENTATION(Int8Array);
// Variable length data follows here.
int8_t data_[0];
};
class RawUint8Array : public RawByteArray {
RAW_HEAP_OBJECT_IMPLEMENTATION(Uint8Array);
// Variable length data follows here.
uint8_t data_[0];
};
class RawInt16Array : public RawByteArray {
RAW_HEAP_OBJECT_IMPLEMENTATION(Int16Array);
// Variable length data follows here.
int16_t data_[0];
};
class RawUint16Array : public RawByteArray {
RAW_HEAP_OBJECT_IMPLEMENTATION(Uint16Array);
// Variable length data follows here.
uint16_t data_[0];
};
class RawInt32Array : public RawByteArray {
RAW_HEAP_OBJECT_IMPLEMENTATION(Int32Array);
// Variable length data follows here.
int32_t data_[0];
};
class RawUint32Array : public RawByteArray {
RAW_HEAP_OBJECT_IMPLEMENTATION(Uint32Array);
// Variable length data follows here.
uint32_t data_[0];
};
class RawInt64Array : public RawByteArray {
RAW_HEAP_OBJECT_IMPLEMENTATION(Int64Array);
// Variable length data follows here.
int64_t data_[0];
};
class RawUint64Array : public RawByteArray {
RAW_HEAP_OBJECT_IMPLEMENTATION(Uint64Array);
// Variable length data follows here.
uint64_t data_[0];
};
class RawFloat32Array : public RawByteArray {
RAW_HEAP_OBJECT_IMPLEMENTATION(Float32Array);
// Variable length data follows here.
float data_[0];
};
class RawFloat64Array : public RawByteArray {
RAW_HEAP_OBJECT_IMPLEMENTATION(Float64Array);
// Variable length data follows here.
double data_[0];
};
template<typename T>
class ExternalByteArrayData {
public:
ExternalByteArrayData(T* data,
void* peer,
Dart_PeerFinalizer callback) :
data_(data), peer_(peer), callback_(callback) {
}
~ExternalByteArrayData() {
if (callback_ != NULL) (*callback_)(peer_);
}
T* data() {
return data_;
}
void* peer() {
return peer_;
}
private:
T* data_;
void* peer_;
Dart_PeerFinalizer callback_;
};
class RawExternalInt8Array : public RawByteArray {
RAW_HEAP_OBJECT_IMPLEMENTATION(ExternalInt8Array);
ExternalByteArrayData<int8_t>* external_data_;
};
class RawExternalUint8Array : public RawByteArray {
RAW_HEAP_OBJECT_IMPLEMENTATION(ExternalUint8Array);
ExternalByteArrayData<uint8_t>* external_data_;
};
class RawExternalInt16Array : public RawByteArray {
RAW_HEAP_OBJECT_IMPLEMENTATION(ExternalInt16Array);
ExternalByteArrayData<int16_t>* external_data_;
};
class RawExternalUint16Array : public RawByteArray {
RAW_HEAP_OBJECT_IMPLEMENTATION(ExternalUint16Array);
ExternalByteArrayData<uint16_t>* external_data_;
};
class RawExternalInt32Array : public RawByteArray {
RAW_HEAP_OBJECT_IMPLEMENTATION(ExternalInt32Array);
ExternalByteArrayData<int32_t>* external_data_;
};
class RawExternalUint32Array : public RawByteArray {
RAW_HEAP_OBJECT_IMPLEMENTATION(ExternalUint32Array);
ExternalByteArrayData<uint32_t>* external_data_;
};
class RawExternalInt64Array : public RawByteArray {
RAW_HEAP_OBJECT_IMPLEMENTATION(ExternalInt64Array);
ExternalByteArrayData<int64_t>* external_data_;
};
class RawExternalUint64Array : public RawByteArray {
RAW_HEAP_OBJECT_IMPLEMENTATION(ExternalUint64Array);
ExternalByteArrayData<uint64_t>* external_data_;
};
class RawExternalFloat32Array : public RawByteArray {
RAW_HEAP_OBJECT_IMPLEMENTATION(ExternalFloat32Array);
ExternalByteArrayData<float>* external_data_;
};
class RawExternalFloat64Array : public RawByteArray {
RAW_HEAP_OBJECT_IMPLEMENTATION(ExternalFloat64Array);
ExternalByteArrayData<double>* external_data_;
};
class RawClosure : public RawInstance {
RAW_HEAP_OBJECT_IMPLEMENTATION(Closure);
RawObject** from() {
return reinterpret_cast<RawObject**>(&ptr()->type_arguments_);
}
RawAbstractTypeArguments* type_arguments_;
RawFunction* function_;
RawContext* context_;
// TODO(iposva): Remove this temporary hack.
RawInteger* smrck_;
RawObject** to() { return reinterpret_cast<RawObject**>(&ptr()->smrck_); }
};
// VM type for capturing stacktraces when exceptions are thrown,
// Currently we don't have any interface that this object is supposed
// to implement so we just support the 'toString' method which
// converts the stack trace into a string.
class RawStacktrace : public RawInstance {
RAW_HEAP_OBJECT_IMPLEMENTATION(Stacktrace);
RawObject** from() {
return reinterpret_cast<RawObject**>(&ptr()->function_array_);
}
RawArray* function_array_; // Function for each frame in the stack trace.
RawArray* code_array_; // Code object for each frame in the stack trace.
RawArray* pc_offset_array_; // Offset of PC for each frame.
RawObject** to() {
return reinterpret_cast<RawObject**>(&ptr()->pc_offset_array_);
}
};
// VM type for capturing JS regular expressions.
class RawJSRegExp : public RawInstance {
RAW_HEAP_OBJECT_IMPLEMENTATION(JSRegExp);
RawObject** from() {
return reinterpret_cast<RawObject**>(&ptr()->data_length_);
}
RawSmi* data_length_;
RawSmi* num_bracket_expressions_;
RawString* pattern_; // Pattern to be used for matching.
RawObject** to() {
return reinterpret_cast<RawObject**>(&ptr()->pattern_);
}
intptr_t type_; // Uninitialized, simple or complex.
intptr_t flags_; // Represents global/local, case insensitive, multiline.
// Variable length data follows here.
uint8_t data_[0];
};
// Class Id predicates.
inline bool RawObject::IsErrorClassId(intptr_t index) {
// Make sure this function is updated when new Error types are added.
ASSERT(kApiErrorCid == kErrorCid + 1 &&
kLanguageErrorCid == kErrorCid + 2 &&
kUnhandledExceptionCid == kErrorCid + 3 &&
kUnwindErrorCid == kErrorCid + 4 &&
kInstanceCid == kErrorCid + 5);
return (index >= kErrorCid && index < kInstanceCid);
}
inline bool RawObject::IsNumberClassId(intptr_t index) {
// Make sure this function is updated when new Number types are added.
ASSERT(kIntegerCid == kNumberCid + 1 &&
kSmiCid == kNumberCid + 2 &&
kMintCid == kNumberCid + 3 &&
kBigintCid == kNumberCid + 4 &&
kDoubleCid == kNumberCid + 5 &&
kStringCid == kNumberCid + 6);
return (index >= kNumberCid && index < kStringCid);
}
inline bool RawObject::IsIntegerClassId(intptr_t index) {
// Make sure this function is updated when new Integer types are added.
ASSERT(kSmiCid == kIntegerCid + 1 &&
kMintCid == kIntegerCid + 2 &&
kBigintCid == kIntegerCid + 3 &&
kDoubleCid == kIntegerCid + 4);
return (index >= kIntegerCid && index < kDoubleCid);
}
inline bool RawObject::IsStringClassId(intptr_t index) {
// Make sure this function is updated when new StringCid types are added.
ASSERT(kOneByteStringCid == kStringCid + 1 &&
kTwoByteStringCid == kStringCid + 2 &&
kFourByteStringCid == kStringCid + 3 &&
kExternalOneByteStringCid == kStringCid + 4 &&
kExternalTwoByteStringCid == kStringCid + 5 &&
kExternalFourByteStringCid == kStringCid + 6 &&
kBoolCid == kStringCid + 7);
return (index >= kStringCid && index < kBoolCid);
}
inline bool RawObject::IsOneByteStringClassId(intptr_t index) {
// Make sure this function is updated when new StringCid types are added.
ASSERT(kOneByteStringCid == kStringCid + 1 &&
kTwoByteStringCid == kStringCid + 2 &&
kFourByteStringCid == kStringCid + 3 &&
kExternalOneByteStringCid == kStringCid + 4 &&
kExternalTwoByteStringCid == kStringCid + 5 &&
kExternalFourByteStringCid == kStringCid + 6 &&
kBoolCid == kStringCid + 7);
return (index == kOneByteStringCid || index == kExternalOneByteStringCid);
}
inline bool RawObject::IsTwoByteStringClassId(intptr_t index) {
// Make sure this function is updated when new StringCid types are added.
ASSERT(kOneByteStringCid == kStringCid + 1 &&
kTwoByteStringCid == kStringCid + 2 &&
kFourByteStringCid == kStringCid + 3 &&
kExternalOneByteStringCid == kStringCid + 4 &&
kExternalTwoByteStringCid == kStringCid + 5 &&
kExternalFourByteStringCid == kStringCid + 6 &&
kBoolCid == kStringCid + 7);
return (index == kOneByteStringCid ||
index == kTwoByteStringCid ||
index == kExternalOneByteStringCid ||
index == kExternalTwoByteStringCid);
}
inline bool RawObject::IsExternalStringClassId(intptr_t index) {
// Make sure this function is updated when new StringCid types are added.
ASSERT(kOneByteStringCid == kStringCid + 1 &&
kTwoByteStringCid == kStringCid + 2 &&
kFourByteStringCid == kStringCid + 3 &&
kExternalOneByteStringCid == kStringCid + 4 &&
kExternalTwoByteStringCid == kStringCid + 5 &&
kExternalFourByteStringCid == kStringCid + 6 &&
kBoolCid == kStringCid + 7);
return (index == kExternalOneByteStringCid ||
index == kExternalTwoByteStringCid ||
index == kExternalFourByteStringCid);
}
inline bool RawObject::IsBuiltinListClassId(intptr_t index) {
// Make sure this function is updated when new builtin List types are added.
ASSERT(kImmutableArrayCid == kArrayCid + 1 &&
kGrowableObjectArrayCid == kArrayCid + 2 &&
kByteArrayCid == kArrayCid + 3);
return (index >= kArrayCid && index < kByteArrayCid) ||
IsByteArrayClassId(index);
}
inline bool RawObject::IsByteArrayClassId(intptr_t index) {
// Make sure this function is updated when new ByteArray types are added.
ASSERT(kInt8ArrayCid == kByteArrayCid + 1 &&
kUint8ArrayCid == kByteArrayCid + 2 &&
kInt16ArrayCid == kByteArrayCid + 3 &&
kUint16ArrayCid == kByteArrayCid + 4 &&
kInt32ArrayCid == kByteArrayCid + 5 &&
kUint32ArrayCid == kByteArrayCid + 6 &&
kInt64ArrayCid == kByteArrayCid + 7 &&
kUint64ArrayCid == kByteArrayCid + 8 &&
kFloat32ArrayCid == kByteArrayCid + 9 &&
kFloat64ArrayCid == kByteArrayCid + 10 &&
kExternalInt8ArrayCid == kByteArrayCid + 11 &&
kExternalUint8ArrayCid == kByteArrayCid + 12 &&
kExternalInt16ArrayCid == kByteArrayCid + 13 &&
kExternalUint16ArrayCid == kByteArrayCid + 14 &&
kExternalInt32ArrayCid == kByteArrayCid + 15 &&
kExternalUint32ArrayCid == kByteArrayCid + 16 &&
kExternalInt64ArrayCid == kByteArrayCid + 17 &&
kExternalUint64ArrayCid == kByteArrayCid + 18 &&
kExternalFloat32ArrayCid == kByteArrayCid + 19 &&
kExternalFloat64ArrayCid == kByteArrayCid + 20 &&
kStacktraceCid == kByteArrayCid + 21);
return (index >= kByteArrayCid && index <= kExternalFloat64ArrayCid);
}
} // namespace dart
#endif // VM_RAW_OBJECT_H_