// 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 "include/dart_api.h" #include "platform/assert.h" #include "vm/assembler.h" #include "vm/bigint_operations.h" #include "vm/bootstrap.h" #include "vm/class_finalizer.h" #include "vm/code_generator.h" #include "vm/code_patcher.h" #include "vm/compiler.h" #include "vm/compiler_stats.h" #include "vm/dart.h" #include "vm/dart_api_state.h" #include "vm/dart_entry.h" #include "vm/datastream.h" #include "vm/debuginfo.h" #include "vm/deopt_instructions.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/symbols.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"); DEFINE_FLAG(bool, show_internal_names, false, "Show names of internal classes (e.g. \"OneByteString\") in error messages " "instead of showing the corresponding interface names (e.g. \"String\")"); 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 Object::builtin_vtables_[kNumPredefinedCids] = { 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); RawArray* Object::empty_array_ = 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::type_arguments_class_ = reinterpret_cast(RAW_NULL); RawClass* Object::instantiated_type_arguments_class_ = reinterpret_cast(RAW_NULL); RawClass* Object::patch_class_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::deopt_info_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::subtypetestcache_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 // Takes a vm internal name and makes it suitable for external user. // // Examples: // // Internal getter and setter prefixes are changed: // // get:foo -> foo // set:foo -> foo= // // Private name mangling is removed, possibly twice: // // _ReceivePortImpl@6be832b -> _ReceivePortImpl // _ReceivePortImpl@6be832b._internal@6be832b -> +ReceivePortImpl._internal // // The trailing . on the default constructor name is dropped: // // List. -> List // // And so forth: // // get:foo@6be832b -> foo // _MyClass@6b3832b. -> _MyClass // _MyClass@6b3832b.named -> _MyClass.named // static RawString* IdentifierPrettyName(const String& name) { intptr_t len = name.Length(); intptr_t start = 0; intptr_t at_pos = len; // Position of '@' in the name. intptr_t dot_pos = len; // Position of '.' in the name. bool is_setter = false; for (int i = 0; i < name.Length(); i++) { if (name.CharAt(i) == ':') { ASSERT(start == 0); if (name.CharAt(0) == 's') { is_setter = true; } start = i + 1; } else if (name.CharAt(i) == '@') { ASSERT(at_pos == len); at_pos = i; } else if (name.CharAt(i) == '.') { dot_pos = i; break; } } intptr_t limit = (at_pos < dot_pos ? at_pos : dot_pos); if (start == 0 && limit == len) { // This name is fine as it is. return name.raw(); } const String& result = String::Handle(String::SubString(name, start, (limit - start))); // Look for a second '@' now to correctly handle names like // "_ReceivePortImpl@6be832b._internal@6be832b". at_pos = len; for (int i = dot_pos; i < name.Length(); i++) { if (name.CharAt(i) == '@') { ASSERT(at_pos == len); at_pos = i; } } intptr_t suffix_len = at_pos - dot_pos; if (suffix_len > 1) { // This is a named constructor. Add the name back to the string. const String& suffix = String::Handle(String::SubString(name, dot_pos, suffix_len)); return String::Concat(result, suffix); } if (is_setter) { // Setters need to end with '='. const String& suffix = String::Handle(Symbols::Equals()); return String::Concat(result, suffix); } return result.raw(); } 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(); } Isolate* isolate = Isolate::Current(); Heap* heap = isolate->heap(); // Allocate and initialize the null instance. // '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); // The call below is using 'null_' to initialize itself. InitializeObject(address, kNullCid, Instance::InstanceSize()); } // 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). empty_array_ = Array::null(); Class& cls = Class::Handle(); // Allocate and initialize the class class. { intptr_t size = Class::InstanceSize(); uword address = heap->Allocate(size, Heap::kOld); class_class_ = reinterpret_cast(address + kHeapObjectTag); InitializeObject(address, Class::kClassId, size); Class fake; // Initialization from Class::New. // Directly set raw_ to break a circular dependency: SetRaw will attempt // to lookup class class in the class table where it is not registered yet. cls.raw_ = class_class_; cls.set_handle_vtable(fake.vtable()); cls.set_instance_size(Class::InstanceSize()); cls.set_next_field_offset(Class::InstanceSize()); cls.set_id(Class::kClassId); cls.raw_ptr()->state_bits_ = 0; cls.set_is_finalized(); cls.raw_ptr()->type_arguments_instance_field_offset_ = Class::kNoTypeArguments; cls.raw_ptr()->num_native_fields_ = 0; cls.InitEmptyFields(); isolate->class_table()->Register(cls); } // Allocate and initialize the null class. cls = Class::New(kNullCid); cls.set_is_finalized(); null_class_ = cls.raw(); // Allocate and initialize the free list element class. cls = Class::New(kFreeListElement); cls.set_is_finalized(); // Allocate and initialize the sentinel values of Null class. { Instance& sentinel = Instance::Handle(); sentinel ^= Object::Allocate(kNullCid, Instance::InstanceSize(), Heap::kOld); sentinel_ = sentinel.raw(); Instance& transition_sentinel = Instance::Handle(); transition_sentinel ^= Object::Allocate(kNullCid, Instance::InstanceSize(), Heap::kOld); transition_sentinel_ = transition_sentinel.raw(); } cls = Class::New(kDynamicCid); 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(kVoidCid); 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(); type_arguments_class_ = cls.raw(); cls = Class::New(); instantiated_type_arguments_class_ = cls.raw(); cls = Class::New(); patch_class_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