1// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5#include "vm/object_store.h"
6
7#include "vm/dart_entry.h"
8#include "vm/exceptions.h"
9#include "vm/isolate.h"
10#include "vm/object.h"
11#include "vm/raw_object.h"
12#include "vm/resolver.h"
13#include "vm/stub_code.h"
14#include "vm/symbols.h"
15#include "vm/visitor.h"
16
17namespace dart {
18
19IsolateObjectStore::IsolateObjectStore(ObjectStore* object_store)
20 : object_store_(object_store) {}
21
22IsolateObjectStore::~IsolateObjectStore() {}
23
24void IsolateObjectStore::VisitObjectPointers(ObjectPointerVisitor* visitor) {
25 ASSERT(visitor != NULL);
26 visitor->set_gc_root_type("isolate_object store");
27 visitor->VisitPointers(from(), to());
28 visitor->clear_gc_root_type();
29}
30
31void IsolateObjectStore::Init() {
32#define INIT_FIELD(Type, name) name##_ = Type::null();
33 ISOLATE_OBJECT_STORE_FIELD_LIST(INIT_FIELD, INIT_FIELD)
34#undef INIT_FIELD
35
36 for (ObjectPtr* current = from(); current <= to(); current++) {
37 ASSERT(*current == Object::null());
38 }
39}
40
41#ifndef PRODUCT
42void IsolateObjectStore::PrintToJSONObject(JSONObject* jsobj) {
43 jsobj->AddProperty("type", "_IsolateObjectStore");
44
45 {
46 JSONObject fields(jsobj, "fields");
47 Object& value = Object::Handle();
48#define PRINT_OBJECT_STORE_FIELD(type, name) \
49 value = name##_; \
50 fields.AddProperty(#name "_", value);
51 ISOLATE_OBJECT_STORE_FIELD_LIST(PRINT_OBJECT_STORE_FIELD,
52 PRINT_OBJECT_STORE_FIELD);
53#undef PRINT_OBJECT_STORE_FIELD
54 }
55}
56#endif // !PRODUCT
57
58static UnhandledExceptionPtr CreatePreallocatedUnandledException(
59 Zone* zone,
60 const Object& out_of_memory) {
61 // Allocate pre-allocated unhandled exception object initialized with the
62 // pre-allocated OutOfMemoryError.
63 const UnhandledException& unhandled_exception =
64 UnhandledException::Handle(UnhandledException::New(
65 Instance::Cast(out_of_memory), StackTrace::Handle(zone)));
66 return unhandled_exception.raw();
67}
68
69static StackTracePtr CreatePreallocatedStackTrace(Zone* zone) {
70 const Array& code_array = Array::Handle(
71 zone, Array::New(StackTrace::kPreallocatedStackdepth, Heap::kOld));
72 const Array& pc_offset_array = Array::Handle(
73 zone, Array::New(StackTrace::kPreallocatedStackdepth, Heap::kOld));
74 const StackTrace& stack_trace =
75 StackTrace::Handle(zone, StackTrace::New(code_array, pc_offset_array));
76 // Expansion of inlined functions requires additional memory at run time,
77 // avoid it.
78 stack_trace.set_expand_inlined(false);
79 return stack_trace.raw();
80}
81
82ErrorPtr IsolateObjectStore::PreallocateObjects() {
83 Thread* thread = Thread::Current();
84 Isolate* isolate = thread->isolate();
85 Zone* zone = thread->zone();
86 ASSERT(isolate != NULL && isolate->isolate_object_store() == this);
87 ASSERT(preallocated_stack_trace() == StackTrace::null());
88 resume_capabilities_ = GrowableObjectArray::New();
89 exit_listeners_ = GrowableObjectArray::New();
90 error_listeners_ = GrowableObjectArray::New();
91
92 // Allocate pre-allocated unhandled exception object initialized with the
93 // pre-allocated OutOfMemoryError.
94 const Object& out_of_memory =
95 Object::Handle(zone, object_store_->out_of_memory());
96 set_preallocated_unhandled_exception(UnhandledException::Handle(
97 CreatePreallocatedUnandledException(zone, out_of_memory)));
98 set_preallocated_stack_trace(
99 StackTrace::Handle(CreatePreallocatedStackTrace(zone)));
100
101 return Error::null();
102}
103
104ObjectStore::ObjectStore() {
105#define INIT_FIELD(Type, name) name##_ = Type::null();
106 OBJECT_STORE_FIELD_LIST(INIT_FIELD, INIT_FIELD, INIT_FIELD, INIT_FIELD)
107#undef INIT_FIELD
108
109 for (ObjectPtr* current = from(); current <= to(); current++) {
110 ASSERT(*current == Object::null());
111 }
112}
113
114ObjectStore::~ObjectStore() {}
115
116void ObjectStore::VisitObjectPointers(ObjectPointerVisitor* visitor) {
117 ASSERT(visitor != NULL);
118 visitor->set_gc_root_type("object store");
119 visitor->VisitPointers(from(), to());
120 visitor->clear_gc_root_type();
121}
122
123void ObjectStore::InitStubs() {
124#define DO(member, name) set_##member(StubCode::name());
125 OBJECT_STORE_STUB_CODE_LIST(DO)
126#undef DO
127}
128
129#ifndef PRODUCT
130void ObjectStore::PrintToJSONObject(JSONObject* jsobj) {
131 jsobj->AddProperty("type", "_ObjectStore");
132
133 {
134 JSONObject fields(jsobj, "fields");
135 Object& value = Object::Handle();
136#define PRINT_OBJECT_STORE_FIELD(type, name) \
137 value = name##_; \
138 fields.AddProperty(#name "_", value);
139 OBJECT_STORE_FIELD_LIST(PRINT_OBJECT_STORE_FIELD, PRINT_OBJECT_STORE_FIELD,
140 PRINT_OBJECT_STORE_FIELD, PRINT_OBJECT_STORE_FIELD);
141#undef PRINT_OBJECT_STORE_FIELD
142 }
143}
144#endif // !PRODUCT
145
146static InstancePtr AllocateObjectByClassName(const Library& library,
147 const String& class_name) {
148 const Class& cls = Class::Handle(library.LookupClassAllowPrivate(class_name));
149 ASSERT(!cls.IsNull());
150 return Instance::New(cls);
151}
152
153ErrorPtr ObjectStore::PreallocateObjects() {
154 Thread* thread = Thread::Current();
155 IsolateGroup* isolate_group = thread->isolate_group();
156 Isolate* isolate = thread->isolate();
157 // Either we are the object store on isolate group, or isolate group has no
158 // object store and we are the object store on the isolate.
159 ASSERT(isolate_group != NULL && (isolate_group->object_store() == this ||
160 (isolate_group->object_store() == nullptr &&
161 isolate->object_store() == this)));
162
163 if (this->stack_overflow() != Instance::null()) {
164 ASSERT(this->out_of_memory() != Instance::null());
165 return Error::null();
166 }
167 ASSERT(this->stack_overflow() == Instance::null());
168 ASSERT(this->out_of_memory() == Instance::null());
169
170 this->closure_functions_ = GrowableObjectArray::New();
171
172 Object& result = Object::Handle();
173 const Library& library = Library::Handle(Library::CoreLibrary());
174
175 result = AllocateObjectByClassName(library, Symbols::StackOverflowError());
176 if (result.IsError()) {
177 return Error::Cast(result).raw();
178 }
179 set_stack_overflow(Instance::Cast(result));
180
181 result = AllocateObjectByClassName(library, Symbols::OutOfMemoryError());
182 if (result.IsError()) {
183 return Error::Cast(result).raw();
184 }
185 set_out_of_memory(Instance::Cast(result));
186
187 return Error::null();
188}
189
190FunctionPtr ObjectStore::PrivateObjectLookup(const String& name) {
191 const Library& core_lib = Library::Handle(core_library());
192 const String& mangled = String::ZoneHandle(core_lib.PrivateName(name));
193 const Class& cls = Class::Handle(object_class());
194 const Function& result = Function::Handle(cls.LookupDynamicFunction(mangled));
195 ASSERT(!result.IsNull());
196 return result.raw();
197}
198
199void ObjectStore::InitKnownObjects() {
200 Thread* thread = Thread::Current();
201 Zone* zone = thread->zone();
202 Class& cls = Class::Handle(zone);
203 const Library& collection_lib = Library::Handle(zone, collection_library());
204 cls = collection_lib.LookupClassAllowPrivate(Symbols::_LinkedHashSet());
205 ASSERT(!cls.IsNull());
206 set_linked_hash_set_class(cls);
207
208#ifdef DART_PRECOMPILED_RUNTIME
209 // The rest of these objects are only needed for code generation.
210 return;
211#else
212 Isolate* isolate = thread->isolate();
213 ASSERT(isolate != NULL && isolate->object_store() == this);
214
215 const Library& async_lib = Library::Handle(zone, async_library());
216 ASSERT(!async_lib.IsNull());
217 cls = async_lib.LookupClass(Symbols::Future());
218 ASSERT(!cls.IsNull());
219 set_future_class(cls);
220 cls = async_lib.LookupClass(Symbols::Completer());
221 ASSERT(!cls.IsNull());
222 set_completer_class(cls);
223
224 String& function_name = String::Handle(zone);
225 Function& function = Function::Handle(zone);
226 function_name = async_lib.PrivateName(Symbols::SetAsyncThreadStackTrace());
227 ASSERT(!function_name.IsNull());
228 function = Resolver::ResolveStatic(async_lib, Object::null_string(),
229 function_name, 0, 1, Object::null_array());
230 ASSERT(!function.IsNull());
231 set_async_set_thread_stack_trace(function);
232
233 function_name = async_lib.PrivateName(Symbols::ClearAsyncThreadStackTrace());
234 ASSERT(!function_name.IsNull());
235 function = Resolver::ResolveStatic(async_lib, Object::null_string(),
236 function_name, 0, 0, Object::null_array());
237 ASSERT(!function.IsNull());
238 set_async_clear_thread_stack_trace(function);
239
240 function_name = async_lib.PrivateName(Symbols::AsyncStarMoveNextHelper());
241 ASSERT(!function_name.IsNull());
242 function = Resolver::ResolveStatic(async_lib, Object::null_string(),
243 function_name, 0, 1, Object::null_array());
244 ASSERT(!function.IsNull());
245 set_async_star_move_next_helper(function);
246
247 function_name = async_lib.PrivateName(Symbols::_CompleteOnAsyncReturn());
248 ASSERT(!function_name.IsNull());
249 function = Resolver::ResolveStatic(async_lib, Object::null_string(),
250 function_name, 0, 2, Object::null_array());
251 ASSERT(!function.IsNull());
252 set_complete_on_async_return(function);
253 if (FLAG_async_debugger) {
254 // Disable debugging and inlining the _CompleteOnAsyncReturn function.
255 function.set_is_debuggable(false);
256 function.set_is_inlinable(false);
257 }
258
259 cls =
260 async_lib.LookupClassAllowPrivate(Symbols::_AsyncStarStreamController());
261 ASSERT(!cls.IsNull());
262 set_async_star_stream_controller(cls);
263
264 if (FLAG_async_debugger) {
265 // Disable debugging and inlining of all functions on the
266 // _AsyncStarStreamController class.
267 const Array& functions = Array::Handle(zone, cls.functions());
268 for (intptr_t i = 0; i < functions.Length(); i++) {
269 function ^= functions.At(i);
270 if (function.IsNull()) {
271 break;
272 }
273 function.set_is_debuggable(false);
274 function.set_is_inlinable(false);
275 }
276 }
277
278 const Library& internal_lib = Library::Handle(zone, _internal_library());
279 cls = internal_lib.LookupClass(Symbols::Symbol());
280 set_symbol_class(cls);
281
282 const Library& core_lib = Library::Handle(zone, core_library());
283 cls = core_lib.LookupClassAllowPrivate(Symbols::_CompileTimeError());
284 ASSERT(!cls.IsNull());
285 set_compiletime_error_class(cls);
286
287 cls = core_lib.LookupClassAllowPrivate(Symbols::Pragma());
288 ASSERT(!cls.IsNull());
289 set_pragma_class(cls);
290 set_pragma_name(Field::Handle(zone, cls.LookupField(Symbols::name())));
291 set_pragma_options(Field::Handle(zone, cls.LookupField(Symbols::options())));
292
293 cls = core_lib.LookupClassAllowPrivate(Symbols::_GrowableList());
294 ASSERT(!cls.IsNull());
295 growable_list_factory_ =
296 cls.LookupFactoryAllowPrivate(Symbols::_GrowableListFactory());
297 ASSERT(growable_list_factory_ != Function::null());
298
299 // Cache the core private functions used for fast instance of checks.
300 simple_instance_of_function_ =
301 PrivateObjectLookup(Symbols::_simpleInstanceOf());
302 simple_instance_of_true_function_ =
303 PrivateObjectLookup(Symbols::_simpleInstanceOfTrue());
304 simple_instance_of_false_function_ =
305 PrivateObjectLookup(Symbols::_simpleInstanceOfFalse());
306
307 // Ensure AddSmiSmiCheckForFastSmiStubs run by the background compiler
308 // will not create new functions.
309 const Class& smi_class = Class::Handle(zone, this->smi_class());
310 function_name =
311 Function::CreateDynamicInvocationForwarderName(Symbols::Plus());
312 Resolver::ResolveDynamicAnyArgs(zone, smi_class, function_name);
313 function_name =
314 Function::CreateDynamicInvocationForwarderName(Symbols::Minus());
315 Resolver::ResolveDynamicAnyArgs(zone, smi_class, function_name);
316 function_name =
317 Function::CreateDynamicInvocationForwarderName(Symbols::Equals());
318 Resolver::ResolveDynamicAnyArgs(zone, smi_class, function_name);
319 function_name =
320 Function::CreateDynamicInvocationForwarderName(Symbols::LAngleBracket());
321 Resolver::ResolveDynamicAnyArgs(zone, smi_class, function_name);
322 function_name =
323 Function::CreateDynamicInvocationForwarderName(Symbols::RAngleBracket());
324 Resolver::ResolveDynamicAnyArgs(zone, smi_class, function_name);
325 function_name =
326 Function::CreateDynamicInvocationForwarderName(Symbols::BitAnd());
327 Resolver::ResolveDynamicAnyArgs(zone, smi_class, function_name);
328 function_name =
329 Function::CreateDynamicInvocationForwarderName(Symbols::BitOr());
330 Resolver::ResolveDynamicAnyArgs(zone, smi_class, function_name);
331 function_name =
332 Function::CreateDynamicInvocationForwarderName(Symbols::Star());
333 Resolver::ResolveDynamicAnyArgs(zone, smi_class, function_name);
334#endif
335}
336
337void ObjectStore::LazyInitCoreTypes() {
338 if (non_nullable_list_rare_type_ == Type::null()) {
339 ASSERT(non_nullable_map_rare_type_ == Type::null());
340 Thread* thread = Thread::Current();
341 Zone* zone = thread->zone();
342 const Library& core_lib = Library::Handle(zone, Library::CoreLibrary());
343 Class& cls = Class::Handle(zone, core_lib.LookupClass(Symbols::List()));
344 ASSERT(!cls.IsNull());
345 Type& type = Type::Handle(zone);
346 type ^= cls.RareType();
347 set_non_nullable_list_rare_type(type);
348 cls = core_lib.LookupClass(Symbols::Map());
349 ASSERT(!cls.IsNull());
350 type ^= cls.RareType();
351 set_non_nullable_map_rare_type(type);
352 }
353}
354
355void ObjectStore::LazyInitFutureTypes() {
356 if (non_nullable_future_rare_type_ == Type::null()) {
357 ASSERT(non_nullable_future_never_type_ == Type::null() &&
358 nullable_future_null_type_ == Type::null());
359 Thread* thread = Thread::Current();
360 Zone* zone = thread->zone();
361 Class& cls = Class::Handle(zone, future_class());
362 if (cls.IsNull()) {
363 const Library& async_lib = Library::Handle(zone, async_library());
364 ASSERT(!async_lib.IsNull());
365 cls = async_lib.LookupClass(Symbols::Future());
366 ASSERT(!cls.IsNull());
367 }
368 TypeArguments& type_args = TypeArguments::Handle(zone);
369 Type& type = Type::Handle(zone);
370 type = never_type();
371 ASSERT(!type.IsNull());
372 type_args = TypeArguments::New(1);
373 type_args.SetTypeAt(0, type);
374 type = Type::New(cls, type_args, TokenPosition::kNoSource,
375 Nullability::kNonNullable);
376 type.SetIsFinalized();
377 type ^= type.Canonicalize();
378 set_non_nullable_future_never_type(type);
379 type = null_type();
380 ASSERT(!type.IsNull());
381 type_args = TypeArguments::New(1);
382 type_args.SetTypeAt(0, type);
383 type = Type::New(cls, type_args, TokenPosition::kNoSource,
384 Nullability::kNullable);
385 type.SetIsFinalized();
386 type ^= type.Canonicalize();
387 set_nullable_future_null_type(type);
388 type ^= cls.RareType();
389 set_non_nullable_future_rare_type(type);
390 }
391}
392
393} // namespace dart
394