// 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/object.h" #include "platform/assert.h" #include "vm/assembler.h" #include "vm/bigint_operations.h" #include "vm/bootstrap.h" #include "vm/code_generator.h" #include "vm/code_patcher.h" #include "vm/compiler.h" #include "vm/compiler_stats.h" #include "vm/class_finalizer.h" #include "vm/dart.h" #include "vm/dart_api_state.h" #include "vm/dart_entry.h" #include "vm/debuginfo.h" #include "vm/double_conversion.h" #include "vm/exceptions.h" #include "vm/growable_array.h" #include "vm/heap.h" #include "vm/object_store.h" #include "vm/parser.h" #include "vm/runtime_entry.h" #include "vm/scopes.h" #include "vm/stack_frame.h" #include "vm/timer.h" #include "vm/unicode.h" namespace dart { DEFINE_FLAG(bool, generate_gdb_symbols, false, "Generate symbols of generated dart functions for debugging with GDB"); DECLARE_FLAG(bool, trace_compiler); DECLARE_FLAG(bool, enable_type_checks); static const char* kGetterPrefix = "get:"; static const intptr_t kGetterPrefixLength = strlen(kGetterPrefix); static const char* kSetterPrefix = "set:"; static const intptr_t kSetterPrefixLength = strlen(kSetterPrefix); cpp_vtable Object::handle_vtable_ = 0; cpp_vtable Smi::handle_vtable_ = 0; // These are initialized to a value that will force a illegal memory access if // they are being used. #if defined(RAW_NULL) #error RAW_NULL should not be defined. #endif #define RAW_NULL kHeapObjectTag RawObject* Object::null_ = reinterpret_cast(RAW_NULL); RawInstance* Object::sentinel_ = reinterpret_cast(RAW_NULL); RawInstance* Object::transition_sentinel_ = reinterpret_cast(RAW_NULL); RawClass* Object::class_class_ = reinterpret_cast(RAW_NULL); RawClass* Object::null_class_ = reinterpret_cast(RAW_NULL); RawClass* Object::dynamic_class_ = reinterpret_cast(RAW_NULL); RawClass* Object::void_class_ = reinterpret_cast(RAW_NULL); RawClass* Object::unresolved_class_class_ = reinterpret_cast(RAW_NULL); RawClass* Object::type_class_ = reinterpret_cast(RAW_NULL); RawClass* Object::type_parameter_class_ = reinterpret_cast(RAW_NULL); RawClass* Object::instantiated_type_class_ = reinterpret_cast(RAW_NULL); RawClass* Object::abstract_type_arguments_class_ = reinterpret_cast(RAW_NULL); RawClass* Object::type_arguments_class_ = reinterpret_cast(RAW_NULL); RawClass* Object::instantiated_type_arguments_class_ = reinterpret_cast(RAW_NULL); RawClass* Object::function_class_ = reinterpret_cast(RAW_NULL); RawClass* Object::field_class_ = reinterpret_cast(RAW_NULL); RawClass* Object::literal_token_class_ = reinterpret_cast(RAW_NULL); RawClass* Object::token_stream_class_ = reinterpret_cast(RAW_NULL); RawClass* Object::script_class_ = reinterpret_cast(RAW_NULL); RawClass* Object::library_class_ = reinterpret_cast(RAW_NULL); RawClass* Object::library_prefix_class_ = reinterpret_cast(RAW_NULL); RawClass* Object::code_class_ = reinterpret_cast(RAW_NULL); RawClass* Object::instructions_class_ = reinterpret_cast(RAW_NULL); RawClass* Object::pc_descriptors_class_ = reinterpret_cast(RAW_NULL); RawClass* Object::stackmap_class_ = reinterpret_cast(RAW_NULL); RawClass* Object::var_descriptors_class_ = reinterpret_cast(RAW_NULL); RawClass* Object::exception_handlers_class_ = reinterpret_cast(RAW_NULL); RawClass* Object::context_class_ = reinterpret_cast(RAW_NULL); RawClass* Object::context_scope_class_ = reinterpret_cast(RAW_NULL); RawClass* Object::icdata_class_ = reinterpret_cast(RAW_NULL); RawClass* Object::api_error_class_ = reinterpret_cast(RAW_NULL); RawClass* Object::language_error_class_ = reinterpret_cast(RAW_NULL); RawClass* Object::unhandled_exception_class_ = reinterpret_cast(RAW_NULL); RawClass* Object::unwind_error_class_ = reinterpret_cast(RAW_NULL); #undef RAW_NULL int Object::GetSingletonClassIndex(const RawClass* raw_class) { ASSERT(raw_class->IsHeapObject()); if (raw_class == class_class()) { return kClassClass; } else if (raw_class == null_class()) { return kNullClass; } else if (raw_class == dynamic_class()) { return kDynamicClass; } else if (raw_class == void_class()) { return kVoidClass; } else if (raw_class == unresolved_class_class()) { return kUnresolvedClassClass; } else if (raw_class == type_class()) { return kTypeClass; } else if (raw_class == type_parameter_class()) { return kTypeParameterClass; } else if (raw_class == instantiated_type_class()) { return kInstantiatedTypeClass; } else if (raw_class == abstract_type_arguments_class()) { return kAbstractTypeArgumentsClass; } else if (raw_class == type_arguments_class()) { return kTypeArgumentsClass; } else if (raw_class == instantiated_type_arguments_class()) { return kInstantiatedTypeArgumentsClass; } else if (raw_class == function_class()) { return kFunctionClass; } else if (raw_class == field_class()) { return kFieldClass; } else if (raw_class == literal_token_class()) { return kLiteralTokenClass; } else if (raw_class == token_stream_class()) { return kTokenStreamClass; } else if (raw_class == script_class()) { return kScriptClass; } else if (raw_class == library_class()) { return kLibraryClass; } else if (raw_class == library_prefix_class()) { return kLibraryPrefixClass; } else if (raw_class == code_class()) { return kCodeClass; } else if (raw_class == instructions_class()) { return kInstructionsClass; } else if (raw_class == pc_descriptors_class()) { return kPcDescriptorsClass; } else if (raw_class == stackmap_class()) { return kStackmapClass; } else if (raw_class == var_descriptors_class()) { return kLocalVarDescriptorsClass; } else if (raw_class == exception_handlers_class()) { return kExceptionHandlersClass; } else if (raw_class == context_class()) { return kContextClass; } else if (raw_class == context_scope_class()) { return kContextScopeClass; } else if (raw_class == icdata_class()) { return kICDataClass; } else if (raw_class == api_error_class()) { return kApiErrorClass; } else if (raw_class == language_error_class()) { return kLanguageErrorClass; } else if (raw_class == unhandled_exception_class()) { return kUnhandledExceptionClass; } else if (raw_class == unwind_error_class()) { return kUnwindErrorClass; } return kInvalidIndex; } RawClass* Object::GetSingletonClass(int index) { switch (index) { case kClassClass: return class_class(); case kNullClass: return null_class(); case kDynamicClass: return dynamic_class(); case kVoidClass: return void_class(); case kUnresolvedClassClass: return unresolved_class_class(); case kTypeClass: return type_class(); case kTypeParameterClass: return type_parameter_class(); case kInstantiatedTypeClass: return instantiated_type_class(); case kAbstractTypeArgumentsClass: return abstract_type_arguments_class(); case kTypeArgumentsClass: return type_arguments_class(); case kInstantiatedTypeArgumentsClass: return instantiated_type_arguments_class(); case kFunctionClass: return function_class(); case kFieldClass: return field_class(); case kLiteralTokenClass: return literal_token_class(); case kTokenStreamClass: return token_stream_class(); case kScriptClass: return script_class(); case kLibraryClass: return library_class(); case kLibraryPrefixClass: return library_prefix_class(); case kCodeClass: return code_class(); case kInstructionsClass: return instructions_class(); case kPcDescriptorsClass: return pc_descriptors_class(); case kStackmapClass: return stackmap_class(); case kLocalVarDescriptorsClass: return var_descriptors_class(); case kExceptionHandlersClass: return exception_handlers_class(); case kContextClass: return context_class(); case kContextScopeClass: return context_scope_class(); case kICDataClass: return icdata_class(); case kApiErrorClass: return api_error_class(); case kLanguageErrorClass: return language_error_class(); case kUnhandledExceptionClass: return unhandled_exception_class(); case kUnwindErrorClass: return unwind_error_class(); default: break; } UNREACHABLE(); return reinterpret_cast(kHeapObjectTag); // return RAW_NULL. } const char* Object::GetSingletonClassName(int index) { switch (index) { case kClassClass: return "Class"; case kNullClass: return "Null"; case kDynamicClass: return "Dynamic"; case kVoidClass: return "void"; case kUnresolvedClassClass: return "UnresolvedClass"; case kTypeClass: return "Type"; case kTypeParameterClass: return "TypeParameter"; case kInstantiatedTypeClass: return "InstantiatedType"; case kAbstractTypeArgumentsClass: return "AbstractTypeArguments"; case kTypeArgumentsClass: return "TypeArguments"; case kInstantiatedTypeArgumentsClass: return "InstantiatedTypeArguments"; case kFunctionClass: return "Function"; case kFieldClass: return "Field"; case kTokenStreamClass: return "TokenStream"; case kScriptClass: return "Script"; case kLibraryClass: return "Library"; case kLibraryPrefixClass: return "LibraryPrefix"; case kCodeClass: return "Code"; case kInstructionsClass: return "Instructions"; case kPcDescriptorsClass: return "PcDescriptors"; case kStackmapClass: return "Stackmap"; case kLocalVarDescriptorsClass: return "LocalVarDescriptors"; case kExceptionHandlersClass: return "ExceptionHandlers"; case kContextClass: return "Context"; case kContextScopeClass: return "ContextScope"; case kICDataClass: return "ICData"; case kApiErrorClass: return "ApiError"; case kLanguageErrorClass: return "LanguageError"; case kUnhandledExceptionClass: return "UnhandledException"; case kUnwindErrorClass: return "UnwindError"; default: break; } UNREACHABLE(); return NULL; } void Object::InitOnce() { // TODO(iposva): NoGCScope needs to be added here. ASSERT(class_class() == null_); // Initialize the static vtable values. { Object fake_object; Smi fake_smi; Object::handle_vtable_ = fake_object.vtable(); Smi::handle_vtable_ = fake_smi.vtable(); } Heap* heap = Isolate::Current()->heap(); // Allocate and initialize the null instance, except its class_ field. // 'null_' must be the first object allocated as it is used in allocation to // clear the object. { uword address = heap->Allocate(Instance::InstanceSize(), Heap::kOld); null_ = reinterpret_cast(address + kHeapObjectTag); InitializeObject(address, Instance::InstanceSize()); // Using 'null_'. null_->ptr()->tags_ = 0; } // Initialize object_store empty array to null_ in order to be able to check // if the empty array was allocated (RAW_NULL is not available). Isolate::Current()->object_store()->set_empty_array(Array::Handle()); Class& cls = Class::Handle(); // Allocate and initialize the class class. // At this point, class_class_ is still RAW_NULL, i.e. different from 'null_', // since 'null_' is not RAW_NULL anymore. However, class_class_ == null_ must // be true before calling Class::New(), or it will fail. class_class_ = Class::Handle().raw(); // Set 'class_class_' to 'null_'. cls = Class::New(); cls.set_is_finalized(); class_class_ = cls.raw(); // Make the class_ field point to itself. class_class_->ptr()->class_ = class_class_; // Allocate and initialize the null class. cls = Class::New(); cls.set_is_finalized(); null_class_ = cls.raw(); // Complete initialization of null_ instance, i.e. initialize its class_ // field. null_->ptr()->class_ = null_class_; // Allocate and initialize the sentinel values of Null class. { cls = null_class_; Instance& sentinel = Instance::Handle(); sentinel ^= Object::Allocate(cls, Instance::InstanceSize(), Heap::kOld); sentinel_ = sentinel.raw(); Instance& transition_sentinel = Instance::Handle(); transition_sentinel ^= Object::Allocate(cls, Instance::InstanceSize(), Heap::kOld); transition_sentinel_ = transition_sentinel.raw(); } // The interface "Dynamic" is not a VM internal class. It is the type class of // the "unknown type". For efficiency, we allocate it in the VM isolate. // Therefore, it cannot have a heap allocated name (the name is hard coded, // see GetSingletonClassIndex) and its array fields cannot be set to the empty // array, but remain null. cls = Class::New(); cls.set_is_finalized(); cls.set_is_interface(); dynamic_class_ = cls.raw(); // Allocate the remaining VM internal classes. cls = Class::New(); unresolved_class_class_ = cls.raw(); cls = Class::New(); cls.set_is_finalized(); void_class_ = cls.raw(); cls = Class::New(); type_class_ = cls.raw(); cls = Class::New(); type_parameter_class_ = cls.raw(); cls = Class::New(); instantiated_type_class_ = cls.raw(); cls = Class::New(); abstract_type_arguments_class_ = cls.raw(); cls = Class::New(); type_arguments_class_ = cls.raw(); cls = Class::New(); instantiated_type_arguments_class_ = cls.raw(); cls = Class::New(); function_class_ = cls.raw(); cls = Class::New(); field_class_ = cls.raw(); cls = Class::New(); literal_token_class_ = cls.raw(); cls = Class::New(); token_stream_class_ = cls.raw(); cls = Class::New