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 "include/dart_api.h"
6#include "include/dart_native_api.h"
7
8#include <memory>
9#include <utility>
10
11#include "lib/stacktrace.h"
12#include "platform/assert.h"
13#include "platform/unicode.h"
14#include "vm/class_finalizer.h"
15#include "vm/clustered_snapshot.h"
16#include "vm/compilation_trace.h"
17#include "vm/compiler/jit/compiler.h"
18#include "vm/dart.h"
19#include "vm/dart_api_impl.h"
20#include "vm/dart_api_message.h"
21#include "vm/dart_api_state.h"
22#include "vm/dart_entry.h"
23#include "vm/debugger.h"
24#include "vm/dwarf.h"
25#include "vm/elf.h"
26#include "vm/exceptions.h"
27#include "vm/flags.h"
28#include "vm/growable_array.h"
29#include "vm/heap/verifier.h"
30#include "vm/image_snapshot.h"
31#include "vm/isolate_reload.h"
32#include "vm/kernel_isolate.h"
33#include "vm/lockers.h"
34#include "vm/message.h"
35#include "vm/message_handler.h"
36#include "vm/native_entry.h"
37#include "vm/native_symbol.h"
38#include "vm/object.h"
39#include "vm/object_store.h"
40#include "vm/os.h"
41#include "vm/os_thread.h"
42#include "vm/port.h"
43#include "vm/profiler.h"
44#include "vm/profiler_service.h"
45#include "vm/program_visitor.h"
46#include "vm/resolver.h"
47#include "vm/reusable_handles.h"
48#include "vm/service.h"
49#include "vm/service_event.h"
50#include "vm/service_isolate.h"
51#include "vm/stack_frame.h"
52#include "vm/symbols.h"
53#include "vm/tags.h"
54#include "vm/thread_registry.h"
55#include "vm/uri.h"
56#include "vm/version.h"
57
58#if !defined(DART_PRECOMPILED_RUNTIME)
59#include "vm/compiler/aot/precompiler.h"
60#include "vm/kernel_loader.h"
61#endif // !defined(DART_PRECOMPILED_RUNTIME)
62
63namespace dart {
64
65// Facilitate quick access to the current zone once we have the current thread.
66#define Z (T->zone())
67
68DECLARE_FLAG(bool, print_class_table);
69DECLARE_FLAG(bool, verify_handles);
70#if defined(DEBUG) && !defined(DART_PRECOMPILED_RUNTIME)
71DEFINE_FLAG(bool,
72 check_function_fingerprints,
73 true,
74 "Check function fingerprints");
75#endif // defined(DEBUG) && !defined(DART_PRECOMPILED_RUNTIME).
76DEFINE_FLAG(bool,
77 verify_acquired_data,
78 false,
79 "Verify correct API acquire/release of typed data.");
80DEFINE_FLAG(bool,
81 dump_tables,
82 false,
83 "Dump common hash tables before snapshotting.");
84
85#define CHECK_ERROR_HANDLE(error) \
86 { \
87 ErrorPtr err = (error); \
88 if (err != Error::null()) { \
89 return Api::NewHandle(T, err); \
90 } \
91 }
92
93ThreadLocalKey Api::api_native_key_ = kUnsetThreadLocalKey;
94Dart_Handle Api::true_handle_ = NULL;
95Dart_Handle Api::false_handle_ = NULL;
96Dart_Handle Api::null_handle_ = NULL;
97Dart_Handle Api::empty_string_handle_ = NULL;
98
99const char* CanonicalFunction(const char* func) {
100 if (strncmp(func, "dart::", 6) == 0) {
101 return func + 6;
102 } else {
103 return func;
104 }
105}
106
107#if defined(DEBUG)
108// An object visitor which will iterate over all the function objects in the
109// heap and check if the result type and parameter types are canonicalized
110// or not. An assertion is raised if a type is not canonicalized.
111class CheckFunctionTypesVisitor : public ObjectVisitor {
112 public:
113 explicit CheckFunctionTypesVisitor(Thread* thread)
114 : classHandle_(Class::Handle(thread->zone())),
115 funcHandle_(Function::Handle(thread->zone())),
116 typeHandle_(AbstractType::Handle(thread->zone())) {}
117
118 void VisitObject(ObjectPtr obj) {
119 if (obj->IsFunction()) {
120 funcHandle_ ^= obj;
121 classHandle_ ^= funcHandle_.Owner();
122 // Signature functions get created, but not canonicalized, when function
123 // types get instantiated during run time type tests.
124 if (funcHandle_.IsSignatureFunction()) {
125 return;
126 }
127 // Verify that the result type of a function is canonical or a
128 // TypeParameter.
129 typeHandle_ ^= funcHandle_.result_type();
130 ASSERT(typeHandle_.IsTypeParameter() || typeHandle_.IsCanonical());
131 // Verify that the types in the function signature are all canonical or
132 // a TypeParameter.
133 const intptr_t num_parameters = funcHandle_.NumParameters();
134 for (intptr_t i = 0; i < num_parameters; i++) {
135 typeHandle_ = funcHandle_.ParameterTypeAt(i);
136 ASSERT(typeHandle_.IsTypeParameter() || typeHandle_.IsCanonical());
137 }
138 }
139 }
140
141 private:
142 Class& classHandle_;
143 Function& funcHandle_;
144 AbstractType& typeHandle_;
145};
146#endif // #if defined(DEBUG).
147
148static InstancePtr GetListInstance(Zone* zone, const Object& obj) {
149 if (obj.IsInstance()) {
150 ObjectStore* object_store = Isolate::Current()->object_store();
151 const Type& list_rare_type =
152 Type::Handle(zone, object_store->non_nullable_list_rare_type());
153 ASSERT(!list_rare_type.IsNull());
154 const Instance& instance = Instance::Cast(obj);
155 const Class& obj_class = Class::Handle(zone, obj.clazz());
156 if (Class::IsSubtypeOf(obj_class, Object::null_type_arguments(),
157 Nullability::kNonNullable, list_rare_type,
158 Heap::kNew)) {
159 return instance.raw();
160 }
161 }
162 return Instance::null();
163}
164
165static InstancePtr GetMapInstance(Zone* zone, const Object& obj) {
166 if (obj.IsInstance()) {
167 ObjectStore* object_store = Isolate::Current()->object_store();
168 const Type& map_rare_type =
169 Type::Handle(zone, object_store->non_nullable_map_rare_type());
170 ASSERT(!map_rare_type.IsNull());
171 const Instance& instance = Instance::Cast(obj);
172 const Class& obj_class = Class::Handle(zone, obj.clazz());
173 if (Class::IsSubtypeOf(obj_class, Object::null_type_arguments(),
174 Nullability::kNonNullable, map_rare_type,
175 Heap::kNew)) {
176 return instance.raw();
177 }
178 }
179 return Instance::null();
180}
181
182static bool IsCompiletimeErrorObject(Zone* zone, const Object& obj) {
183#if defined(DART_PRECOMPILED_RUNTIME)
184 // All compile-time errors were handled at snapshot generation time and
185 // compiletime_error_class was removed.
186 return false;
187#else
188 Isolate* I = Thread::Current()->isolate();
189 const Class& error_class =
190 Class::Handle(zone, I->object_store()->compiletime_error_class());
191 ASSERT(!error_class.IsNull());
192 return (obj.GetClassId() == error_class.id());
193#endif
194}
195
196static bool GetNativeStringArgument(NativeArguments* arguments,
197 int arg_index,
198 Dart_Handle* str,
199 void** peer) {
200 ASSERT(peer != NULL);
201 if (Api::StringGetPeerHelper(arguments, arg_index, peer)) {
202 *str = NULL;
203 return true;
204 }
205 Thread* thread = arguments->thread();
206 ASSERT(thread == Thread::Current());
207 *peer = NULL;
208 REUSABLE_OBJECT_HANDLESCOPE(thread);
209 Object& obj = thread->ObjectHandle();
210 obj = arguments->NativeArgAt(arg_index);
211 if (IsStringClassId(obj.GetClassId())) {
212 ASSERT(thread->api_top_scope() != NULL);
213 *str = Api::NewHandle(thread, obj.raw());
214 return true;
215 }
216 if (obj.IsNull()) {
217 *str = Api::Null();
218 return true;
219 }
220 return false;
221}
222
223static bool GetNativeIntegerArgument(NativeArguments* arguments,
224 int arg_index,
225 int64_t* value) {
226 ASSERT(value != NULL);
227 return Api::GetNativeIntegerArgument(arguments, arg_index, value);
228}
229
230static bool GetNativeUnsignedIntegerArgument(NativeArguments* arguments,
231 int arg_index,
232 uint64_t* value) {
233 ASSERT(value != NULL);
234 int64_t arg_value = 0;
235 if (Api::GetNativeIntegerArgument(arguments, arg_index, &arg_value)) {
236 *value = static_cast<uint64_t>(arg_value);
237 return true;
238 }
239 return false;
240}
241
242static bool GetNativeDoubleArgument(NativeArguments* arguments,
243 int arg_index,
244 double* value) {
245 ASSERT(value != NULL);
246 return Api::GetNativeDoubleArgument(arguments, arg_index, value);
247}
248
249static Dart_Handle GetNativeFieldsOfArgument(NativeArguments* arguments,
250 int arg_index,
251 int num_fields,
252 intptr_t* field_values,
253 const char* current_func) {
254 ASSERT(field_values != NULL);
255 if (Api::GetNativeFieldsOfArgument(arguments, arg_index, num_fields,
256 field_values)) {
257 return Api::Success();
258 }
259 Thread* thread = arguments->thread();
260 ASSERT(thread == Thread::Current());
261 REUSABLE_OBJECT_HANDLESCOPE(thread);
262 Object& obj = thread->ObjectHandle();
263 obj = arguments->NativeArgAt(arg_index);
264 if (obj.IsNull()) {
265 memset(field_values, 0, (num_fields * sizeof(field_values[0])));
266 return Api::Success();
267 }
268 // We did not succeed in extracting the native fields report the
269 // appropriate error.
270 if (!obj.IsInstance()) {
271 return Api::NewError(
272 "%s expects argument at index '%d' to be of"
273 " type Instance.",
274 current_func, arg_index);
275 }
276 const Instance& instance = Instance::Cast(obj);
277 int field_count = instance.NumNativeFields();
278 ASSERT(num_fields != field_count);
279 return Api::NewError("%s: expected %d 'num_fields' but was passed in %d.",
280 current_func, field_count, num_fields);
281}
282
283static ObjectPtr Send0Arg(const Instance& receiver, const String& selector) {
284 const intptr_t kTypeArgsLen = 0;
285 const intptr_t kNumArgs = 1;
286 ArgumentsDescriptor args_desc(
287 Array::Handle(ArgumentsDescriptor::NewBoxed(kTypeArgsLen, kNumArgs)));
288 const Function& function =
289 Function::Handle(Resolver::ResolveDynamic(receiver, selector, args_desc));
290 if (function.IsNull()) {
291 return ApiError::New(String::Handle(String::New("")));
292 }
293 const Array& args = Array::Handle(Array::New(kNumArgs));
294 args.SetAt(0, receiver);
295 return DartEntry::InvokeFunction(function, args);
296}
297
298static ObjectPtr Send1Arg(const Instance& receiver,
299 const String& selector,
300 const Instance& argument) {
301 const intptr_t kTypeArgsLen = 0;
302 const intptr_t kNumArgs = 2;
303 ArgumentsDescriptor args_desc(
304 Array::Handle(ArgumentsDescriptor::NewBoxed(kTypeArgsLen, kNumArgs)));
305 const Function& function =
306 Function::Handle(Resolver::ResolveDynamic(receiver, selector, args_desc));
307 if (function.IsNull()) {
308 return ApiError::New(String::Handle(String::New("")));
309 }
310 const Array& args = Array::Handle(Array::New(kNumArgs));
311 args.SetAt(0, receiver);
312 args.SetAt(1, argument);
313 return DartEntry::InvokeFunction(function, args);
314}
315
316static const char* GetErrorString(Thread* thread, const Object& obj) {
317 // This function requires an API scope to be present.
318 if (obj.IsError()) {
319 ASSERT(thread->api_top_scope() != NULL);
320 const Error& error = Error::Cast(obj);
321 const char* str = error.ToErrorCString();
322 intptr_t len = strlen(str) + 1;
323 char* str_copy = Api::TopScope(thread)->zone()->Alloc<char>(len);
324 strncpy(str_copy, str, len);
325 // Strip a possible trailing '\n'.
326 if ((len > 1) && (str_copy[len - 2] == '\n')) {
327 str_copy[len - 2] = '\0';
328 }
329 return str_copy;
330 } else {
331 return "";
332 }
333}
334
335Dart_Handle Api::InitNewHandle(Thread* thread, ObjectPtr raw) {
336 LocalHandles* local_handles = Api::TopScope(thread)->local_handles();
337 ASSERT(local_handles != NULL);
338 LocalHandle* ref = local_handles->AllocateHandle();
339 ref->set_raw(raw);
340 return ref->apiHandle();
341}
342
343Dart_Handle Api::NewHandle(Thread* thread, ObjectPtr raw) {
344 if (raw == Object::null()) {
345 return Null();
346 }
347 if (raw == Bool::True().raw()) {
348 return True();
349 }
350 if (raw == Bool::False().raw()) {
351 return False();
352 }
353 ASSERT(thread->execution_state() == Thread::kThreadInVM);
354 return InitNewHandle(thread, raw);
355}
356
357ObjectPtr Api::UnwrapHandle(Dart_Handle object) {
358#if defined(DEBUG)
359 Thread* thread = Thread::Current();
360 ASSERT(thread->execution_state() == Thread::kThreadInVM);
361 ASSERT(thread->IsMutatorThread());
362 ASSERT(thread->isolate() != NULL);
363 ASSERT(!FLAG_verify_handles || thread->IsValidLocalHandle(object) ||
364 thread->isolate()->group()->api_state()->IsActivePersistentHandle(
365 reinterpret_cast<Dart_PersistentHandle>(object)) ||
366 Dart::IsReadOnlyApiHandle(object));
367 ASSERT(FinalizablePersistentHandle::raw_offset() == 0 &&
368 PersistentHandle::raw_offset() == 0 && LocalHandle::raw_offset() == 0);
369#endif
370 return (reinterpret_cast<LocalHandle*>(object))->raw();
371}
372
373#define DEFINE_UNWRAP(type) \
374 const type& Api::Unwrap##type##Handle(Zone* zone, Dart_Handle dart_handle) { \
375 const Object& obj = Object::Handle(zone, Api::UnwrapHandle(dart_handle)); \
376 if (obj.Is##type()) { \
377 return type::Cast(obj); \
378 } \
379 return type::Handle(zone); \
380 }
381CLASS_LIST_FOR_HANDLES(DEFINE_UNWRAP)
382#undef DEFINE_UNWRAP
383
384const String& Api::UnwrapStringHandle(const ReusableObjectHandleScope& reuse,
385 Dart_Handle dart_handle) {
386 Object& ref = reuse.Handle();
387 ref = Api::UnwrapHandle(dart_handle);
388 if (ref.IsString()) {
389 return String::Cast(ref);
390 }
391 return Object::null_string();
392}
393
394const Instance& Api::UnwrapInstanceHandle(
395 const ReusableObjectHandleScope& reuse,
396 Dart_Handle dart_handle) {
397 Object& ref = reuse.Handle();
398 ref = Api::UnwrapHandle(dart_handle);
399 if (ref.IsInstance()) {
400 return Instance::Cast(ref);
401 }
402 return Object::null_instance();
403}
404
405Dart_Handle Api::CheckAndFinalizePendingClasses(Thread* thread) {
406 Isolate* isolate = thread->isolate();
407 if (!isolate->AllowClassFinalization()) {
408 // Class finalization is blocked for the isolate. Do nothing.
409 return Api::Success();
410 }
411 if (ClassFinalizer::ProcessPendingClasses()) {
412 return Api::Success();
413 }
414 ASSERT(thread->sticky_error() != Object::null());
415 return Api::NewHandle(thread, thread->sticky_error());
416}
417
418Dart_Isolate Api::CastIsolate(Isolate* isolate) {
419 return reinterpret_cast<Dart_Isolate>(isolate);
420}
421
422Dart_IsolateGroup Api::CastIsolateGroup(IsolateGroup* isolate_group) {
423 return reinterpret_cast<Dart_IsolateGroup>(isolate_group);
424}
425
426Dart_Handle Api::NewError(const char* format, ...) {
427 Thread* T = Thread::Current();
428 CHECK_API_SCOPE(T);
429 CHECK_CALLBACK_STATE(T);
430 // Ensure we transition safepoint state to VM if we are not already in
431 // that state.
432 TransitionToVM transition(T);
433 HANDLESCOPE(T);
434
435 va_list args;
436 va_start(args, format);
437 char* buffer = OS::VSCreate(Z, format, args);
438 va_end(args);
439
440 const String& message = String::Handle(Z, String::New(buffer));
441 return Api::NewHandle(T, ApiError::New(message));
442}
443
444Dart_Handle Api::NewArgumentError(const char* format, ...) {
445 Thread* T = Thread::Current();
446 CHECK_API_SCOPE(T);
447 CHECK_CALLBACK_STATE(T);
448 // Ensure we transition safepoint state to VM if we are not already in
449 // that state.
450 TransitionToVM transition(T);
451 HANDLESCOPE(T);
452
453 va_list args;
454 va_start(args, format);
455 char* buffer = OS::VSCreate(Z, format, args);
456 va_end(args);
457
458 const String& message = String::Handle(Z, String::New(buffer));
459 const Array& arguments = Array::Handle(Z, Array::New(1));
460 arguments.SetAt(0, message);
461 Object& error = Object::Handle(
462 Z, DartLibraryCalls::InstanceCreate(
463 Library::Handle(Z, Library::CoreLibrary()),
464 Symbols::ArgumentError(), Symbols::Dot(), arguments));
465 if (!error.IsError()) {
466 error = UnhandledException::New(Instance::Cast(error), Instance::Handle());
467 }
468 return Api::NewHandle(T, error.raw());
469}
470
471Dart_Handle Api::AcquiredError(IsolateGroup* isolate_group) {
472 ApiState* state = isolate_group->api_state();
473 ASSERT(state != NULL);
474 PersistentHandle* acquired_error_handle = state->AcquiredError();
475 return reinterpret_cast<Dart_Handle>(acquired_error_handle);
476}
477
478bool Api::IsValid(Dart_Handle handle) {
479 Isolate* isolate = Isolate::Current();
480 Thread* thread = Thread::Current();
481 ASSERT(thread->IsMutatorThread());
482 CHECK_ISOLATE(isolate);
483
484 // Check against all of the handles in the current isolate as well as the
485 // read-only handles.
486 return thread->IsValidHandle(handle) ||
487 isolate->group()->api_state()->IsActivePersistentHandle(
488 reinterpret_cast<Dart_PersistentHandle>(handle)) ||
489 isolate->group()->api_state()->IsActiveWeakPersistentHandle(
490 reinterpret_cast<Dart_WeakPersistentHandle>(handle)) ||
491 Dart::IsReadOnlyApiHandle(handle) ||
492 Dart::IsReadOnlyHandle(reinterpret_cast<uword>(handle));
493}
494
495ApiLocalScope* Api::TopScope(Thread* thread) {
496 ASSERT(thread != NULL);
497 ApiLocalScope* scope = thread->api_top_scope();
498 ASSERT(scope != NULL);
499 return scope;
500}
501
502void Api::Init() {
503 if (api_native_key_ == kUnsetThreadLocalKey) {
504 api_native_key_ = OSThread::CreateThreadLocal();
505 }
506 ASSERT(api_native_key_ != kUnsetThreadLocalKey);
507}
508
509static Dart_Handle InitNewReadOnlyApiHandle(ObjectPtr raw) {
510 ASSERT(raw->ptr()->InVMIsolateHeap());
511 LocalHandle* ref = Dart::AllocateReadOnlyApiHandle();
512 ref->set_raw(raw);
513 return ref->apiHandle();
514}
515
516void Api::InitHandles() {
517 Isolate* isolate = Isolate::Current();
518 ASSERT(isolate != NULL);
519 ASSERT(isolate == Dart::vm_isolate());
520 ApiState* state = isolate->group()->api_state();
521 ASSERT(state != NULL);
522
523 ASSERT(true_handle_ == NULL);
524 true_handle_ = InitNewReadOnlyApiHandle(Bool::True().raw());
525
526 ASSERT(false_handle_ == NULL);
527 false_handle_ = InitNewReadOnlyApiHandle(Bool::False().raw());
528
529 ASSERT(null_handle_ == NULL);
530 null_handle_ = InitNewReadOnlyApiHandle(Object::null());
531
532 ASSERT(empty_string_handle_ == NULL);
533 empty_string_handle_ = InitNewReadOnlyApiHandle(Symbols::Empty().raw());
534}
535
536void Api::Cleanup() {
537 true_handle_ = NULL;
538 false_handle_ = NULL;
539 null_handle_ = NULL;
540 empty_string_handle_ = NULL;
541}
542
543bool Api::StringGetPeerHelper(NativeArguments* arguments,
544 int arg_index,
545 void** peer) {
546 NoSafepointScope no_safepoint_scope;
547 ObjectPtr raw_obj = arguments->NativeArgAt(arg_index);
548 if (!raw_obj->IsHeapObject()) {
549 return false;
550 }
551 intptr_t cid = raw_obj->GetClassId();
552 if (cid == kExternalOneByteStringCid) {
553 ExternalOneByteStringPtr raw_string =
554 static_cast<ExternalOneByteStringPtr>(raw_obj);
555 *peer = raw_string->ptr()->peer_;
556 return true;
557 }
558 if (cid == kOneByteStringCid || cid == kTwoByteStringCid) {
559 Isolate* isolate = arguments->thread()->isolate();
560 *peer = isolate->heap()->GetPeer(raw_obj);
561 return (*peer != 0);
562 }
563 if (cid == kExternalTwoByteStringCid) {
564 ExternalTwoByteStringPtr raw_string =
565 static_cast<ExternalTwoByteStringPtr>(raw_obj);
566 *peer = raw_string->ptr()->peer_;
567 return true;
568 }
569 return false;
570}
571
572bool Api::GetNativeReceiver(NativeArguments* arguments, intptr_t* value) {
573 NoSafepointScope no_safepoint_scope;
574 ObjectPtr raw_obj = arguments->NativeArg0();
575 if (raw_obj->IsHeapObject()) {
576 intptr_t cid = raw_obj->GetClassId();
577 if (cid >= kNumPredefinedCids) {
578 ASSERT(Instance::Cast(Object::Handle(raw_obj)).IsValidNativeIndex(0));
579 TypedDataPtr native_fields = *reinterpret_cast<TypedDataPtr*>(
580 ObjectLayout::ToAddr(raw_obj) + sizeof(ObjectLayout));
581 if (native_fields == TypedData::null()) {
582 *value = 0;
583 } else {
584 *value = *bit_cast<intptr_t*, uint8_t*>(native_fields->ptr()->data());
585 }
586 return true;
587 }
588 }
589 return false;
590}
591
592bool Api::GetNativeBooleanArgument(NativeArguments* arguments,
593 int arg_index,
594 bool* value) {
595 NoSafepointScope no_safepoint_scope;
596 ObjectPtr raw_obj = arguments->NativeArgAt(arg_index);
597 if (raw_obj->IsHeapObject()) {
598 intptr_t cid = raw_obj->GetClassId();
599 if (cid == kBoolCid) {
600 *value = (raw_obj == Object::bool_true().raw());
601 return true;
602 }
603 if (cid == kNullCid) {
604 *value = false;
605 return true;
606 }
607 }
608 return false;
609}
610
611bool Api::GetNativeIntegerArgument(NativeArguments* arguments,
612 int arg_index,
613 int64_t* value) {
614 NoSafepointScope no_safepoint_scope;
615 ObjectPtr raw_obj = arguments->NativeArgAt(arg_index);
616 if (raw_obj->IsHeapObject()) {
617 intptr_t cid = raw_obj->GetClassId();
618 if (cid == kMintCid) {
619 *value = static_cast<MintPtr>(raw_obj)->ptr()->value_;
620 return true;
621 }
622 return false;
623 }
624 *value = Smi::Value(static_cast<SmiPtr>(raw_obj));
625 return true;
626}
627
628bool Api::GetNativeDoubleArgument(NativeArguments* arguments,
629 int arg_index,
630 double* value) {
631 NoSafepointScope no_safepoint_scope;
632 ObjectPtr raw_obj = arguments->NativeArgAt(arg_index);
633 if (raw_obj->IsHeapObject()) {
634 intptr_t cid = raw_obj->GetClassId();
635 if (cid == kDoubleCid) {
636 *value = static_cast<DoublePtr>(raw_obj)->ptr()->value_;
637 return true;
638 }
639 if (cid == kMintCid) {
640 *value =
641 static_cast<double>(static_cast<MintPtr>(raw_obj)->ptr()->value_);
642 return true;
643 }
644 return false;
645 }
646 *value = static_cast<double>(Smi::Value(static_cast<SmiPtr>(raw_obj)));
647 return true;
648}
649
650bool Api::GetNativeFieldsOfArgument(NativeArguments* arguments,
651 int arg_index,
652 int num_fields,
653 intptr_t* field_values) {
654 NoSafepointScope no_safepoint_scope;
655 ObjectPtr raw_obj = arguments->NativeArgAt(arg_index);
656 if (raw_obj->IsHeapObject()) {
657 intptr_t cid = raw_obj->GetClassId();
658 if (cid >= kNumPredefinedCids) {
659 TypedDataPtr native_fields = *reinterpret_cast<TypedDataPtr*>(
660 ObjectLayout::ToAddr(raw_obj) + sizeof(ObjectLayout));
661 if (native_fields == TypedData::null()) {
662 memset(field_values, 0, (num_fields * sizeof(field_values[0])));
663 } else if (num_fields == Smi::Value(native_fields->ptr()->length_)) {
664 intptr_t* native_values =
665 bit_cast<intptr_t*, uint8_t*>(native_fields->ptr()->data());
666 memmove(field_values, native_values,
667 (num_fields * sizeof(field_values[0])));
668 }
669 return true;
670 }
671 }
672 return false;
673}
674
675void Api::SetWeakHandleReturnValue(NativeArguments* args,
676 Dart_WeakPersistentHandle retval) {
677 args->SetReturnUnsafe(FinalizablePersistentHandle::Cast(retval)->raw());
678}
679
680PersistentHandle* PersistentHandle::Cast(Dart_PersistentHandle handle) {
681 ASSERT(IsolateGroup::Current()->api_state()->IsValidPersistentHandle(handle));
682 return reinterpret_cast<PersistentHandle*>(handle);
683}
684
685FinalizablePersistentHandle* FinalizablePersistentHandle::Cast(
686 Dart_WeakPersistentHandle handle) {
687#if defined(DEBUG)
688 ApiState* state = IsolateGroup::Current()->api_state();
689 ASSERT(state->IsValidWeakPersistentHandle(handle));
690#endif
691 return reinterpret_cast<FinalizablePersistentHandle*>(handle);
692}
693FinalizablePersistentHandle* FinalizablePersistentHandle::Cast(
694 Dart_FinalizableHandle handle) {
695#if defined(DEBUG)
696 ApiState* state = IsolateGroup::Current()->api_state();
697 ASSERT(state->IsValidFinalizableHandle(handle));
698#endif
699 return reinterpret_cast<FinalizablePersistentHandle*>(handle);
700}
701
702void FinalizablePersistentHandle::Finalize(
703 IsolateGroup* isolate_group,
704 FinalizablePersistentHandle* handle) {
705 if (!handle->raw()->IsHeapObject()) {
706 return; // Free handle.
707 }
708 void* peer = handle->peer();
709 ApiState* state = isolate_group->api_state();
710 ASSERT(state != NULL);
711
712 ASSERT(handle->auto_delete());
713
714 if (handle->callback_signature_ == CallbackSignature::kHandleFinalizer) {
715 Dart_HandleFinalizer callback = handle->callback();
716 ASSERT(callback != NULL);
717 (*callback)(isolate_group->embedder_data(), peer);
718 } else {
719 Dart_WeakPersistentHandleFinalizer callback =
720 handle->CallbackWeakFinalizer();
721 ASSERT(callback != NULL);
722 Dart_WeakPersistentHandle object = handle->ApiWeakPersistentHandle();
723 (*callback)(isolate_group->embedder_data(), object, peer);
724 }
725
726 state->FreeWeakPersistentHandle(handle);
727}
728
729// --- Handles ---
730
731DART_EXPORT bool Dart_IsError(Dart_Handle handle) {
732 Thread* thread = Thread::Current();
733 TransitionNativeToVM transition(thread);
734 return Api::IsError(handle);
735}
736
737DART_EXPORT void Dart_KillIsolate(Dart_Isolate handle) {
738 Isolate* isolate = reinterpret_cast<Isolate*>(handle);
739 CHECK_ISOLATE(isolate);
740 Isolate::KillIfExists(isolate, Isolate::kKillMsg);
741}
742
743DART_EXPORT bool Dart_IsApiError(Dart_Handle object) {
744 Thread* thread = Thread::Current();
745 TransitionNativeToVM transition(thread);
746 return Api::ClassId(object) == kApiErrorCid;
747}
748
749DART_EXPORT bool Dart_IsUnhandledExceptionError(Dart_Handle object) {
750 Thread* thread = Thread::Current();
751 TransitionNativeToVM transition(thread);
752 return Api::ClassId(object) == kUnhandledExceptionCid;
753}
754
755DART_EXPORT bool Dart_IsCompilationError(Dart_Handle object) {
756 if (::Dart_IsUnhandledExceptionError(object)) {
757 DARTSCOPE(Thread::Current());
758 const UnhandledException& error =
759 UnhandledException::Cast(Object::Handle(Z, Api::UnwrapHandle(object)));
760 const Instance& exc = Instance::Handle(Z, error.exception());
761 return IsCompiletimeErrorObject(Z, exc);
762 }
763
764 Thread* thread = Thread::Current();
765 TransitionNativeToVM transition(thread);
766 return Api::ClassId(object) == kLanguageErrorCid;
767}
768
769DART_EXPORT bool Dart_IsFatalError(Dart_Handle object) {
770 Thread* thread = Thread::Current();
771 TransitionNativeToVM transition(thread);
772 return Api::ClassId(object) == kUnwindErrorCid;
773}
774
775DART_EXPORT const char* Dart_GetError(Dart_Handle handle) {
776 DARTSCOPE(Thread::Current());
777 API_TIMELINE_DURATION(T);
778 const Object& obj = Object::Handle(Z, Api::UnwrapHandle(handle));
779 return GetErrorString(T, obj);
780}
781
782DART_EXPORT bool Dart_ErrorHasException(Dart_Handle handle) {
783 DARTSCOPE(Thread::Current());
784 const Object& obj = Object::Handle(Z, Api::UnwrapHandle(handle));
785 return obj.IsUnhandledException();
786}
787
788DART_EXPORT Dart_Handle Dart_ErrorGetException(Dart_Handle handle) {
789 DARTSCOPE(Thread::Current());
790 const Object& obj = Object::Handle(Z, Api::UnwrapHandle(handle));
791 if (obj.IsUnhandledException()) {
792 const UnhandledException& error = UnhandledException::Cast(obj);
793 return Api::NewHandle(T, error.exception());
794 } else if (obj.IsError()) {
795 return Api::NewError("This error is not an unhandled exception error.");
796 } else {
797 return Api::NewError("Can only get exceptions from error handles.");
798 }
799}
800
801DART_EXPORT Dart_Handle Dart_ErrorGetStackTrace(Dart_Handle handle) {
802 DARTSCOPE(Thread::Current());
803 const Object& obj = Object::Handle(Z, Api::UnwrapHandle(handle));
804 if (obj.IsUnhandledException()) {
805 const UnhandledException& error = UnhandledException::Cast(obj);
806 return Api::NewHandle(T, error.stacktrace());
807 } else if (obj.IsError()) {
808 return Api::NewError("This error is not an unhandled exception error.");
809 } else {
810 return Api::NewError("Can only get stacktraces from error handles.");
811 }
812}
813
814DART_EXPORT Dart_Handle Dart_NewApiError(const char* error) {
815 DARTSCOPE(Thread::Current());
816 CHECK_CALLBACK_STATE(T);
817
818 const String& message = String::Handle(Z, String::New(error));
819 return Api::NewHandle(T, ApiError::New(message));
820}
821
822DART_EXPORT Dart_Handle Dart_NewCompilationError(const char* error) {
823 DARTSCOPE(Thread::Current());
824 CHECK_CALLBACK_STATE(T);
825
826 const String& message = String::Handle(Z, String::New(error));
827 return Api::NewHandle(T, LanguageError::New(message));
828}
829
830DART_EXPORT Dart_Handle Dart_NewUnhandledExceptionError(Dart_Handle exception) {
831 DARTSCOPE(Thread::Current());
832 CHECK_CALLBACK_STATE(T);
833
834 Instance& obj = Instance::Handle(Z);
835 intptr_t class_id = Api::ClassId(exception);
836 if ((class_id == kApiErrorCid) || (class_id == kLanguageErrorCid)) {
837 const Object& excp = Object::Handle(Z, Api::UnwrapHandle(exception));
838 obj = String::New(GetErrorString(T, excp));
839 } else {
840 obj = Api::UnwrapInstanceHandle(Z, exception).raw();
841 if (obj.IsNull()) {
842 RETURN_TYPE_ERROR(Z, exception, Instance);
843 }
844 }
845 const StackTrace& stacktrace = StackTrace::Handle(Z);
846 return Api::NewHandle(T, UnhandledException::New(obj, stacktrace));
847}
848
849DART_EXPORT void Dart_PropagateError(Dart_Handle handle) {
850 Thread* thread = Thread::Current();
851 CHECK_ISOLATE(thread->isolate());
852 TransitionNativeToVM transition(thread);
853 const Object& obj = Object::Handle(thread->zone(), Api::UnwrapHandle(handle));
854 if (!obj.IsError()) {
855 FATAL1(
856 "%s expects argument 'handle' to be an error handle. "
857 "Did you forget to check Dart_IsError first?",
858 CURRENT_FUNC);
859 }
860 if (thread->top_exit_frame_info() == 0) {
861 // There are no dart frames on the stack so it would be illegal to
862 // propagate an error here.
863 FATAL("No Dart frames on stack, cannot propagate error.");
864 }
865 // Unwind all the API scopes till the exit frame before propagating.
866 const Error* error;
867 {
868 // We need to preserve the error object across the destruction of zones
869 // when the ApiScopes are unwound. By using NoSafepointScope, we can ensure
870 // that GC won't touch the raw error object before creating a valid
871 // handle for it in the surviving zone.
872 NoSafepointScope no_safepoint;
873 ErrorPtr raw_error = Api::UnwrapErrorHandle(thread->zone(), handle).raw();
874 thread->UnwindScopes(thread->top_exit_frame_info());
875 // Note that thread's zone is different here than at the beginning of this
876 // function.
877 error = &Error::Handle(thread->zone(), raw_error);
878 }
879 Exceptions::PropagateError(*error);
880 UNREACHABLE();
881}
882
883DART_EXPORT Dart_Handle Dart_ToString(Dart_Handle object) {
884 DARTSCOPE(Thread::Current());
885 const Object& obj = Object::Handle(Z, Api::UnwrapHandle(object));
886 if (obj.IsString()) {
887 return Api::NewHandle(T, obj.raw());
888 } else if (obj.IsInstance()) {
889 CHECK_CALLBACK_STATE(T);
890 const Instance& receiver = Instance::Cast(obj);
891 return Api::NewHandle(T, DartLibraryCalls::ToString(receiver));
892 } else {
893 CHECK_CALLBACK_STATE(T);
894 // This is a VM internal object. Call the C++ method of printing.
895 return Api::NewHandle(T, String::New(obj.ToCString()));
896 }
897}
898
899DART_EXPORT bool Dart_IdentityEquals(Dart_Handle obj1, Dart_Handle obj2) {
900 DARTSCOPE(Thread::Current());
901 {
902 NoSafepointScope no_safepoint_scope;
903 if (Api::UnwrapHandle(obj1) == Api::UnwrapHandle(obj2)) {
904 return true;
905 }
906 }
907 const Object& object1 = Object::Handle(Z, Api::UnwrapHandle(obj1));
908 const Object& object2 = Object::Handle(Z, Api::UnwrapHandle(obj2));
909 if (object1.IsInstance() && object2.IsInstance()) {
910 return Instance::Cast(object1).IsIdenticalTo(Instance::Cast(object2));
911 }
912 return false;
913}
914
915DART_EXPORT Dart_Handle
916Dart_HandleFromPersistent(Dart_PersistentHandle object) {
917 Thread* thread = Thread::Current();
918 Isolate* isolate = thread->isolate();
919 CHECK_ISOLATE(isolate);
920 ApiState* state = isolate->group()->api_state();
921 ASSERT(state != NULL);
922 TransitionNativeToVM transition(thread);
923 NoSafepointScope no_safepoint_scope;
924 PersistentHandle* ref = PersistentHandle::Cast(object);
925 return Api::NewHandle(thread, ref->raw());
926}
927
928DART_EXPORT Dart_Handle
929Dart_HandleFromWeakPersistent(Dart_WeakPersistentHandle object) {
930 Thread* thread = Thread::Current();
931 Isolate* isolate = thread->isolate();
932 CHECK_ISOLATE(isolate);
933 ApiState* state = isolate->group()->api_state();
934 ASSERT(state != NULL);
935 TransitionNativeToVM transition(thread);
936 NoSafepointScope no_safepoint_scope;
937 FinalizablePersistentHandle* weak_ref =
938 FinalizablePersistentHandle::Cast(object);
939 return Api::NewHandle(thread, weak_ref->raw());
940}
941
942static Dart_Handle HandleFromFinalizable(Dart_FinalizableHandle object) {
943 Thread* thread = Thread::Current();
944 Isolate* isolate = thread->isolate();
945 CHECK_ISOLATE(isolate);
946 ApiState* state = isolate->group()->api_state();
947 ASSERT(state != NULL);
948 TransitionNativeToVM transition(thread);
949 NoSafepointScope no_safepoint_scope;
950 FinalizablePersistentHandle* weak_ref =
951 FinalizablePersistentHandle::Cast(object);
952 return Api::NewHandle(thread, weak_ref->raw());
953}
954
955DART_EXPORT Dart_PersistentHandle Dart_NewPersistentHandle(Dart_Handle object) {
956 DARTSCOPE(Thread::Current());
957 Isolate* I = T->isolate();
958 ApiState* state = I->group()->api_state();
959 ASSERT(state != NULL);
960 const Object& old_ref = Object::Handle(Z, Api::UnwrapHandle(object));
961 PersistentHandle* new_ref = state->AllocatePersistentHandle();
962 new_ref->set_raw(old_ref);
963 return new_ref->apiHandle();
964}
965
966DART_EXPORT void Dart_SetPersistentHandle(Dart_PersistentHandle obj1,
967 Dart_Handle obj2) {
968 DARTSCOPE(Thread::Current());
969 Isolate* I = T->isolate();
970 ApiState* state = I->group()->api_state();
971 ASSERT(state != NULL);
972 ASSERT(state->IsValidPersistentHandle(obj1));
973 const Object& obj2_ref = Object::Handle(Z, Api::UnwrapHandle(obj2));
974 PersistentHandle* obj1_ref = PersistentHandle::Cast(obj1);
975 obj1_ref->set_raw(obj2_ref);
976}
977
978static Dart_WeakPersistentHandle AllocateWeakPersistentHandle(
979 Thread* thread,
980 const Object& ref,
981 void* peer,
982 intptr_t external_allocation_size,
983 Dart_WeakPersistentHandleFinalizer callback) {
984 if (!ref.raw()->IsHeapObject()) {
985 return NULL;
986 }
987 FinalizablePersistentHandle* finalizable_ref =
988 FinalizablePersistentHandle::New(thread->isolate(), ref, peer, callback,
989 external_allocation_size,
990 /*auto_delete=*/true);
991 return finalizable_ref->ApiWeakPersistentHandle();
992}
993
994static Dart_WeakPersistentHandle AllocateWeakPersistentHandle(
995 Thread* thread,
996 Dart_Handle object,
997 void* peer,
998 intptr_t external_allocation_size,
999 Dart_WeakPersistentHandleFinalizer callback) {
1000 REUSABLE_OBJECT_HANDLESCOPE(thread);
1001 Object& ref = thread->ObjectHandle();
1002 ref = Api::UnwrapHandle(object);
1003 return AllocateWeakPersistentHandle(thread, ref, peer,
1004 external_allocation_size, callback);
1005}
1006
1007static Dart_FinalizableHandle AllocateFinalizableHandle(
1008 Thread* thread,
1009 const Object& ref,
1010 void* peer,
1011 intptr_t external_allocation_size,
1012 Dart_HandleFinalizer callback) {
1013 if (!ref.raw()->IsHeapObject()) {
1014 return NULL;
1015 }
1016
1017 FinalizablePersistentHandle* finalizable_ref =
1018 FinalizablePersistentHandle::New(thread->isolate(), ref, peer, callback,
1019 external_allocation_size,
1020 /*auto_delete=*/true);
1021 return finalizable_ref->ApiFinalizableHandle();
1022}
1023
1024static Dart_FinalizableHandle AllocateFinalizableHandle(
1025 Thread* thread,
1026 Dart_Handle object,
1027 void* peer,
1028 intptr_t external_allocation_size,
1029 Dart_HandleFinalizer callback) {
1030 REUSABLE_OBJECT_HANDLESCOPE(thread);
1031 Object& ref = thread->ObjectHandle();
1032 ref = Api::UnwrapHandle(object);
1033 return AllocateFinalizableHandle(thread, ref, peer, external_allocation_size,
1034 callback);
1035}
1036
1037DART_EXPORT Dart_WeakPersistentHandle
1038Dart_NewWeakPersistentHandle(Dart_Handle object,
1039 void* peer,
1040 intptr_t external_allocation_size,
1041 Dart_WeakPersistentHandleFinalizer callback) {
1042 Thread* thread = Thread::Current();
1043 CHECK_ISOLATE(thread->isolate());
1044 if (callback == NULL) {
1045 return NULL;
1046 }
1047 TransitionNativeToVM transition(thread);
1048
1049 return AllocateWeakPersistentHandle(thread, object, peer,
1050 external_allocation_size, callback);
1051}
1052
1053DART_EXPORT Dart_FinalizableHandle
1054Dart_NewFinalizableHandle(Dart_Handle object,
1055 void* peer,
1056 intptr_t external_allocation_size,
1057 Dart_HandleFinalizer callback) {
1058 Thread* thread = Thread::Current();
1059 CHECK_ISOLATE(thread->isolate());
1060 if (callback == nullptr) {
1061 return nullptr;
1062 }
1063 TransitionNativeToVM transition(thread);
1064 return AllocateFinalizableHandle(thread, object, peer,
1065 external_allocation_size, callback);
1066}
1067
1068DART_EXPORT void Dart_UpdateExternalSize(Dart_WeakPersistentHandle object,
1069 intptr_t external_size) {
1070 IsolateGroup* isolate_group = IsolateGroup::Current();
1071 CHECK_ISOLATE_GROUP(isolate_group);
1072 NoSafepointScope no_safepoint_scope;
1073 ApiState* state = isolate_group->api_state();
1074 ASSERT(state != NULL);
1075 ASSERT(state->IsActiveWeakPersistentHandle(object));
1076 auto weak_ref = FinalizablePersistentHandle::Cast(object);
1077 weak_ref->UpdateExternalSize(external_size, isolate_group);
1078}
1079
1080DART_EXPORT void Dart_UpdateFinalizableExternalSize(
1081 Dart_FinalizableHandle object,
1082 Dart_Handle strong_ref_to_object,
1083 intptr_t external_allocation_size) {
1084 if (!::Dart_IdentityEquals(strong_ref_to_object,
1085 HandleFromFinalizable(object))) {
1086 FATAL1(
1087 "%s expects arguments 'object' and 'strong_ref_to_object' to point to "
1088 "the same object.",
1089 CURRENT_FUNC);
1090 }
1091 auto wph_object = reinterpret_cast<Dart_WeakPersistentHandle>(object);
1092 ::Dart_UpdateExternalSize(wph_object, external_allocation_size);
1093}
1094
1095DART_EXPORT void Dart_DeletePersistentHandle(Dart_PersistentHandle object) {
1096 IsolateGroup* isolate_group = IsolateGroup::Current();
1097 CHECK_ISOLATE_GROUP(isolate_group);
1098 NoSafepointScope no_safepoint_scope;
1099 ApiState* state = isolate_group->api_state();
1100 ASSERT(state != NULL);
1101 ASSERT(state->IsActivePersistentHandle(object));
1102 PersistentHandle* ref = PersistentHandle::Cast(object);
1103 ASSERT(!state->IsProtectedHandle(ref));
1104 if (!state->IsProtectedHandle(ref)) {
1105 state->FreePersistentHandle(ref);
1106 }
1107}
1108
1109DART_EXPORT void Dart_DeleteWeakPersistentHandle(
1110 Dart_WeakPersistentHandle object) {
1111 IsolateGroup* isolate_group = IsolateGroup::Current();
1112 CHECK_ISOLATE_GROUP(isolate_group);
1113 NoSafepointScope no_safepoint_scope;
1114 ApiState* state = isolate_group->api_state();
1115 ASSERT(state != NULL);
1116 ASSERT(state->IsActiveWeakPersistentHandle(object));
1117 auto weak_ref = FinalizablePersistentHandle::Cast(object);
1118 weak_ref->EnsureFreedExternal(isolate_group);
1119 state->FreeWeakPersistentHandle(weak_ref);
1120}
1121
1122DART_EXPORT void Dart_DeleteFinalizableHandle(
1123 Dart_FinalizableHandle object,
1124 Dart_Handle strong_ref_to_object) {
1125 if (!::Dart_IdentityEquals(strong_ref_to_object,
1126 HandleFromFinalizable(object))) {
1127 FATAL1(
1128 "%s expects arguments 'object' and 'strong_ref_to_object' to point to "
1129 "the same object.",
1130 CURRENT_FUNC);
1131 }
1132
1133 auto wph_object = reinterpret_cast<Dart_WeakPersistentHandle>(object);
1134
1135 ::Dart_DeleteWeakPersistentHandle(wph_object);
1136}
1137
1138// --- Initialization and Globals ---
1139
1140DART_EXPORT const char* Dart_VersionString() {
1141 return Version::String();
1142}
1143
1144DART_EXPORT char* Dart_Initialize(Dart_InitializeParams* params) {
1145 if (params == NULL) {
1146 return Utils::StrDup(
1147 "Dart_Initialize: "
1148 "Dart_InitializeParams is null.");
1149 }
1150
1151 if (params->version != DART_INITIALIZE_PARAMS_CURRENT_VERSION) {
1152 return Utils::StrDup(
1153 "Dart_Initialize: "
1154 "Invalid Dart_InitializeParams version.");
1155 }
1156
1157 return Dart::Init(params->vm_snapshot_data, params->vm_snapshot_instructions,
1158 params->create_group, params->initialize_isolate,
1159 params->shutdown_isolate, params->cleanup_isolate,
1160 params->cleanup_group, params->thread_exit,
1161 params->file_open, params->file_read, params->file_write,
1162 params->file_close, params->entropy_source,
1163 params->get_service_assets, params->start_kernel_isolate,
1164 params->code_observer);
1165}
1166
1167DART_EXPORT char* Dart_Cleanup() {
1168 CHECK_NO_ISOLATE(Isolate::Current());
1169 return Dart::Cleanup();
1170}
1171
1172DART_EXPORT char* Dart_SetVMFlags(int argc, const char** argv) {
1173 return Flags::ProcessCommandLineFlags(argc, argv);
1174}
1175
1176DART_EXPORT bool Dart_IsVMFlagSet(const char* flag_name) {
1177 return Flags::IsSet(flag_name);
1178}
1179
1180#if !defined(PRODUCT)
1181#define VM_METRIC_API(type, variable, name, unit) \
1182 DART_EXPORT int64_t Dart_VM##variable##Metric() { \
1183 return vm_metric_##variable.Value(); \
1184 }
1185VM_METRIC_LIST(VM_METRIC_API);
1186#undef VM_METRIC_API
1187#else // !defined(PRODUCT)
1188#define VM_METRIC_API(type, variable, name, unit) \
1189 DART_EXPORT int64_t Dart_VM##variable##Metric() { return -1; }
1190VM_METRIC_LIST(VM_METRIC_API)
1191#undef VM_METRIC_API
1192#endif // !defined(PRODUCT)
1193
1194#define ISOLATE_GROUP_METRIC_API(type, variable, name, unit) \
1195 DART_EXPORT int64_t Dart_Isolate##variable##Metric(Dart_Isolate isolate) { \
1196 if (isolate == nullptr) { \
1197 FATAL1("%s expects argument 'isolate' to be non-null.", CURRENT_FUNC); \
1198 } \
1199 Isolate* iso = reinterpret_cast<Isolate*>(isolate); \
1200 return iso->group()->Get##variable##Metric()->Value(); \
1201 }
1202ISOLATE_GROUP_METRIC_LIST(ISOLATE_GROUP_METRIC_API)
1203#undef ISOLATE_GROUP_METRIC_API
1204
1205#if !defined(PRODUCT)
1206#define ISOLATE_METRIC_API(type, variable, name, unit) \
1207 DART_EXPORT int64_t Dart_Isolate##variable##Metric(Dart_Isolate isolate) { \
1208 if (isolate == NULL) { \
1209 FATAL1("%s expects argument 'isolate' to be non-null.", CURRENT_FUNC); \
1210 } \
1211 Isolate* iso = reinterpret_cast<Isolate*>(isolate); \
1212 return iso->Get##variable##Metric()->Value(); \
1213 }
1214ISOLATE_METRIC_LIST(ISOLATE_METRIC_API)
1215#undef ISOLATE_METRIC_API
1216#else // !defined(PRODUCT)
1217#define ISOLATE_METRIC_API(type, variable, name, unit) \
1218 DART_EXPORT int64_t Dart_Isolate##variable##Metric(Dart_Isolate isolate) { \
1219 return -1; \
1220 }
1221ISOLATE_METRIC_LIST(ISOLATE_METRIC_API)
1222#undef ISOLATE_METRIC_API
1223#endif // !defined(PRODUCT)
1224
1225// --- Isolates ---
1226
1227static Dart_Isolate CreateIsolate(IsolateGroup* group,
1228 bool is_new_group,
1229 const char* name,
1230 void* isolate_data,
1231 char** error) {
1232 CHECK_NO_ISOLATE(Isolate::Current());
1233
1234 auto source = group->source();
1235 Isolate* I = Dart::CreateIsolate(name, source->flags, group);
1236 if (I == NULL) {
1237 if (error != NULL) {
1238 *error = Utils::StrDup("Isolate creation failed");
1239 }
1240 return reinterpret_cast<Dart_Isolate>(NULL);
1241 }
1242
1243 Thread* T = Thread::Current();
1244 bool success = false;
1245 {
1246 StackZone zone(T);
1247 HANDLESCOPE(T);
1248 // We enter an API scope here as InitializeIsolate could compile some
1249 // bootstrap library files which call out to a tag handler that may create
1250 // Api Handles when an error is encountered.
1251 T->EnterApiScope();
1252 const Error& error_obj = Error::Handle(
1253 Z, Dart::InitializeIsolate(
1254 source->snapshot_data, source->snapshot_instructions,
1255 source->kernel_buffer, source->kernel_buffer_size,
1256 is_new_group ? nullptr : group, isolate_data));
1257 if (error_obj.IsNull()) {
1258#if defined(DEBUG) && !defined(DART_PRECOMPILED_RUNTIME)
1259 if (FLAG_check_function_fingerprints && !FLAG_precompiled_mode) {
1260 Library::CheckFunctionFingerprints();
1261 }
1262#endif // defined(DEBUG) && !defined(DART_PRECOMPILED_RUNTIME).
1263 success = true;
1264 } else if (error != NULL) {
1265 *error = Utils::StrDup(error_obj.ToErrorCString());
1266 }
1267 // We exit the API scope entered above.
1268 T->ExitApiScope();
1269 }
1270
1271 if (success) {
1272 if (is_new_group) {
1273 I->heap()->InitGrowthControl();
1274 }
1275 // A Thread structure has been associated to the thread, we do the
1276 // safepoint transition explicitly here instead of using the
1277 // TransitionXXX scope objects as the reverse transition happens
1278 // outside this scope in Dart_ShutdownIsolate/Dart_ExitIsolate.
1279 T->set_execution_state(Thread::kThreadInNative);
1280 T->EnterSafepoint();
1281 if (error != NULL) {
1282 *error = NULL;
1283 }
1284 return Api::CastIsolate(I);
1285 }
1286
1287 Dart::ShutdownIsolate();
1288 return reinterpret_cast<Dart_Isolate>(NULL);
1289}
1290
1291static bool IsServiceOrKernelIsolateName(const char* name) {
1292 if (ServiceIsolate::NameEquals(name)) {
1293 ASSERT(!ServiceIsolate::Exists());
1294 return true;
1295 }
1296#if !defined(DART_PRECOMPILED_RUNTIME)
1297 if (KernelIsolate::NameEquals(name)) {
1298 ASSERT(!KernelIsolate::Exists());
1299 return true;
1300 }
1301#endif // !defined(DART_PRECOMPILED_RUNTIME)
1302 return false;
1303}
1304
1305Isolate* CreateWithinExistingIsolateGroupAOT(IsolateGroup* group,
1306 const char* name,
1307 char** error) {
1308#if defined(DART_PRECOMPILED_RUNTIME)
1309 API_TIMELINE_DURATION(Thread::Current());
1310 CHECK_NO_ISOLATE(Isolate::Current());
1311
1312 auto spawning_group = group;
1313
1314 Isolate* isolate = reinterpret_cast<Isolate*>(
1315 CreateIsolate(spawning_group, /*is_new_group=*/false, name,
1316 /*isolate_data=*/nullptr, error));
1317 if (isolate == nullptr) return nullptr;
1318
1319 auto source = spawning_group->source();
1320 ASSERT(isolate->source() == source);
1321
1322 return isolate;
1323#else
1324 UNREACHABLE();
1325#endif
1326}
1327
1328Isolate* CreateWithinExistingIsolateGroup(IsolateGroup* group,
1329 const char* name,
1330 char** error) {
1331#if !defined(DART_PRECOMPILED_RUNTIME)
1332 API_TIMELINE_DURATION(Thread::Current());
1333 CHECK_NO_ISOLATE(Isolate::Current());
1334
1335 // During isolate start we'll make a temporary anonymous group from the same
1336 // [source]. Once the isolate has been fully loaded we will merge it's heap
1337 // into the shared heap.
1338 auto spawning_group = new IsolateGroup(group->shareable_source(),
1339 /*isolate_group_data=*/nullptr);
1340 IsolateGroup::RegisterIsolateGroup(spawning_group);
1341 spawning_group->CreateHeap(
1342 /*is_vm_isolate=*/false,
1343 IsServiceOrKernelIsolateName(group->source()->name));
1344
1345 Isolate* isolate = reinterpret_cast<Isolate*>(
1346 CreateIsolate(spawning_group, /*is_new_group=*/false, name,
1347 /*isolate_data=*/nullptr, error));
1348 if (isolate == nullptr) return nullptr;
1349
1350 auto source = spawning_group->source();
1351 ASSERT(isolate->source() == source);
1352
1353 if (source->script_kernel_buffer != nullptr) {
1354 Dart_EnterScope();
1355 {
1356 Thread* T = Thread::Current();
1357 TransitionNativeToVM transition(T);
1358 HANDLESCOPE(T);
1359 StackZone zone(T);
1360
1361 // NOTE: We do not attach a finalizer for this object, because the
1362 // embedder will free it once the isolate group has shutdown.
1363 const auto& td = ExternalTypedData::Handle(ExternalTypedData::New(
1364 kExternalTypedDataUint8ArrayCid,
1365 const_cast<uint8_t*>(source->script_kernel_buffer),
1366 source->script_kernel_size, Heap::kOld));
1367
1368 std::unique_ptr<kernel::Program> program =
1369 kernel::Program::ReadFromTypedData(td,
1370 const_cast<const char**>(error));
1371 if (program == nullptr) {
1372 UNIMPLEMENTED();
1373 }
1374 const Object& tmp =
1375 kernel::KernelLoader::LoadEntireProgram(program.get());
1376
1377 // If the existing isolate could spawn with a root library we should be
1378 // able to do the same
1379 RELEASE_ASSERT(!tmp.IsNull() && tmp.IsLibrary());
1380 isolate->object_store()->set_root_library(Library::Cast(tmp));
1381 }
1382 Dart_ExitScope();
1383 }
1384
1385 // If we are running in AppJIT training mode we'll have to remap class ids.
1386 if (auto permutation_map = group->source()->cid_permutation_map.get()) {
1387 Dart_EnterScope();
1388 {
1389 auto T = Thread::Current();
1390 TransitionNativeToVM transition(T);
1391 HANDLESCOPE(T);
1392
1393 // Remap all class ids loaded atm (e.g. from snapshot) and do appropriate
1394 // re-hashing of constants and types.
1395 ClassFinalizer::RemapClassIds(permutation_map);
1396 // Types use cid's as part of their hashes.
1397 ClassFinalizer::RehashTypes();
1398 // Const objects use cid's as part of their hashes.
1399 isolate->RehashConstants();
1400 }
1401 Dart_ExitScope();
1402 }
1403
1404 auto thread = Thread::Current();
1405 {
1406 TransitionNativeToVM native_to_vm(thread);
1407
1408 // Ensure there are no helper threads running.
1409 BackgroundCompiler::Stop(isolate);
1410 isolate->heap()->WaitForMarkerTasks(thread);
1411 isolate->heap()->WaitForSweeperTasks(thread);
1412 RELEASE_ASSERT(isolate->heap()->old_space()->tasks() == 0);
1413 }
1414
1415 Dart_ExitIsolate();
1416 {
1417 const bool kBypassSafepoint = false;
1418 Thread::EnterIsolateGroupAsHelper(group, Thread::kUnknownTask,
1419 kBypassSafepoint);
1420 ASSERT(group == IsolateGroup::Current());
1421
1422 {
1423 auto thread = Thread::Current();
1424
1425 // Prevent additions of new isolates to [group] until we're done.
1426 group->RunWithLockedGroup([&]() {
1427 // Ensure no other old space GC tasks are running and "occupy" the old
1428 // space.
1429 {
1430 auto old_space = group->heap()->old_space();
1431 MonitorLocker ml(old_space->tasks_lock());
1432 while (old_space->tasks() > 0) {
1433 ml.WaitWithSafepointCheck(thread);
1434 }
1435 old_space->set_tasks(1);
1436 }
1437
1438 // Merge the heap from [spawning_group] to [group].
1439 {
1440 SafepointOperationScope safepoint_scope(thread);
1441 group->heap()->MergeFrom(isolate->group()->heap());
1442 }
1443
1444 spawning_group->UnregisterIsolate(isolate);
1445 const bool shutdown_group =
1446 spawning_group->UnregisterIsolateDecrementCount(isolate);
1447 ASSERT(shutdown_group);
1448
1449 isolate->isolate_group_ = group;
1450 group->RegisterIsolateLocked(isolate);
1451 isolate->class_table()->shared_class_table_ =
1452 group->shared_class_table();
1453 isolate->set_shared_class_table(group->shared_class_table());
1454
1455 // Even though the mutator thread was descheduled, it will still
1456 // retain its [Thread] structure with valid isolate/isolate_group
1457 // pointers.
1458 // If GC happens before the mutator gets scheduled again, we have to
1459 // ensure the isolate group change is reflected in the threads
1460 // structure.
1461 ASSERT(isolate->mutator_thread() != nullptr);
1462 ASSERT(isolate->mutator_thread()->isolate_group() == spawning_group);
1463 isolate->mutator_thread()->isolate_group_ = group;
1464
1465 // Allow other old space GC tasks to run again.
1466 {
1467 auto old_space = group->heap()->old_space();
1468 MonitorLocker ml(old_space->tasks_lock());
1469 ASSERT(old_space->tasks() == 1);
1470 old_space->set_tasks(0);
1471 ml.NotifyAll();
1472 }
1473 });
1474 }
1475
1476 Thread::ExitIsolateGroupAsHelper(kBypassSafepoint);
1477 }
1478
1479 spawning_group->Shutdown();
1480
1481 Dart_EnterIsolate(Api::CastIsolate(isolate));
1482 ASSERT(Thread::Current()->isolate_group() == isolate->group());
1483
1484 return isolate;
1485#else
1486 UNREACHABLE();
1487#endif
1488}
1489
1490DART_EXPORT void Dart_IsolateFlagsInitialize(Dart_IsolateFlags* flags) {
1491 Isolate::FlagsInitialize(flags);
1492}
1493
1494DART_EXPORT Dart_Isolate
1495Dart_CreateIsolateGroup(const char* script_uri,
1496 const char* name,
1497 const uint8_t* snapshot_data,
1498 const uint8_t* snapshot_instructions,
1499 Dart_IsolateFlags* flags,
1500 void* isolate_group_data,
1501 void* isolate_data,
1502 char** error) {
1503 API_TIMELINE_DURATION(Thread::Current());
1504
1505 Dart_IsolateFlags api_flags;
1506 if (flags == nullptr) {
1507 Isolate::FlagsInitialize(&api_flags);
1508 flags = &api_flags;
1509 }
1510
1511 const char* non_null_name = name == nullptr ? "isolate" : name;
1512 std::unique_ptr<IsolateGroupSource> source(
1513 new IsolateGroupSource(script_uri, non_null_name, snapshot_data,
1514 snapshot_instructions, nullptr, -1, *flags));
1515 auto group = new IsolateGroup(std::move(source), isolate_group_data);
1516 group->CreateHeap(
1517 /*is_vm_isolate=*/false, IsServiceOrKernelIsolateName(non_null_name));
1518 IsolateGroup::RegisterIsolateGroup(group);
1519 Dart_Isolate isolate = CreateIsolate(group, /*is_new_group=*/true,
1520 non_null_name, isolate_data, error);
1521 if (isolate != nullptr) {
1522 group->set_initial_spawn_successful();
1523 }
1524 return isolate;
1525}
1526
1527DART_EXPORT Dart_Isolate
1528Dart_CreateIsolateGroupFromKernel(const char* script_uri,
1529 const char* name,
1530 const uint8_t* kernel_buffer,
1531 intptr_t kernel_buffer_size,
1532 Dart_IsolateFlags* flags,
1533 void* isolate_group_data,
1534 void* isolate_data,
1535 char** error) {
1536 API_TIMELINE_DURATION(Thread::Current());
1537
1538 Dart_IsolateFlags api_flags;
1539 if (flags == nullptr) {
1540 Isolate::FlagsInitialize(&api_flags);
1541 flags = &api_flags;
1542 }
1543
1544 const char* non_null_name = name == nullptr ? "isolate" : name;
1545 std::shared_ptr<IsolateGroupSource> source(
1546 new IsolateGroupSource(script_uri, non_null_name, nullptr, nullptr,
1547 kernel_buffer, kernel_buffer_size, *flags));
1548 auto group = new IsolateGroup(source, isolate_group_data);
1549 IsolateGroup::RegisterIsolateGroup(group);
1550 group->CreateHeap(
1551 /*is_vm_isolate=*/false, IsServiceOrKernelIsolateName(non_null_name));
1552 Dart_Isolate isolate = CreateIsolate(group, /*is_new_group=*/true,
1553 non_null_name, isolate_data, error);
1554 if (isolate != nullptr) {
1555 group->set_initial_spawn_successful();
1556 }
1557 return isolate;
1558}
1559
1560DART_EXPORT void Dart_ShutdownIsolate() {
1561 Thread* T = Thread::Current();
1562 Isolate* I = T->isolate();
1563 CHECK_ISOLATE(I);
1564
1565 // The Thread structure is disassociated from the isolate, we do the
1566 // safepoint transition explicitly here instead of using the TransitionXXX
1567 // scope objects as the original transition happened outside this scope in
1568 // Dart_EnterIsolate/Dart_CreateIsolateGroup.
1569 ASSERT(T->execution_state() == Thread::kThreadInNative);
1570 T->ExitSafepoint();
1571 T->set_execution_state(Thread::kThreadInVM);
1572
1573 I->WaitForOutstandingSpawns();
1574
1575 // Release any remaining API scopes.
1576 ApiLocalScope* scope = T->api_top_scope();
1577 while (scope != NULL) {
1578 ApiLocalScope* previous = scope->previous();
1579 delete scope;
1580 scope = previous;
1581 }
1582 T->set_api_top_scope(NULL);
1583
1584 {
1585 StackZone zone(T);
1586 HandleScope handle_scope(T);
1587 Dart::RunShutdownCallback();
1588 }
1589 Dart::ShutdownIsolate();
1590}
1591
1592DART_EXPORT Dart_Isolate Dart_CurrentIsolate() {
1593 return Api::CastIsolate(Isolate::Current());
1594}
1595
1596DART_EXPORT void* Dart_CurrentIsolateData() {
1597 Isolate* isolate = Isolate::Current();
1598 CHECK_ISOLATE(isolate);
1599 NoSafepointScope no_safepoint_scope;
1600 return isolate->init_callback_data();
1601}
1602
1603DART_EXPORT void* Dart_IsolateData(Dart_Isolate isolate) {
1604 if (isolate == NULL) {
1605 FATAL1("%s expects argument 'isolate' to be non-null.", CURRENT_FUNC);
1606 }
1607 // TODO(http://dartbug.com/16615): Validate isolate parameter.
1608 return reinterpret_cast<Isolate*>(isolate)->init_callback_data();
1609}
1610
1611DART_EXPORT Dart_IsolateGroup Dart_CurrentIsolateGroup() {
1612 return Api::CastIsolateGroup(IsolateGroup::Current());
1613}
1614
1615DART_EXPORT void* Dart_CurrentIsolateGroupData() {
1616 IsolateGroup* isolate_group = IsolateGroup::Current();
1617 CHECK_ISOLATE_GROUP(isolate_group);
1618 NoSafepointScope no_safepoint_scope;
1619 return isolate_group->embedder_data();
1620}
1621
1622DART_EXPORT void* Dart_IsolateGroupData(Dart_Isolate isolate) {
1623 if (isolate == NULL) {
1624 FATAL1("%s expects argument 'isolate' to be non-null.", CURRENT_FUNC);
1625 }
1626 // TODO(http://dartbug.com/16615): Validate isolate parameter.
1627 return reinterpret_cast<Isolate*>(isolate)->group()->embedder_data();
1628}
1629
1630DART_EXPORT Dart_Handle Dart_DebugName() {
1631 DARTSCOPE(Thread::Current());
1632 Isolate* I = T->isolate();
1633 return Api::NewHandle(
1634 T, String::NewFormatted("(%" Pd64 ") '%s'",
1635 static_cast<int64_t>(I->main_port()), I->name()));
1636}
1637
1638DART_EXPORT const char* Dart_IsolateServiceId(Dart_Isolate isolate) {
1639 if (isolate == NULL) {
1640 FATAL1("%s expects argument 'isolate' to be non-null.", CURRENT_FUNC);
1641 }
1642 // TODO(http://dartbug.com/16615): Validate isolate parameter.
1643 Isolate* I = reinterpret_cast<Isolate*>(isolate);
1644 int64_t main_port = static_cast<int64_t>(I->main_port());
1645 return OS::SCreate(NULL, "isolates/%" Pd64, main_port);
1646}
1647
1648DART_EXPORT void Dart_EnterIsolate(Dart_Isolate isolate) {
1649 CHECK_NO_ISOLATE(Isolate::Current());
1650 // TODO(http://dartbug.com/16615): Validate isolate parameter.
1651 Isolate* iso = reinterpret_cast<Isolate*>(isolate);
1652 if (!Thread::EnterIsolate(iso)) {
1653 FATAL(
1654 "Unable to Enter Isolate : "
1655 "Multiple mutators entering an isolate / "
1656 "Dart VM is shutting down");
1657 }
1658 // A Thread structure has been associated to the thread, we do the
1659 // safepoint transition explicitly here instead of using the
1660 // TransitionXXX scope objects as the reverse transition happens
1661 // outside this scope in Dart_ExitIsolate/Dart_ShutdownIsolate.
1662 Thread* T = Thread::Current();
1663 T->set_execution_state(Thread::kThreadInNative);
1664 T->EnterSafepoint();
1665}
1666
1667DART_EXPORT void Dart_StartProfiling() {
1668#if !defined(PRODUCT)
1669 if (!FLAG_profiler) {
1670 FLAG_profiler = true;
1671 Profiler::Init();
1672 }
1673#endif // !defined(PRODUCT)
1674}
1675
1676DART_EXPORT void Dart_StopProfiling() {
1677#if !defined(PRODUCT)
1678 if (FLAG_profiler) {
1679 Profiler::Cleanup();
1680 FLAG_profiler = false;
1681 }
1682#endif // !defined(PRODUCT)
1683}
1684
1685DART_EXPORT void Dart_ThreadDisableProfiling() {
1686 OSThread* os_thread = OSThread::Current();
1687 if (os_thread == NULL) {
1688 return;
1689 }
1690 os_thread->DisableThreadInterrupts();
1691}
1692
1693DART_EXPORT void Dart_ThreadEnableProfiling() {
1694 OSThread* os_thread = OSThread::Current();
1695 if (os_thread == NULL) {
1696 return;
1697 }
1698 os_thread->EnableThreadInterrupts();
1699}
1700
1701DART_EXPORT void Dart_AddSymbols(const char* dso_name,
1702 void* buffer,
1703 intptr_t buffer_size) {
1704 NativeSymbolResolver::AddSymbols(dso_name, buffer, buffer_size);
1705}
1706
1707DART_EXPORT bool Dart_WriteProfileToTimeline(Dart_Port main_port,
1708 char** error) {
1709#if defined(PRODUCT)
1710 return false;
1711#else
1712 if (!FLAG_profiler) {
1713 if (error != NULL) {
1714 *error = Utils::StrDup("The profiler is not running.");
1715 }
1716 return false;
1717 }
1718
1719 const intptr_t kBufferLength = 512;
1720 char method[kBufferLength];
1721
1722 // clang-format off
1723 intptr_t method_length = snprintf(method, kBufferLength, "{"
1724 "\"jsonrpc\": \"2.0\","
1725 "\"method\": \"_writeCpuProfileTimeline\","
1726 "\"id\": \"\","
1727 "\"params\": {"
1728 " \"isolateId\": \"isolates/%" Pd64 "\","
1729 " \"tags\": \"None\""
1730 "}"
1731 "}", main_port);
1732 // clang-format on
1733 ASSERT(method_length <= kBufferLength);
1734
1735 char* response = NULL;
1736 intptr_t response_length;
1737 bool success = Dart_InvokeVMServiceMethod(
1738 reinterpret_cast<uint8_t*>(method), method_length,
1739 reinterpret_cast<uint8_t**>(&response), &response_length, error);
1740 free(response);
1741 return success;
1742#endif
1743}
1744
1745DART_EXPORT bool Dart_ShouldPauseOnStart() {
1746#if defined(PRODUCT)
1747 return false;
1748#else
1749 Isolate* isolate = Isolate::Current();
1750 CHECK_ISOLATE(isolate);
1751 NoSafepointScope no_safepoint_scope;
1752 return isolate->message_handler()->should_pause_on_start();
1753#endif
1754}
1755
1756DART_EXPORT void Dart_SetShouldPauseOnStart(bool should_pause) {
1757#if defined(PRODUCT)
1758 if (should_pause) {
1759 FATAL1("%s(true) is not supported in a PRODUCT build", CURRENT_FUNC);
1760 }
1761#else
1762 Isolate* isolate = Isolate::Current();
1763 CHECK_ISOLATE(isolate);
1764 NoSafepointScope no_safepoint_scope;
1765 if (isolate->is_runnable()) {
1766 FATAL1("%s expects the current isolate to not be runnable yet.",
1767 CURRENT_FUNC);
1768 }
1769 isolate->message_handler()->set_should_pause_on_start(should_pause);
1770#endif
1771}
1772
1773DART_EXPORT bool Dart_IsPausedOnStart() {
1774#if defined(PRODUCT)
1775 return false;
1776#else
1777 Isolate* isolate = Isolate::Current();
1778 CHECK_ISOLATE(isolate);
1779 NoSafepointScope no_safepoint_scope;
1780 return isolate->message_handler()->is_paused_on_start();
1781#endif
1782}
1783
1784DART_EXPORT void Dart_SetPausedOnStart(bool paused) {
1785#if defined(PRODUCT)
1786 if (paused) {
1787 FATAL1("%s(true) is not supported in a PRODUCT build", CURRENT_FUNC);
1788 }
1789#else
1790 Isolate* isolate = Isolate::Current();
1791 CHECK_ISOLATE(isolate);
1792 NoSafepointScope no_safepoint_scope;
1793 if (isolate->message_handler()->is_paused_on_start() != paused) {
1794 isolate->message_handler()->PausedOnStart(paused);
1795 }
1796#endif
1797}
1798
1799DART_EXPORT bool Dart_ShouldPauseOnExit() {
1800#if defined(PRODUCT)
1801 return false;
1802#else
1803 Isolate* isolate = Isolate::Current();
1804 CHECK_ISOLATE(isolate);
1805 NoSafepointScope no_safepoint_scope;
1806 return isolate->message_handler()->should_pause_on_exit();
1807#endif
1808}
1809
1810DART_EXPORT void Dart_SetShouldPauseOnExit(bool should_pause) {
1811#if defined(PRODUCT)
1812 if (should_pause) {
1813 FATAL1("%s(true) is not supported in a PRODUCT build", CURRENT_FUNC);
1814 }
1815#else
1816 Isolate* isolate = Isolate::Current();
1817 CHECK_ISOLATE(isolate);
1818 NoSafepointScope no_safepoint_scope;
1819 isolate->message_handler()->set_should_pause_on_exit(should_pause);
1820#endif
1821}
1822
1823DART_EXPORT bool Dart_IsPausedOnExit() {
1824#if defined(PRODUCT)
1825 return false;
1826#else
1827 Isolate* isolate = Isolate::Current();
1828 CHECK_ISOLATE(isolate);
1829 NoSafepointScope no_safepoint_scope;
1830 return isolate->message_handler()->is_paused_on_exit();
1831#endif
1832}
1833
1834DART_EXPORT void Dart_SetPausedOnExit(bool paused) {
1835#if defined(PRODUCT)
1836 if (paused) {
1837 FATAL1("%s(true) is not supported in a PRODUCT build", CURRENT_FUNC);
1838 }
1839#else
1840 Isolate* isolate = Isolate::Current();
1841 CHECK_ISOLATE(isolate);
1842 NoSafepointScope no_safepoint_scope;
1843 if (isolate->message_handler()->is_paused_on_exit() != paused) {
1844 isolate->message_handler()->PausedOnExit(paused);
1845 }
1846#endif
1847}
1848
1849DART_EXPORT void Dart_SetStickyError(Dart_Handle error) {
1850 Thread* thread = Thread::Current();
1851 DARTSCOPE(thread);
1852 Isolate* isolate = thread->isolate();
1853 CHECK_ISOLATE(isolate);
1854 NoSafepointScope no_safepoint_scope;
1855 const Error& error_handle = Api::UnwrapErrorHandle(Z, error);
1856 if ((isolate->sticky_error() != Error::null()) &&
1857 (error_handle.raw() != Object::null())) {
1858 FATAL1("%s expects there to be no sticky error.", CURRENT_FUNC);
1859 }
1860 if (!error_handle.IsUnhandledException() &&
1861 (error_handle.raw() != Object::null())) {
1862 FATAL1("%s expects the error to be an unhandled exception error or null.",
1863 CURRENT_FUNC);
1864 }
1865 isolate->SetStickyError(error_handle.raw());
1866}
1867
1868DART_EXPORT bool Dart_HasStickyError() {
1869 Thread* T = Thread::Current();
1870 Isolate* isolate = T->isolate();
1871 CHECK_ISOLATE(isolate);
1872 NoSafepointScope no_safepoint_scope;
1873 return isolate->sticky_error() != Error::null();
1874}
1875
1876DART_EXPORT Dart_Handle Dart_GetStickyError() {
1877 Thread* T = Thread::Current();
1878 Isolate* I = T->isolate();
1879 CHECK_ISOLATE(I);
1880 {
1881 NoSafepointScope no_safepoint_scope;
1882 if (I->sticky_error() == Error::null()) {
1883 return Api::Null();
1884 }
1885 }
1886 TransitionNativeToVM transition(T);
1887 return Api::NewHandle(T, I->sticky_error());
1888}
1889
1890DART_EXPORT void Dart_HintFreed(intptr_t size) {
1891 if (size < 0) {
1892 FATAL1("%s requires a non-negative size", CURRENT_FUNC);
1893 }
1894 Thread* T = Thread::Current();
1895 CHECK_ISOLATE(T->isolate());
1896 API_TIMELINE_BEGIN_END(T);
1897 TransitionNativeToVM transition(T);
1898 T->heap()->HintFreed(size);
1899}
1900
1901DART_EXPORT void Dart_NotifyIdle(int64_t deadline) {
1902 Thread* T = Thread::Current();
1903 CHECK_ISOLATE(T->isolate());
1904 API_TIMELINE_BEGIN_END(T);
1905 TransitionNativeToVM transition(T);
1906 T->isolate()->group()->idle_time_handler()->NotifyIdle(deadline);
1907}
1908
1909DART_EXPORT void Dart_NotifyLowMemory() {
1910 API_TIMELINE_BEGIN_END(Thread::Current());
1911 Isolate::NotifyLowMemory();
1912}
1913
1914DART_EXPORT void Dart_ExitIsolate() {
1915 Thread* T = Thread::Current();
1916 CHECK_ISOLATE(T->isolate());
1917 // The Thread structure is disassociated from the isolate, we do the
1918 // safepoint transition explicitly here instead of using the TransitionXXX
1919 // scope objects as the original transition happened outside this scope in
1920 // Dart_EnterIsolate/Dart_CreateIsolateGroup.
1921 ASSERT(T->execution_state() == Thread::kThreadInNative);
1922 T->ExitSafepoint();
1923 T->set_execution_state(Thread::kThreadInVM);
1924 Thread::ExitIsolate();
1925}
1926
1927#if !defined(DART_PRECOMPILED_RUNTIME)
1928static uint8_t* ApiReallocate(uint8_t* ptr,
1929 intptr_t old_size,
1930 intptr_t new_size) {
1931 return Api::TopScope(Thread::Current())
1932 ->zone()
1933 ->Realloc<uint8_t>(ptr, old_size, new_size);
1934}
1935#endif
1936
1937DART_EXPORT Dart_Handle
1938Dart_CreateSnapshot(uint8_t** vm_snapshot_data_buffer,
1939 intptr_t* vm_snapshot_data_size,
1940 uint8_t** isolate_snapshot_data_buffer,
1941 intptr_t* isolate_snapshot_data_size) {
1942#if defined(DART_PRECOMPILED_RUNTIME)
1943 return Api::NewError("Cannot create snapshots on an AOT runtime.");
1944#else
1945 DARTSCOPE(Thread::Current());
1946 API_TIMELINE_DURATION(T);
1947 Isolate* I = T->isolate();
1948 if (vm_snapshot_data_buffer != NULL && vm_snapshot_data_size == NULL) {
1949 RETURN_NULL_ERROR(vm_snapshot_data_size);
1950 }
1951 CHECK_NULL(isolate_snapshot_data_buffer);
1952 CHECK_NULL(isolate_snapshot_data_size);
1953 // Finalize all classes if needed.
1954 Dart_Handle state = Api::CheckAndFinalizePendingClasses(T);
1955 if (Api::IsError(state)) {
1956 return state;
1957 }
1958 BackgroundCompiler::Stop(I);
1959
1960#if defined(DEBUG)
1961 I->heap()->CollectAllGarbage();
1962 {
1963 HeapIterationScope iteration(T);
1964 CheckFunctionTypesVisitor check_canonical(T);
1965 iteration.IterateObjects(&check_canonical);
1966 }
1967#endif // #if defined(DEBUG)
1968
1969 Symbols::Compact();
1970
1971 FullSnapshotWriter writer(Snapshot::kFull, vm_snapshot_data_buffer,
1972 isolate_snapshot_data_buffer, ApiReallocate,
1973 NULL /* vm_image_writer */,
1974 NULL /* isolate_image_writer */);
1975 writer.WriteFullSnapshot();
1976 if (vm_snapshot_data_buffer != NULL) {
1977 *vm_snapshot_data_size = writer.VmIsolateSnapshotSize();
1978 }
1979 *isolate_snapshot_data_size = writer.IsolateSnapshotSize();
1980 return Api::Success();
1981#endif
1982}
1983
1984DART_EXPORT bool Dart_IsKernel(const uint8_t* buffer, intptr_t buffer_size) {
1985 if (buffer_size < 4) {
1986 return false;
1987 }
1988 return (buffer[0] == 0x90) && (buffer[1] == 0xab) && (buffer[2] == 0xcd) &&
1989 (buffer[3] == 0xef);
1990}
1991
1992DART_EXPORT char* Dart_IsolateMakeRunnable(Dart_Isolate isolate) {
1993 CHECK_NO_ISOLATE(Isolate::Current());
1994 API_TIMELINE_DURATION(Thread::Current());
1995 if (isolate == NULL) {
1996 FATAL1("%s expects argument 'isolate' to be non-null.", CURRENT_FUNC);
1997 }
1998 // TODO(16615): Validate isolate parameter.
1999 Isolate* iso = reinterpret_cast<Isolate*>(isolate);
2000 const char* error;
2001 if (iso->object_store()->root_library() == Library::null()) {
2002 // The embedder should have called Dart_LoadScriptFromKernel by now.
2003 error = "Missing root library";
2004 } else {
2005 error = iso->MakeRunnable();
2006 }
2007 if (error != NULL) {
2008 return Utils::StrDup(error);
2009 }
2010 return NULL;
2011}
2012
2013// --- Messages and Ports ---
2014
2015DART_EXPORT void Dart_SetMessageNotifyCallback(
2016 Dart_MessageNotifyCallback message_notify_callback) {
2017 Isolate* isolate = Isolate::Current();
2018 CHECK_ISOLATE(isolate);
2019
2020 {
2021 NoSafepointScope no_safepoint_scope;
2022 isolate->set_message_notify_callback(message_notify_callback);
2023 }
2024
2025 if (message_notify_callback != nullptr && isolate->HasPendingMessages()) {
2026 ::Dart_ExitIsolate();
2027
2028 // If a new handler gets installed and there are pending messages in the
2029 // queue (e.g. OOB messages for doing vm service work) we need to notify
2030 // the newly registered callback, otherwise the embedder might never get
2031 // notified about the pending messages.
2032 message_notify_callback(Api::CastIsolate(isolate));
2033
2034 ::Dart_EnterIsolate(Api::CastIsolate(isolate));
2035 }
2036}
2037
2038DART_EXPORT Dart_MessageNotifyCallback Dart_GetMessageNotifyCallback() {
2039 Isolate* isolate = Isolate::Current();
2040 CHECK_ISOLATE(isolate);
2041 NoSafepointScope no_safepoint_scope;
2042 return isolate->message_notify_callback();
2043}
2044
2045struct RunLoopData {
2046 Monitor* monitor;
2047 bool done;
2048};
2049
2050static void RunLoopDone(uword param) {
2051 RunLoopData* data = reinterpret_cast<RunLoopData*>(param);
2052 ASSERT(data->monitor != NULL);
2053 MonitorLocker ml(data->monitor);
2054 data->done = true;
2055 ml.Notify();
2056}
2057
2058DART_EXPORT Dart_Handle Dart_RunLoop() {
2059 Isolate* I;
2060 {
2061 Thread* T = Thread::Current();
2062 I = T->isolate();
2063 CHECK_API_SCOPE(T);
2064 CHECK_CALLBACK_STATE(T);
2065 }
2066 API_TIMELINE_BEGIN_END(Thread::Current());
2067 // The message handler run loop does not expect to have a current isolate
2068 // so we exit the isolate here and enter it again after the runloop is done.
2069 ::Dart_ExitIsolate();
2070 {
2071 Monitor monitor;
2072 MonitorLocker ml(&monitor);
2073 RunLoopData data;
2074 data.monitor = &monitor;
2075 data.done = false;
2076 I->message_handler()->Run(I->group()->thread_pool(), NULL, RunLoopDone,
2077 reinterpret_cast<uword>(&data));
2078 while (!data.done) {
2079 ml.Wait();
2080 }
2081 }
2082 ::Dart_EnterIsolate(Api::CastIsolate(I));
2083 if (I->sticky_error() != Object::null()) {
2084 Thread* T = Thread::Current();
2085 TransitionNativeToVM transition(T);
2086 return Api::NewHandle(T, I->StealStickyError());
2087 }
2088 if (FLAG_print_class_table) {
2089 HANDLESCOPE(Thread::Current());
2090 I->class_table()->Print();
2091 }
2092 return Api::Success();
2093}
2094
2095DART_EXPORT Dart_Handle Dart_HandleMessage() {
2096 Thread* T = Thread::Current();
2097 Isolate* I = T->isolate();
2098 CHECK_API_SCOPE(T);
2099 CHECK_CALLBACK_STATE(T);
2100 API_TIMELINE_BEGIN_END_BASIC(T);
2101 TransitionNativeToVM transition(T);
2102 if (I->message_handler()->HandleNextMessage() != MessageHandler::kOK) {
2103 return Api::NewHandle(T, T->StealStickyError());
2104 }
2105 return Api::Success();
2106}
2107
2108DART_EXPORT Dart_Handle Dart_WaitForEvent(int64_t timeout_millis) {
2109 Thread* T = Thread::Current();
2110 Isolate* I = T->isolate();
2111 CHECK_API_SCOPE(T);
2112 CHECK_CALLBACK_STATE(T);
2113 API_TIMELINE_BEGIN_END_BASIC(T);
2114 TransitionNativeToVM transition(T);
2115 if (I->message_notify_callback() != NULL) {
2116 return Api::NewError("waitForEventSync is not supported by this embedder");
2117 }
2118 Object& result =
2119 Object::Handle(Z, DartLibraryCalls::EnsureScheduleImmediate());
2120 if (result.IsError()) {
2121 return Api::NewHandle(T, result.raw());
2122 }
2123
2124 // Drain the microtask queue. Propagate any errors to the entry frame.
2125 result = DartLibraryCalls::DrainMicrotaskQueue();
2126 if (result.IsError()) {
2127 // Persist the error across unwiding scopes before propagating.
2128 const Error* error;
2129 {
2130 NoSafepointScope no_safepoint;
2131 ErrorPtr raw_error = Error::Cast(result).raw();
2132 T->UnwindScopes(T->top_exit_frame_info());
2133 error = &Error::Handle(T->zone(), raw_error);
2134 }
2135 Exceptions::PropagateToEntry(*error);
2136 UNREACHABLE();
2137 return Api::NewError("Unreachable");
2138 }
2139
2140 // Block to wait for messages and then handle them. Propagate any errors to
2141 // the entry frame.
2142 if (I->message_handler()->PauseAndHandleAllMessages(timeout_millis) !=
2143 MessageHandler::kOK) {
2144 // Persist the error across unwiding scopes before propagating.
2145 const Error* error;
2146 {
2147 NoSafepointScope no_safepoint;
2148 ErrorPtr raw_error = T->StealStickyError();
2149 T->UnwindScopes(T->top_exit_frame_info());
2150 error = &Error::Handle(T->zone(), raw_error);
2151 }
2152 Exceptions::PropagateToEntry(*error);
2153 UNREACHABLE();
2154 return Api::NewError("Unreachable");
2155 }
2156 return Api::Success();
2157}
2158
2159DART_EXPORT bool Dart_HandleServiceMessages() {
2160#if defined(PRODUCT)
2161 return true;
2162#else
2163 Thread* T = Thread::Current();
2164 Isolate* I = T->isolate();
2165 CHECK_API_SCOPE(T);
2166 CHECK_CALLBACK_STATE(T);
2167 API_TIMELINE_DURATION(T);
2168 TransitionNativeToVM transition(T);
2169 ASSERT(I->GetAndClearResumeRequest() == false);
2170 MessageHandler::MessageStatus status =
2171 I->message_handler()->HandleOOBMessages();
2172 bool resume = I->GetAndClearResumeRequest();
2173 return (status != MessageHandler::kOK) || resume;
2174#endif
2175}
2176
2177DART_EXPORT bool Dart_HasServiceMessages() {
2178#if defined(PRODUCT)
2179 return false;
2180#else
2181 Isolate* isolate = Isolate::Current();
2182 ASSERT(isolate);
2183 NoSafepointScope no_safepoint_scope;
2184 return isolate->message_handler()->HasOOBMessages();
2185#endif
2186}
2187
2188DART_EXPORT bool Dart_HasLivePorts() {
2189 Isolate* isolate = Isolate::Current();
2190 ASSERT(isolate);
2191 NoSafepointScope no_safepoint_scope;
2192 return isolate->message_handler()->HasLivePorts();
2193}
2194
2195DART_EXPORT bool Dart_Post(Dart_Port port_id, Dart_Handle handle) {
2196 DARTSCOPE(Thread::Current());
2197 API_TIMELINE_DURATION(T);
2198 NoSafepointScope no_safepoint_scope;
2199 if (port_id == ILLEGAL_PORT) {
2200 return false;
2201 }
2202
2203 // Smis and null can be sent without serialization.
2204 ObjectPtr raw_obj = Api::UnwrapHandle(handle);
2205 if (ApiObjectConverter::CanConvert(raw_obj)) {
2206 return PortMap::PostMessage(
2207 Message::New(port_id, raw_obj, Message::kNormalPriority));
2208 }
2209
2210 const Object& object = Object::Handle(Z, raw_obj);
2211 MessageWriter writer(false);
2212 return PortMap::PostMessage(
2213 writer.WriteMessage(object, port_id, Message::kNormalPriority));
2214}
2215
2216DART_EXPORT Dart_Handle Dart_NewSendPort(Dart_Port port_id) {
2217 DARTSCOPE(Thread::Current());
2218 CHECK_CALLBACK_STATE(T);
2219 if (port_id == ILLEGAL_PORT) {
2220 return Api::NewError("%s: illegal port_id %" Pd64 ".", CURRENT_FUNC,
2221 port_id);
2222 }
2223 return Api::NewHandle(T, SendPort::New(port_id));
2224}
2225
2226DART_EXPORT Dart_Handle Dart_SendPortGetId(Dart_Handle port,
2227 Dart_Port* port_id) {
2228 DARTSCOPE(Thread::Current());
2229 CHECK_CALLBACK_STATE(T);
2230 API_TIMELINE_DURATION(T);
2231 const SendPort& send_port = Api::UnwrapSendPortHandle(Z, port);
2232 if (send_port.IsNull()) {
2233 RETURN_TYPE_ERROR(Z, port, SendPort);
2234 }
2235 if (port_id == NULL) {
2236 RETURN_NULL_ERROR(port_id);
2237 }
2238 *port_id = send_port.Id();
2239 return Api::Success();
2240}
2241
2242DART_EXPORT Dart_Port Dart_GetMainPortId() {
2243 Isolate* isolate = Isolate::Current();
2244 CHECK_ISOLATE(isolate);
2245 return isolate->main_port();
2246}
2247
2248// --- Scopes ----
2249
2250DART_EXPORT void Dart_EnterScope() {
2251 Thread* thread = Thread::Current();
2252 Isolate* isolate = thread->isolate();
2253 CHECK_ISOLATE(isolate);
2254 TransitionNativeToVM transition(thread);
2255 thread->EnterApiScope();
2256}
2257
2258DART_EXPORT void Dart_ExitScope() {
2259 Thread* thread = Thread::Current();
2260 CHECK_API_SCOPE(thread);
2261 TransitionNativeToVM transition(thread);
2262 thread->ExitApiScope();
2263}
2264
2265DART_EXPORT uint8_t* Dart_ScopeAllocate(intptr_t size) {
2266 Zone* zone;
2267 Thread* thread = Thread::Current();
2268 if (thread != NULL) {
2269 ApiLocalScope* scope = thread->api_top_scope();
2270 zone = scope->zone();
2271 } else {
2272 ApiNativeScope* scope = ApiNativeScope::Current();
2273 if (scope == NULL) return NULL;
2274 zone = scope->zone();
2275 }
2276 return reinterpret_cast<uint8_t*>(zone->AllocUnsafe(size));
2277}
2278
2279// --- Objects ----
2280
2281DART_EXPORT Dart_Handle Dart_Null() {
2282 ASSERT(Isolate::Current() != NULL);
2283 return Api::Null();
2284}
2285
2286DART_EXPORT bool Dart_IsNull(Dart_Handle object) {
2287 TransitionNativeToVM transition(Thread::Current());
2288 return Api::UnwrapHandle(object) == Object::null();
2289}
2290
2291DART_EXPORT Dart_Handle Dart_EmptyString() {
2292 ASSERT(Isolate::Current() != NULL);
2293 return Api::EmptyString();
2294}
2295
2296DART_EXPORT Dart_Handle Dart_TypeDynamic() {
2297 DARTSCOPE(Thread::Current());
2298 CHECK_CALLBACK_STATE(T);
2299 API_TIMELINE_DURATION(T);
2300 return Api::NewHandle(T, Type::DynamicType());
2301}
2302
2303DART_EXPORT Dart_Handle Dart_TypeVoid() {
2304 DARTSCOPE(Thread::Current());
2305 CHECK_CALLBACK_STATE(T);
2306 API_TIMELINE_DURATION(T);
2307 return Api::NewHandle(T, Type::VoidType());
2308}
2309
2310DART_EXPORT Dart_Handle Dart_TypeNever() {
2311 DARTSCOPE(Thread::Current());
2312 CHECK_CALLBACK_STATE(T);
2313 API_TIMELINE_DURATION(T);
2314 return Api::NewHandle(T, Type::NeverType());
2315}
2316
2317DART_EXPORT Dart_Handle Dart_ObjectEquals(Dart_Handle obj1,
2318 Dart_Handle obj2,
2319 bool* value) {
2320 DARTSCOPE(Thread::Current());
2321 CHECK_CALLBACK_STATE(T);
2322 const Instance& expected =
2323 Instance::CheckedHandle(Z, Api::UnwrapHandle(obj1));
2324 const Instance& actual = Instance::CheckedHandle(Z, Api::UnwrapHandle(obj2));
2325 const Object& result =
2326 Object::Handle(Z, DartLibraryCalls::Equals(expected, actual));
2327 if (result.IsBool()) {
2328 *value = Bool::Cast(result).value();
2329 return Api::Success();
2330 } else if (result.IsError()) {
2331 return Api::NewHandle(T, result.raw());
2332 } else {
2333 return Api::NewError("Expected boolean result from ==");
2334 }
2335}
2336
2337// Assumes type is non-null.
2338static bool InstanceIsType(const Thread* thread,
2339 const Instance& instance,
2340 const Type& type) {
2341 ASSERT(!type.IsNull());
2342 CHECK_CALLBACK_STATE(thread);
2343 return instance.IsInstanceOf(type, Object::null_type_arguments(),
2344 Object::null_type_arguments());
2345}
2346
2347DART_EXPORT Dart_Handle Dart_ObjectIsType(Dart_Handle object,
2348 Dart_Handle type,
2349 bool* value) {
2350 DARTSCOPE(Thread::Current());
2351
2352 const Type& type_obj = Api::UnwrapTypeHandle(Z, type);
2353 if (type_obj.IsNull()) {
2354 *value = false;
2355 RETURN_TYPE_ERROR(Z, type, Type);
2356 }
2357 if (!type_obj.IsFinalized()) {
2358 return Api::NewError(
2359 "%s expects argument 'type' to be a fully resolved type.",
2360 CURRENT_FUNC);
2361 }
2362 if (object == Api::Null()) {
2363 *value = false;
2364 return Api::Success();
2365 }
2366 const Instance& instance = Api::UnwrapInstanceHandle(Z, object);
2367 if (instance.IsNull()) {
2368 *value = false;
2369 RETURN_TYPE_ERROR(Z, object, Instance);
2370 }
2371 *value = InstanceIsType(T, instance, type_obj);
2372 return Api::Success();
2373}
2374
2375DART_EXPORT bool Dart_IsInstance(Dart_Handle object) {
2376 Thread* thread = Thread::Current();
2377 CHECK_ISOLATE(thread->isolate());
2378 TransitionNativeToVM transition(thread);
2379 REUSABLE_OBJECT_HANDLESCOPE(thread);
2380 Object& ref = thread->ObjectHandle();
2381 ref = Api::UnwrapHandle(object);
2382 return ref.IsInstance();
2383}
2384
2385DART_EXPORT bool Dart_IsNumber(Dart_Handle object) {
2386 Thread* thread = Thread::Current();
2387 CHECK_ISOLATE(thread->isolate());
2388 TransitionNativeToVM transition(thread);
2389 return IsNumberClassId(Api::ClassId(object));
2390}
2391
2392DART_EXPORT bool Dart_IsInteger(Dart_Handle object) {
2393 Thread* thread = Thread::Current();
2394 CHECK_ISOLATE(thread->isolate());
2395 TransitionNativeToVM transition(thread);
2396 return IsIntegerClassId(Api::ClassId(object));
2397}
2398
2399DART_EXPORT bool Dart_IsDouble(Dart_Handle object) {
2400 Thread* thread = Thread::Current();
2401 CHECK_ISOLATE(thread->isolate());
2402 TransitionNativeToVM transition(thread);
2403 return Api::ClassId(object) == kDoubleCid;
2404}
2405
2406DART_EXPORT bool Dart_IsBoolean(Dart_Handle object) {
2407 Thread* thread = Thread::Current();
2408 CHECK_ISOLATE(thread->isolate());
2409 TransitionNativeToVM transition(thread);
2410 return Api::ClassId(object) == kBoolCid;
2411}
2412
2413DART_EXPORT bool Dart_IsString(Dart_Handle object) {
2414 Thread* thread = Thread::Current();
2415 CHECK_ISOLATE(thread->isolate());
2416 TransitionNativeToVM transition(thread);
2417 return IsStringClassId(Api::ClassId(object));
2418}
2419
2420DART_EXPORT bool Dart_IsStringLatin1(Dart_Handle object) {
2421 Thread* thread = Thread::Current();
2422 CHECK_ISOLATE(thread->isolate());
2423 TransitionNativeToVM transition(thread);
2424 return IsOneByteStringClassId(Api::ClassId(object));
2425}
2426
2427DART_EXPORT bool Dart_IsExternalString(Dart_Handle object) {
2428 Thread* thread = Thread::Current();
2429 CHECK_ISOLATE(thread->isolate());
2430 TransitionNativeToVM transition(thread);
2431 return IsExternalStringClassId(Api::ClassId(object));
2432}
2433
2434DART_EXPORT bool Dart_IsList(Dart_Handle object) {
2435 DARTSCOPE(Thread::Current());
2436 if (IsBuiltinListClassId(Api::ClassId(object))) {
2437 return true;
2438 }
2439
2440 const Object& obj = Object::Handle(Z, Api::UnwrapHandle(object));
2441 return GetListInstance(Z, obj) != Instance::null();
2442}
2443
2444DART_EXPORT bool Dart_IsMap(Dart_Handle object) {
2445 DARTSCOPE(Thread::Current());
2446 const Object& obj = Object::Handle(Z, Api::UnwrapHandle(object));
2447 return GetMapInstance(Z, obj) != Instance::null();
2448}
2449
2450DART_EXPORT bool Dart_IsLibrary(Dart_Handle object) {
2451 Thread* thread = Thread::Current();
2452 CHECK_ISOLATE(thread->isolate());
2453 TransitionNativeToVM transition(thread);
2454 return Api::ClassId(object) == kLibraryCid;
2455}
2456
2457DART_EXPORT bool Dart_IsType(Dart_Handle handle) {
2458 Thread* thread = Thread::Current();
2459 CHECK_ISOLATE(thread->isolate());
2460 TransitionNativeToVM transition(thread);
2461 return Api::ClassId(handle) == kTypeCid;
2462}
2463
2464DART_EXPORT bool Dart_IsFunction(Dart_Handle handle) {
2465 Thread* thread = Thread::Current();
2466 CHECK_ISOLATE(thread->isolate());
2467 TransitionNativeToVM transition(thread);
2468 return Api::ClassId(handle) == kFunctionCid;
2469}
2470
2471DART_EXPORT bool Dart_IsVariable(Dart_Handle handle) {
2472 Thread* thread = Thread::Current();
2473 CHECK_ISOLATE(thread->isolate());
2474 TransitionNativeToVM transition(thread);
2475 return Api::ClassId(handle) == kFieldCid;
2476}
2477
2478DART_EXPORT bool Dart_IsTypeVariable(Dart_Handle handle) {
2479 Thread* thread = Thread::Current();
2480 CHECK_ISOLATE(thread->isolate());
2481 TransitionNativeToVM transition(thread);
2482 return Api::ClassId(handle) == kTypeParameterCid;
2483}
2484
2485DART_EXPORT bool Dart_IsClosure(Dart_Handle object) {
2486 Thread* thread = Thread::Current();
2487 CHECK_ISOLATE(thread->isolate());
2488 TransitionNativeToVM transition(thread);
2489 return Api::ClassId(object) == kClosureCid;
2490}
2491
2492DART_EXPORT bool Dart_IsTearOff(Dart_Handle object) {
2493 DARTSCOPE(Thread::Current());
2494 API_TIMELINE_DURATION(T);
2495 const Object& obj = Object::Handle(Z, Api::UnwrapHandle(object));
2496 if (obj.IsClosure()) {
2497 const Closure& closure = Closure::Cast(obj);
2498 const Function& func = Function::Handle(Z, closure.function());
2499 return func.IsImplicitClosureFunction();
2500 }
2501 return false;
2502}
2503
2504DART_EXPORT bool Dart_IsTypedData(Dart_Handle handle) {
2505 Thread* thread = Thread::Current();
2506 CHECK_ISOLATE(thread->isolate());
2507 TransitionNativeToVM transition(thread);
2508 intptr_t cid = Api::ClassId(handle);
2509 return IsTypedDataClassId(cid) || IsExternalTypedDataClassId(cid) ||
2510 IsTypedDataViewClassId(cid);
2511}
2512
2513DART_EXPORT bool Dart_IsByteBuffer(Dart_Handle handle) {
2514 Thread* thread = Thread::Current();
2515 CHECK_ISOLATE(thread->isolate());
2516 TransitionNativeToVM transition(thread);
2517 return Api::ClassId(handle) == kByteBufferCid;
2518}
2519
2520DART_EXPORT bool Dart_IsFuture(Dart_Handle handle) {
2521 DARTSCOPE(Thread::Current());
2522 API_TIMELINE_DURATION(T);
2523 const Object& obj = Object::Handle(Z, Api::UnwrapHandle(handle));
2524 if (obj.IsInstance()) {
2525 ObjectStore* object_store = T->isolate()->object_store();
2526 const Type& future_rare_type =
2527 Type::Handle(Z, object_store->non_nullable_future_rare_type());
2528 ASSERT(!future_rare_type.IsNull());
2529 const Class& obj_class = Class::Handle(Z, obj.clazz());
2530 bool is_future = Class::IsSubtypeOf(
2531 obj_class, Object::null_type_arguments(), Nullability::kNonNullable,
2532 future_rare_type, Heap::kNew);
2533 return is_future;
2534 }
2535 return false;
2536}
2537
2538// --- Instances ----
2539
2540DART_EXPORT Dart_Handle Dart_InstanceGetType(Dart_Handle instance) {
2541 DARTSCOPE(Thread::Current());
2542 API_TIMELINE_DURATION(T);
2543 Isolate* I = T->isolate();
2544 const Object& obj = Object::Handle(Z, Api::UnwrapHandle(instance));
2545 if (obj.IsNull()) {
2546 return Api::NewHandle(T, I->object_store()->null_type());
2547 }
2548 if (!obj.IsInstance()) {
2549 RETURN_TYPE_ERROR(Z, instance, Instance);
2550 }
2551 const AbstractType& type =
2552 AbstractType::Handle(Instance::Cast(obj).GetType(Heap::kNew));
2553 return Api::NewHandle(T, type.Canonicalize());
2554}
2555
2556DART_EXPORT Dart_Handle Dart_FunctionName(Dart_Handle function) {
2557 DARTSCOPE(Thread::Current());
2558 const Function& func = Api::UnwrapFunctionHandle(Z, function);
2559 if (func.IsNull()) {
2560 RETURN_TYPE_ERROR(Z, function, Function);
2561 }
2562 return Api::NewHandle(T, func.UserVisibleName());
2563}
2564
2565DART_EXPORT Dart_Handle Dart_ClassName(Dart_Handle cls_type) {
2566 DARTSCOPE(Thread::Current());
2567 const Type& type_obj = Api::UnwrapTypeHandle(Z, cls_type);
2568 if (type_obj.IsNull()) {
2569 RETURN_TYPE_ERROR(Z, cls_type, Type);
2570 }
2571 const Class& klass = Class::Handle(Z, type_obj.type_class());
2572 if (klass.IsNull()) {
2573 return Api::NewError(
2574 "cls_type must be a Type object which represents a Class.");
2575 }
2576 return Api::NewHandle(T, klass.UserVisibleName());
2577}
2578
2579DART_EXPORT Dart_Handle Dart_FunctionOwner(Dart_Handle function) {
2580 DARTSCOPE(Thread::Current());
2581 const Function& func = Api::UnwrapFunctionHandle(Z, function);
2582 if (func.IsNull()) {
2583 RETURN_TYPE_ERROR(Z, function, Function);
2584 }
2585 if (func.IsNonImplicitClosureFunction()) {
2586 FunctionPtr parent_function = func.parent_function();
2587 return Api::NewHandle(T, parent_function);
2588 }
2589 const Class& owner = Class::Handle(Z, func.Owner());
2590 ASSERT(!owner.IsNull());
2591 if (owner.IsTopLevel()) {
2592// Top-level functions are implemented as members of a hidden class. We hide
2593// that class here and instead answer the library.
2594#if defined(DEBUG)
2595 const Library& lib = Library::Handle(Z, owner.library());
2596 if (lib.IsNull()) {
2597 ASSERT(owner.IsDynamicClass() || owner.IsVoidClass() ||
2598 owner.IsNeverClass());
2599 }
2600#endif
2601 return Api::NewHandle(T, owner.library());
2602 } else {
2603 return Api::NewHandle(T, owner.RareType());
2604 }
2605}
2606
2607DART_EXPORT Dart_Handle Dart_FunctionIsStatic(Dart_Handle function,
2608 bool* is_static) {
2609 DARTSCOPE(Thread::Current());
2610 if (is_static == NULL) {
2611 RETURN_NULL_ERROR(is_static);
2612 }
2613 const Function& func = Api::UnwrapFunctionHandle(Z, function);
2614 if (func.IsNull()) {
2615 RETURN_TYPE_ERROR(Z, function, Function);
2616 }
2617 *is_static = func.is_static();
2618 return Api::Success();
2619}
2620
2621DART_EXPORT Dart_Handle Dart_ClosureFunction(Dart_Handle closure) {
2622 DARTSCOPE(Thread::Current());
2623 const Instance& closure_obj = Api::UnwrapInstanceHandle(Z, closure);
2624 if (closure_obj.IsNull() || !closure_obj.IsClosure()) {
2625 RETURN_TYPE_ERROR(Z, closure, Instance);
2626 }
2627
2628 ASSERT(ClassFinalizer::AllClassesFinalized());
2629
2630 FunctionPtr rf = Closure::Cast(closure_obj).function();
2631 return Api::NewHandle(T, rf);
2632}
2633
2634DART_EXPORT Dart_Handle Dart_ClassLibrary(Dart_Handle cls_type) {
2635 DARTSCOPE(Thread::Current());
2636 const Type& type_obj = Api::UnwrapTypeHandle(Z, cls_type);
2637 const Class& klass = Class::Handle(Z, type_obj.type_class());
2638 if (klass.IsNull()) {
2639 return Api::NewError(
2640 "cls_type must be a Type object which represents a Class.");
2641 }
2642 const Library& library = Library::Handle(klass.library());
2643 if (library.IsNull()) {
2644 return Dart_Null();
2645 }
2646 return Api::NewHandle(Thread::Current(), library.raw());
2647}
2648
2649// --- Numbers, Integers and Doubles ----
2650
2651DART_EXPORT Dart_Handle Dart_IntegerFitsIntoInt64(Dart_Handle integer,
2652 bool* fits) {
2653 // Fast path for Smis and Mints.
2654 Thread* thread = Thread::Current();
2655 API_TIMELINE_DURATION(thread);
2656 Isolate* isolate = thread->isolate();
2657 CHECK_ISOLATE(isolate);
2658 if (Api::IsSmi(integer)) {
2659 *fits = true;
2660 return Api::Success();
2661 }
2662 // Slow path for mints and type error.
2663 DARTSCOPE(thread);
2664 if (Api::ClassId(integer) == kMintCid) {
2665 *fits = true;
2666 return Api::Success();
2667 }
2668 const Integer& int_obj = Api::UnwrapIntegerHandle(Z, integer);
2669 ASSERT(int_obj.IsNull());
2670 RETURN_TYPE_ERROR(Z, integer, Integer);
2671}
2672
2673DART_EXPORT Dart_Handle Dart_IntegerFitsIntoUint64(Dart_Handle integer,
2674 bool* fits) {
2675 // Fast path for Smis.
2676 Thread* thread = Thread::Current();
2677 Isolate* isolate = thread->isolate();
2678 CHECK_ISOLATE(isolate);
2679 API_TIMELINE_DURATION(thread);
2680 if (Api::IsSmi(integer)) {
2681 *fits = (Api::SmiValue(integer) >= 0);
2682 return Api::Success();
2683 }
2684 // Slow path for Mints.
2685 DARTSCOPE(thread);
2686 const Integer& int_obj = Api::UnwrapIntegerHandle(Z, integer);
2687 if (int_obj.IsNull()) {
2688 RETURN_TYPE_ERROR(Z, integer, Integer);
2689 }
2690 ASSERT(int_obj.IsMint());
2691 *fits = !int_obj.IsNegative();
2692 return Api::Success();
2693}
2694
2695DART_EXPORT Dart_Handle Dart_NewInteger(int64_t value) {
2696 // Fast path for Smis.
2697 Thread* thread = Thread::Current();
2698 Isolate* isolate = thread->isolate();
2699 CHECK_ISOLATE(isolate);
2700 API_TIMELINE_DURATION(thread);
2701 DARTSCOPE(thread);
2702 CHECK_CALLBACK_STATE(thread);
2703 return Api::NewHandle(thread, Integer::New(value));
2704}
2705
2706DART_EXPORT Dart_Handle Dart_NewIntegerFromUint64(uint64_t value) {
2707 DARTSCOPE(Thread::Current());
2708 CHECK_CALLBACK_STATE(T);
2709 API_TIMELINE_DURATION(T);
2710 if (Integer::IsValueInRange(value)) {
2711 return Api::NewHandle(T, Integer::NewFromUint64(value));
2712 }
2713 return Api::NewError("%s: Cannot create Dart integer from value %" Pu64,
2714 CURRENT_FUNC, value);
2715}
2716
2717DART_EXPORT Dart_Handle Dart_NewIntegerFromHexCString(const char* str) {
2718 DARTSCOPE(Thread::Current());
2719 CHECK_CALLBACK_STATE(T);
2720 API_TIMELINE_DURATION(T);
2721 const String& str_obj = String::Handle(Z, String::New(str));
2722 IntegerPtr integer = Integer::New(str_obj);
2723 if (integer == Integer::null()) {
2724 return Api::NewError("%s: Cannot create Dart integer from string %s",
2725 CURRENT_FUNC, str);
2726 }
2727 return Api::NewHandle(T, integer);
2728}
2729
2730DART_EXPORT Dart_Handle Dart_IntegerToInt64(Dart_Handle integer,
2731 int64_t* value) {
2732 // Fast path for Smis.
2733 Thread* thread = Thread::Current();
2734 Isolate* isolate = thread->isolate();
2735 CHECK_ISOLATE(isolate);
2736 if (Api::IsSmi(integer)) {
2737 *value = Api::SmiValue(integer);
2738 return Api::Success();
2739 }
2740 // Slow path for Mints.
2741 DARTSCOPE(thread);
2742 const Integer& int_obj = Api::UnwrapIntegerHandle(Z, integer);
2743 if (int_obj.IsNull()) {
2744 RETURN_TYPE_ERROR(Z, integer, Integer);
2745 }
2746 ASSERT(int_obj.IsMint());
2747 *value = int_obj.AsInt64Value();
2748 return Api::Success();
2749}
2750
2751DART_EXPORT Dart_Handle Dart_IntegerToUint64(Dart_Handle integer,
2752 uint64_t* value) {
2753 // Fast path for Smis.
2754 Thread* thread = Thread::Current();
2755 Isolate* isolate = thread->isolate();
2756 CHECK_ISOLATE(isolate);
2757 if (Api::IsSmi(integer)) {
2758 intptr_t smi_value = Api::SmiValue(integer);
2759 if (smi_value >= 0) {
2760 *value = smi_value;
2761 return Api::Success();
2762 }
2763 }
2764 // Slow path for Mints.
2765 DARTSCOPE(thread);
2766 const Integer& int_obj = Api::UnwrapIntegerHandle(Z, integer);
2767 if (int_obj.IsNull()) {
2768 RETURN_TYPE_ERROR(Z, integer, Integer);
2769 }
2770 if (int_obj.IsSmi()) {
2771 ASSERT(int_obj.IsNegative());
2772 } else {
2773 ASSERT(int_obj.IsMint());
2774 if (!int_obj.IsNegative()) {
2775 *value = int_obj.AsInt64Value();
2776 return Api::Success();
2777 }
2778 }
2779 return Api::NewError("%s: Integer %s cannot be represented as a uint64_t.",
2780 CURRENT_FUNC, int_obj.ToCString());
2781}
2782
2783DART_EXPORT Dart_Handle Dart_IntegerToHexCString(Dart_Handle integer,
2784 const char** value) {
2785 DARTSCOPE(Thread::Current());
2786 API_TIMELINE_DURATION(T);
2787 const Integer& int_obj = Api::UnwrapIntegerHandle(Z, integer);
2788 if (int_obj.IsNull()) {
2789 RETURN_TYPE_ERROR(Z, integer, Integer);
2790 }
2791 Zone* scope_zone = Api::TopScope(Thread::Current())->zone();
2792 *value = int_obj.ToHexCString(scope_zone);
2793 return Api::Success();
2794}
2795
2796DART_EXPORT Dart_Handle Dart_NewDouble(double value) {
2797 DARTSCOPE(Thread::Current());
2798 CHECK_CALLBACK_STATE(T);
2799 return Api::NewHandle(T, Double::New(value));
2800}
2801
2802DART_EXPORT Dart_Handle Dart_DoubleValue(Dart_Handle double_obj,
2803 double* value) {
2804 DARTSCOPE(Thread::Current());
2805 const Double& obj = Api::UnwrapDoubleHandle(Z, double_obj);
2806 if (obj.IsNull()) {
2807 RETURN_TYPE_ERROR(Z, double_obj, Double);
2808 }
2809 *value = obj.value();
2810 return Api::Success();
2811}
2812
2813DART_EXPORT Dart_Handle Dart_GetStaticMethodClosure(Dart_Handle library,
2814 Dart_Handle cls_type,
2815 Dart_Handle function_name) {
2816 DARTSCOPE(Thread::Current());
2817 const Library& lib = Api::UnwrapLibraryHandle(Z, library);
2818 if (lib.IsNull()) {
2819 RETURN_TYPE_ERROR(Z, library, Library);
2820 }
2821
2822 const Type& type_obj = Api::UnwrapTypeHandle(Z, cls_type);
2823 if (type_obj.IsNull()) {
2824 RETURN_TYPE_ERROR(Z, cls_type, Type);
2825 }
2826
2827 const Class& klass = Class::Handle(Z, type_obj.type_class());
2828 if (klass.IsNull()) {
2829 return Api::NewError(
2830 "cls_type must be a Type object which represents a Class");
2831 }
2832
2833 const String& func_name = Api::UnwrapStringHandle(Z, function_name);
2834 if (func_name.IsNull()) {
2835 RETURN_TYPE_ERROR(Z, function_name, String);
2836 }
2837
2838 Function& func =
2839 Function::Handle(Z, klass.LookupStaticFunctionAllowPrivate(func_name));
2840 if (func.IsNull()) {
2841 return Dart_Null();
2842 }
2843
2844 if (!func.is_static()) {
2845 return Api::NewError("function_name must refer to a static method.");
2846 }
2847
2848 if (func.kind() != FunctionLayout::kRegularFunction) {
2849 return Api::NewError(
2850 "function_name must be the name of a regular function.");
2851 }
2852 func = func.ImplicitClosureFunction();
2853 if (func.IsNull()) {
2854 return Dart_Null();
2855 }
2856
2857 return Api::NewHandle(T, func.ImplicitStaticClosure());
2858}
2859
2860// --- Booleans ----
2861
2862DART_EXPORT Dart_Handle Dart_True() {
2863 ASSERT(Isolate::Current() != NULL);
2864 return Api::True();
2865}
2866
2867DART_EXPORT Dart_Handle Dart_False() {
2868 ASSERT(Isolate::Current() != NULL);
2869 return Api::False();
2870}
2871
2872DART_EXPORT Dart_Handle Dart_NewBoolean(bool value) {
2873 Isolate* isolate = Isolate::Current();
2874 CHECK_ISOLATE(isolate);
2875 return value ? Api::True() : Api::False();
2876}
2877
2878DART_EXPORT Dart_Handle Dart_BooleanValue(Dart_Handle boolean_obj,
2879 bool* value) {
2880 DARTSCOPE(Thread::Current());
2881 const Bool& obj = Api::UnwrapBoolHandle(Z, boolean_obj);
2882 if (obj.IsNull()) {
2883 RETURN_TYPE_ERROR(Z, boolean_obj, Bool);
2884 }
2885 *value = obj.value();
2886 return Api::Success();
2887}
2888
2889// --- Strings ---
2890
2891DART_EXPORT Dart_Handle Dart_StringLength(Dart_Handle str, intptr_t* len) {
2892 Thread* thread = Thread::Current();
2893 DARTSCOPE(thread);
2894 ReusableObjectHandleScope reused_obj_handle(thread);
2895 const String& str_obj = Api::UnwrapStringHandle(reused_obj_handle, str);
2896 if (str_obj.IsNull()) {
2897 RETURN_TYPE_ERROR(thread->zone(), str, String);
2898 }
2899 *len = str_obj.Length();
2900 return Api::Success();
2901}
2902
2903DART_EXPORT Dart_Handle Dart_NewStringFromCString(const char* str) {
2904 DARTSCOPE(Thread::Current());
2905 API_TIMELINE_DURATION(T);
2906 if (str == NULL) {
2907 RETURN_NULL_ERROR(str);
2908 }
2909 CHECK_CALLBACK_STATE(T);
2910 return Api::NewHandle(T, String::New(str));
2911}
2912
2913DART_EXPORT Dart_Handle Dart_NewStringFromUTF8(const uint8_t* utf8_array,
2914 intptr_t length) {
2915 DARTSCOPE(Thread::Current());
2916 API_TIMELINE_DURATION(T);
2917 if (utf8_array == NULL && length != 0) {
2918 RETURN_NULL_ERROR(utf8_array);
2919 }
2920 CHECK_LENGTH(length, String::kMaxElements);
2921 if (!Utf8::IsValid(utf8_array, length)) {
2922 return Api::NewError("%s expects argument 'str' to be valid UTF-8.",
2923 CURRENT_FUNC);
2924 }
2925 CHECK_CALLBACK_STATE(T);
2926 return Api::NewHandle(T, String::FromUTF8(utf8_array, length));
2927}
2928
2929DART_EXPORT Dart_Handle Dart_NewStringFromUTF16(const uint16_t* utf16_array,
2930 intptr_t length) {
2931 DARTSCOPE(Thread::Current());
2932 if (utf16_array == NULL && length != 0) {
2933 RETURN_NULL_ERROR(utf16_array);
2934 }
2935 CHECK_LENGTH(length, String::kMaxElements);
2936 CHECK_CALLBACK_STATE(T);
2937 return Api::NewHandle(T, String::FromUTF16(utf16_array, length));
2938}
2939
2940DART_EXPORT Dart_Handle Dart_NewStringFromUTF32(const int32_t* utf32_array,
2941 intptr_t length) {
2942 DARTSCOPE(Thread::Current());
2943 API_TIMELINE_DURATION(T);
2944 if (utf32_array == NULL && length != 0) {
2945 RETURN_NULL_ERROR(utf32_array);
2946 }
2947 CHECK_LENGTH(length, String::kMaxElements);
2948 CHECK_CALLBACK_STATE(T);
2949 return Api::NewHandle(T, String::FromUTF32(utf32_array, length));
2950}
2951
2952DART_EXPORT Dart_Handle
2953Dart_NewExternalLatin1String(const uint8_t* latin1_array,
2954 intptr_t length,
2955 void* peer,
2956 intptr_t external_allocation_size,
2957 Dart_WeakPersistentHandleFinalizer callback) {
2958 DARTSCOPE(Thread::Current());
2959 API_TIMELINE_DURATION(T);
2960 if (latin1_array == NULL && length != 0) {
2961 RETURN_NULL_ERROR(latin1_array);
2962 }
2963 if (callback == NULL) {
2964 RETURN_NULL_ERROR(callback);
2965 }
2966 CHECK_LENGTH(length, String::kMaxElements);
2967 CHECK_CALLBACK_STATE(T);
2968 return Api::NewHandle(
2969 T,
2970 String::NewExternal(latin1_array, length, peer, external_allocation_size,
2971 callback, T->heap()->SpaceForExternal(length)));
2972}
2973
2974DART_EXPORT Dart_Handle
2975Dart_NewExternalUTF16String(const uint16_t* utf16_array,
2976 intptr_t length,
2977 void* peer,
2978 intptr_t external_allocation_size,
2979 Dart_WeakPersistentHandleFinalizer callback) {
2980 DARTSCOPE(Thread::Current());
2981 if (utf16_array == NULL && length != 0) {
2982 RETURN_NULL_ERROR(utf16_array);
2983 }
2984 if (callback == NULL) {
2985 RETURN_NULL_ERROR(callback);
2986 }
2987 CHECK_LENGTH(length, String::kMaxElements);
2988 CHECK_CALLBACK_STATE(T);
2989 intptr_t bytes = length * sizeof(*utf16_array);
2990 return Api::NewHandle(
2991 T,
2992 String::NewExternal(utf16_array, length, peer, external_allocation_size,
2993 callback, T->heap()->SpaceForExternal(bytes)));
2994}
2995
2996DART_EXPORT Dart_Handle Dart_StringToCString(Dart_Handle object,
2997 const char** cstr) {
2998 DARTSCOPE(Thread::Current());
2999 API_TIMELINE_DURATION(T);
3000 if (cstr == NULL) {
3001 RETURN_NULL_ERROR(cstr);
3002 }
3003 const String& str_obj = Api::UnwrapStringHandle(Z, object);
3004 if (str_obj.IsNull()) {
3005 RETURN_TYPE_ERROR(Z, object, String);
3006 }
3007 intptr_t string_length = Utf8::Length(str_obj);
3008 char* res = Api::TopScope(T)->zone()->Alloc<char>(string_length + 1);
3009 if (res == NULL) {
3010 return Api::NewError("Unable to allocate memory");
3011 }
3012 const char* string_value = str_obj.ToCString();
3013 memmove(res, string_value, string_length + 1);
3014 ASSERT(res[string_length] == '\0');
3015 *cstr = res;
3016 return Api::Success();
3017}
3018
3019DART_EXPORT Dart_Handle Dart_StringToUTF8(Dart_Handle str,
3020 uint8_t** utf8_array,
3021 intptr_t* length) {
3022 DARTSCOPE(Thread::Current());
3023 API_TIMELINE_DURATION(T);
3024 if (utf8_array == NULL) {
3025 RETURN_NULL_ERROR(utf8_array);
3026 }
3027 if (length == NULL) {
3028 RETURN_NULL_ERROR(length);
3029 }
3030 const String& str_obj = Api::UnwrapStringHandle(Z, str);
3031 if (str_obj.IsNull()) {
3032 RETURN_TYPE_ERROR(Z, str, String);
3033 }
3034 intptr_t str_len = Utf8::Length(str_obj);
3035 *utf8_array = Api::TopScope(T)->zone()->Alloc<uint8_t>(str_len);
3036 if (*utf8_array == NULL) {
3037 return Api::NewError("Unable to allocate memory");
3038 }
3039 str_obj.ToUTF8(*utf8_array, str_len);
3040 *length = str_len;
3041 return Api::Success();
3042}
3043
3044DART_EXPORT Dart_Handle Dart_StringToLatin1(Dart_Handle str,
3045 uint8_t* latin1_array,
3046 intptr_t* length) {
3047 DARTSCOPE(Thread::Current());
3048 API_TIMELINE_DURATION(T);
3049 if (latin1_array == NULL) {
3050 RETURN_NULL_ERROR(latin1_array);
3051 }
3052 if (length == NULL) {
3053 RETURN_NULL_ERROR(length);
3054 }
3055 const String& str_obj = Api::UnwrapStringHandle(Z, str);
3056 if (str_obj.IsNull() || !str_obj.IsOneByteString()) {
3057 RETURN_TYPE_ERROR(Z, str, String);
3058 }
3059 intptr_t str_len = str_obj.Length();
3060 intptr_t copy_len = (str_len > *length) ? *length : str_len;
3061
3062 // We have already asserted that the string object is a Latin-1 string
3063 // so we can copy the characters over using a simple loop.
3064 for (intptr_t i = 0; i < copy_len; i++) {
3065 latin1_array[i] = str_obj.CharAt(i);
3066 }
3067 *length = copy_len;
3068 return Api::Success();
3069}
3070
3071DART_EXPORT Dart_Handle Dart_StringToUTF16(Dart_Handle str,
3072 uint16_t* utf16_array,
3073 intptr_t* length) {
3074 DARTSCOPE(Thread::Current());
3075 API_TIMELINE_DURATION(T);
3076 const String& str_obj = Api::UnwrapStringHandle(Z, str);
3077 if (str_obj.IsNull()) {
3078 RETURN_TYPE_ERROR(Z, str, String);
3079 }
3080 intptr_t str_len = str_obj.Length();
3081 intptr_t copy_len = (str_len > *length) ? *length : str_len;
3082 for (intptr_t i = 0; i < copy_len; i++) {
3083 utf16_array[i] = str_obj.CharAt(i);
3084 }
3085 *length = copy_len;
3086 return Api::Success();
3087}
3088
3089DART_EXPORT Dart_Handle Dart_StringStorageSize(Dart_Handle str,
3090 intptr_t* size) {
3091 Thread* thread = Thread::Current();
3092 CHECK_ISOLATE(thread->isolate());
3093 TransitionNativeToVM transition(thread);
3094 ReusableObjectHandleScope reused_obj_handle(thread);
3095 const String& str_obj = Api::UnwrapStringHandle(reused_obj_handle, str);
3096 if (str_obj.IsNull()) {
3097 RETURN_TYPE_ERROR(thread->zone(), str, String);
3098 }
3099 if (size == NULL) {
3100 RETURN_NULL_ERROR(size);
3101 }
3102 *size = (str_obj.Length() * str_obj.CharSize());
3103 return Api::Success();
3104}
3105
3106DART_EXPORT Dart_Handle Dart_StringGetProperties(Dart_Handle object,
3107 intptr_t* char_size,
3108 intptr_t* str_len,
3109 void** peer) {
3110 Thread* thread = Thread::Current();
3111 CHECK_ISOLATE(thread->isolate());
3112 TransitionNativeToVM transition(thread);
3113 ReusableObjectHandleScope reused_obj_handle(thread);
3114 const String& str = Api::UnwrapStringHandle(reused_obj_handle, object);
3115 if (str.IsNull()) {
3116 RETURN_TYPE_ERROR(thread->zone(), object, String);
3117 }
3118 if (str.IsExternal()) {
3119 *peer = str.GetPeer();
3120 ASSERT(*peer != NULL);
3121 } else {
3122 NoSafepointScope no_safepoint_scope;
3123 *peer = thread->isolate()->heap()->GetPeer(str.raw());
3124 }
3125 *char_size = str.CharSize();
3126 *str_len = str.Length();
3127 return Api::Success();
3128}
3129
3130// --- Lists ---
3131
3132DART_EXPORT Dart_Handle Dart_NewList(intptr_t length) {
3133 return Dart_NewListOf(Dart_CoreType_Dynamic, length);
3134}
3135
3136static TypeArgumentsPtr TypeArgumentsForElementType(
3137 ObjectStore* store,
3138 Dart_CoreType_Id element_type_id) {
3139 switch (element_type_id) {
3140 case Dart_CoreType_Dynamic:
3141 return TypeArguments::null();
3142 case Dart_CoreType_Int:
3143 return store->type_argument_legacy_int();
3144 case Dart_CoreType_String:
3145 return store->type_argument_legacy_string();
3146 }
3147 UNREACHABLE();
3148 return TypeArguments::null();
3149}
3150
3151DART_EXPORT Dart_Handle Dart_NewListOf(Dart_CoreType_Id element_type_id,
3152 intptr_t length) {
3153 DARTSCOPE(Thread::Current());
3154 if (T->isolate()->null_safety() && element_type_id != Dart_CoreType_Dynamic) {
3155 return Api::NewError(
3156 "Cannot use legacy types with --sound-null-safety enabled. "
3157 "Use Dart_NewListOfType or Dart_NewListOfTypeFilled instead.");
3158 }
3159 CHECK_LENGTH(length, Array::kMaxElements);
3160 CHECK_CALLBACK_STATE(T);
3161 const Array& arr = Array::Handle(Z, Array::New(length));
3162 if (element_type_id != Dart_CoreType_Dynamic) {
3163 arr.SetTypeArguments(TypeArguments::Handle(
3164 Z, TypeArgumentsForElementType(T->isolate()->object_store(),
3165 element_type_id)));
3166 }
3167 return Api::NewHandle(T, arr.raw());
3168}
3169
3170static bool CanTypeContainNull(const Type& type) {
3171 return (type.nullability() == Nullability::kLegacy) ||
3172 (type.nullability() == Nullability::kNullable);
3173}
3174
3175DART_EXPORT Dart_Handle Dart_NewListOfType(Dart_Handle element_type,
3176 intptr_t length) {
3177 DARTSCOPE(Thread::Current());
3178 CHECK_LENGTH(length, Array::kMaxElements);
3179 CHECK_CALLBACK_STATE(T);
3180 const Type& type = Api::UnwrapTypeHandle(Z, element_type);
3181 if (type.IsNull()) {
3182 RETURN_TYPE_ERROR(Z, element_type, Type);
3183 }
3184 if (!type.IsFinalized()) {
3185 return Api::NewError(
3186 "%s expects argument 'type' to be a fully resolved type.",
3187 CURRENT_FUNC);
3188 }
3189 if ((length > 0) && !CanTypeContainNull(type)) {
3190 return Api::NewError("%s expects argument 'type' to be a nullable type.",
3191 CURRENT_FUNC);
3192 }
3193 return Api::NewHandle(T, Array::New(length, type));
3194}
3195
3196DART_EXPORT Dart_Handle Dart_NewListOfTypeFilled(Dart_Handle element_type,
3197 Dart_Handle fill_object,
3198 intptr_t length) {
3199 DARTSCOPE(Thread::Current());
3200 CHECK_LENGTH(length, Array::kMaxElements);
3201 CHECK_CALLBACK_STATE(T);
3202 const Type& type = Api::UnwrapTypeHandle(Z, element_type);
3203 if (type.IsNull()) {
3204 RETURN_TYPE_ERROR(Z, element_type, Type);
3205 }
3206 if (!type.IsFinalized()) {
3207 return Api::NewError(
3208 "%s expects argument 'type' to be a fully resolved type.",
3209 CURRENT_FUNC);
3210 }
3211 const Instance& instance = Api::UnwrapInstanceHandle(Z, fill_object);
3212 if (!instance.IsNull() && !InstanceIsType(T, instance, type)) {
3213 return Api::NewError(
3214 "%s expects argument 'fill_object' to have the same type as "
3215 "'element_type'.",
3216 CURRENT_FUNC);
3217 }
3218 if ((length > 0) && instance.IsNull() && !CanTypeContainNull(type)) {
3219 return Api::NewError(
3220 "%s expects argument 'fill_object' to be non-null for a non-nullable "
3221 "'element_type'.",
3222 CURRENT_FUNC);
3223 }
3224 Array& arr = Array::Handle(Z, Array::New(length, type));
3225 for (intptr_t i = 0; i < arr.Length(); ++i) {
3226 arr.SetAt(i, instance);
3227 }
3228 return Api::NewHandle(T, arr.raw());
3229}
3230
3231#define GET_LIST_LENGTH(zone, type, obj, len) \
3232 type& array = type::Handle(zone); \
3233 array ^= obj.raw(); \
3234 *len = array.Length(); \
3235 return Api::Success();
3236
3237DART_EXPORT Dart_Handle Dart_ListLength(Dart_Handle list, intptr_t* len) {
3238 DARTSCOPE(Thread::Current());
3239 const Object& obj = Object::Handle(Z, Api::UnwrapHandle(list));
3240 if (obj.IsError()) {
3241 // Pass through errors.
3242 return list;
3243 }
3244 if (obj.IsTypedData()) {
3245 GET_LIST_LENGTH(Z, TypedData, obj, len);
3246 }
3247 if (obj.IsArray()) {
3248 GET_LIST_LENGTH(Z, Array, obj, len);
3249 }
3250 if (obj.IsGrowableObjectArray()) {
3251 GET_LIST_LENGTH(Z, GrowableObjectArray, obj, len);
3252 }
3253 if (obj.IsExternalTypedData()) {
3254 GET_LIST_LENGTH(Z, ExternalTypedData, obj, len);
3255 }
3256 CHECK_CALLBACK_STATE(T);
3257
3258 // Now check and handle a dart object that implements the List interface.
3259 const Instance& instance = Instance::Handle(Z, GetListInstance(Z, obj));
3260 if (instance.IsNull()) {
3261 return Api::NewArgumentError(
3262 "Object does not implement the List interface");
3263 }
3264 const String& name = String::Handle(Z, Field::GetterName(Symbols::Length()));
3265 const int kTypeArgsLen = 0;
3266 const int kNumArgs = 1;
3267 ArgumentsDescriptor args_desc(
3268 Array::Handle(Z, ArgumentsDescriptor::NewBoxed(kTypeArgsLen, kNumArgs)));
3269 const Function& function =
3270 Function::Handle(Z, Resolver::ResolveDynamic(instance, name, args_desc));
3271 if (function.IsNull()) {
3272 return Api::NewArgumentError("List object does not have a 'length' field.");
3273 }
3274
3275 const Array& args = Array::Handle(Z, Array::New(kNumArgs));
3276 args.SetAt(0, instance); // Set up the receiver as the first argument.
3277 const Object& retval =
3278 Object::Handle(Z, DartEntry::InvokeFunction(function, args));
3279 if (retval.IsSmi()) {
3280 *len = Smi::Cast(retval).Value();
3281 return Api::Success();
3282 } else if (retval.IsMint()) {
3283 int64_t mint_value = Mint::Cast(retval).value();
3284 if (mint_value >= kIntptrMin && mint_value <= kIntptrMax) {
3285 *len = static_cast<intptr_t>(mint_value);
3286 return Api::Success();
3287 }
3288 return Api::NewError(
3289 "Length of List object is greater than the "
3290 "maximum value that 'len' parameter can hold");
3291 } else if (retval.IsError()) {
3292 return Api::NewHandle(T, retval.raw());
3293 } else {
3294 return Api::NewError("Length of List object is not an integer");
3295 }
3296}
3297
3298#define GET_LIST_ELEMENT(thread, type, obj, index) \
3299 const type& array_obj = type::Cast(obj); \
3300 if ((index >= 0) && (index < array_obj.Length())) { \
3301 return Api::NewHandle(thread, array_obj.At(index)); \
3302 } \
3303 return Api::NewError("Invalid index passed in to access list element");
3304
3305DART_EXPORT Dart_Handle Dart_ListGetAt(Dart_Handle list, intptr_t index) {
3306 DARTSCOPE(Thread::Current());
3307 const Object& obj = Object::Handle(Z, Api::UnwrapHandle(list));
3308 if (obj.IsArray()) {
3309 GET_LIST_ELEMENT(T, Array, obj, index);
3310 } else if (obj.IsGrowableObjectArray()) {
3311 GET_LIST_ELEMENT(T, GrowableObjectArray, obj, index);
3312 } else if (obj.IsError()) {
3313 return list;
3314 } else {
3315 CHECK_CALLBACK_STATE(T);
3316 // Check and handle a dart object that implements the List interface.
3317 const Instance& instance = Instance::Handle(Z, GetListInstance(Z, obj));
3318 if (!instance.IsNull()) {
3319 return Api::NewHandle(T,
3320 Send1Arg(instance, Symbols::IndexToken(),
3321 Instance::Handle(Z, Integer::New(index))));
3322 }
3323 return Api::NewArgumentError(
3324 "Object does not implement the 'List' interface");
3325 }
3326}
3327
3328#define GET_LIST_RANGE(thread, type, obj, offset, length) \
3329 const type& array_obj = type::Cast(obj); \
3330 if ((offset >= 0) && (offset + length <= array_obj.Length())) { \
3331 for (intptr_t index = 0; index < length; ++index) { \
3332 result[index] = Api::NewHandle(thread, array_obj.At(index + offset)); \
3333 } \
3334 return Api::Success(); \
3335 } \
3336 return Api::NewError("Invalid offset/length passed in to access list");
3337
3338DART_EXPORT Dart_Handle Dart_ListGetRange(Dart_Handle list,
3339 intptr_t offset,
3340 intptr_t length,
3341 Dart_Handle* result) {
3342 DARTSCOPE(Thread::Current());
3343 if (result == NULL) {
3344 RETURN_NULL_ERROR(result);
3345 }
3346 const Object& obj = Object::Handle(Z, Api::UnwrapHandle(list));
3347 if (obj.IsArray()) {
3348 GET_LIST_RANGE(T, Array, obj, offset, length);
3349 } else if (obj.IsGrowableObjectArray()) {
3350 GET_LIST_RANGE(T, GrowableObjectArray, obj, offset, length);
3351 } else if (obj.IsError()) {
3352 return list;
3353 } else {
3354 CHECK_CALLBACK_STATE(T);
3355 // Check and handle a dart object that implements the List interface.
3356 const Instance& instance = Instance::Handle(Z, GetListInstance(Z, obj));
3357 if (!instance.IsNull()) {
3358 const intptr_t kTypeArgsLen = 0;
3359 const intptr_t kNumArgs = 2;
3360 ArgumentsDescriptor args_desc(
3361 Array::Handle(ArgumentsDescriptor::NewBoxed(kTypeArgsLen, kNumArgs)));
3362 const Function& function = Function::Handle(
3363 Z, Resolver::ResolveDynamic(instance, Symbols::AssignIndexToken(),
3364 args_desc));
3365 if (!function.IsNull()) {
3366 const Array& args = Array::Handle(Array::New(kNumArgs));
3367 args.SetAt(0, instance);
3368 Instance& index = Instance::Handle(Z);
3369 for (intptr_t i = 0; i < length; ++i) {
3370 index = Integer::New(i);
3371 args.SetAt(1, index);
3372 Dart_Handle value =
3373 Api::NewHandle(T, DartEntry::InvokeFunction(function, args));
3374 if (Api::IsError(value)) return value;
3375 result[i] = value;
3376 }
3377 return Api::Success();
3378 }
3379 }
3380 return Api::NewArgumentError(
3381 "Object does not implement the 'List' interface");
3382 }
3383}
3384
3385#define SET_LIST_ELEMENT(type, obj, index, value) \
3386 const type& array = type::Cast(obj); \
3387 const Object& value_obj = Object::Handle(Z, Api::UnwrapHandle(value)); \
3388 if (!value_obj.IsNull() && !value_obj.IsInstance()) { \
3389 RETURN_TYPE_ERROR(Z, value, Instance); \
3390 } \
3391 if ((index >= 0) && (index < array.Length())) { \
3392 array.SetAt(index, value_obj); \
3393 return Api::Success(); \
3394 } \
3395 return Api::NewError("Invalid index passed in to set list element");
3396
3397DART_EXPORT Dart_Handle Dart_ListSetAt(Dart_Handle list,
3398 intptr_t index,
3399 Dart_Handle value) {
3400 DARTSCOPE(Thread::Current());
3401 const Object& obj = Object::Handle(Z, Api::UnwrapHandle(list));
3402 // If the list is immutable we call into Dart for the indexed setter to
3403 // get the unsupported operation exception as the result.
3404 if (obj.IsArray() && !Array::Cast(obj).IsImmutable()) {
3405 SET_LIST_ELEMENT(Array, obj, index, value);
3406 } else if (obj.IsGrowableObjectArray()) {
3407 SET_LIST_ELEMENT(GrowableObjectArray, obj, index, value);
3408 } else if (obj.IsError()) {
3409 return list;
3410 } else {
3411 CHECK_CALLBACK_STATE(T);
3412
3413 // Check and handle a dart object that implements the List interface.
3414 const Instance& instance = Instance::Handle(Z, GetListInstance(Z, obj));
3415 if (!instance.IsNull()) {
3416 const intptr_t kTypeArgsLen = 0;
3417 const intptr_t kNumArgs = 3;
3418 ArgumentsDescriptor args_desc(
3419 Array::Handle(ArgumentsDescriptor::NewBoxed(kTypeArgsLen, kNumArgs)));
3420 const Function& function = Function::Handle(
3421 Z, Resolver::ResolveDynamic(instance, Symbols::AssignIndexToken(),
3422 args_desc));
3423 if (!function.IsNull()) {
3424 const Integer& index_obj = Integer::Handle(Z, Integer::New(index));
3425 const Object& value_obj = Object::Handle(Z, Api::UnwrapHandle(value));
3426 if (!value_obj.IsNull() && !value_obj.IsInstance()) {
3427 RETURN_TYPE_ERROR(Z, value, Instance);
3428 }
3429 const Array& args = Array::Handle(Z, Array::New(kNumArgs));
3430 args.SetAt(0, instance);
3431 args.SetAt(1, index_obj);
3432 args.SetAt(2, value_obj);
3433 return Api::NewHandle(T, DartEntry::InvokeFunction(function, args));
3434 }
3435 }
3436 return Api::NewArgumentError(
3437 "Object does not implement the 'List' interface");
3438 }
3439}
3440
3441static ObjectPtr ResolveConstructor(const char* current_func,
3442 const Class& cls,
3443 const String& class_name,
3444 const String& dotted_name,
3445 int num_args);
3446
3447static ObjectPtr ThrowArgumentError(const char* exception_message) {
3448 Thread* thread = Thread::Current();
3449 Zone* zone = thread->zone();
3450 // Lookup the class ArgumentError in dart:core.
3451 const String& lib_url = String::Handle(String::New("dart:core"));
3452 const String& class_name = String::Handle(String::New("ArgumentError"));
3453 const Library& lib =
3454 Library::Handle(zone, Library::LookupLibrary(thread, lib_url));
3455 if (lib.IsNull()) {
3456 const String& message = String::Handle(String::NewFormatted(
3457 "%s: library '%s' not found.", CURRENT_FUNC, lib_url.ToCString()));
3458 return ApiError::New(message);
3459 }
3460 const Class& cls =
3461 Class::Handle(zone, lib.LookupClassAllowPrivate(class_name));
3462 ASSERT(!cls.IsNull());
3463 Object& result = Object::Handle(zone);
3464 String& dot_name = String::Handle(String::New("."));
3465 String& constr_name = String::Handle(String::Concat(class_name, dot_name));
3466 result = ResolveConstructor(CURRENT_FUNC, cls, class_name, constr_name, 1);
3467 if (result.IsError()) return result.raw();
3468 ASSERT(result.IsFunction());
3469 Function& constructor = Function::Handle(zone);
3470 constructor ^= result.raw();
3471 if (!constructor.IsGenerativeConstructor()) {
3472 const String& message = String::Handle(
3473 String::NewFormatted("%s: class '%s' is not a constructor.",
3474 CURRENT_FUNC, class_name.ToCString()));
3475 return ApiError::New(message);
3476 }
3477 Instance& exception = Instance::Handle(zone);
3478 exception = Instance::New(cls);
3479 const Array& args = Array::Handle(zone, Array::New(2));
3480 args.SetAt(0, exception);
3481 args.SetAt(1, String::Handle(String::New(exception_message)));
3482 result = DartEntry::InvokeFunction(constructor, args);
3483 if (result.IsError()) return result.raw();
3484 ASSERT(result.IsNull());
3485
3486 if (thread->top_exit_frame_info() == 0) {
3487 // There are no dart frames on the stack so it would be illegal to
3488 // throw an exception here.
3489 const String& message = String::Handle(
3490 String::New("No Dart frames on stack, cannot throw exception"));
3491 return ApiError::New(message);
3492 }
3493 // Unwind all the API scopes till the exit frame before throwing an
3494 // exception.
3495 const Instance* saved_exception;
3496 {
3497 NoSafepointScope no_safepoint;
3498 InstancePtr raw_exception = exception.raw();
3499 thread->UnwindScopes(thread->top_exit_frame_info());
3500 saved_exception = &Instance::Handle(raw_exception);
3501 }
3502 Exceptions::Throw(thread, *saved_exception);
3503 const String& message =
3504 String::Handle(String::New("Exception was not thrown, internal error"));
3505 return ApiError::New(message);
3506}
3507
3508// TODO(sgjesse): value should always be smaller then 0xff. Add error handling.
3509#define GET_LIST_ELEMENT_AS_BYTES(type, obj, native_array, offset, length) \
3510 const type& array = type::Cast(obj); \
3511 if (Utils::RangeCheck(offset, length, array.Length())) { \
3512 Object& element = Object::Handle(Z); \
3513 for (int i = 0; i < length; i++) { \
3514 element = array.At(offset + i); \
3515 if (!element.IsInteger()) { \
3516 return Api::NewHandle( \
3517 T, ThrowArgumentError("List contains non-int elements")); \
3518 } \
3519 const Integer& integer = Integer::Cast(element); \
3520 native_array[i] = static_cast<uint8_t>(integer.AsInt64Value() & 0xff); \
3521 ASSERT(integer.AsInt64Value() <= 0xff); \
3522 } \
3523 return Api::Success(); \
3524 } \
3525 return Api::NewError("Invalid length passed in to access array elements");
3526
3527template <typename T>
3528static Dart_Handle CopyBytes(const T& array,
3529 intptr_t offset,
3530 uint8_t* native_array,
3531 intptr_t length) {
3532 ASSERT(array.ElementSizeInBytes() == 1);
3533 NoSafepointScope no_safepoint;
3534 memmove(native_array, reinterpret_cast<uint8_t*>(array.DataAddr(offset)),
3535 length);
3536 return Api::Success();
3537}
3538
3539DART_EXPORT Dart_Handle Dart_ListGetAsBytes(Dart_Handle list,
3540 intptr_t offset,
3541 uint8_t* native_array,
3542 intptr_t length) {
3543 DARTSCOPE(Thread::Current());
3544 const Object& obj = Object::Handle(Z, Api::UnwrapHandle(list));
3545 if (obj.IsTypedData()) {
3546 const TypedData& array = TypedData::Cast(obj);
3547 if (array.ElementSizeInBytes() == 1) {
3548 if (!Utils::RangeCheck(offset, length, array.Length())) {
3549 return Api::NewError(
3550 "Invalid length passed in to access list elements");
3551 }
3552 return CopyBytes(array, offset, native_array, length);
3553 }
3554 }
3555 if (obj.IsExternalTypedData()) {
3556 const ExternalTypedData& external_array = ExternalTypedData::Cast(obj);
3557 if (external_array.ElementSizeInBytes() == 1) {
3558 if (!Utils::RangeCheck(offset, length, external_array.Length())) {
3559 return Api::NewError(
3560 "Invalid length passed in to access list elements");
3561 }
3562 return CopyBytes(external_array, offset, native_array, length);
3563 }
3564 }
3565 if (IsTypedDataViewClassId(obj.GetClassId())) {
3566 const auto& view = TypedDataView::Cast(obj);
3567 if (view.ElementSizeInBytes() == 1) {
3568 const intptr_t view_length = Smi::Value(view.length());
3569 if (!Utils::RangeCheck(offset, length, view_length)) {
3570 return Api::NewError(
3571 "Invalid length passed in to access list elements");
3572 }
3573 const auto& data = Instance::Handle(view.typed_data());
3574 if (data.IsTypedData()) {
3575 const TypedData& array = TypedData::Cast(data);
3576 if (array.ElementSizeInBytes() == 1) {
3577 const intptr_t data_offset =
3578 Smi::Value(view.offset_in_bytes()) + offset;
3579 // Range check already performed on the view object.
3580 ASSERT(Utils::RangeCheck(data_offset, length, array.Length()));
3581 return CopyBytes(array, data_offset, native_array, length);
3582 }
3583 }
3584 }
3585 }
3586 if (obj.IsArray()) {
3587 GET_LIST_ELEMENT_AS_BYTES(Array, obj, native_array, offset, length);
3588 }
3589 if (obj.IsGrowableObjectArray()) {
3590 GET_LIST_ELEMENT_AS_BYTES(GrowableObjectArray, obj, native_array, offset,
3591 length);
3592 }
3593 if (obj.IsError()) {
3594 return list;
3595 }
3596 CHECK_CALLBACK_STATE(T);
3597
3598 // Check and handle a dart object that implements the List interface.
3599 const Instance& instance = Instance::Handle(Z, GetListInstance(Z, obj));
3600 if (!instance.IsNull()) {
3601 const int kTypeArgsLen = 0;
3602 const int kNumArgs = 2;
3603 ArgumentsDescriptor args_desc(
3604 Array::Handle(ArgumentsDescriptor::NewBoxed(kTypeArgsLen, kNumArgs)));
3605 const Function& function = Function::Handle(
3606 Z,
3607 Resolver::ResolveDynamic(instance, Symbols::IndexToken(), args_desc));
3608 if (!function.IsNull()) {
3609 Object& result = Object::Handle(Z);
3610 Integer& intobj = Integer::Handle(Z);
3611 const Array& args = Array::Handle(Z, Array::New(kNumArgs));
3612 args.SetAt(0, instance); // Set up the receiver as the first argument.
3613 for (int i = 0; i < length; i++) {
3614 HANDLESCOPE(T);
3615 intobj = Integer::New(offset + i);
3616 args.SetAt(1, intobj);
3617 result = DartEntry::InvokeFunction(function, args);
3618 if (result.IsError()) {
3619 return Api::NewHandle(T, result.raw());
3620 }
3621 if (!result.IsInteger()) {
3622 return Api::NewError(
3623 "%s expects the argument 'list' to be "
3624 "a List of int",
3625 CURRENT_FUNC);
3626 }
3627 const Integer& integer_result = Integer::Cast(result);
3628 ASSERT(integer_result.AsInt64Value() <= 0xff);
3629 // TODO(hpayer): value should always be smaller then 0xff. Add error
3630 // handling.
3631 native_array[i] =
3632 static_cast<uint8_t>(integer_result.AsInt64Value() & 0xff);
3633 }
3634 return Api::Success();
3635 }
3636 }
3637 return Api::NewArgumentError(
3638 "Object does not implement the 'List' interface");
3639}
3640
3641#define SET_LIST_ELEMENT_AS_BYTES(type, obj, native_array, offset, length) \
3642 const type& array = type::Cast(obj); \
3643 Integer& integer = Integer::Handle(Z); \
3644 if (Utils::RangeCheck(offset, length, array.Length())) { \
3645 for (int i = 0; i < length; i++) { \
3646 integer = Integer::New(native_array[i]); \
3647 array.SetAt(offset + i, integer); \
3648 } \
3649 return Api::Success(); \
3650 } \
3651 return Api::NewError("Invalid length passed in to set array elements");
3652
3653DART_EXPORT Dart_Handle Dart_ListSetAsBytes(Dart_Handle list,
3654 intptr_t offset,
3655 const uint8_t* native_array,
3656 intptr_t length) {
3657 DARTSCOPE(Thread::Current());
3658 const Object& obj = Object::Handle(Z, Api::UnwrapHandle(list));
3659 if (obj.IsTypedData()) {
3660 const TypedData& array = TypedData::Cast(obj);
3661 if (array.ElementSizeInBytes() == 1) {
3662 if (Utils::RangeCheck(offset, length, array.Length())) {
3663 NoSafepointScope no_safepoint;
3664 memmove(reinterpret_cast<uint8_t*>(array.DataAddr(offset)),
3665 native_array, length);
3666 return Api::Success();
3667 }
3668 return Api::NewError("Invalid length passed in to access list elements");
3669 }
3670 }
3671 if (obj.IsArray() && !Array::Cast(obj).IsImmutable()) {
3672 // If the list is immutable we call into Dart for the indexed setter to
3673 // get the unsupported operation exception as the result.
3674 SET_LIST_ELEMENT_AS_BYTES(Array, obj, native_array, offset, length);
3675 }
3676 if (obj.IsGrowableObjectArray()) {
3677 SET_LIST_ELEMENT_AS_BYTES(GrowableObjectArray, obj, native_array, offset,
3678 length);
3679 }
3680 if (obj.IsError()) {
3681 return list;
3682 }
3683 CHECK_CALLBACK_STATE(T);
3684
3685 // Check and handle a dart object that implements the List interface.
3686 const Instance& instance = Instance::Handle(Z, GetListInstance(Z, obj));
3687 if (!instance.IsNull()) {
3688 const int kTypeArgsLen = 0;
3689 const int kNumArgs = 3;
3690 ArgumentsDescriptor args_desc(Array::Handle(
3691 Z, ArgumentsDescriptor::NewBoxed(kTypeArgsLen, kNumArgs)));
3692 const Function& function = Function::Handle(
3693 Z, Resolver::ResolveDynamic(instance, Symbols::AssignIndexToken(),
3694 args_desc));
3695 if (!function.IsNull()) {
3696 Integer& indexobj = Integer::Handle(Z);
3697 Integer& valueobj = Integer::Handle(Z);
3698 const Array& args = Array::Handle(Z, Array::New(kNumArgs));
3699 args.SetAt(0, instance); // Set up the receiver as the first argument.
3700 for (int i = 0; i < length; i++) {
3701 indexobj = Integer::New(offset + i);
3702 valueobj = Integer::New(native_array[i]);
3703 args.SetAt(1, indexobj);
3704 args.SetAt(2, valueobj);
3705 const Object& result =
3706 Object::Handle(Z, DartEntry::InvokeFunction(function, args));
3707 if (result.IsError()) {
3708 return Api::NewHandle(T, result.raw());
3709 }
3710 }
3711 return Api::Success();
3712 }
3713 }
3714 return Api::NewArgumentError(
3715 "Object does not implement the 'List' interface");
3716}
3717
3718// --- Maps ---
3719
3720DART_EXPORT Dart_Handle Dart_MapGetAt(Dart_Handle map, Dart_Handle key) {
3721 DARTSCOPE(Thread::Current());
3722 CHECK_CALLBACK_STATE(T);
3723 const Object& obj = Object::Handle(Z, Api::UnwrapHandle(map));
3724 const Instance& instance = Instance::Handle(Z, GetMapInstance(Z, obj));
3725 if (!instance.IsNull()) {
3726 const Object& key_obj = Object::Handle(Api::UnwrapHandle(key));
3727 if (!(key_obj.IsInstance() || key_obj.IsNull())) {
3728 return Api::NewError("Key is not an instance");
3729 }
3730 return Api::NewHandle(
3731 T, Send1Arg(instance, Symbols::IndexToken(), Instance::Cast(key_obj)));
3732 }
3733 return Api::NewArgumentError("Object does not implement the 'Map' interface");
3734}
3735
3736DART_EXPORT Dart_Handle Dart_MapContainsKey(Dart_Handle map, Dart_Handle key) {
3737 DARTSCOPE(Thread::Current());
3738 CHECK_CALLBACK_STATE(T);
3739 const Object& obj = Object::Handle(Z, Api::UnwrapHandle(map));
3740 const Instance& instance = Instance::Handle(Z, GetMapInstance(Z, obj));
3741 if (!instance.IsNull()) {
3742 const Object& key_obj = Object::Handle(Z, Api::UnwrapHandle(key));
3743 if (!(key_obj.IsInstance() || key_obj.IsNull())) {
3744 return Api::NewError("Key is not an instance");
3745 }
3746 return Api::NewHandle(
3747 T, Send1Arg(instance, String::Handle(Z, String::New("containsKey")),
3748 Instance::Cast(key_obj)));
3749 }
3750 return Api::NewArgumentError("Object does not implement the 'Map' interface");
3751}
3752
3753DART_EXPORT Dart_Handle Dart_MapKeys(Dart_Handle map) {
3754 DARTSCOPE(Thread::Current());
3755 CHECK_CALLBACK_STATE(T);
3756 Object& obj = Object::Handle(Z, Api::UnwrapHandle(map));
3757 Instance& instance = Instance::Handle(Z, GetMapInstance(Z, obj));
3758 if (!instance.IsNull()) {
3759 const Object& iterator = Object::Handle(
3760 Send0Arg(instance, String::Handle(Z, String::New("get:keys"))));
3761 if (!iterator.IsInstance()) {
3762 return Api::NewHandle(T, iterator.raw());
3763 }
3764 return Api::NewHandle(T, Send0Arg(Instance::Cast(iterator),
3765 String::Handle(String::New("toList"))));
3766 }
3767 return Api::NewArgumentError("Object does not implement the 'Map' interface");
3768}
3769
3770// --- Typed Data ---
3771
3772// Helper method to get the type of a TypedData object.
3773static Dart_TypedData_Type GetType(intptr_t class_id) {
3774 Dart_TypedData_Type type;
3775 switch (class_id) {
3776 case kByteDataViewCid:
3777 type = Dart_TypedData_kByteData;
3778 break;
3779 case kTypedDataInt8ArrayCid:
3780 case kTypedDataInt8ArrayViewCid:
3781 case kExternalTypedDataInt8ArrayCid:
3782 type = Dart_TypedData_kInt8;
3783 break;
3784 case kTypedDataUint8ArrayCid:
3785 case kTypedDataUint8ArrayViewCid:
3786 case kExternalTypedDataUint8ArrayCid:
3787 type = Dart_TypedData_kUint8;
3788 break;
3789 case kTypedDataUint8ClampedArrayCid:
3790 case kTypedDataUint8ClampedArrayViewCid:
3791 case kExternalTypedDataUint8ClampedArrayCid:
3792 type = Dart_TypedData_kUint8Clamped;
3793 break;
3794 case kTypedDataInt16ArrayCid:
3795 case kTypedDataInt16ArrayViewCid:
3796 case kExternalTypedDataInt16ArrayCid:
3797 type = Dart_TypedData_kInt16;
3798 break;
3799 case kTypedDataUint16ArrayCid:
3800 case kTypedDataUint16ArrayViewCid:
3801 case kExternalTypedDataUint16ArrayCid:
3802 type = Dart_TypedData_kUint16;
3803 break;
3804 case kTypedDataInt32ArrayCid:
3805 case kTypedDataInt32ArrayViewCid:
3806 case kExternalTypedDataInt32ArrayCid:
3807 type = Dart_TypedData_kInt32;
3808 break;
3809 case kTypedDataUint32ArrayCid:
3810 case kTypedDataUint32ArrayViewCid:
3811 case kExternalTypedDataUint32ArrayCid:
3812 type = Dart_TypedData_kUint32;
3813 break;
3814 case kTypedDataInt64ArrayCid:
3815 case kTypedDataInt64ArrayViewCid:
3816 case kExternalTypedDataInt64ArrayCid:
3817 type = Dart_TypedData_kInt64;
3818 break;
3819 case kTypedDataUint64ArrayCid:
3820 case kTypedDataUint64ArrayViewCid:
3821 case kExternalTypedDataUint64ArrayCid:
3822 type = Dart_TypedData_kUint64;
3823 break;
3824 case kTypedDataFloat32ArrayCid:
3825 case kTypedDataFloat32ArrayViewCid:
3826 case kExternalTypedDataFloat32ArrayCid:
3827 type = Dart_TypedData_kFloat32;
3828 break;
3829 case kTypedDataFloat64ArrayCid:
3830 case kTypedDataFloat64ArrayViewCid:
3831 case kExternalTypedDataFloat64ArrayCid:
3832 type = Dart_TypedData_kFloat64;
3833 break;
3834 case kTypedDataInt32x4ArrayCid:
3835 case kTypedDataInt32x4ArrayViewCid:
3836 case kExternalTypedDataInt32x4ArrayCid:
3837 type = Dart_TypedData_kInt32x4;
3838 break;
3839 case kTypedDataFloat32x4ArrayCid:
3840 case kTypedDataFloat32x4ArrayViewCid:
3841 case kExternalTypedDataFloat32x4ArrayCid:
3842 type = Dart_TypedData_kFloat32x4;
3843 break;
3844 case kTypedDataFloat64x2ArrayCid:
3845 case kTypedDataFloat64x2ArrayViewCid:
3846 case kExternalTypedDataFloat64x2ArrayCid:
3847 type = Dart_TypedData_kFloat64x2;
3848 break;
3849 default:
3850 type = Dart_TypedData_kInvalid;
3851 break;
3852 }
3853 return type;
3854}
3855
3856DART_EXPORT Dart_TypedData_Type Dart_GetTypeOfTypedData(Dart_Handle object) {
3857 Thread* thread = Thread::Current();
3858 API_TIMELINE_DURATION(thread);
3859 TransitionNativeToVM transition(thread);
3860 intptr_t class_id = Api::ClassId(object);
3861 if (IsTypedDataClassId(class_id) || IsTypedDataViewClassId(class_id)) {
3862 return GetType(class_id);
3863 }
3864 return Dart_TypedData_kInvalid;
3865}
3866
3867DART_EXPORT Dart_TypedData_Type
3868Dart_GetTypeOfExternalTypedData(Dart_Handle object) {
3869 Thread* thread = Thread::Current();
3870 API_TIMELINE_DURATION(thread);
3871 TransitionNativeToVM transition(thread);
3872 intptr_t class_id = Api::ClassId(object);
3873 if (IsExternalTypedDataClassId(class_id)) {
3874 return GetType(class_id);
3875 }
3876 if (IsTypedDataViewClassId(class_id)) {
3877 // Check if data object of the view is external.
3878 Zone* zone = thread->zone();
3879 const auto& view_obj = Api::UnwrapTypedDataViewHandle(zone, object);
3880 ASSERT(!view_obj.IsNull());
3881 const auto& data_obj = Instance::Handle(zone, view_obj.typed_data());
3882 if (ExternalTypedData::IsExternalTypedData(data_obj)) {
3883 return GetType(class_id);
3884 }
3885 }
3886 return Dart_TypedData_kInvalid;
3887}
3888
3889static ObjectPtr GetByteDataConstructor(Thread* thread,
3890 const String& constructor_name,
3891 intptr_t num_args) {
3892 const Library& lib =
3893 Library::Handle(thread->isolate()->object_store()->typed_data_library());
3894 ASSERT(!lib.IsNull());
3895 const Class& cls = Class::Handle(
3896 thread->zone(), lib.LookupClassAllowPrivate(Symbols::ByteData()));
3897 ASSERT(!cls.IsNull());
3898 return ResolveConstructor(CURRENT_FUNC, cls, Symbols::ByteData(),
3899 constructor_name, num_args);
3900}
3901
3902static Dart_Handle NewByteData(Thread* thread, intptr_t length) {
3903 CHECK_LENGTH(length, TypedData::MaxElements(kTypedDataInt8ArrayCid));
3904 Zone* zone = thread->zone();
3905 Object& result = Object::Handle(zone);
3906 result = GetByteDataConstructor(thread, Symbols::ByteDataDot(), 1);
3907 ASSERT(!result.IsNull());
3908 ASSERT(result.IsFunction());
3909 const Function& factory = Function::Cast(result);
3910 ASSERT(!factory.IsGenerativeConstructor());
3911
3912 // Create the argument list.
3913 const Array& args = Array::Handle(zone, Array::New(2));
3914 // Factories get type arguments.
3915 args.SetAt(0, Object::null_type_arguments());
3916 args.SetAt(1, Smi::Handle(zone, Smi::New(length)));
3917
3918 // Invoke the constructor and return the new object.
3919 result = DartEntry::InvokeFunction(factory, args);
3920 ASSERT(result.IsInstance() || result.IsNull() || result.IsError());
3921 return Api::NewHandle(thread, result.raw());
3922}
3923
3924static Dart_Handle NewTypedData(Thread* thread, intptr_t cid, intptr_t length) {
3925 CHECK_LENGTH(length, TypedData::MaxElements(cid));
3926 return Api::NewHandle(thread, TypedData::New(cid, length));
3927}
3928
3929static Dart_Handle NewExternalTypedData(
3930 Thread* thread,
3931 intptr_t cid,
3932 void* data,
3933 intptr_t length,
3934 void* peer,
3935 intptr_t external_allocation_size,
3936 Dart_WeakPersistentHandleFinalizer callback) {
3937 CHECK_LENGTH(length, ExternalTypedData::MaxElements(cid));
3938 Zone* zone = thread->zone();
3939 intptr_t bytes = length * ExternalTypedData::ElementSizeInBytes(cid);
3940 auto& cls = Class::Handle(zone, thread->isolate()->class_table()->At(cid));
3941 auto& result = Object::Handle(zone, cls.EnsureIsAllocateFinalized(thread));
3942 if (result.IsError()) {
3943 return Api::NewHandle(thread, result.raw());
3944 }
3945 result = ExternalTypedData::New(cid, reinterpret_cast<uint8_t*>(data), length,
3946 thread->heap()->SpaceForExternal(bytes));
3947 if (callback != nullptr) {
3948 AllocateWeakPersistentHandle(thread, result, peer, external_allocation_size,
3949 callback);
3950 }
3951 return Api::NewHandle(thread, result.raw());
3952}
3953
3954static Dart_Handle NewExternalByteData(
3955 Thread* thread,
3956 void* data,
3957 intptr_t length,
3958 void* peer,
3959 intptr_t external_allocation_size,
3960 Dart_WeakPersistentHandleFinalizer callback) {
3961 Zone* zone = thread->zone();
3962 Dart_Handle ext_data =
3963 NewExternalTypedData(thread, kExternalTypedDataUint8ArrayCid, data,
3964 length, peer, external_allocation_size, callback);
3965 if (Api::IsError(ext_data)) {
3966 return ext_data;
3967 }
3968 Object& result = Object::Handle(zone);
3969 result = GetByteDataConstructor(thread, Symbols::ByteDataDot_view(), 3);
3970 ASSERT(!result.IsNull());
3971 ASSERT(result.IsFunction());
3972 const Function& factory = Function::Cast(result);
3973 ASSERT(!factory.IsGenerativeConstructor());
3974
3975 // Create the argument list.
3976 const intptr_t num_args = 3;
3977 const Array& args = Array::Handle(zone, Array::New(num_args + 1));
3978 // Factories get type arguments.
3979 args.SetAt(0, Object::null_type_arguments());
3980 const ExternalTypedData& array =
3981 Api::UnwrapExternalTypedDataHandle(zone, ext_data);
3982 args.SetAt(1, array);
3983 Smi& smi = Smi::Handle(zone);
3984 smi = Smi::New(0);
3985 args.SetAt(2, smi);
3986 smi = Smi::New(length);
3987 args.SetAt(3, smi);
3988
3989 // Invoke the constructor and return the new object.
3990 result = DartEntry::InvokeFunction(factory, args);
3991 ASSERT(result.IsNull() || result.IsInstance() || result.IsError());
3992 return Api::NewHandle(thread, result.raw());
3993}
3994
3995DART_EXPORT Dart_Handle Dart_NewTypedData(Dart_TypedData_Type type,
3996 intptr_t length) {
3997 DARTSCOPE(Thread::Current());
3998 CHECK_CALLBACK_STATE(T);
3999 switch (type) {
4000 case Dart_TypedData_kByteData:
4001 return NewByteData(T, length);
4002 case Dart_TypedData_kInt8:
4003 return NewTypedData(T, kTypedDataInt8ArrayCid, length);
4004 case Dart_TypedData_kUint8:
4005 return NewTypedData(T, kTypedDataUint8ArrayCid, length);
4006 case Dart_TypedData_kUint8Clamped:
4007 return NewTypedData(T, kTypedDataUint8ClampedArrayCid, length);
4008 case Dart_TypedData_kInt16:
4009 return NewTypedData(T, kTypedDataInt16ArrayCid, length);
4010 case Dart_TypedData_kUint16:
4011 return NewTypedData(T, kTypedDataUint16ArrayCid, length);
4012 case Dart_TypedData_kInt32:
4013 return NewTypedData(T, kTypedDataInt32ArrayCid, length);
4014 case Dart_TypedData_kUint32:
4015 return NewTypedData(T, kTypedDataUint32ArrayCid, length);
4016 case Dart_TypedData_kInt64:
4017 return NewTypedData(T, kTypedDataInt64ArrayCid, length);
4018 case Dart_TypedData_kUint64:
4019 return NewTypedData(T, kTypedDataUint64ArrayCid, length);
4020 case Dart_TypedData_kFloat32:
4021 return NewTypedData(T, kTypedDataFloat32ArrayCid, length);
4022 case Dart_TypedData_kFloat64:
4023 return NewTypedData(T, kTypedDataFloat64ArrayCid, length);
4024 case Dart_TypedData_kInt32x4:
4025 return NewTypedData(T, kTypedDataInt32x4ArrayCid, length);
4026 case Dart_TypedData_kFloat32x4:
4027 return NewTypedData(T, kTypedDataFloat32x4ArrayCid, length);
4028 case Dart_TypedData_kFloat64x2:
4029 return NewTypedData(T, kTypedDataFloat64x2ArrayCid, length);
4030 default:
4031 return Api::NewError("%s expects argument 'type' to be of 'TypedData'",
4032 CURRENT_FUNC);
4033 }
4034 UNREACHABLE();
4035 return Api::Null();
4036}
4037
4038DART_EXPORT Dart_Handle Dart_NewExternalTypedData(Dart_TypedData_Type type,
4039 void* data,
4040 intptr_t length) {
4041 return Dart_NewExternalTypedDataWithFinalizer(type, data, length, NULL, 0,
4042 NULL);
4043}
4044
4045DART_EXPORT Dart_Handle Dart_NewExternalTypedDataWithFinalizer(
4046 Dart_TypedData_Type type,
4047 void* data,
4048 intptr_t length,
4049 void* peer,
4050 intptr_t external_allocation_size,
4051 Dart_WeakPersistentHandleFinalizer callback) {
4052 DARTSCOPE(Thread::Current());
4053 if (data == NULL && length != 0) {
4054 RETURN_NULL_ERROR(data);
4055 }
4056 CHECK_CALLBACK_STATE(T);
4057 switch (type) {
4058 case Dart_TypedData_kByteData:
4059 return NewExternalByteData(T, data, length, peer,
4060 external_allocation_size, callback);
4061 case Dart_TypedData_kInt8:
4062 return NewExternalTypedData(T, kExternalTypedDataInt8ArrayCid, data,
4063 length, peer, external_allocation_size,
4064 callback);
4065 case Dart_TypedData_kUint8:
4066 return NewExternalTypedData(T, kExternalTypedDataUint8ArrayCid, data,
4067 length, peer, external_allocation_size,
4068 callback);
4069 case Dart_TypedData_kUint8Clamped:
4070 return NewExternalTypedData(T, kExternalTypedDataUint8ClampedArrayCid,
4071 data, length, peer, external_allocation_size,
4072 callback);
4073 case Dart_TypedData_kInt16:
4074 return NewExternalTypedData(T, kExternalTypedDataInt16ArrayCid, data,
4075 length, peer, external_allocation_size,
4076 callback);
4077 case Dart_TypedData_kUint16:
4078 return NewExternalTypedData(T, kExternalTypedDataUint16ArrayCid, data,
4079 length, peer, external_allocation_size,
4080 callback);
4081 case Dart_TypedData_kInt32:
4082 return NewExternalTypedData(T, kExternalTypedDataInt32ArrayCid, data,
4083 length, peer, external_allocation_size,
4084 callback);
4085 case Dart_TypedData_kUint32:
4086 return NewExternalTypedData(T, kExternalTypedDataUint32ArrayCid, data,
4087 length, peer, external_allocation_size,
4088 callback);
4089 case Dart_TypedData_kInt64:
4090 return NewExternalTypedData(T, kExternalTypedDataInt64ArrayCid, data,
4091 length, peer, external_allocation_size,
4092 callback);
4093 case Dart_TypedData_kUint64:
4094 return NewExternalTypedData(T, kExternalTypedDataUint64ArrayCid, data,
4095 length, peer, external_allocation_size,
4096 callback);
4097 case Dart_TypedData_kFloat32:
4098 return NewExternalTypedData(T, kExternalTypedDataFloat32ArrayCid, data,
4099 length, peer, external_allocation_size,
4100 callback);
4101 case Dart_TypedData_kFloat64:
4102 return NewExternalTypedData(T, kExternalTypedDataFloat64ArrayCid, data,
4103 length, peer, external_allocation_size,
4104 callback);
4105 case Dart_TypedData_kInt32x4:
4106 return NewExternalTypedData(T, kExternalTypedDataInt32x4ArrayCid, data,
4107 length, peer, external_allocation_size,
4108 callback);
4109 case Dart_TypedData_kFloat32x4:
4110 return NewExternalTypedData(T, kExternalTypedDataFloat32x4ArrayCid, data,
4111 length, peer, external_allocation_size,
4112 callback);
4113 case Dart_TypedData_kFloat64x2:
4114 return NewExternalTypedData(T, kExternalTypedDataFloat64x2ArrayCid, data,
4115 length, peer, external_allocation_size,
4116 callback);
4117 default:
4118 return Api::NewError(
4119 "%s expects argument 'type' to be of"
4120 " 'external TypedData'",
4121 CURRENT_FUNC);
4122 }
4123 UNREACHABLE();
4124 return Api::Null();
4125}
4126
4127static ObjectPtr GetByteBufferConstructor(Thread* thread,
4128 const String& class_name,
4129 const String& constructor_name,
4130 intptr_t num_args) {
4131 const Library& lib =
4132 Library::Handle(thread->isolate()->object_store()->typed_data_library());
4133 ASSERT(!lib.IsNull());
4134 const Class& cls =
4135 Class::Handle(thread->zone(), lib.LookupClassAllowPrivate(class_name));
4136 ASSERT(!cls.IsNull());
4137 return ResolveConstructor(CURRENT_FUNC, cls, class_name, constructor_name,
4138 num_args);
4139}
4140
4141DART_EXPORT Dart_Handle Dart_NewByteBuffer(Dart_Handle typed_data) {
4142 DARTSCOPE(Thread::Current());
4143 intptr_t class_id = Api::ClassId(typed_data);
4144 if (!IsExternalTypedDataClassId(class_id) &&
4145 !IsTypedDataViewClassId(class_id) && !IsTypedDataClassId(class_id)) {
4146 RETURN_TYPE_ERROR(Z, typed_data, 'TypedData');
4147 }
4148 Object& result = Object::Handle(Z);
4149 result = GetByteBufferConstructor(T, Symbols::_ByteBuffer(),
4150 Symbols::_ByteBufferDot_New(), 1);
4151 ASSERT(!result.IsNull());
4152 ASSERT(result.IsFunction());
4153 const Function& factory = Function::Cast(result);
4154 ASSERT(!factory.IsGenerativeConstructor());
4155
4156 // Create the argument list.
4157 const Array& args = Array::Handle(Z, Array::New(2));
4158 // Factories get type arguments.
4159 args.SetAt(0, Object::null_type_arguments());
4160 const Object& obj = Object::Handle(Z, Api::UnwrapHandle(typed_data));
4161 args.SetAt(1, obj);
4162
4163 // Invoke the factory constructor and return the new object.
4164 result = DartEntry::InvokeFunction(factory, args);
4165 ASSERT(result.IsInstance() || result.IsNull() || result.IsError());
4166 return Api::NewHandle(T, result.raw());
4167}
4168
4169// Structure to record acquired typed data for verification purposes.
4170class AcquiredData {
4171 public:
4172 AcquiredData(void* data, intptr_t size_in_bytes, bool copy)
4173 : size_in_bytes_(size_in_bytes), data_(data), data_copy_(NULL) {
4174 if (copy) {
4175 data_copy_ = malloc(size_in_bytes_);
4176 memmove(data_copy_, data_, size_in_bytes_);
4177 }
4178 }
4179
4180 // The pointer to hand out via the API.
4181 void* GetData() const { return data_copy_ != NULL ? data_copy_ : data_; }
4182
4183 // Writes back and deletes/zaps, if a copy was made.
4184 ~AcquiredData() {
4185 if (data_copy_ != NULL) {
4186 memmove(data_, data_copy_, size_in_bytes_);
4187 memset(data_copy_, kZapReleasedByte, size_in_bytes_);
4188 free(data_copy_);
4189 }
4190 }
4191
4192 private:
4193 static const uint8_t kZapReleasedByte = 0xda;
4194 intptr_t size_in_bytes_;
4195 void* data_;
4196 void* data_copy_;
4197
4198 DISALLOW_COPY_AND_ASSIGN(AcquiredData);
4199};
4200
4201DART_EXPORT Dart_Handle Dart_TypedDataAcquireData(Dart_Handle object,
4202 Dart_TypedData_Type* type,
4203 void** data,
4204 intptr_t* len) {
4205 DARTSCOPE(Thread::Current());
4206 Isolate* I = T->isolate();
4207 intptr_t class_id = Api::ClassId(object);
4208 if (!IsExternalTypedDataClassId(class_id) &&
4209 !IsTypedDataViewClassId(class_id) && !IsTypedDataClassId(class_id)) {
4210 RETURN_TYPE_ERROR(Z, object, 'TypedData');
4211 }
4212 if (type == NULL) {
4213 RETURN_NULL_ERROR(type);
4214 }
4215 if (data == NULL) {
4216 RETURN_NULL_ERROR(data);
4217 }
4218 if (len == NULL) {
4219 RETURN_NULL_ERROR(len);
4220 }
4221 // Get the type of typed data object.
4222 *type = GetType(class_id);
4223 intptr_t length = 0;
4224 intptr_t size_in_bytes = 0;
4225 void* data_tmp = NULL;
4226 bool external = false;
4227 T->IncrementNoSafepointScopeDepth();
4228 START_NO_CALLBACK_SCOPE(T);
4229 if (IsExternalTypedDataClassId(class_id)) {
4230 const ExternalTypedData& obj =
4231 Api::UnwrapExternalTypedDataHandle(Z, object);
4232 ASSERT(!obj.IsNull());
4233 length = obj.Length();
4234 size_in_bytes = length * ExternalTypedData::ElementSizeInBytes(class_id);
4235 data_tmp = obj.DataAddr(0);
4236 external = true;
4237 } else if (IsTypedDataClassId(class_id)) {
4238 const TypedData& obj = Api::UnwrapTypedDataHandle(Z, object);
4239 ASSERT(!obj.IsNull());
4240 length = obj.Length();
4241 size_in_bytes = length * TypedData::ElementSizeInBytes(class_id);
4242 data_tmp = obj.DataAddr(0);
4243 } else {
4244 ASSERT(IsTypedDataViewClassId(class_id));
4245 const auto& view_obj = Api::UnwrapTypedDataViewHandle(Z, object);
4246 ASSERT(!view_obj.IsNull());
4247 Smi& val = Smi::Handle();
4248 val = view_obj.length();
4249 length = val.Value();
4250 size_in_bytes = length * TypedDataView::ElementSizeInBytes(class_id);
4251 val = view_obj.offset_in_bytes();
4252 intptr_t offset_in_bytes = val.Value();
4253 const auto& obj = Instance::Handle(view_obj.typed_data());
4254 if (TypedData::IsTypedData(obj)) {
4255 const TypedData& data_obj = TypedData::Cast(obj);
4256 data_tmp = data_obj.DataAddr(offset_in_bytes);
4257 } else {
4258 ASSERT(ExternalTypedData::IsExternalTypedData(obj));
4259 const ExternalTypedData& data_obj = ExternalTypedData::Cast(obj);
4260 data_tmp = data_obj.DataAddr(offset_in_bytes);
4261 external = true;
4262 }
4263 }
4264 if (FLAG_verify_acquired_data) {
4265 if (external) {
4266 ASSERT(!I->heap()->Contains(reinterpret_cast<uword>(data_tmp)));
4267 } else {
4268 ASSERT(I->heap()->Contains(reinterpret_cast<uword>(data_tmp)));
4269 }
4270 const Object& obj = Object::Handle(Z, Api::UnwrapHandle(object));
4271 WeakTable* table = I->group()->api_state()->acquired_table();
4272 intptr_t current = table->GetValue(obj.raw());
4273 if (current != 0) {
4274 return Api::NewError("Data was already acquired for this object.");
4275 }
4276 // Do not make a copy if the data is external. Some callers expect external
4277 // data to remain in place, even though the API spec doesn't guarantee it.
4278 // TODO(koda/asiva): Make final decision and document it.
4279 AcquiredData* ad = new AcquiredData(data_tmp, size_in_bytes, !external);
4280 table->SetValue(obj.raw(), reinterpret_cast<intptr_t>(ad));
4281 data_tmp = ad->GetData();
4282 }
4283 *data = data_tmp;
4284 *len = length;
4285 return Api::Success();
4286}
4287
4288DART_EXPORT Dart_Handle Dart_TypedDataReleaseData(Dart_Handle object) {
4289 DARTSCOPE(Thread::Current());
4290 Isolate* I = T->isolate();
4291 intptr_t class_id = Api::ClassId(object);
4292 if (!IsExternalTypedDataClassId(class_id) &&
4293 !IsTypedDataViewClassId(class_id) && !IsTypedDataClassId(class_id)) {
4294 RETURN_TYPE_ERROR(Z, object, 'TypedData');
4295 }
4296 T->DecrementNoSafepointScopeDepth();
4297 END_NO_CALLBACK_SCOPE(T);
4298 if (FLAG_verify_acquired_data) {
4299 const Object& obj = Object::Handle(Z, Api::UnwrapHandle(object));
4300 WeakTable* table = I->group()->api_state()->acquired_table();
4301 intptr_t current = table->GetValue(obj.raw());
4302 if (current == 0) {
4303 return Api::NewError("Data was not acquired for this object.");
4304 }
4305 AcquiredData* ad = reinterpret_cast<AcquiredData*>(current);
4306 table->SetValue(obj.raw(), 0); // Delete entry from table.
4307 delete ad;
4308 }
4309 return Api::Success();
4310}
4311
4312DART_EXPORT Dart_Handle Dart_GetDataFromByteBuffer(Dart_Handle object) {
4313 Thread* thread = Thread::Current();
4314 Zone* zone = thread->zone();
4315 Isolate* isolate = thread->isolate();
4316 CHECK_ISOLATE(isolate);
4317 TransitionNativeToVM transition(thread);
4318 intptr_t class_id = Api::ClassId(object);
4319 if (class_id != kByteBufferCid) {
4320 RETURN_TYPE_ERROR(zone, object, 'ByteBuffer');
4321 }
4322 const Instance& instance = Api::UnwrapInstanceHandle(zone, object);
4323 ASSERT(!instance.IsNull());
4324 return Api::NewHandle(thread, ByteBuffer::Data(instance));
4325}
4326
4327// --- Invoking Constructors, Methods, and Field accessors ---
4328
4329static ObjectPtr ResolveConstructor(const char* current_func,
4330 const Class& cls,
4331 const String& class_name,
4332 const String& constr_name,
4333 int num_args) {
4334 // The constructor must be present in the interface.
4335 const Function& constructor =
4336 Function::Handle(cls.LookupFunctionAllowPrivate(constr_name));
4337 if (constructor.IsNull() ||
4338 (!constructor.IsGenerativeConstructor() && !constructor.IsFactory())) {
4339 const String& lookup_class_name = String::Handle(cls.Name());
4340 if (!class_name.Equals(lookup_class_name)) {
4341 // When the class name used to build the constructor name is
4342 // different than the name of the class in which we are doing
4343 // the lookup, it can be confusing to the user to figure out
4344 // what's going on. Be a little more explicit for these error
4345 // messages.
4346 const String& message = String::Handle(String::NewFormatted(
4347 "%s: could not find factory '%s' in class '%s'.", current_func,
4348 constr_name.ToCString(), lookup_class_name.ToCString()));
4349 return ApiError::New(message);
4350 } else {
4351 const String& message = String::Handle(
4352 String::NewFormatted("%s: could not find constructor '%s'.",
4353 current_func, constr_name.ToCString()));
4354 return ApiError::New(message);
4355 }
4356 }
4357 const int kTypeArgsLen = 0;
4358 const int extra_args = 1;
4359 String& error_message = String::Handle();
4360 if (!constructor.AreValidArgumentCounts(kTypeArgsLen, num_args + extra_args,
4361 0, &error_message)) {
4362 const String& message = String::Handle(String::NewFormatted(
4363 "%s: wrong argument count for "
4364 "constructor '%s': %s.",
4365 current_func, constr_name.ToCString(), error_message.ToCString()));
4366 return ApiError::New(message);
4367 }
4368 ErrorPtr error = constructor.VerifyCallEntryPoint();
4369 if (error != Error::null()) return error;
4370 return constructor.raw();
4371}
4372
4373DART_EXPORT Dart_Handle Dart_New(Dart_Handle type,
4374 Dart_Handle constructor_name,
4375 int number_of_arguments,
4376 Dart_Handle* arguments) {
4377 DARTSCOPE(Thread::Current());
4378 CHECK_CALLBACK_STATE(T);
4379 Object& result = Object::Handle(Z);
4380
4381 if (number_of_arguments < 0) {
4382 return Api::NewError(
4383 "%s expects argument 'number_of_arguments' to be non-negative.",
4384 CURRENT_FUNC);
4385 }
4386
4387 // Get the class to instantiate.
4388 Object& unchecked_type = Object::Handle(Api::UnwrapHandle(type));
4389 if (unchecked_type.IsNull() || !unchecked_type.IsType()) {
4390 RETURN_TYPE_ERROR(Z, type, Type);
4391 }
4392 Type& type_obj = Type::Handle();
4393 type_obj ^= unchecked_type.raw();
4394 if (!type_obj.IsFinalized()) {
4395 return Api::NewError(
4396 "%s expects argument 'type' to be a fully resolved type.",
4397 CURRENT_FUNC);
4398 }
4399 Class& cls = Class::Handle(Z, type_obj.type_class());
4400 CHECK_ERROR_HANDLE(cls.EnsureIsAllocateFinalized(T));
4401
4402 TypeArguments& type_arguments =
4403 TypeArguments::Handle(Z, type_obj.arguments());
4404
4405 const String& base_constructor_name = String::Handle(Z, cls.Name());
4406
4407 // And get the name of the constructor to invoke.
4408 String& dot_name = String::Handle(Z);
4409 result = Api::UnwrapHandle(constructor_name);
4410 if (result.IsNull()) {
4411 dot_name = Symbols::Dot().raw();
4412 } else if (result.IsString()) {
4413 dot_name = String::Concat(Symbols::Dot(), String::Cast(result));
4414 } else {
4415 RETURN_TYPE_ERROR(Z, constructor_name, String);
4416 }
4417
4418 // Resolve the constructor.
4419 String& constr_name =
4420 String::Handle(String::Concat(base_constructor_name, dot_name));
4421 result = ResolveConstructor("Dart_New", cls, base_constructor_name,
4422 constr_name, number_of_arguments);
4423 if (result.IsError()) {
4424 return Api::NewHandle(T, result.raw());
4425 }
4426 ASSERT(result.IsFunction());
4427 Function& constructor = Function::Handle(Z);
4428 constructor ^= result.raw();
4429
4430 Instance& new_object = Instance::Handle(Z);
4431 if (constructor.IsRedirectingFactory()) {
4432 Type& redirect_type = Type::Handle(constructor.RedirectionType());
4433 constructor = constructor.RedirectionTarget();
4434 ASSERT(!constructor.IsNull());
4435
4436 if (!redirect_type.IsInstantiated()) {
4437 // The type arguments of the redirection type are instantiated from the
4438 // type arguments of the type argument.
4439 // We do not support generic constructors.
4440 ASSERT(redirect_type.IsInstantiated(kFunctions));
4441 redirect_type ^= redirect_type.InstantiateFrom(
4442 type_arguments, Object::null_type_arguments(), kNoneFree, Heap::kNew);
4443 redirect_type ^= redirect_type.Canonicalize();
4444 }
4445
4446 type_obj = redirect_type.raw();
4447 type_arguments = redirect_type.arguments();
4448
4449 cls = type_obj.type_class();
4450 }
4451 if (constructor.IsGenerativeConstructor()) {
4452 CHECK_ERROR_HANDLE(cls.VerifyEntryPoint());
4453#if defined(DEBUG)
4454 if (!cls.is_allocated() &&
4455 (Dart::vm_snapshot_kind() == Snapshot::kFullAOT)) {
4456 return Api::NewError("Precompilation dropped '%s'", cls.ToCString());
4457 }
4458#endif
4459 // Create the new object.
4460 new_object = Instance::New(cls);
4461 }
4462
4463 // Create the argument list.
4464 intptr_t arg_index = 0;
4465 int extra_args = 1;
4466 const Array& args =
4467 Array::Handle(Z, Array::New(number_of_arguments + extra_args));
4468 if (constructor.IsGenerativeConstructor()) {
4469 // Constructors get the uninitialized object.
4470 if (!type_arguments.IsNull()) {
4471 // The type arguments will be null if the class has no type parameters, in
4472 // which case the following call would fail because there is no slot
4473 // reserved in the object for the type vector.
4474 new_object.SetTypeArguments(type_arguments);
4475 }
4476 args.SetAt(arg_index++, new_object);
4477 } else {
4478 // Factories get type arguments.
4479 args.SetAt(arg_index++, type_arguments);
4480 }
4481 Object& argument = Object::Handle(Z);
4482 for (int i = 0; i < number_of_arguments; i++) {
4483 argument = Api::UnwrapHandle(arguments[i]);
4484 if (!argument.IsNull() && !argument.IsInstance()) {
4485 if (argument.IsError()) {
4486 return Api::NewHandle(T, argument.raw());
4487 } else {
4488 return Api::NewError(
4489 "%s expects arguments[%d] to be an Instance handle.", CURRENT_FUNC,
4490 i);
4491 }
4492 }
4493 args.SetAt(arg_index++, argument);
4494 }
4495
4496 // Invoke the constructor and return the new object.
4497 result = DartEntry::InvokeFunction(constructor, args);
4498 if (result.IsError()) {
4499 return Api::NewHandle(T, result.raw());
4500 }
4501
4502 if (constructor.IsGenerativeConstructor()) {
4503 ASSERT(result.IsNull());
4504 } else {
4505 ASSERT(result.IsNull() || result.IsInstance());
4506 new_object ^= result.raw();
4507 }
4508 return Api::NewHandle(T, new_object.raw());
4509}
4510
4511static InstancePtr AllocateObject(Thread* thread, const Class& cls) {
4512 if (!cls.is_fields_marked_nullable()) {
4513 // Mark all fields as nullable.
4514 Zone* zone = thread->zone();
4515 Class& iterate_cls = Class::Handle(zone, cls.raw());
4516 Field& field = Field::Handle(zone);
4517 Array& fields = Array::Handle(zone);
4518 while (!iterate_cls.IsNull()) {
4519 ASSERT(iterate_cls.is_finalized());
4520 iterate_cls.set_is_fields_marked_nullable();
4521 fields = iterate_cls.fields();
4522 iterate_cls = iterate_cls.SuperClass();
4523 for (int field_num = 0; field_num < fields.Length(); field_num++) {
4524 field ^= fields.At(field_num);
4525 if (field.is_static()) {
4526 continue;
4527 }
4528 field.RecordStore(Object::null_object());
4529 }
4530 }
4531 }
4532
4533 // Allocate an object for the given class.
4534 return Instance::New(cls);
4535}
4536
4537DART_EXPORT Dart_Handle Dart_Allocate(Dart_Handle type) {
4538 DARTSCOPE(Thread::Current());
4539 CHECK_CALLBACK_STATE(T);
4540
4541 const Type& type_obj = Api::UnwrapTypeHandle(Z, type);
4542 // Get the class to instantiate.
4543 if (type_obj.IsNull()) {
4544 RETURN_TYPE_ERROR(Z, type, Type);
4545 }
4546 const Class& cls = Class::Handle(Z, type_obj.type_class());
4547 CHECK_ERROR_HANDLE(cls.VerifyEntryPoint());
4548#if defined(DEBUG)
4549 if (!cls.is_allocated() && (Dart::vm_snapshot_kind() == Snapshot::kFullAOT)) {
4550 return Api::NewError("Precompilation dropped '%s'", cls.ToCString());
4551 }
4552#endif
4553 CHECK_ERROR_HANDLE(cls.EnsureIsFinalized(T));
4554 return Api::NewHandle(T, AllocateObject(T, cls));
4555}
4556
4557DART_EXPORT Dart_Handle
4558Dart_AllocateWithNativeFields(Dart_Handle type,
4559 intptr_t num_native_fields,
4560 const intptr_t* native_fields) {
4561 DARTSCOPE(Thread::Current());
4562 CHECK_CALLBACK_STATE(T);
4563
4564 const Type& type_obj = Api::UnwrapTypeHandle(Z, type);
4565 // Get the class to instantiate.
4566 if (type_obj.IsNull()) {
4567 RETURN_TYPE_ERROR(Z, type, Type);
4568 }
4569 if (native_fields == NULL) {
4570 RETURN_NULL_ERROR(native_fields);
4571 }
4572 const Class& cls = Class::Handle(Z, type_obj.type_class());
4573 CHECK_ERROR_HANDLE(cls.VerifyEntryPoint());
4574#if defined(DEBUG)
4575 if (!cls.is_allocated() && (Dart::vm_snapshot_kind() == Snapshot::kFullAOT)) {
4576 return Api::NewError("Precompilation dropped '%s'", cls.ToCString());
4577 }
4578#endif
4579 CHECK_ERROR_HANDLE(cls.EnsureIsFinalized(T));
4580 if (num_native_fields != cls.num_native_fields()) {
4581 return Api::NewError(
4582 "%s: invalid number of native fields %" Pd " passed in, expected %d",
4583 CURRENT_FUNC, num_native_fields, cls.num_native_fields());
4584 }
4585 const Instance& instance = Instance::Handle(Z, AllocateObject(T, cls));
4586 instance.SetNativeFields(num_native_fields, native_fields);
4587 return Api::NewHandle(T, instance.raw());
4588}
4589
4590static Dart_Handle SetupArguments(Thread* thread,
4591 int num_args,
4592 Dart_Handle* arguments,
4593 int extra_args,
4594 Array* args) {
4595 Zone* zone = thread->zone();
4596 // Check for malformed arguments in the arguments list.
4597 *args = Array::New(num_args + extra_args);
4598 Object& arg = Object::Handle(zone);
4599 for (int i = 0; i < num_args; i++) {
4600 arg = Api::UnwrapHandle(arguments[i]);
4601 if (!arg.IsNull() && !arg.IsInstance()) {
4602 *args = Array::null();
4603 if (arg.IsError()) {
4604 return Api::NewHandle(thread, arg.raw());
4605 } else {
4606 return Api::NewError(
4607 "%s expects arguments[%d] to be an Instance handle.", "Dart_Invoke",
4608 i);
4609 }
4610 }
4611 args->SetAt((i + extra_args), arg);
4612 }
4613 return Api::Success();
4614}
4615
4616DART_EXPORT Dart_Handle Dart_InvokeConstructor(Dart_Handle object,
4617 Dart_Handle name,
4618 int number_of_arguments,
4619 Dart_Handle* arguments) {
4620 DARTSCOPE(Thread::Current());
4621 API_TIMELINE_DURATION(T);
4622 CHECK_CALLBACK_STATE(T);
4623
4624 if (number_of_arguments < 0) {
4625 return Api::NewError(
4626 "%s expects argument 'number_of_arguments' to be non-negative.",
4627 CURRENT_FUNC);
4628 }
4629 const Instance& instance = Api::UnwrapInstanceHandle(Z, object);
4630 if (instance.IsNull()) {
4631 RETURN_TYPE_ERROR(Z, object, Instance);
4632 }
4633
4634 // Since we have allocated an object it would mean that the type
4635 // is finalized.
4636 // TODO(asiva): How do we ensure that a constructor is not called more than
4637 // once for the same object.
4638
4639 // Construct name of the constructor to invoke.
4640 const String& constructor_name = Api::UnwrapStringHandle(Z, name);
4641 const AbstractType& type_obj =
4642 AbstractType::Handle(Z, instance.GetType(Heap::kNew));
4643 const Class& cls = Class::Handle(Z, type_obj.type_class());
4644 const String& class_name = String::Handle(Z, cls.Name());
4645 const Array& strings = Array::Handle(Z, Array::New(3));
4646 strings.SetAt(0, class_name);
4647 strings.SetAt(1, Symbols::Dot());
4648 if (constructor_name.IsNull()) {
4649 strings.SetAt(2, Symbols::Empty());
4650 } else {
4651 strings.SetAt(2, constructor_name);
4652 }
4653 const String& dot_name = String::Handle(Z, String::ConcatAll(strings));
4654 const TypeArguments& type_arguments =
4655 TypeArguments::Handle(Z, type_obj.arguments());
4656 const Function& constructor =
4657 Function::Handle(Z, cls.LookupFunctionAllowPrivate(dot_name));
4658 const int kTypeArgsLen = 0;
4659 const int extra_args = 1;
4660 if (!constructor.IsNull() && constructor.IsGenerativeConstructor() &&
4661 constructor.AreValidArgumentCounts(
4662 kTypeArgsLen, number_of_arguments + extra_args, 0, NULL)) {
4663 CHECK_ERROR_HANDLE(constructor.VerifyCallEntryPoint());
4664 // Create the argument list.
4665 // Constructors get the uninitialized object.
4666 if (!type_arguments.IsNull()) {
4667 // The type arguments will be null if the class has no type
4668 // parameters, in which case the following call would fail
4669 // because there is no slot reserved in the object for the
4670 // type vector.
4671 instance.SetTypeArguments(type_arguments);
4672 }
4673 Dart_Handle result;
4674 Array& args = Array::Handle(Z);
4675 result =
4676 SetupArguments(T, number_of_arguments, arguments, extra_args, &args);
4677 if (!Api::IsError(result)) {
4678 args.SetAt(0, instance);
4679 const Object& retval =
4680 Object::Handle(Z, DartEntry::InvokeFunction(constructor, args));
4681 if (retval.IsError()) {
4682 result = Api::NewHandle(T, retval.raw());
4683 } else {
4684 result = Api::NewHandle(T, instance.raw());
4685 }
4686 }
4687 return result;
4688 }
4689 return Api::NewError("%s expects argument 'name' to be a valid constructor.",
4690 CURRENT_FUNC);
4691}
4692
4693DART_EXPORT Dart_Handle Dart_Invoke(Dart_Handle target,
4694 Dart_Handle name,
4695 int number_of_arguments,
4696 Dart_Handle* arguments) {
4697 DARTSCOPE(Thread::Current());
4698 API_TIMELINE_DURATION(T);
4699 CHECK_CALLBACK_STATE(T);
4700
4701 String& function_name =
4702 String::Handle(Z, Api::UnwrapStringHandle(Z, name).raw());
4703 if (function_name.IsNull()) {
4704 RETURN_TYPE_ERROR(Z, name, String);
4705 }
4706 if (number_of_arguments < 0) {
4707 return Api::NewError(
4708 "%s expects argument 'number_of_arguments' to be non-negative.",
4709 CURRENT_FUNC);
4710 }
4711 const Object& obj = Object::Handle(Z, Api::UnwrapHandle(target));
4712 if (obj.IsError()) {
4713 return target;
4714 }
4715 Dart_Handle result;
4716 Array& args = Array::Handle(Z);
4717 // This API does not provide a way to pass named parameters.
4718 const Array& arg_names = Object::empty_array();
4719 const bool respect_reflectable = false;
4720 const bool check_is_entrypoint = FLAG_verify_entry_points;
4721 if (obj.IsType()) {
4722 if (!Type::Cast(obj).IsFinalized()) {
4723 return Api::NewError(
4724 "%s expects argument 'target' to be a fully resolved type.",
4725 CURRENT_FUNC);
4726 }
4727
4728 const Class& cls = Class::Handle(Z, Type::Cast(obj).type_class());
4729 if (Library::IsPrivate(function_name)) {
4730 const Library& lib = Library::Handle(Z, cls.library());
4731 function_name = lib.PrivateName(function_name);
4732 }
4733
4734 // Setup args and check for malformed arguments in the arguments list.
4735 result = SetupArguments(T, number_of_arguments, arguments, 0, &args);
4736 if (Api::IsError(result)) {
4737 return result;
4738 }
4739 return Api::NewHandle(
4740 T, cls.Invoke(function_name, args, arg_names, respect_reflectable,
4741 check_is_entrypoint));
4742 } else if (obj.IsNull() || obj.IsInstance()) {
4743 // Since we have allocated an object it would mean that the type of the
4744 // receiver is already resolved and finalized, hence it is not necessary
4745 // to check here.
4746 Instance& instance = Instance::Handle(Z);
4747 instance ^= obj.raw();
4748
4749 // Setup args and check for malformed arguments in the arguments list.
4750 result = SetupArguments(T, number_of_arguments, arguments, 1, &args);
4751 if (Api::IsError(result)) {
4752 return result;
4753 }
4754 args.SetAt(0, instance);
4755 return Api::NewHandle(
4756 T, instance.Invoke(function_name, args, arg_names, respect_reflectable,
4757 check_is_entrypoint));
4758 } else if (obj.IsLibrary()) {
4759 // Check whether class finalization is needed.
4760 const Library& lib = Library::Cast(obj);
4761
4762 // Check that the library is loaded.
4763 if (!lib.Loaded()) {
4764 return Api::NewError("%s expects library argument 'target' to be loaded.",
4765 CURRENT_FUNC);
4766 }
4767
4768 if (Library::IsPrivate(function_name)) {
4769 function_name = lib.PrivateName(function_name);
4770 }
4771
4772 // Setup args and check for malformed arguments in the arguments list.
4773 result = SetupArguments(T, number_of_arguments, arguments, 0, &args);
4774 if (Api::IsError(result)) {
4775 return result;
4776 }
4777
4778 return Api::NewHandle(
4779 T, lib.Invoke(function_name, args, arg_names, respect_reflectable,
4780 check_is_entrypoint));
4781 } else {
4782 return Api::NewError(
4783 "%s expects argument 'target' to be an object, type, or library.",
4784 CURRENT_FUNC);
4785 }
4786}
4787
4788DART_EXPORT Dart_Handle Dart_InvokeClosure(Dart_Handle closure,
4789 int number_of_arguments,
4790 Dart_Handle* arguments) {
4791 DARTSCOPE(Thread::Current());
4792 API_TIMELINE_DURATION(T);
4793 CHECK_CALLBACK_STATE(T);
4794 const Instance& closure_obj = Api::UnwrapInstanceHandle(Z, closure);
4795 if (closure_obj.IsNull() || !closure_obj.IsCallable(NULL)) {
4796 RETURN_TYPE_ERROR(Z, closure, Instance);
4797 }
4798 if (number_of_arguments < 0) {
4799 return Api::NewError(
4800 "%s expects argument 'number_of_arguments' to be non-negative.",
4801 CURRENT_FUNC);
4802 }
4803
4804 // Set up arguments to include the closure as the first argument.
4805 const Array& args = Array::Handle(Z, Array::New(number_of_arguments + 1));
4806 Object& obj = Object::Handle(Z);
4807 args.SetAt(0, closure_obj);
4808 for (int i = 0; i < number_of_arguments; i++) {
4809 obj = Api::UnwrapHandle(arguments[i]);
4810 if (!obj.IsNull() && !obj.IsInstance()) {
4811 RETURN_TYPE_ERROR(Z, arguments[i], Instance);
4812 }
4813 args.SetAt(i + 1, obj);
4814 }
4815 // Now try to invoke the closure.
4816 return Api::NewHandle(T, DartEntry::InvokeClosure(args));
4817}
4818
4819DART_EXPORT Dart_Handle Dart_GetField(Dart_Handle container, Dart_Handle name) {
4820 DARTSCOPE(Thread::Current());
4821 API_TIMELINE_DURATION(T);
4822 CHECK_CALLBACK_STATE(T);
4823
4824 String& field_name =
4825 String::Handle(Z, Api::UnwrapStringHandle(Z, name).raw());
4826 if (field_name.IsNull()) {
4827 RETURN_TYPE_ERROR(Z, name, String);
4828 }
4829 const Object& obj = Object::Handle(Z, Api::UnwrapHandle(container));
4830 const bool throw_nsm_if_absent = true;
4831 const bool respect_reflectable = false;
4832 const bool check_is_entrypoint = FLAG_verify_entry_points;
4833
4834 if (obj.IsType()) {
4835 if (!Type::Cast(obj).IsFinalized()) {
4836 return Api::NewError(
4837 "%s expects argument 'container' to be a fully resolved type.",
4838 CURRENT_FUNC);
4839 }
4840 Class& cls = Class::Handle(Z, Type::Cast(obj).type_class());
4841 if (Library::IsPrivate(field_name)) {
4842 const Library& lib = Library::Handle(Z, cls.library());
4843 field_name = lib.PrivateName(field_name);
4844 }
4845 return Api::NewHandle(
4846 T, cls.InvokeGetter(field_name, throw_nsm_if_absent,
4847 respect_reflectable, check_is_entrypoint));
4848 } else if (obj.IsNull() || obj.IsInstance()) {
4849 Instance& instance = Instance::Handle(Z);
4850 instance ^= obj.raw();
4851 if (Library::IsPrivate(field_name)) {
4852 const Class& cls = Class::Handle(Z, instance.clazz());
4853 const Library& lib = Library::Handle(Z, cls.library());
4854 field_name = lib.PrivateName(field_name);
4855 }
4856 return Api::NewHandle(T,
4857 instance.InvokeGetter(field_name, respect_reflectable,
4858 check_is_entrypoint));
4859 } else if (obj.IsLibrary()) {
4860 const Library& lib = Library::Cast(obj);
4861 // Check that the library is loaded.
4862 if (!lib.Loaded()) {
4863 return Api::NewError(
4864 "%s expects library argument 'container' to be loaded.",
4865 CURRENT_FUNC);
4866 }
4867 if (Library::IsPrivate(field_name)) {
4868 field_name = lib.PrivateName(field_name);
4869 }
4870 return Api::NewHandle(
4871 T, lib.InvokeGetter(field_name, throw_nsm_if_absent,
4872 respect_reflectable, check_is_entrypoint));
4873 } else if (obj.IsError()) {
4874 return container;
4875 } else {
4876 return Api::NewError(
4877 "%s expects argument 'container' to be an object, type, or library.",
4878 CURRENT_FUNC);
4879 }
4880}
4881
4882DART_EXPORT Dart_Handle Dart_SetField(Dart_Handle container,
4883 Dart_Handle name,
4884 Dart_Handle value) {
4885 DARTSCOPE(Thread::Current());
4886 API_TIMELINE_DURATION(T);
4887 CHECK_CALLBACK_STATE(T);
4888
4889 String& field_name =
4890 String::Handle(Z, Api::UnwrapStringHandle(Z, name).raw());
4891 if (field_name.IsNull()) {
4892 RETURN_TYPE_ERROR(Z, name, String);
4893 }
4894
4895 // Since null is allowed for value, we don't use UnwrapInstanceHandle.
4896 const Object& value_obj = Object::Handle(Z, Api::UnwrapHandle(value));
4897 if (!value_obj.IsNull() && !value_obj.IsInstance()) {
4898 RETURN_TYPE_ERROR(Z, value, Instance);
4899 }
4900 Instance& value_instance = Instance::Handle(Z);
4901 value_instance ^= value_obj.raw();
4902
4903 const Object& obj = Object::Handle(Z, Api::UnwrapHandle(container));
4904 const bool respect_reflectable = false;
4905 const bool check_is_entrypoint = FLAG_verify_entry_points;
4906
4907 if (obj.IsType()) {
4908 if (!Type::Cast(obj).IsFinalized()) {
4909 return Api::NewError(
4910 "%s expects argument 'container' to be a fully resolved type.",
4911 CURRENT_FUNC);
4912 }
4913
4914 // To access a static field we may need to use the Field or the
4915 // setter Function.
4916 Class& cls = Class::Handle(Z, Type::Cast(obj).type_class());
4917 if (Library::IsPrivate(field_name)) {
4918 const Library& lib = Library::Handle(Z, cls.library());
4919 field_name = lib.PrivateName(field_name);
4920 }
4921 return Api::NewHandle(
4922 T, cls.InvokeSetter(field_name, value_instance, respect_reflectable,
4923 check_is_entrypoint));
4924 } else if (obj.IsNull() || obj.IsInstance()) {
4925 Instance& instance = Instance::Handle(Z);
4926 instance ^= obj.raw();
4927 if (Library::IsPrivate(field_name)) {
4928 const Class& cls = Class::Handle(Z, instance.clazz());
4929 const Library& lib = Library::Handle(Z, cls.library());
4930 field_name = lib.PrivateName(field_name);
4931 }
4932 return Api::NewHandle(
4933 T, instance.InvokeSetter(field_name, value_instance,
4934 respect_reflectable, check_is_entrypoint));
4935 } else if (obj.IsLibrary()) {
4936 // To access a top-level we may need to use the Field or the
4937 // setter Function. The setter function may either be in the
4938 // library or in the field's owner class, depending.
4939 const Library& lib = Library::Cast(obj);
4940 // Check that the library is loaded.
4941 if (!lib.Loaded()) {
4942 return Api::NewError(
4943 "%s expects library argument 'container' to be loaded.",
4944 CURRENT_FUNC);
4945 }
4946
4947 if (Library::IsPrivate(field_name)) {
4948 field_name = lib.PrivateName(field_name);
4949 }
4950 return Api::NewHandle(
4951 T, lib.InvokeSetter(field_name, value_instance, respect_reflectable,
4952 check_is_entrypoint));
4953 } else if (obj.IsError()) {
4954 return container;
4955 }
4956 return Api::NewError(
4957 "%s expects argument 'container' to be an object, type, or library.",
4958 CURRENT_FUNC);
4959}
4960
4961// --- Exceptions ----
4962
4963DART_EXPORT Dart_Handle Dart_ThrowException(Dart_Handle exception) {
4964 Thread* thread = Thread::Current();
4965 Zone* zone = thread->zone();
4966 Isolate* isolate = thread->isolate();
4967 CHECK_ISOLATE(isolate);
4968 CHECK_CALLBACK_STATE(thread);
4969 if (::Dart_IsError(exception)) {
4970 ::Dart_PropagateError(exception);
4971 }
4972 TransitionNativeToVM transition(thread);
4973 const Instance& excp = Api::UnwrapInstanceHandle(zone, exception);
4974 if (excp.IsNull()) {
4975 RETURN_TYPE_ERROR(zone, exception, Instance);
4976 }
4977 if (thread->top_exit_frame_info() == 0) {
4978 // There are no dart frames on the stack so it would be illegal to
4979 // throw an exception here.
4980 return Api::NewError("No Dart frames on stack, cannot throw exception");
4981 }
4982 // Unwind all the API scopes till the exit frame before throwing an
4983 // exception.
4984 const Instance* saved_exception;
4985 {
4986 NoSafepointScope no_safepoint;
4987 InstancePtr raw_exception =
4988 Api::UnwrapInstanceHandle(zone, exception).raw();
4989 thread->UnwindScopes(thread->top_exit_frame_info());
4990 saved_exception = &Instance::Handle(raw_exception);
4991 }
4992 Exceptions::Throw(thread, *saved_exception);
4993 return Api::NewError("Exception was not thrown, internal error");
4994}
4995
4996DART_EXPORT Dart_Handle Dart_ReThrowException(Dart_Handle exception,
4997 Dart_Handle stacktrace) {
4998 Thread* thread = Thread::Current();
4999 Zone* zone = thread->zone();
5000 Isolate* isolate = thread->isolate();
5001 CHECK_ISOLATE(isolate);
5002 CHECK_CALLBACK_STATE(thread);
5003 TransitionNativeToVM transition(thread);
5004 {
5005 const Instance& excp = Api::UnwrapInstanceHandle(zone, exception);
5006 if (excp.IsNull()) {
5007 RETURN_TYPE_ERROR(zone, exception, Instance);
5008 }
5009 const Instance& stk = Api::UnwrapInstanceHandle(zone, stacktrace);
5010 if (stk.IsNull()) {
5011 RETURN_TYPE_ERROR(zone, stacktrace, Instance);
5012 }
5013 }
5014 if (thread->top_exit_frame_info() == 0) {
5015 // There are no dart frames on the stack so it would be illegal to
5016 // throw an exception here.
5017 return Api::NewError("No Dart frames on stack, cannot throw exception");
5018 }
5019 // Unwind all the API scopes till the exit frame before throwing an
5020 // exception.
5021 const Instance* saved_exception;
5022 const StackTrace* saved_stacktrace;
5023 {
5024 NoSafepointScope no_safepoint;
5025 InstancePtr raw_exception =
5026 Api::UnwrapInstanceHandle(zone, exception).raw();
5027 StackTracePtr raw_stacktrace =
5028 Api::UnwrapStackTraceHandle(zone, stacktrace).raw();
5029 thread->UnwindScopes(thread->top_exit_frame_info());
5030 saved_exception = &Instance::Handle(raw_exception);
5031 saved_stacktrace = &StackTrace::Handle(raw_stacktrace);
5032 }
5033 Exceptions::ReThrow(thread, *saved_exception, *saved_stacktrace);
5034 return Api::NewError("Exception was not re thrown, internal error");
5035}
5036
5037// --- Native fields and functions ---
5038
5039DART_EXPORT Dart_Handle Dart_GetNativeInstanceFieldCount(Dart_Handle obj,
5040 int* count) {
5041 Thread* thread = Thread::Current();
5042 CHECK_ISOLATE(thread->isolate());
5043 TransitionNativeToVM transition(thread);
5044 ReusableObjectHandleScope reused_obj_handle(thread);
5045 const Instance& instance = Api::UnwrapInstanceHandle(reused_obj_handle, obj);
5046 if (instance.IsNull()) {
5047 RETURN_TYPE_ERROR(thread->zone(), obj, Instance);
5048 }
5049 *count = instance.NumNativeFields();
5050 return Api::Success();
5051}
5052
5053DART_EXPORT Dart_Handle Dart_GetNativeInstanceField(Dart_Handle obj,
5054 int index,
5055 intptr_t* value) {
5056 Thread* thread = Thread::Current();
5057 CHECK_ISOLATE(thread->isolate());
5058 TransitionNativeToVM transition(thread);
5059 ReusableObjectHandleScope reused_obj_handle(thread);
5060 const Instance& instance = Api::UnwrapInstanceHandle(reused_obj_handle, obj);
5061 if (instance.IsNull()) {
5062 RETURN_TYPE_ERROR(thread->zone(), obj, Instance);
5063 }
5064 if (!instance.IsValidNativeIndex(index)) {
5065 return Api::NewError(
5066 "%s: invalid index %d passed in to access native instance field",
5067 CURRENT_FUNC, index);
5068 }
5069 *value = instance.GetNativeField(index);
5070 return Api::Success();
5071}
5072
5073DART_EXPORT Dart_Handle Dart_SetNativeInstanceField(Dart_Handle obj,
5074 int index,
5075 intptr_t value) {
5076 DARTSCOPE(Thread::Current());
5077 const Instance& instance = Api::UnwrapInstanceHandle(Z, obj);
5078 if (instance.IsNull()) {
5079 RETURN_TYPE_ERROR(Z, obj, Instance);
5080 }
5081 if (!instance.IsValidNativeIndex(index)) {
5082 return Api::NewError(
5083 "%s: invalid index %d passed in to set native instance field",
5084 CURRENT_FUNC, index);
5085 }
5086 instance.SetNativeField(index, value);
5087 return Api::Success();
5088}
5089
5090DART_EXPORT void* Dart_GetNativeIsolateGroupData(Dart_NativeArguments args) {
5091 NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
5092 Isolate* isolate = arguments->thread()->isolate();
5093 ASSERT(isolate == Isolate::Current());
5094 return isolate->init_callback_data();
5095}
5096
5097DART_EXPORT Dart_Handle Dart_GetNativeArguments(
5098 Dart_NativeArguments args,
5099 int num_arguments,
5100 const Dart_NativeArgument_Descriptor* argument_descriptors,
5101 Dart_NativeArgument_Value* arg_values) {
5102 NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
5103 TransitionNativeToVM transition(arguments->thread());
5104 ASSERT(arguments->thread()->isolate() == Isolate::Current());
5105 if (arg_values == NULL) {
5106 RETURN_NULL_ERROR(arg_values);
5107 }
5108 for (int i = 0; i < num_arguments; i++) {
5109 Dart_NativeArgument_Descriptor desc = argument_descriptors[i];
5110 Dart_NativeArgument_Type arg_type =
5111 static_cast<Dart_NativeArgument_Type>(desc.type);
5112 int arg_index = desc.index;
5113 ASSERT(arg_index >= 0 && arg_index < arguments->NativeArgCount());
5114 Dart_NativeArgument_Value* native_value = &(arg_values[i]);
5115 switch (arg_type) {
5116 case Dart_NativeArgument_kBool:
5117 if (!Api::GetNativeBooleanArgument(arguments, arg_index,
5118 &(native_value->as_bool))) {
5119 return Api::NewArgumentError(
5120 "%s: expects argument at index %d to be of"
5121 " type Boolean.",
5122 CURRENT_FUNC, i);
5123 }
5124 break;
5125
5126 case Dart_NativeArgument_kInt32: {
5127 int64_t value = 0;
5128 if (!GetNativeIntegerArgument(arguments, arg_index, &value)) {
5129 return Api::NewArgumentError(
5130 "%s: expects argument at index %d to be of"
5131 " type Integer.",
5132 CURRENT_FUNC, i);
5133 }
5134 if (value < INT32_MIN || value > INT32_MAX) {
5135 return Api::NewArgumentError(
5136 "%s: argument value at index %d is out of range", CURRENT_FUNC,
5137 i);
5138 }
5139 native_value->as_int32 = static_cast<int32_t>(value);
5140 break;
5141 }
5142
5143 case Dart_NativeArgument_kUint32: {
5144 int64_t value = 0;
5145 if (!GetNativeIntegerArgument(arguments, arg_index, &value)) {
5146 return Api::NewArgumentError(
5147 "%s: expects argument at index %d to be of"
5148 " type Integer.",
5149 CURRENT_FUNC, i);
5150 }
5151 if (value < 0 || value > UINT32_MAX) {
5152 return Api::NewArgumentError(
5153 "%s: argument value at index %d is out of range", CURRENT_FUNC,
5154 i);
5155 }
5156 native_value->as_uint32 = static_cast<uint32_t>(value);
5157 break;
5158 }
5159
5160 case Dart_NativeArgument_kInt64: {
5161 int64_t value = 0;
5162 if (!GetNativeIntegerArgument(arguments, arg_index, &value)) {
5163 return Api::NewArgumentError(
5164 "%s: expects argument at index %d to be of"
5165 " type Integer.",
5166 CURRENT_FUNC, i);
5167 }
5168 native_value->as_int64 = value;
5169 break;
5170 }
5171
5172 case Dart_NativeArgument_kUint64: {
5173 uint64_t value = 0;
5174 if (!GetNativeUnsignedIntegerArgument(arguments, arg_index, &value)) {
5175 return Api::NewArgumentError(
5176 "%s: expects argument at index %d to be of"
5177 " type Integer.",
5178 CURRENT_FUNC, i);
5179 }
5180 native_value->as_uint64 = value;
5181 break;
5182 }
5183
5184 case Dart_NativeArgument_kDouble:
5185 if (!GetNativeDoubleArgument(arguments, arg_index,
5186 &(native_value->as_double))) {
5187 return Api::NewArgumentError(
5188 "%s: expects argument at index %d to be of"
5189 " type Double.",
5190 CURRENT_FUNC, i);
5191 }
5192 break;
5193
5194 case Dart_NativeArgument_kString:
5195 if (!GetNativeStringArgument(arguments, arg_index,
5196 &(native_value->as_string.dart_str),
5197 &(native_value->as_string.peer))) {
5198 return Api::NewArgumentError(
5199 "%s: expects argument at index %d to be of"
5200 " type String.",
5201 CURRENT_FUNC, i);
5202 }
5203 break;
5204
5205 case Dart_NativeArgument_kNativeFields: {
5206 Dart_Handle result = GetNativeFieldsOfArgument(
5207 arguments, arg_index, native_value->as_native_fields.num_fields,
5208 native_value->as_native_fields.values, CURRENT_FUNC);
5209 if (result != Api::Success()) {
5210 return result;
5211 }
5212 break;
5213 }
5214
5215 case Dart_NativeArgument_kInstance: {
5216 ASSERT(arguments->thread() == Thread::Current());
5217 ASSERT(arguments->thread()->api_top_scope() != NULL);
5218 native_value->as_instance = Api::NewHandle(
5219 arguments->thread(), arguments->NativeArgAt(arg_index));
5220 break;
5221 }
5222
5223 default:
5224 return Api::NewArgumentError("%s: invalid argument type %d.",
5225 CURRENT_FUNC, arg_type);
5226 }
5227 }
5228 return Api::Success();
5229}
5230
5231DART_EXPORT Dart_Handle Dart_GetNativeArgument(Dart_NativeArguments args,
5232 int index) {
5233 NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
5234 if ((index < 0) || (index >= arguments->NativeArgCount())) {
5235 return Api::NewError(
5236 "%s: argument 'index' out of range. Expected 0..%d but saw %d.",
5237 CURRENT_FUNC, arguments->NativeArgCount() - 1, index);
5238 }
5239 TransitionNativeToVM transition(arguments->thread());
5240 return Api::NewHandle(arguments->thread(), arguments->NativeArgAt(index));
5241}
5242
5243DART_EXPORT int Dart_GetNativeArgumentCount(Dart_NativeArguments args) {
5244 NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
5245 return arguments->NativeArgCount();
5246}
5247
5248DART_EXPORT Dart_Handle
5249Dart_GetNativeFieldsOfArgument(Dart_NativeArguments args,
5250 int arg_index,
5251 int num_fields,
5252 intptr_t* field_values) {
5253 NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
5254 if ((arg_index < 0) || (arg_index >= arguments->NativeArgCount())) {
5255 return Api::NewError(
5256 "%s: argument 'arg_index' out of range. Expected 0..%d but saw %d.",
5257 CURRENT_FUNC, arguments->NativeArgCount() - 1, arg_index);
5258 }
5259 if (field_values == NULL) {
5260 RETURN_NULL_ERROR(field_values);
5261 }
5262 return GetNativeFieldsOfArgument(arguments, arg_index, num_fields,
5263 field_values, CURRENT_FUNC);
5264}
5265
5266DART_EXPORT Dart_Handle Dart_GetNativeReceiver(Dart_NativeArguments args,
5267 intptr_t* value) {
5268 NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
5269 TransitionNativeToVM transition(arguments->thread());
5270 ASSERT(arguments->thread()->isolate() == Isolate::Current());
5271 if (value == NULL) {
5272 RETURN_NULL_ERROR(value);
5273 }
5274 if (Api::GetNativeReceiver(arguments, value)) {
5275 return Api::Success();
5276 }
5277 return Api::NewError(
5278 "%s expects receiver argument to be non-null and of"
5279 " type Instance.",
5280 CURRENT_FUNC);
5281}
5282
5283DART_EXPORT Dart_Handle Dart_GetNativeStringArgument(Dart_NativeArguments args,
5284 int arg_index,
5285 void** peer) {
5286 NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
5287 TransitionNativeToVM transition(arguments->thread());
5288 Dart_Handle result = Api::Null();
5289 if (!GetNativeStringArgument(arguments, arg_index, &result, peer)) {
5290 return Api::NewArgumentError(
5291 "%s expects argument at %d to be of"
5292 " type String.",
5293 CURRENT_FUNC, arg_index);
5294 }
5295 return result;
5296}
5297
5298DART_EXPORT Dart_Handle Dart_GetNativeIntegerArgument(Dart_NativeArguments args,
5299 int index,
5300 int64_t* value) {
5301 NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
5302 if ((index < 0) || (index >= arguments->NativeArgCount())) {
5303 return Api::NewError(
5304 "%s: argument 'index' out of range. Expected 0..%d but saw %d.",
5305 CURRENT_FUNC, arguments->NativeArgCount() - 1, index);
5306 }
5307 if (!GetNativeIntegerArgument(arguments, index, value)) {
5308 return Api::NewArgumentError(
5309 "%s: expects argument at %d to be of"
5310 " type Integer.",
5311 CURRENT_FUNC, index);
5312 }
5313 return Api::Success();
5314}
5315
5316DART_EXPORT Dart_Handle Dart_GetNativeBooleanArgument(Dart_NativeArguments args,
5317 int index,
5318 bool* value) {
5319 NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
5320 if ((index < 0) || (index >= arguments->NativeArgCount())) {
5321 return Api::NewError(
5322 "%s: argument 'index' out of range. Expected 0..%d but saw %d.",
5323 CURRENT_FUNC, arguments->NativeArgCount() - 1, index);
5324 }
5325 if (!Api::GetNativeBooleanArgument(arguments, index, value)) {
5326 return Api::NewArgumentError(
5327 "%s: expects argument at %d to be of type Boolean.", CURRENT_FUNC,
5328 index);
5329 }
5330 return Api::Success();
5331}
5332
5333DART_EXPORT Dart_Handle Dart_GetNativeDoubleArgument(Dart_NativeArguments args,
5334 int index,
5335 double* value) {
5336 NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
5337 if ((index < 0) || (index >= arguments->NativeArgCount())) {
5338 return Api::NewError(
5339 "%s: argument 'index' out of range. Expected 0..%d but saw %d.",
5340 CURRENT_FUNC, arguments->NativeArgCount() - 1, index);
5341 }
5342 if (!GetNativeDoubleArgument(arguments, index, value)) {
5343 return Api::NewArgumentError(
5344 "%s: expects argument at %d to be of"
5345 " type Double.",
5346 CURRENT_FUNC, index);
5347 }
5348 return Api::Success();
5349}
5350
5351DART_EXPORT void Dart_SetReturnValue(Dart_NativeArguments args,
5352 Dart_Handle retval) {
5353 NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
5354 ASSERT(arguments->thread()->isolate() == Isolate::Current());
5355 ASSERT_CALLBACK_STATE(arguments->thread());
5356 TransitionNativeToVM transition(arguments->thread());
5357 if ((retval != Api::Null()) && !Api::IsInstance(retval) &&
5358 !Api::IsError(retval)) {
5359 // Print the current stack trace to make the problematic caller
5360 // easier to find.
5361 const StackTrace& stacktrace = GetCurrentStackTrace(0);
5362 OS::PrintErr("=== Current Trace:\n%s===\n", stacktrace.ToCString());
5363
5364 const Object& ret_obj = Object::Handle(Api::UnwrapHandle(retval));
5365 FATAL1(
5366 "Return value check failed: saw '%s' expected a dart Instance or "
5367 "an Error.",
5368 ret_obj.ToCString());
5369 }
5370 ASSERT(retval != 0);
5371 Api::SetReturnValue(arguments, retval);
5372}
5373
5374DART_EXPORT void Dart_SetWeakHandleReturnValue(Dart_NativeArguments args,
5375 Dart_WeakPersistentHandle rval) {
5376 NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
5377 TransitionNativeToVM transition(arguments->thread());
5378#if defined(DEBUG)
5379 Isolate* isolate = arguments->thread()->isolate();
5380 ASSERT(isolate == Isolate::Current());
5381 ASSERT(isolate->group()->api_state() != NULL &&
5382 (isolate->group()->api_state()->IsValidWeakPersistentHandle(rval)));
5383#endif
5384 Api::SetWeakHandleReturnValue(arguments, rval);
5385}
5386
5387// --- Environment ---
5388StringPtr Api::GetEnvironmentValue(Thread* thread, const String& name) {
5389 String& result = String::Handle(CallEnvironmentCallback(thread, name));
5390 if (result.IsNull()) {
5391 // Every 'dart:X' library introduces an environment variable
5392 // 'dart.library.X' that is set to 'true'.
5393 // We just need to make sure to hide private libraries (starting with
5394 // "_", and the mirrors library, if it is not supported.
5395
5396 if (!FLAG_enable_mirrors && name.Equals(Symbols::DartLibraryMirrors())) {
5397 return Symbols::False().raw();
5398 }
5399
5400 if (!Api::IsFfiEnabled() && name.Equals(Symbols::DartLibraryFfi())) {
5401 return Symbols::False().raw();
5402 }
5403
5404 if (name.Equals(Symbols::DartVMProduct())) {
5405#ifdef PRODUCT
5406 return Symbols::True().raw();
5407#else
5408 return Symbols::False().raw();
5409#endif
5410 }
5411
5412 if (name.Equals(Symbols::DartDeveloperTimeline())) {
5413#ifdef SUPPORT_TIMELINE
5414 return Symbols::True().raw();
5415#else
5416 return Symbols::False().raw();
5417#endif
5418 }
5419
5420 const String& prefix = Symbols::DartLibrary();
5421 if (name.StartsWith(prefix)) {
5422 const String& library_name =
5423 String::Handle(String::SubString(name, prefix.Length()));
5424
5425 // Private libraries (starting with "_") are not exposed to the user.
5426 if (!library_name.IsNull() && library_name.CharAt(0) != '_') {
5427 const String& dart_library_name =
5428 String::Handle(String::Concat(Symbols::DartScheme(), library_name));
5429 const Library& library =
5430 Library::Handle(Library::LookupLibrary(thread, dart_library_name));
5431 if (!library.IsNull()) {
5432 return Symbols::True().raw();
5433 }
5434 }
5435 }
5436 // Check for default VM provided values. If it was not overridden on the
5437 // command line.
5438 if (Symbols::DartIsVM().Equals(name)) {
5439 return Symbols::True().raw();
5440 }
5441 if (FLAG_causal_async_stacks) {
5442 if (Symbols::DartDeveloperCausalAsyncStacks().Equals(name)) {
5443 return Symbols::True().raw();
5444 }
5445 }
5446 }
5447 return result.raw();
5448}
5449
5450StringPtr Api::CallEnvironmentCallback(Thread* thread, const String& name) {
5451 Isolate* isolate = thread->isolate();
5452 Dart_EnvironmentCallback callback = isolate->environment_callback();
5453 if (callback != NULL) {
5454 Scope api_scope(thread);
5455 Dart_Handle api_name = Api::NewHandle(thread, name.raw());
5456 Dart_Handle api_response;
5457 {
5458 TransitionVMToNative transition(thread);
5459 api_response = callback(api_name);
5460 }
5461 const Object& response =
5462 Object::Handle(thread->zone(), Api::UnwrapHandle(api_response));
5463 if (response.IsString()) {
5464 return String::Cast(response).raw();
5465 } else if (response.IsError()) {
5466 Exceptions::ThrowArgumentError(
5467 String::Handle(String::New(Error::Cast(response).ToErrorCString())));
5468 } else if (!response.IsNull()) {
5469 // At this point everything except null are invalid environment values.
5470 Exceptions::ThrowArgumentError(
5471 String::Handle(String::New("Illegal environment value")));
5472 }
5473 }
5474 return String::null();
5475}
5476
5477DART_EXPORT Dart_Handle
5478Dart_SetEnvironmentCallback(Dart_EnvironmentCallback callback) {
5479 Isolate* isolate = Isolate::Current();
5480 CHECK_ISOLATE(isolate);
5481 isolate->set_environment_callback(callback);
5482 return Api::Success();
5483}
5484
5485// --- Scripts and Libraries ---
5486DART_EXPORT void Dart_SetBooleanReturnValue(Dart_NativeArguments args,
5487 bool retval) {
5488 NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
5489 TransitionNativeToVM transition(arguments->thread());
5490 ASSERT(arguments->thread()->isolate() == Isolate::Current());
5491 ASSERT_CALLBACK_STATE(arguments->thread());
5492 arguments->SetReturn(Bool::Get(retval));
5493}
5494
5495DART_EXPORT void Dart_SetIntegerReturnValue(Dart_NativeArguments args,
5496 int64_t retval) {
5497 NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
5498 TransitionNativeToVM transition(arguments->thread());
5499 ASSERT(arguments->thread()->isolate() == Isolate::Current());
5500 ASSERT_CALLBACK_STATE(arguments->thread());
5501 if (Smi::IsValid(retval)) {
5502 Api::SetSmiReturnValue(arguments, static_cast<intptr_t>(retval));
5503 } else {
5504 // Slow path for Mints.
5505 Api::SetIntegerReturnValue(arguments, retval);
5506 }
5507}
5508
5509DART_EXPORT void Dart_SetDoubleReturnValue(Dart_NativeArguments args,
5510 double retval) {
5511 NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
5512 ASSERT(arguments->thread()->isolate() == Isolate::Current());
5513 ASSERT_CALLBACK_STATE(arguments->thread());
5514 TransitionNativeToVM transition(arguments->thread());
5515 Api::SetDoubleReturnValue(arguments, retval);
5516}
5517
5518// --- Scripts and Libraries ---
5519
5520DART_EXPORT Dart_Handle
5521Dart_SetLibraryTagHandler(Dart_LibraryTagHandler handler) {
5522 Isolate* isolate = Isolate::Current();
5523 CHECK_ISOLATE(isolate);
5524 isolate->group()->set_library_tag_handler(handler);
5525 return Api::Success();
5526}
5527
5528DART_EXPORT Dart_Handle Dart_DefaultCanonicalizeUrl(Dart_Handle base_url,
5529 Dart_Handle url) {
5530 DARTSCOPE(Thread::Current());
5531 API_TIMELINE_DURATION(T);
5532 CHECK_CALLBACK_STATE(T);
5533
5534 const String& base_uri = Api::UnwrapStringHandle(Z, base_url);
5535 if (base_uri.IsNull()) {
5536 RETURN_TYPE_ERROR(Z, base_url, String);
5537 }
5538 const String& uri = Api::UnwrapStringHandle(Z, url);
5539 if (uri.IsNull()) {
5540 RETURN_TYPE_ERROR(Z, url, String);
5541 }
5542
5543 const char* resolved_uri;
5544 if (!ResolveUri(uri.ToCString(), base_uri.ToCString(), &resolved_uri)) {
5545 return Api::NewError("%s: Unable to canonicalize uri '%s'.", CURRENT_FUNC,
5546 uri.ToCString());
5547 }
5548 return Api::NewHandle(T, String::New(resolved_uri));
5549}
5550
5551DART_EXPORT Dart_Handle
5552Dart_SetDeferredLoadHandler(Dart_DeferredLoadHandler handler) {
5553 Isolate* isolate = Isolate::Current();
5554 CHECK_ISOLATE(isolate);
5555 isolate->group()->set_deferred_load_handler(handler);
5556 return Api::Success();
5557}
5558
5559DART_EXPORT Dart_Handle Dart_LoadScriptFromKernel(const uint8_t* buffer,
5560 intptr_t buffer_size) {
5561#if defined(DART_PRECOMPILED_RUNTIME)
5562 return Api::NewError("%s: Cannot compile on an AOT runtime.", CURRENT_FUNC);
5563#else
5564 DARTSCOPE(Thread::Current());
5565 API_TIMELINE_DURATION(T);
5566 StackZone zone(T);
5567 Isolate* I = T->isolate();
5568
5569 Library& library = Library::Handle(Z, I->object_store()->root_library());
5570 if (!library.IsNull()) {
5571 const String& library_url = String::Handle(Z, library.url());
5572 return Api::NewError("%s: A script has already been loaded from '%s'.",
5573 CURRENT_FUNC, library_url.ToCString());
5574 }
5575 CHECK_CALLBACK_STATE(T);
5576
5577 // NOTE: We do not attach a finalizer for this object, because the embedder
5578 // will free it once the isolate group has shutdown.
5579 const auto& td = ExternalTypedData::Handle(ExternalTypedData::New(
5580 kExternalTypedDataUint8ArrayCid, const_cast<uint8_t*>(buffer),
5581 buffer_size, Heap::kOld));
5582
5583 const char* error = nullptr;
5584 std::unique_ptr<kernel::Program> program =
5585 kernel::Program::ReadFromTypedData(td, &error);
5586 if (program == nullptr) {
5587 return Api::NewError("Can't load Kernel binary: %s.", error);
5588 }
5589 const Object& tmp = kernel::KernelLoader::LoadEntireProgram(program.get());
5590 program.reset();
5591
5592 if (tmp.IsError()) {
5593 return Api::NewHandle(T, tmp.raw());
5594 }
5595
5596 I->source()->script_kernel_size = buffer_size;
5597 I->source()->script_kernel_buffer = buffer;
5598
5599 // TODO(32618): Setting root library based on whether it has 'main' or not
5600 // is not correct because main can be in the exported namespace of a library
5601 // or it could be a getter.
5602 if (tmp.IsNull()) {
5603 return Api::NewError("%s: The binary program does not contain 'main'.",
5604 CURRENT_FUNC);
5605 }
5606 library ^= tmp.raw();
5607 I->object_store()->set_root_library(library);
5608 return Api::NewHandle(T, library.raw());
5609#endif // defined(DART_PRECOMPILED_RUNTIME)
5610}
5611
5612DART_EXPORT Dart_Handle Dart_RootLibrary() {
5613 Thread* thread = Thread::Current();
5614 Isolate* isolate = thread->isolate();
5615 CHECK_ISOLATE(isolate);
5616 TransitionNativeToVM transition(thread);
5617 return Api::NewHandle(thread, isolate->object_store()->root_library());
5618}
5619
5620DART_EXPORT Dart_Handle Dart_SetRootLibrary(Dart_Handle library) {
5621 DARTSCOPE(Thread::Current());
5622 const Object& obj = Object::Handle(Z, Api::UnwrapHandle(library));
5623 if (obj.IsNull() || obj.IsLibrary()) {
5624 Library& lib = Library::Handle(Z);
5625 lib ^= obj.raw();
5626 T->isolate()->object_store()->set_root_library(lib);
5627 return library;
5628 }
5629 RETURN_TYPE_ERROR(Z, library, Library);
5630}
5631
5632DART_EXPORT Dart_Handle Dart_GetClass(Dart_Handle library,
5633 Dart_Handle class_name) {
5634 DARTSCOPE(Thread::Current());
5635 const Library& lib = Api::UnwrapLibraryHandle(Z, library);
5636 if (lib.IsNull()) {
5637 RETURN_TYPE_ERROR(Z, library, Library);
5638 }
5639 const String& cls_name = Api::UnwrapStringHandle(Z, class_name);
5640 if (cls_name.IsNull()) {
5641 RETURN_TYPE_ERROR(Z, class_name, String);
5642 }
5643 const Class& cls = Class::Handle(Z, lib.LookupClassAllowPrivate(cls_name));
5644 if (cls.IsNull()) {
5645 // TODO(turnidge): Return null or error in this case?
5646 const String& lib_name = String::Handle(Z, lib.name());
5647 return Api::NewError("Class '%s' not found in library '%s'.",
5648 cls_name.ToCString(), lib_name.ToCString());
5649 }
5650 cls.EnsureDeclarationLoaded();
5651 CHECK_ERROR_HANDLE(cls.VerifyEntryPoint());
5652 return Api::NewHandle(T, cls.RareType());
5653}
5654
5655static Dart_Handle GetTypeCommon(Dart_Handle library,
5656 Dart_Handle class_name,
5657 intptr_t number_of_type_arguments,
5658 Dart_Handle* type_arguments,
5659 Nullability nullability) {
5660 DARTSCOPE(Thread::Current());
5661 // Validate the input arguments.
5662 const Library& lib = Api::UnwrapLibraryHandle(Z, library);
5663 if (lib.IsNull()) {
5664 RETURN_TYPE_ERROR(Z, library, Library);
5665 }
5666 if (!lib.Loaded()) {
5667 return Api::NewError("%s expects library argument 'library' to be loaded.",
5668 CURRENT_FUNC);
5669 }
5670 const String& name_str = Api::UnwrapStringHandle(Z, class_name);
5671 if (name_str.IsNull()) {
5672 RETURN_TYPE_ERROR(Z, class_name, String);
5673 }
5674 const Class& cls = Class::Handle(Z, lib.LookupClassAllowPrivate(name_str));
5675 if (cls.IsNull()) {
5676 const String& lib_name = String::Handle(Z, lib.name());
5677 return Api::NewError("Type '%s' not found in library '%s'.",
5678 name_str.ToCString(), lib_name.ToCString());
5679 }
5680 cls.EnsureDeclarationLoaded();
5681 CHECK_ERROR_HANDLE(cls.VerifyEntryPoint());
5682
5683 Type& type = Type::Handle();
5684 if (cls.NumTypeArguments() == 0) {
5685 if (number_of_type_arguments != 0) {
5686 return Api::NewError(
5687 "Invalid number of type arguments specified, "
5688 "got %" Pd " expected 0",
5689 number_of_type_arguments);
5690 }
5691 type ^= Type::NewNonParameterizedType(cls);
5692 type ^= type.ToNullability(nullability, Heap::kOld);
5693 } else {
5694 intptr_t num_expected_type_arguments = cls.NumTypeParameters();
5695 TypeArguments& type_args_obj = TypeArguments::Handle();
5696 if (number_of_type_arguments > 0) {
5697 if (type_arguments == NULL) {
5698 RETURN_NULL_ERROR(type_arguments);
5699 }
5700 if (num_expected_type_arguments != number_of_type_arguments) {
5701 return Api::NewError(
5702 "Invalid number of type arguments specified, "
5703 "got %" Pd " expected %" Pd,
5704 number_of_type_arguments, num_expected_type_arguments);
5705 }
5706 const Array& array = Api::UnwrapArrayHandle(Z, *type_arguments);
5707 if (array.IsNull()) {
5708 RETURN_TYPE_ERROR(Z, *type_arguments, Array);
5709 }
5710 if (array.Length() != num_expected_type_arguments) {
5711 return Api::NewError(
5712 "Invalid type arguments specified, expected an "
5713 "array of len %" Pd " but got an array of len %" Pd,
5714 number_of_type_arguments, array.Length());
5715 }
5716 // Set up the type arguments array.
5717 type_args_obj = TypeArguments::New(num_expected_type_arguments);
5718 AbstractType& type_arg = AbstractType::Handle();
5719 for (intptr_t i = 0; i < number_of_type_arguments; i++) {
5720 type_arg ^= array.At(i);
5721 type_args_obj.SetTypeAt(i, type_arg);
5722 }
5723 }
5724
5725 // Construct the type object, canonicalize it and return.
5726 type ^=
5727 Type::New(cls, type_args_obj, TokenPosition::kNoSource, nullability);
5728 }
5729 type ^= ClassFinalizer::FinalizeType(cls, type);
5730 return Api::NewHandle(T, type.raw());
5731}
5732
5733DART_EXPORT Dart_Handle Dart_GetType(Dart_Handle library,
5734 Dart_Handle class_name,
5735 intptr_t number_of_type_arguments,
5736 Dart_Handle* type_arguments) {
5737 if (Thread::Current()->isolate()->null_safety()) {
5738 return Api::NewError(
5739 "Cannot use legacy types with --sound-null-safety enabled. "
5740 "Use Dart_GetNullableType or Dart_GetNonNullableType instead.");
5741 }
5742 return GetTypeCommon(library, class_name, number_of_type_arguments,
5743 type_arguments, Nullability::kLegacy);
5744}
5745
5746DART_EXPORT Dart_Handle Dart_GetNullableType(Dart_Handle library,
5747 Dart_Handle class_name,
5748 intptr_t number_of_type_arguments,
5749 Dart_Handle* type_arguments) {
5750 return GetTypeCommon(library, class_name, number_of_type_arguments,
5751 type_arguments, Nullability::kNullable);
5752}
5753
5754DART_EXPORT Dart_Handle
5755Dart_GetNonNullableType(Dart_Handle library,
5756 Dart_Handle class_name,
5757 intptr_t number_of_type_arguments,
5758 Dart_Handle* type_arguments) {
5759 return GetTypeCommon(library, class_name, number_of_type_arguments,
5760 type_arguments, Nullability::kNonNullable);
5761}
5762
5763static Dart_Handle TypeToHelper(Dart_Handle type, Nullability nullability) {
5764 DARTSCOPE(Thread::Current());
5765 const Type& ty = Api::UnwrapTypeHandle(Z, type);
5766 if (ty.IsNull()) {
5767 RETURN_TYPE_ERROR(Z, type, Type);
5768 }
5769 if (ty.nullability() == nullability) {
5770 return type;
5771 }
5772 return Api::NewHandle(T, ty.ToNullability(nullability, Heap::kOld));
5773}
5774
5775DART_EXPORT Dart_Handle Dart_TypeToNullableType(Dart_Handle type) {
5776 return TypeToHelper(type, Nullability::kNullable);
5777}
5778
5779DART_EXPORT Dart_Handle Dart_TypeToNonNullableType(Dart_Handle type) {
5780 return TypeToHelper(type, Nullability::kNonNullable);
5781}
5782
5783static Dart_Handle IsOfTypeNullabilityHelper(Dart_Handle type,
5784 Nullability nullability,
5785 bool* result) {
5786 DARTSCOPE(Thread::Current());
5787 const Type& ty = Api::UnwrapTypeHandle(Z, type);
5788 if (ty.IsNull()) {
5789 *result = false;
5790 RETURN_TYPE_ERROR(Z, type, Type);
5791 }
5792 *result = (ty.nullability() == nullability);
5793 return Api::Success();
5794}
5795
5796DART_EXPORT Dart_Handle Dart_IsNullableType(Dart_Handle type, bool* result) {
5797 return IsOfTypeNullabilityHelper(type, Nullability::kNullable, result);
5798}
5799
5800DART_EXPORT Dart_Handle Dart_IsNonNullableType(Dart_Handle type, bool* result) {
5801 return IsOfTypeNullabilityHelper(type, Nullability::kNonNullable, result);
5802}
5803
5804DART_EXPORT Dart_Handle Dart_IsLegacyType(Dart_Handle type, bool* result) {
5805 return IsOfTypeNullabilityHelper(type, Nullability::kLegacy, result);
5806}
5807
5808DART_EXPORT Dart_Handle Dart_LibraryUrl(Dart_Handle library) {
5809 DARTSCOPE(Thread::Current());
5810 const Library& lib = Api::UnwrapLibraryHandle(Z, library);
5811 if (lib.IsNull()) {
5812 RETURN_TYPE_ERROR(Z, library, Library);
5813 }
5814 const String& url = String::Handle(Z, lib.url());
5815 ASSERT(!url.IsNull());
5816 return Api::NewHandle(T, url.raw());
5817}
5818
5819DART_EXPORT Dart_Handle Dart_LibraryResolvedUrl(Dart_Handle library) {
5820 DARTSCOPE(Thread::Current());
5821 const Library& lib = Api::UnwrapLibraryHandle(Z, library);
5822 if (lib.IsNull()) {
5823 RETURN_TYPE_ERROR(Z, library, Library);
5824 }
5825 const Class& toplevel = Class::Handle(lib.toplevel_class());
5826 ASSERT(!toplevel.IsNull());
5827 const Script& script = Script::Handle(toplevel.script());
5828 ASSERT(!script.IsNull());
5829 const String& url = String::Handle(script.resolved_url());
5830 ASSERT(!url.IsNull());
5831 return Api::NewHandle(T, url.raw());
5832}
5833
5834DART_EXPORT Dart_Handle Dart_GetLoadedLibraries() {
5835 DARTSCOPE(Thread::Current());
5836 Isolate* I = T->isolate();
5837
5838 const GrowableObjectArray& libs =
5839 GrowableObjectArray::Handle(Z, I->object_store()->libraries());
5840 int num_libs = libs.Length();
5841
5842 // Create new list and populate with the loaded libraries.
5843 Library& lib = Library::Handle();
5844 const Array& library_list = Array::Handle(Z, Array::New(num_libs));
5845 for (int i = 0; i < num_libs; i++) {
5846 lib ^= libs.At(i);
5847 ASSERT(!lib.IsNull());
5848 library_list.SetAt(i, lib);
5849 }
5850 return Api::NewHandle(T, library_list.raw());
5851}
5852
5853DART_EXPORT Dart_Handle Dart_LookupLibrary(Dart_Handle url) {
5854 DARTSCOPE(Thread::Current());
5855 const String& url_str = Api::UnwrapStringHandle(Z, url);
5856 if (url_str.IsNull()) {
5857 RETURN_TYPE_ERROR(Z, url, String);
5858 }
5859 const Library& library =
5860 Library::Handle(Z, Library::LookupLibrary(T, url_str));
5861 if (library.IsNull()) {
5862 return Api::NewError("%s: library '%s' not found.", CURRENT_FUNC,
5863 url_str.ToCString());
5864 } else {
5865 return Api::NewHandle(T, library.raw());
5866 }
5867}
5868
5869DART_EXPORT Dart_Handle Dart_LibraryHandleError(Dart_Handle library_in,
5870 Dart_Handle error_in) {
5871 DARTSCOPE(Thread::Current());
5872
5873 const Library& lib = Api::UnwrapLibraryHandle(Z, library_in);
5874 if (lib.IsNull()) {
5875 RETURN_TYPE_ERROR(Z, library_in, Library);
5876 }
5877 const Instance& err = Api::UnwrapInstanceHandle(Z, error_in);
5878 if (err.IsNull()) {
5879 RETURN_TYPE_ERROR(Z, error_in, Instance);
5880 }
5881 CHECK_CALLBACK_STATE(T);
5882
5883 return error_in;
5884}
5885
5886DART_EXPORT Dart_Handle Dart_LoadLibraryFromKernel(const uint8_t* buffer,
5887 intptr_t buffer_size) {
5888#if defined(DART_PRECOMPILED_RUNTIME)
5889 return Api::NewError("%s: Cannot compile on an AOT runtime.", CURRENT_FUNC);
5890#else
5891 DARTSCOPE(Thread::Current());
5892 API_TIMELINE_DURATION(T);
5893 StackZone zone(T);
5894
5895 CHECK_CALLBACK_STATE(T);
5896
5897 // NOTE: We do not attach a finalizer for this object, because the embedder
5898 // will/should free it once the isolate group has shutdown.
5899 // See also http://dartbug.com/37030.
5900 const auto& td = ExternalTypedData::Handle(ExternalTypedData::New(
5901 kExternalTypedDataUint8ArrayCid, const_cast<uint8_t*>(buffer),
5902 buffer_size, Heap::kOld));
5903
5904 const char* error = nullptr;
5905 std::unique_ptr<kernel::Program> program =
5906 kernel::Program::ReadFromTypedData(td, &error);
5907 if (program == nullptr) {
5908 return Api::NewError("Can't load Kernel binary: %s.", error);
5909 }
5910 const Object& result =
5911 kernel::KernelLoader::LoadEntireProgram(program.get(), false);
5912 program.reset();
5913
5914 IsolateGroupSource* source = Isolate::Current()->source();
5915 source->add_loaded_blob(Z, td);
5916
5917 return Api::NewHandle(T, result.raw());
5918#endif // defined(DART_PRECOMPILED_RUNTIME)
5919}
5920
5921DART_EXPORT Dart_Handle Dart_GetImportsOfScheme(Dart_Handle scheme) {
5922 DARTSCOPE(Thread::Current());
5923 Isolate* I = T->isolate();
5924 const String& scheme_vm = Api::UnwrapStringHandle(Z, scheme);
5925 if (scheme_vm.IsNull()) {
5926 RETURN_TYPE_ERROR(Z, scheme, String);
5927 }
5928
5929 const GrowableObjectArray& libraries =
5930 GrowableObjectArray::Handle(Z, I->object_store()->libraries());
5931 const GrowableObjectArray& result =
5932 GrowableObjectArray::Handle(Z, GrowableObjectArray::New());
5933 Library& importer = Library::Handle(Z);
5934 Array& imports = Array::Handle(Z);
5935 Namespace& ns = Namespace::Handle(Z);
5936 Library& importee = Library::Handle(Z);
5937 String& importee_uri = String::Handle(Z);
5938 for (intptr_t i = 0; i < libraries.Length(); i++) {
5939 importer ^= libraries.At(i);
5940 imports = importer.imports();
5941 for (intptr_t j = 0; j < imports.Length(); j++) {
5942 ns ^= imports.At(j);
5943 if (ns.IsNull()) continue;
5944 importee = ns.library();
5945 importee_uri = importee.url();
5946 if (importee_uri.StartsWith(scheme_vm)) {
5947 result.Add(importer);
5948 result.Add(importee);
5949 }
5950 }
5951 }
5952
5953 return Api::NewHandle(T, Array::MakeFixedLength(result));
5954}
5955
5956// Finalizes classes and invokes Dart core library function that completes
5957// futures of loadLibrary calls (deferred library loading).
5958DART_EXPORT Dart_Handle Dart_FinalizeLoading(bool complete_futures) {
5959 DARTSCOPE(Thread::Current());
5960 API_TIMELINE_DURATION(T);
5961 Isolate* I = T->isolate();
5962 CHECK_CALLBACK_STATE(T);
5963
5964 // Finalize all classes if needed.
5965 Dart_Handle state = Api::CheckAndFinalizePendingClasses(T);
5966 if (Api::IsError(state)) {
5967 return state;
5968 }
5969
5970#if !defined(PRODUCT)
5971 // Now that the newly loaded classes are finalized, notify the debugger
5972 // that new code has been loaded. If there are latent breakpoints in
5973 // the new code, the debugger convert them to unresolved source breakpoints.
5974 // The code that completes the futures (invoked below) may call into the
5975 // newly loaded code and trigger one of these breakpoints.
5976 I->debugger()->NotifyDoneLoading();
5977#endif
5978
5979 // After having loaded all the code, we can let the GC set reaonsable limits
5980 // for the heap growth.
5981 // If this is an auxiliary isolate inside a larger isolate group, we will not
5982 // re-initialize the growth policy.
5983 if (I->group()->ContainsOnlyOneIsolate()) {
5984 I->heap()->old_space()->EvaluateAfterLoading();
5985 }
5986
5987#if !defined(DART_PRECOMPILED_RUNTIME)
5988 if (FLAG_enable_mirrors) {
5989 // Notify mirrors that MirrorSystem.libraries needs to be recomputed.
5990 const Library& libmirrors = Library::Handle(Z, Library::MirrorsLibrary());
5991 const Field& dirty_bit = Field::Handle(
5992 Z, libmirrors.LookupLocalField(String::Handle(String::New("_dirty"))));
5993 ASSERT(!dirty_bit.IsNull() && dirty_bit.is_static());
5994 dirty_bit.SetStaticValue(Bool::True());
5995 }
5996#endif
5997
5998 return Api::Success();
5999}
6000
6001static Dart_Handle DeferredLoadComplete(intptr_t loading_unit_id,
6002 bool error,
6003 const uint8_t* snapshot_data,
6004 const uint8_t* snapshot_instructions,
6005 const char* error_message,
6006 bool transient_error) {
6007 DARTSCOPE(Thread::Current());
6008 API_TIMELINE_DURATION(T);
6009 Isolate* I = T->isolate();
6010 CHECK_CALLBACK_STATE(T);
6011
6012 const Array& loading_units =
6013 Array::Handle(I->object_store()->loading_units());
6014 if (loading_units.IsNull() || (loading_unit_id < LoadingUnit::kRootId) ||
6015 (loading_unit_id >= loading_units.Length())) {
6016 return Api::NewError("Invalid loading unit");
6017 }
6018 LoadingUnit& unit = LoadingUnit::Handle();
6019 unit ^= loading_units.At(loading_unit_id);
6020 if (unit.loaded()) {
6021 return Api::NewError("Unit already loaded");
6022 }
6023
6024 if (error) {
6025 CHECK_NULL(error_message);
6026 unit.CompleteLoad(String::Handle(String::New(error_message)),
6027 transient_error);
6028 } else {
6029#if defined(SUPPORT_TIMELINE)
6030 TimelineBeginEndScope tbes(T, Timeline::GetIsolateStream(),
6031 "ReadUnitSnapshot");
6032#endif // defined(SUPPORT_TIMELINE)
6033 const Snapshot* snapshot = Snapshot::SetupFromBuffer(snapshot_data);
6034 if (snapshot == NULL) {
6035 return Api::NewError("Invalid snapshot");
6036 }
6037 if (!IsSnapshotCompatible(Dart::vm_snapshot_kind(), snapshot->kind())) {
6038 const String& message = String::Handle(String::NewFormatted(
6039 "Incompatible snapshot kinds: vm '%s', isolate '%s'",
6040 Snapshot::KindToCString(Dart::vm_snapshot_kind()),
6041 Snapshot::KindToCString(snapshot->kind())));
6042 return Api::NewHandle(T, ApiError::New(message));
6043 }
6044
6045 FullSnapshotReader reader(snapshot, snapshot_instructions, T);
6046 const Error& error = Error::Handle(reader.ReadUnitSnapshot(unit));
6047 if (!error.IsNull()) {
6048 return Api::NewHandle(T, error.raw());
6049 }
6050
6051 unit.CompleteLoad(String::Handle(), false);
6052 }
6053
6054 return Api::Success();
6055}
6056
6057DART_EXPORT Dart_Handle
6058Dart_DeferredLoadComplete(intptr_t loading_unit_id,
6059 const uint8_t* snapshot_data,
6060 const uint8_t* snapshot_instructions) {
6061 return DeferredLoadComplete(loading_unit_id, false, snapshot_data,
6062 snapshot_instructions, nullptr, false);
6063}
6064
6065DART_EXPORT Dart_Handle
6066Dart_DeferredLoadCompleteError(intptr_t loading_unit_id,
6067 const char* error_message,
6068 bool transient) {
6069 return DeferredLoadComplete(loading_unit_id, true, nullptr, nullptr,
6070 error_message, transient);
6071}
6072
6073DART_EXPORT Dart_Handle
6074Dart_SetNativeResolver(Dart_Handle library,
6075 Dart_NativeEntryResolver resolver,
6076 Dart_NativeEntrySymbol symbol) {
6077 DARTSCOPE(Thread::Current());
6078 const Library& lib = Api::UnwrapLibraryHandle(Z, library);
6079 if (lib.IsNull()) {
6080 RETURN_TYPE_ERROR(Z, library, Library);
6081 }
6082 lib.set_native_entry_resolver(resolver);
6083 lib.set_native_entry_symbol_resolver(symbol);
6084 return Api::Success();
6085}
6086
6087DART_EXPORT Dart_Handle
6088Dart_GetNativeResolver(Dart_Handle library,
6089 Dart_NativeEntryResolver* resolver) {
6090 if (resolver == NULL) {
6091 RETURN_NULL_ERROR(resolver);
6092 }
6093 *resolver = NULL;
6094 DARTSCOPE(Thread::Current());
6095 const Library& lib = Api::UnwrapLibraryHandle(Z, library);
6096 if (lib.IsNull()) {
6097 RETURN_TYPE_ERROR(Z, library, Library);
6098 }
6099 *resolver = lib.native_entry_resolver();
6100 return Api::Success();
6101}
6102
6103DART_EXPORT Dart_Handle Dart_GetNativeSymbol(Dart_Handle library,
6104 Dart_NativeEntrySymbol* resolver) {
6105 if (resolver == NULL) {
6106 RETURN_NULL_ERROR(resolver);
6107 }
6108 *resolver = NULL;
6109 DARTSCOPE(Thread::Current());
6110 const Library& lib = Api::UnwrapLibraryHandle(Z, library);
6111 if (lib.IsNull()) {
6112 RETURN_TYPE_ERROR(Z, library, Library);
6113 }
6114 *resolver = lib.native_entry_symbol_resolver();
6115 return Api::Success();
6116}
6117
6118// --- Peer support ---
6119
6120DART_EXPORT Dart_Handle Dart_GetPeer(Dart_Handle object, void** peer) {
6121 if (peer == NULL) {
6122 RETURN_NULL_ERROR(peer);
6123 }
6124 Thread* thread = Thread::Current();
6125 CHECK_ISOLATE(thread->isolate());
6126 TransitionNativeToVM transition(thread);
6127 REUSABLE_OBJECT_HANDLESCOPE(thread);
6128 Object& obj = thread->ObjectHandle();
6129 obj = Api::UnwrapHandle(object);
6130 if (obj.IsNull() || obj.IsNumber() || obj.IsBool()) {
6131 const char* msg =
6132 "%s: argument 'object' cannot be a subtype of Null, num, or bool";
6133 return Api::NewError(msg, CURRENT_FUNC);
6134 }
6135 {
6136 NoSafepointScope no_safepoint;
6137 ObjectPtr raw_obj = obj.raw();
6138 *peer = thread->isolate()->heap()->GetPeer(raw_obj);
6139 }
6140 return Api::Success();
6141}
6142
6143DART_EXPORT Dart_Handle Dart_SetPeer(Dart_Handle object, void* peer) {
6144 Thread* thread = Thread::Current();
6145 CHECK_ISOLATE(thread->isolate());
6146 TransitionNativeToVM transition(thread);
6147 REUSABLE_OBJECT_HANDLESCOPE(thread);
6148 Object& obj = thread->ObjectHandle();
6149 obj = Api::UnwrapHandle(object);
6150 if (obj.IsNull() || obj.IsNumber() || obj.IsBool()) {
6151 const char* msg =
6152 "%s: argument 'object' cannot be a subtype of Null, num, or bool";
6153 return Api::NewError(msg, CURRENT_FUNC);
6154 }
6155 {
6156 NoSafepointScope no_safepoint;
6157 ObjectPtr raw_obj = obj.raw();
6158 thread->isolate()->heap()->SetPeer(raw_obj, peer);
6159 }
6160 return Api::Success();
6161}
6162
6163// --- Dart Front-End (Kernel) support ---
6164
6165DART_EXPORT bool Dart_IsKernelIsolate(Dart_Isolate isolate) {
6166#if defined(DART_PRECOMPILED_RUNTIME)
6167 return false;
6168#else
6169 Isolate* iso = reinterpret_cast<Isolate*>(isolate);
6170 return KernelIsolate::IsKernelIsolate(iso);
6171#endif
6172}
6173
6174DART_EXPORT bool Dart_KernelIsolateIsRunning() {
6175#if defined(DART_PRECOMPILED_RUNTIME)
6176 return false;
6177#else
6178 return KernelIsolate::IsRunning();
6179#endif
6180}
6181
6182DART_EXPORT Dart_Port Dart_KernelPort() {
6183#if defined(DART_PRECOMPILED_RUNTIME)
6184 return false;
6185#else
6186 return KernelIsolate::KernelPort();
6187#endif
6188}
6189
6190DART_EXPORT Dart_KernelCompilationResult
6191Dart_CompileToKernel(const char* script_uri,
6192 const uint8_t* platform_kernel,
6193 intptr_t platform_kernel_size,
6194 bool incremental_compile,
6195 const char* package_config) {
6196 API_TIMELINE_DURATION(Thread::Current());
6197
6198 Dart_KernelCompilationResult result = {};
6199#if defined(DART_PRECOMPILED_RUNTIME)
6200 result.status = Dart_KernelCompilationStatus_Unknown;
6201 result.error = Utils::StrDup("Dart_CompileToKernel is unsupported.");
6202#else
6203 result = KernelIsolate::CompileToKernel(script_uri, platform_kernel,
6204 platform_kernel_size, 0, NULL,
6205 incremental_compile, package_config);
6206 if (result.status == Dart_KernelCompilationStatus_Ok) {
6207 Dart_KernelCompilationResult accept_result =
6208 KernelIsolate::AcceptCompilation();
6209 if (accept_result.status != Dart_KernelCompilationStatus_Ok) {
6210 FATAL1(
6211 "An error occurred in the CFE while accepting the most recent"
6212 " compilation results: %s",
6213 accept_result.error);
6214 }
6215 }
6216#endif
6217 return result;
6218}
6219
6220DART_EXPORT Dart_KernelCompilationResult Dart_KernelListDependencies() {
6221 Dart_KernelCompilationResult result = {};
6222#if defined(DART_PRECOMPILED_RUNTIME)
6223 result.status = Dart_KernelCompilationStatus_Unknown;
6224 result.error = Utils::StrDup("Dart_KernelListDependencies is unsupported.");
6225#else
6226 result = KernelIsolate::ListDependencies();
6227#endif
6228 return result;
6229}
6230
6231DART_EXPORT void Dart_SetDartLibrarySourcesKernel(
6232 const uint8_t* platform_kernel,
6233 const intptr_t platform_kernel_size) {
6234#if !defined(PRODUCT)
6235 Service::SetDartLibraryKernelForSources(platform_kernel,
6236 platform_kernel_size);
6237#endif
6238}
6239
6240DART_EXPORT bool Dart_DetectNullSafety(const char* script_uri,
6241 const char* package_config,
6242 const char* original_working_directory,
6243 const uint8_t* snapshot_data,
6244 const uint8_t* snapshot_instructions,
6245 const uint8_t* kernel_buffer,
6246 intptr_t kernel_buffer_size) {
6247#if defined(DART_PRECOMPILED_RUNTIME)
6248 ASSERT(FLAG_sound_null_safety != kNullSafetyOptionUnspecified);
6249 return (FLAG_sound_null_safety == kNullSafetyOptionStrong);
6250#else
6251 bool null_safety;
6252 if (FLAG_sound_null_safety == kNullSafetyOptionUnspecified) {
6253 null_safety = Dart::DetectNullSafety(
6254 script_uri, snapshot_data, snapshot_instructions, kernel_buffer,
6255 kernel_buffer_size, package_config, original_working_directory);
6256 } else {
6257 null_safety = (FLAG_sound_null_safety == kNullSafetyOptionStrong);
6258 }
6259 return null_safety;
6260#endif // defined(DART_PRECOMPILED_RUNTIME)
6261}
6262
6263// --- Service support ---
6264
6265DART_EXPORT bool Dart_IsServiceIsolate(Dart_Isolate isolate) {
6266 Isolate* iso = reinterpret_cast<Isolate*>(isolate);
6267 return ServiceIsolate::IsServiceIsolate(iso);
6268}
6269
6270DART_EXPORT int64_t Dart_TimelineGetMicros() {
6271 return OS::GetCurrentMonotonicMicros();
6272}
6273
6274DART_EXPORT void Dart_RegisterIsolateServiceRequestCallback(
6275 const char* name,
6276 Dart_ServiceRequestCallback callback,
6277 void* user_data) {
6278#if !defined(PRODUCT)
6279 Service::RegisterIsolateEmbedderCallback(name, callback, user_data);
6280#endif
6281}
6282
6283DART_EXPORT void Dart_RegisterRootServiceRequestCallback(
6284 const char* name,
6285 Dart_ServiceRequestCallback callback,
6286 void* user_data) {
6287#if !defined(PRODUCT)
6288 Service::RegisterRootEmbedderCallback(name, callback, user_data);
6289#endif
6290}
6291
6292DART_EXPORT void Dart_SetEmbedderInformationCallback(
6293 Dart_EmbedderInformationCallback callback) {
6294#if !defined(PRODUCT)
6295 Service::SetEmbedderInformationCallback(callback);
6296#endif
6297}
6298
6299DART_EXPORT char* Dart_SetServiceStreamCallbacks(
6300 Dart_ServiceStreamListenCallback listen_callback,
6301 Dart_ServiceStreamCancelCallback cancel_callback) {
6302#if defined(PRODUCT)
6303 return NULL;
6304#else
6305 if (listen_callback != NULL) {
6306 if (Service::stream_listen_callback() != NULL) {
6307 return Utils::StrDup(
6308 "Dart_SetServiceStreamCallbacks "
6309 "permits only one listen callback to be registered, please "
6310 "remove the existing callback and then add this callback");
6311 }
6312 } else {
6313 if (Service::stream_listen_callback() == NULL) {
6314 return Utils::StrDup(
6315 "Dart_SetServiceStreamCallbacks "
6316 "expects 'listen_callback' to be present in the callback set.");
6317 }
6318 }
6319 if (cancel_callback != NULL) {
6320 if (Service::stream_cancel_callback() != NULL) {
6321 return Utils::StrDup(
6322 "Dart_SetServiceStreamCallbacks "
6323 "permits only one cancel callback to be registered, please "
6324 "remove the existing callback and then add this callback");
6325 }
6326 } else {
6327 if (Service::stream_cancel_callback() == NULL) {
6328 return Utils::StrDup(
6329 "Dart_SetServiceStreamCallbacks "
6330 "expects 'cancel_callback' to be present in the callback set.");
6331 }
6332 }
6333 Service::SetEmbedderStreamCallbacks(listen_callback, cancel_callback);
6334 return NULL;
6335#endif
6336}
6337
6338DART_EXPORT void Dart_SetNativeServiceStreamCallback(
6339 Dart_NativeStreamConsumer consumer,
6340 const char* stream_id) {
6341#if !defined(PRODUCT)
6342 Service::SetNativeServiceStreamCallback(consumer, stream_id);
6343#endif
6344}
6345
6346DART_EXPORT Dart_Handle Dart_ServiceSendDataEvent(const char* stream_id,
6347 const char* event_kind,
6348 const uint8_t* bytes,
6349 intptr_t bytes_length) {
6350#if !defined(PRODUCT)
6351 DARTSCOPE(Thread::Current());
6352 Isolate* I = T->isolate();
6353 if (stream_id == NULL) {
6354 RETURN_NULL_ERROR(stream_id);
6355 }
6356 if (event_kind == NULL) {
6357 RETURN_NULL_ERROR(event_kind);
6358 }
6359 if (bytes == NULL) {
6360 RETURN_NULL_ERROR(bytes);
6361 }
6362 if (bytes_length < 0) {
6363 return Api::NewError("%s expects argument 'bytes_length' to be >= 0.",
6364 CURRENT_FUNC);
6365 }
6366 Service::SendEmbedderEvent(I, stream_id, event_kind, bytes, bytes_length);
6367#endif
6368 return Api::Success();
6369}
6370
6371DART_EXPORT char* Dart_SetFileModifiedCallback(
6372 Dart_FileModifiedCallback file_modified_callback) {
6373#if !defined(PRODUCT)
6374#if !defined(DART_PRECOMPILED_RUNTIME)
6375 if (file_modified_callback != NULL) {
6376 if (IsolateGroupReloadContext::file_modified_callback() != NULL) {
6377 return Utils::StrDup(
6378 "Dart_SetFileModifiedCallback permits only one callback to be"
6379 " registered, please remove the existing callback and then add"
6380 " this callback");
6381 }
6382 } else {
6383 if (IsolateGroupReloadContext::file_modified_callback() == NULL) {
6384 return Utils::StrDup(
6385 "Dart_SetFileModifiedCallback expects 'file_modified_callback' to"
6386 " be set before it is cleared.");
6387 }
6388 }
6389 IsolateGroupReloadContext::SetFileModifiedCallback(file_modified_callback);
6390#endif // !defined(DART_PRECOMPILED_RUNTIME)
6391#endif // !defined(PRODUCT)
6392 return NULL;
6393}
6394
6395DART_EXPORT bool Dart_IsReloading() {
6396#if defined(PRODUCT) || defined(DART_PRECOMPILED_RUNTIME)
6397 return false;
6398#else
6399 Thread* thread = Thread::Current();
6400 Isolate* isolate = thread->isolate();
6401 CHECK_ISOLATE(isolate);
6402 return isolate->group()->IsReloading();
6403#endif
6404}
6405
6406DART_EXPORT void Dart_GlobalTimelineSetRecordedStreams(int64_t stream_mask) {
6407#if defined(SUPPORT_TIMELINE)
6408 const bool api_enabled = (stream_mask & DART_TIMELINE_STREAM_API) != 0;
6409 const bool compiler_enabled =
6410 (stream_mask & DART_TIMELINE_STREAM_COMPILER) != 0;
6411 const bool dart_enabled = (stream_mask & DART_TIMELINE_STREAM_DART) != 0;
6412 const bool debugger_enabled =
6413 (stream_mask & DART_TIMELINE_STREAM_DEBUGGER) != 0;
6414 const bool embedder_enabled =
6415 (stream_mask & DART_TIMELINE_STREAM_EMBEDDER) != 0;
6416 const bool gc_enabled = (stream_mask & DART_TIMELINE_STREAM_GC) != 0;
6417 const bool isolate_enabled =
6418 (stream_mask & DART_TIMELINE_STREAM_ISOLATE) != 0;
6419 const bool vm_enabled = (stream_mask & DART_TIMELINE_STREAM_VM) != 0;
6420 Timeline::SetStreamAPIEnabled(api_enabled);
6421 Timeline::SetStreamCompilerEnabled(compiler_enabled);
6422 Timeline::SetStreamDartEnabled(dart_enabled);
6423 Timeline::SetStreamDebuggerEnabled(debugger_enabled);
6424 Timeline::SetStreamEmbedderEnabled(embedder_enabled);
6425 Timeline::SetStreamGCEnabled(gc_enabled);
6426 Timeline::SetStreamIsolateEnabled(isolate_enabled);
6427 Timeline::SetStreamVMEnabled(vm_enabled);
6428#endif
6429}
6430
6431DART_EXPORT void Dart_TimelineEvent(const char* label,
6432 int64_t timestamp0,
6433 int64_t timestamp1_or_async_id,
6434 Dart_Timeline_Event_Type type,
6435 intptr_t argument_count,
6436 const char** argument_names,
6437 const char** argument_values) {
6438#if defined(SUPPORT_TIMELINE)
6439 if (type < Dart_Timeline_Event_Begin) {
6440 return;
6441 }
6442 if (type > Dart_Timeline_Event_Flow_End) {
6443 return;
6444 }
6445 TimelineStream* stream = Timeline::GetEmbedderStream();
6446 ASSERT(stream != NULL);
6447 TimelineEvent* event = stream->StartEvent();
6448 if (event == NULL) {
6449 return;
6450 }
6451 switch (type) {
6452 case Dart_Timeline_Event_Begin:
6453 event->Begin(label, timestamp0);
6454 break;
6455 case Dart_Timeline_Event_End:
6456 event->End(label, timestamp0);
6457 break;
6458 case Dart_Timeline_Event_Instant:
6459 event->Instant(label, timestamp0);
6460 break;
6461 case Dart_Timeline_Event_Duration:
6462 event->Duration(label, timestamp0, timestamp1_or_async_id);
6463 break;
6464 case Dart_Timeline_Event_Async_Begin:
6465 event->AsyncBegin(label, timestamp1_or_async_id, timestamp0);
6466 break;
6467 case Dart_Timeline_Event_Async_End:
6468 event->AsyncEnd(label, timestamp1_or_async_id, timestamp0);
6469 break;
6470 case Dart_Timeline_Event_Async_Instant:
6471 event->AsyncInstant(label, timestamp1_or_async_id, timestamp0);
6472 break;
6473 case Dart_Timeline_Event_Counter:
6474 event->Counter(label, timestamp0);
6475 break;
6476 case Dart_Timeline_Event_Flow_Begin:
6477 event->FlowBegin(label, timestamp1_or_async_id, timestamp0);
6478 break;
6479 case Dart_Timeline_Event_Flow_Step:
6480 event->FlowStep(label, timestamp1_or_async_id, timestamp0);
6481 break;
6482 case Dart_Timeline_Event_Flow_End:
6483 event->FlowEnd(label, timestamp1_or_async_id, timestamp0);
6484 break;
6485 default:
6486 FATAL("Unknown Dart_Timeline_Event_Type");
6487 }
6488 event->SetNumArguments(argument_count);
6489 for (intptr_t i = 0; i < argument_count; i++) {
6490 event->CopyArgument(i, argument_names[i], argument_values[i]);
6491 }
6492 event->Complete();
6493#endif
6494}
6495
6496DART_EXPORT void Dart_SetThreadName(const char* name) {
6497 OSThread* thread = OSThread::Current();
6498 if (thread == NULL) {
6499 // VM is shutting down.
6500 return;
6501 }
6502 thread->SetName(name);
6503}
6504
6505DART_EXPORT
6506Dart_Handle Dart_SaveCompilationTrace(uint8_t** buffer,
6507 intptr_t* buffer_length) {
6508#if defined(DART_PRECOMPILED_RUNTIME)
6509 return Api::NewError("%s: Cannot compile on an AOT runtime.", CURRENT_FUNC);
6510#else
6511 Thread* thread = Thread::Current();
6512 API_TIMELINE_DURATION(thread);
6513 DARTSCOPE(thread);
6514 CHECK_NULL(buffer);
6515 CHECK_NULL(buffer_length);
6516 CompilationTraceSaver saver(thread->zone());
6517 ProgramVisitor::WalkProgram(thread->zone(), thread->isolate(), &saver);
6518 saver.StealBuffer(buffer, buffer_length);
6519 return Api::Success();
6520#endif // defined(DART_PRECOMPILED_RUNTIME)
6521}
6522
6523DART_EXPORT
6524Dart_Handle Dart_SaveTypeFeedback(uint8_t** buffer, intptr_t* buffer_length) {
6525#if defined(DART_PRECOMPILED_RUNTIME)
6526 return Api::NewError("%s: Cannot compile on an AOT runtime.", CURRENT_FUNC);
6527#else
6528 Thread* thread = Thread::Current();
6529 API_TIMELINE_DURATION(thread);
6530 DARTSCOPE(thread);
6531 CHECK_NULL(buffer);
6532 CHECK_NULL(buffer_length);
6533
6534 WriteStream stream(buffer, ApiReallocate, MB);
6535 TypeFeedbackSaver saver(&stream);
6536 saver.WriteHeader();
6537 saver.SaveClasses();
6538 saver.SaveFields();
6539 ProgramVisitor::WalkProgram(thread->zone(), thread->isolate(), &saver);
6540 *buffer_length = stream.bytes_written();
6541
6542 return Api::Success();
6543#endif // defined(DART_PRECOMPILED_RUNTIME)
6544}
6545
6546DART_EXPORT
6547Dart_Handle Dart_LoadCompilationTrace(uint8_t* buffer, intptr_t buffer_length) {
6548#if defined(DART_PRECOMPILED_RUNTIME)
6549 return Api::NewError("%s: Cannot compile on an AOT runtime.", CURRENT_FUNC);
6550#else
6551 Thread* thread = Thread::Current();
6552 API_TIMELINE_DURATION(thread);
6553 DARTSCOPE(thread);
6554 CHECK_NULL(buffer);
6555 Dart_Handle state = Api::CheckAndFinalizePendingClasses(T);
6556 if (Api::IsError(state)) {
6557 return state;
6558 }
6559 CompilationTraceLoader loader(thread);
6560 const Object& error =
6561 Object::Handle(loader.CompileTrace(buffer, buffer_length));
6562 if (error.IsError()) {
6563 return Api::NewHandle(T, Error::Cast(error).raw());
6564 }
6565 return Api::Success();
6566#endif // defined(DART_PRECOMPILED_RUNTIME)
6567}
6568
6569DART_EXPORT
6570Dart_Handle Dart_LoadTypeFeedback(uint8_t* buffer, intptr_t buffer_length) {
6571#if defined(DART_PRECOMPILED_RUNTIME)
6572 return Api::NewError("%s: Cannot compile on an AOT runtime.", CURRENT_FUNC);
6573#else
6574 Thread* thread = Thread::Current();
6575 API_TIMELINE_DURATION(thread);
6576 DARTSCOPE(thread);
6577 CHECK_NULL(buffer);
6578 Dart_Handle state = Api::CheckAndFinalizePendingClasses(T);
6579 if (Api::IsError(state)) {
6580 return state;
6581 }
6582 ReadStream stream(buffer, buffer_length);
6583 TypeFeedbackLoader loader(thread);
6584 const Object& error = Object::Handle(loader.LoadFeedback(&stream));
6585 if (error.IsError()) {
6586 return Api::NewHandle(T, Error::Cast(error).raw());
6587 }
6588 return Api::Success();
6589#endif // defined(DART_PRECOMPILED_RUNTIME)
6590}
6591
6592DART_EXPORT Dart_Handle Dart_SortClasses() {
6593#if defined(DART_PRECOMPILED_RUNTIME)
6594 return Api::NewError("%s: Cannot compile on an AOT runtime.", CURRENT_FUNC);
6595#else
6596 DARTSCOPE(Thread::Current());
6597 // Prevent background compiler from running while code is being cleared and
6598 // adding new code.
6599 BackgroundCompiler::Stop(Isolate::Current());
6600 // We don't have mechanisms to change class-ids that are embedded in code and
6601 // ICData.
6602 ClassFinalizer::ClearAllCode();
6603 // Make sure that ICData etc. that have been cleared are also removed from
6604 // the heap so that they are not found by the heap verifier.
6605 Isolate::Current()->heap()->CollectAllGarbage();
6606 ClassFinalizer::SortClasses();
6607 return Api::Success();
6608#endif // defined(DART_PRECOMPILED_RUNTIME)
6609}
6610
6611DART_EXPORT Dart_Handle Dart_Precompile() {
6612#if defined(TARGET_ARCH_IA32)
6613 return Api::NewError("AOT compilation is not supported on IA32.");
6614#elif !defined(DART_PRECOMPILER)
6615 return Api::NewError(
6616 "This VM was built without support for AOT compilation.");
6617#else
6618 DARTSCOPE(Thread::Current());
6619 API_TIMELINE_BEGIN_END(T);
6620 if (!FLAG_precompiled_mode) {
6621 return Api::NewError("Flag --precompilation was not specified.");
6622 }
6623 Dart_Handle result = Api::CheckAndFinalizePendingClasses(T);
6624 if (Api::IsError(result)) {
6625 return result;
6626 }
6627 CHECK_CALLBACK_STATE(T);
6628 CompilerState state(Thread::Current(), /*is_aot=*/true);
6629 CHECK_ERROR_HANDLE(Precompiler::CompileAll());
6630 return Api::Success();
6631#endif
6632}
6633
6634// Used for StreamingWriteStream/BlobImageWriter sizes for ELF and blobs.
6635#if !defined(TARGET_ARCH_IA32) && defined(DART_PRECOMPILER)
6636static const intptr_t kInitialSize = 2 * MB;
6637static const intptr_t kInitialDebugSize = 1 * MB;
6638
6639static void CreateAppAOTSnapshot(
6640 Dart_StreamingWriteCallback callback,
6641 void* callback_data,
6642 bool strip,
6643 bool as_elf,
6644 void* debug_callback_data,
6645 GrowableArray<LoadingUnitSerializationData*>* units,
6646 LoadingUnitSerializationData* unit,
6647 uint32_t program_hash) {
6648 Thread* T = Thread::Current();
6649
6650 NOT_IN_PRODUCT(TimelineBeginEndScope tbes2(T, Timeline::GetIsolateStream(),
6651 "WriteAppAOTSnapshot"));
6652
6653 uint8_t* vm_snapshot_data_buffer = nullptr;
6654 uint8_t* vm_snapshot_instructions_buffer = nullptr;
6655 uint8_t* isolate_snapshot_data_buffer = nullptr;
6656 uint8_t* isolate_snapshot_instructions_buffer = nullptr;
6657
6658 const bool generate_debug = debug_callback_data != nullptr;
6659
6660 if (as_elf) {
6661 StreamingWriteStream elf_stream(kInitialSize, callback, callback_data);
6662 StreamingWriteStream debug_stream(generate_debug ? kInitialDebugSize : 0,
6663 callback, debug_callback_data);
6664
6665 auto const dwarf = strip ? nullptr : new (Z) Dwarf(Z);
6666 auto const elf = new (Z) Elf(Z, &elf_stream, Elf::Type::Snapshot, dwarf);
6667 // Re-use the same DWARF object if the snapshot is unstripped.
6668 auto const debug_elf =
6669 generate_debug ? new (Z) Elf(Z, &debug_stream, Elf::Type::DebugInfo,
6670 strip ? new (Z) Dwarf(Z) : dwarf)
6671 : nullptr;
6672
6673 BlobImageWriter vm_image_writer(T, &vm_snapshot_instructions_buffer,
6674 ApiReallocate, kInitialSize, debug_elf,
6675 elf);
6676 BlobImageWriter isolate_image_writer(
6677 T, &isolate_snapshot_instructions_buffer, ApiReallocate, kInitialSize,
6678 debug_elf, elf);
6679 FullSnapshotWriter writer(Snapshot::kFullAOT, &vm_snapshot_data_buffer,
6680 &isolate_snapshot_data_buffer, ApiReallocate,
6681 &vm_image_writer, &isolate_image_writer);
6682
6683 if (unit == nullptr || unit->id() == LoadingUnit::kRootId) {
6684 writer.WriteFullSnapshot(units);
6685 } else {
6686 writer.WriteUnitSnapshot(units, unit, program_hash);
6687 }
6688
6689 elf->Finalize();
6690 if (debug_elf != nullptr) {
6691 debug_elf->Finalize();
6692 }
6693 } else {
6694 StreamingWriteStream debug_stream(generate_debug ? kInitialDebugSize : 0,
6695 callback, debug_callback_data);
6696
6697 auto const elf = generate_debug
6698 ? new (Z) Elf(Z, &debug_stream, Elf::Type::DebugInfo,
6699 new (Z) Dwarf(Z))
6700 : nullptr;
6701
6702 AssemblyImageWriter image_writer(T, callback, callback_data, strip, elf);
6703 uint8_t* vm_snapshot_data_buffer = NULL;
6704 uint8_t* isolate_snapshot_data_buffer = NULL;
6705 FullSnapshotWriter writer(Snapshot::kFullAOT, &vm_snapshot_data_buffer,
6706 &isolate_snapshot_data_buffer, ApiReallocate,
6707 &image_writer, &image_writer);
6708
6709 if (unit == nullptr || unit->id() == LoadingUnit::kRootId) {
6710 writer.WriteFullSnapshot(units);
6711 } else {
6712 writer.WriteUnitSnapshot(units, unit, program_hash);
6713 }
6714 image_writer.Finalize();
6715 }
6716}
6717
6718static void Split(Dart_CreateLoadingUnitCallback next_callback,
6719 void* next_callback_data,
6720 bool strip,
6721 bool as_elf,
6722 Dart_StreamingWriteCallback write_callback,
6723 Dart_StreamingCloseCallback close_callback) {
6724 Thread* T = Thread::Current();
6725 ProgramVisitor::AssignUnits(T);
6726
6727 const Array& loading_units =
6728 Array::Handle(T->isolate()->object_store()->loading_units());
6729 const uint32_t program_hash = ProgramVisitor::Hash(T);
6730 loading_units.SetAt(0, Smi::Handle(Z, Smi::New(program_hash)));
6731 GrowableArray<LoadingUnitSerializationData*> data;
6732 data.SetLength(loading_units.Length());
6733 data[0] = nullptr;
6734
6735 LoadingUnit& loading_unit = LoadingUnit::Handle();
6736 LoadingUnit& parent = LoadingUnit::Handle();
6737 for (intptr_t id = 1; id < loading_units.Length(); id++) {
6738 loading_unit ^= loading_units.At(id);
6739 parent = loading_unit.parent();
6740 LoadingUnitSerializationData* parent_data =
6741 parent.IsNull() ? nullptr : data[parent.id()];
6742 data[id] = new LoadingUnitSerializationData(id, parent_data);
6743 }
6744
6745 for (intptr_t id = 1; id < loading_units.Length(); id++) {
6746 void* write_callback_data = nullptr;
6747 void* write_debug_callback_data = nullptr;
6748 next_callback(next_callback_data, id, &write_callback_data,
6749 &write_debug_callback_data);
6750 CreateAppAOTSnapshot(write_callback, write_callback_data, strip, as_elf,
6751 write_debug_callback_data, &data, data[id],
6752 program_hash);
6753 close_callback(write_callback_data);
6754 if (write_debug_callback_data != nullptr) {
6755 close_callback(write_debug_callback_data);
6756 }
6757 }
6758}
6759#endif
6760
6761DART_EXPORT Dart_Handle
6762Dart_CreateAppAOTSnapshotAsAssembly(Dart_StreamingWriteCallback callback,
6763 void* callback_data,
6764 bool strip,
6765 void* debug_callback_data) {
6766#if defined(TARGET_ARCH_IA32)
6767 return Api::NewError("AOT compilation is not supported on IA32.");
6768#elif defined(TARGET_OS_WINDOWS)
6769 return Api::NewError("Assembly generation is not implemented for Windows.");
6770#elif !defined(DART_PRECOMPILER)
6771 return Api::NewError(
6772 "This VM was built without support for AOT compilation.");
6773#else
6774 DARTSCOPE(Thread::Current());
6775 API_TIMELINE_DURATION(T);
6776 CHECK_NULL(callback);
6777
6778 // Mark as not split.
6779 T->isolate()->object_store()->set_loading_units(Object::null_array());
6780
6781 CreateAppAOTSnapshot(callback, callback_data, strip, /*as_elf*/ false,
6782 debug_callback_data, nullptr, nullptr, 0);
6783
6784 return Api::Success();
6785#endif
6786}
6787
6788DART_EXPORT Dart_Handle Dart_CreateAppAOTSnapshotAsAssemblies(
6789 Dart_CreateLoadingUnitCallback next_callback,
6790 void* next_callback_data,
6791 bool strip,
6792 Dart_StreamingWriteCallback write_callback,
6793 Dart_StreamingCloseCallback close_callback) {
6794#if defined(TARGET_ARCH_IA32)
6795 return Api::NewError("AOT compilation is not supported on IA32.");
6796#elif defined(TARGET_OS_WINDOWS)
6797 return Api::NewError("Assembly generation is not implemented for Windows.");
6798#elif !defined(DART_PRECOMPILER)
6799 return Api::NewError(
6800 "This VM was built without support for AOT compilation.");
6801#else
6802 if (FLAG_use_bare_instructions && FLAG_use_table_dispatch) {
6803 return Api::NewError(
6804 "Splitting is not compatible with --use_table_dispatch.");
6805 }
6806
6807 DARTSCOPE(Thread::Current());
6808 API_TIMELINE_DURATION(T);
6809 CHECK_NULL(next_callback);
6810 CHECK_NULL(write_callback);
6811 CHECK_NULL(close_callback);
6812
6813 Split(next_callback, next_callback_data, strip, /*as_elf*/ false,
6814 write_callback, close_callback);
6815
6816 return Api::Success();
6817#endif
6818}
6819
6820DART_EXPORT Dart_Handle
6821Dart_CreateVMAOTSnapshotAsAssembly(Dart_StreamingWriteCallback callback,
6822 void* callback_data) {
6823#if defined(TARGET_ARCH_IA32)
6824 return Api::NewError("AOT compilation is not supported on IA32.");
6825#elif defined(TARGET_OS_WINDOWS)
6826 return Api::NewError("Assembly generation is not implemented for Windows.");
6827#elif !defined(DART_PRECOMPILER)
6828 return Api::NewError(
6829 "This VM was built without support for AOT compilation.");
6830#else
6831 DARTSCOPE(Thread::Current());
6832 API_TIMELINE_DURATION(T);
6833 CHECK_NULL(callback);
6834
6835 TIMELINE_DURATION(T, Isolate, "WriteVMAOTSnapshot");
6836 AssemblyImageWriter image_writer(T, callback, callback_data);
6837 uint8_t* vm_snapshot_data_buffer = nullptr;
6838 FullSnapshotWriter writer(Snapshot::kFullAOT, &vm_snapshot_data_buffer,
6839 nullptr, ApiReallocate, &image_writer, nullptr);
6840
6841 writer.WriteFullSnapshot();
6842
6843 return Api::Success();
6844#endif
6845}
6846
6847DART_EXPORT Dart_Handle
6848Dart_CreateAppAOTSnapshotAsElf(Dart_StreamingWriteCallback callback,
6849 void* callback_data,
6850 bool strip,
6851 void* debug_callback_data) {
6852#if defined(TARGET_ARCH_IA32)
6853 return Api::NewError("AOT compilation is not supported on IA32.");
6854#elif !defined(DART_PRECOMPILER)
6855 return Api::NewError(
6856 "This VM was built without support for AOT compilation.");
6857#else
6858 DARTSCOPE(Thread::Current());
6859 API_TIMELINE_DURATION(T);
6860 CHECK_NULL(callback);
6861
6862 // Mark as not split.
6863 T->isolate()->object_store()->set_loading_units(Object::null_array());
6864
6865 CreateAppAOTSnapshot(callback, callback_data, strip, /*as_elf*/ true,
6866 debug_callback_data, nullptr, nullptr, 0);
6867
6868 return Api::Success();
6869#endif
6870}
6871
6872DART_EXPORT Dart_Handle
6873Dart_CreateAppAOTSnapshotAsElfs(Dart_CreateLoadingUnitCallback next_callback,
6874 void* next_callback_data,
6875 bool strip,
6876 Dart_StreamingWriteCallback write_callback,
6877 Dart_StreamingCloseCallback close_callback) {
6878#if defined(TARGET_ARCH_IA32)
6879 return Api::NewError("AOT compilation is not supported on IA32.");
6880#elif !defined(DART_PRECOMPILER)
6881 return Api::NewError(
6882 "This VM was built without support for AOT compilation.");
6883#else
6884 if (FLAG_use_bare_instructions && FLAG_use_table_dispatch) {
6885 return Api::NewError(
6886 "Splitting is not compatible with --use_table_dispatch.");
6887 }
6888
6889 DARTSCOPE(Thread::Current());
6890 API_TIMELINE_DURATION(T);
6891 CHECK_NULL(next_callback);
6892 CHECK_NULL(write_callback);
6893 CHECK_NULL(close_callback);
6894
6895 Split(next_callback, next_callback_data, strip, /*as_elf*/ true,
6896 write_callback, close_callback);
6897
6898 return Api::Success();
6899#endif
6900}
6901
6902#if (!defined(TARGET_ARCH_IA32) && !defined(DART_PRECOMPILED_RUNTIME))
6903
6904// Any flag that affects how we compile code might cause a problem when the
6905// snapshot writer generates code with one value of the flag and the snapshot
6906// reader expects code to behave according to another value of the flag.
6907// Normally, we add these flags to Dart::FeaturesString and refuse to run the
6908// snapshot it they don't match, but since --interpret-irregexp affects only
6909// 2 functions we choose to remove the code instead. See issue #34422.
6910static void DropRegExpMatchCode(Zone* zone) {
6911 const String& execute_match_name =
6912 String::Handle(zone, String::New("_ExecuteMatch"));
6913 const String& execute_match_sticky_name =
6914 String::Handle(zone, String::New("_ExecuteMatchSticky"));
6915
6916 const Library& core_lib = Library::Handle(zone, Library::CoreLibrary());
6917 const Class& reg_exp_class =
6918 Class::Handle(zone, core_lib.LookupClassAllowPrivate(Symbols::_RegExp()));
6919 ASSERT(!reg_exp_class.IsNull());
6920
6921 Function& func = Function::Handle(
6922 zone, reg_exp_class.LookupFunctionAllowPrivate(execute_match_name));
6923 ASSERT(!func.IsNull());
6924 Code& code = Code::Handle(zone);
6925 if (func.HasCode()) {
6926 code = func.CurrentCode();
6927 ASSERT(!code.IsNull());
6928 code.DisableDartCode();
6929 }
6930 func.ClearCode();
6931 func.ClearICDataArray();
6932 ASSERT(!func.HasCode());
6933
6934 func = reg_exp_class.LookupFunctionAllowPrivate(execute_match_sticky_name);
6935 ASSERT(!func.IsNull());
6936 if (func.HasCode()) {
6937 code = func.CurrentCode();
6938 ASSERT(!code.IsNull());
6939 code.DisableDartCode();
6940 }
6941 func.ClearCode();
6942 func.ClearICDataArray();
6943 ASSERT(!func.HasCode());
6944}
6945
6946#endif // (!defined(TARGET_ARCH_IA32) && !defined(DART_PRECOMPILED_RUNTIME))
6947
6948DART_EXPORT Dart_Handle Dart_CreateCoreJITSnapshotAsBlobs(
6949 uint8_t** vm_snapshot_data_buffer,
6950 intptr_t* vm_snapshot_data_size,
6951 uint8_t** vm_snapshot_instructions_buffer,
6952 intptr_t* vm_snapshot_instructions_size,
6953 uint8_t** isolate_snapshot_data_buffer,
6954 intptr_t* isolate_snapshot_data_size,
6955 uint8_t** isolate_snapshot_instructions_buffer,
6956 intptr_t* isolate_snapshot_instructions_size) {
6957#if defined(TARGET_ARCH_IA32)
6958 return Api::NewError("Snapshots with code are not supported on IA32.");
6959#elif defined(DART_PRECOMPILED_RUNTIME)
6960 return Api::NewError("JIT app snapshots cannot be taken from an AOT runtime");
6961#else
6962 DARTSCOPE(Thread::Current());
6963 API_TIMELINE_DURATION(T);
6964 Isolate* I = T->isolate();
6965 CHECK_NULL(vm_snapshot_data_buffer);
6966 CHECK_NULL(vm_snapshot_data_size);
6967 CHECK_NULL(vm_snapshot_instructions_buffer);
6968 CHECK_NULL(vm_snapshot_instructions_size);
6969 CHECK_NULL(isolate_snapshot_data_buffer);
6970 CHECK_NULL(isolate_snapshot_data_size);
6971 CHECK_NULL(isolate_snapshot_instructions_buffer);
6972 CHECK_NULL(isolate_snapshot_instructions_size);
6973 // Finalize all classes if needed.
6974 Dart_Handle state = Api::CheckAndFinalizePendingClasses(T);
6975 if (Api::IsError(state)) {
6976 return state;
6977 }
6978 BackgroundCompiler::Stop(I);
6979 DropRegExpMatchCode(Z);
6980
6981 ProgramVisitor::Dedup(T);
6982 Symbols::Compact();
6983
6984 TIMELINE_DURATION(T, Isolate, "WriteCoreJITSnapshot");
6985 BlobImageWriter vm_image_writer(T, vm_snapshot_instructions_buffer,
6986 ApiReallocate, 2 * MB /* initial_size */);
6987 BlobImageWriter isolate_image_writer(T, isolate_snapshot_instructions_buffer,
6988 ApiReallocate,
6989 2 * MB /* initial_size */);
6990 FullSnapshotWriter writer(Snapshot::kFullJIT, vm_snapshot_data_buffer,
6991 isolate_snapshot_data_buffer, ApiReallocate,
6992 &vm_image_writer, &isolate_image_writer);
6993 writer.WriteFullSnapshot();
6994
6995 *vm_snapshot_data_size = writer.VmIsolateSnapshotSize();
6996 *vm_snapshot_instructions_size = vm_image_writer.InstructionsBlobSize();
6997 *isolate_snapshot_data_size = writer.IsolateSnapshotSize();
6998 *isolate_snapshot_instructions_size =
6999 isolate_image_writer.InstructionsBlobSize();
7000
7001 return Api::Success();
7002#endif
7003}
7004
7005#if !defined(TARGET_ARCH_IA32) && !defined(DART_PRECOMPILED_RUNTIME)
7006static void KillNonMainIsolatesSlow(Thread* thread, Isolate* main_isolate) {
7007 auto group = main_isolate->group();
7008 while (true) {
7009 bool non_main_isolates_alive = false;
7010 {
7011 SafepointOperationScope safepoint(thread);
7012 group->ForEachIsolate([&](Isolate* isolate) {
7013 if (isolate != main_isolate) {
7014 Isolate::KillIfExists(isolate, Isolate::kKillMsg);
7015 non_main_isolates_alive = true;
7016 }
7017 });
7018 if (!non_main_isolates_alive) {
7019 break;
7020 }
7021 }
7022 OS::SleepMicros(10 * 1000);
7023 }
7024}
7025#endif // !defined(TARGET_ARCH_IA32) && !defined(DART_PRECOMPILED_RUNTIME)
7026
7027DART_EXPORT Dart_Handle
7028Dart_CreateAppJITSnapshotAsBlobs(uint8_t** isolate_snapshot_data_buffer,
7029 intptr_t* isolate_snapshot_data_size,
7030 uint8_t** isolate_snapshot_instructions_buffer,
7031 intptr_t* isolate_snapshot_instructions_size) {
7032#if defined(TARGET_ARCH_IA32)
7033 return Api::NewError("Snapshots with code are not supported on IA32.");
7034#elif defined(DART_PRECOMPILED_RUNTIME)
7035 return Api::NewError("JIT app snapshots cannot be taken from an AOT runtime");
7036#else
7037 DARTSCOPE(Thread::Current());
7038 API_TIMELINE_DURATION(T);
7039 Isolate* I = T->isolate();
7040 CHECK_NULL(isolate_snapshot_data_buffer);
7041 CHECK_NULL(isolate_snapshot_data_size);
7042 CHECK_NULL(isolate_snapshot_instructions_buffer);
7043 CHECK_NULL(isolate_snapshot_instructions_size);
7044
7045 // Finalize all classes if needed.
7046 Dart_Handle state = Api::CheckAndFinalizePendingClasses(T);
7047 if (Api::IsError(state)) {
7048 return state;
7049 }
7050
7051 // Kill off any auxiliary isolates before starting with deduping.
7052 KillNonMainIsolatesSlow(T, I);
7053
7054 BackgroundCompiler::Stop(I);
7055 DropRegExpMatchCode(Z);
7056
7057 ProgramVisitor::Dedup(T);
7058 Symbols::Compact();
7059
7060 if (FLAG_dump_tables) {
7061 Symbols::DumpTable(I);
7062 DumpTypeTable(I);
7063 DumpTypeParameterTable(I);
7064 DumpTypeArgumentsTable(I);
7065 }
7066
7067 TIMELINE_DURATION(T, Isolate, "WriteAppJITSnapshot");
7068 BlobImageWriter isolate_image_writer(T, isolate_snapshot_instructions_buffer,
7069 ApiReallocate,
7070 2 * MB /* initial_size */);
7071 FullSnapshotWriter writer(Snapshot::kFullJIT, NULL,
7072 isolate_snapshot_data_buffer, ApiReallocate, NULL,
7073 &isolate_image_writer);
7074 writer.WriteFullSnapshot();
7075
7076 *isolate_snapshot_data_size = writer.IsolateSnapshotSize();
7077 *isolate_snapshot_instructions_size =
7078 isolate_image_writer.InstructionsBlobSize();
7079
7080 return Api::Success();
7081#endif
7082}
7083
7084DART_EXPORT Dart_Handle Dart_GetObfuscationMap(uint8_t** buffer,
7085 intptr_t* buffer_length) {
7086#if defined(DART_PRECOMPILED_RUNTIME)
7087 return Api::NewError("No obfuscation map to save on an AOT runtime.");
7088#elif !defined(DART_PRECOMPILER)
7089 return Api::NewError("Obfuscation is only supported for AOT compiler.");
7090#else
7091 Thread* thread = Thread::Current();
7092 DARTSCOPE(thread);
7093 Isolate* isolate = thread->isolate();
7094
7095 if (buffer == NULL) {
7096 RETURN_NULL_ERROR(buffer);
7097 }
7098 if (buffer_length == NULL) {
7099 RETURN_NULL_ERROR(buffer_length);
7100 }
7101
7102 // Note: can't use JSONStream in PRODUCT builds.
7103 const intptr_t kInitialBufferSize = 1 * MB;
7104 TextBuffer text_buffer(kInitialBufferSize);
7105
7106 text_buffer.AddChar('[');
7107 if (isolate->obfuscation_map() != NULL) {
7108 for (intptr_t i = 0; isolate->obfuscation_map()[i] != NULL; i++) {
7109 if (i > 0) {
7110 text_buffer.AddChar(',');
7111 }
7112 text_buffer.AddChar('"');
7113 text_buffer.AddEscapedString(isolate->obfuscation_map()[i]);
7114 text_buffer.AddChar('"');
7115 }
7116 }
7117 text_buffer.AddChar(']');
7118
7119 *buffer_length = text_buffer.length();
7120 *reinterpret_cast<char**>(buffer) = text_buffer.Steal();
7121 return Api::Success();
7122#endif
7123}
7124
7125DART_EXPORT bool Dart_IsPrecompiledRuntime() {
7126#if defined(DART_PRECOMPILED_RUNTIME)
7127 return true;
7128#else
7129 return false;
7130#endif
7131}
7132
7133DART_EXPORT void Dart_DumpNativeStackTrace(void* context) {
7134#ifndef PRODUCT
7135 Profiler::DumpStackTrace(context);
7136#endif
7137}
7138
7139DART_EXPORT void Dart_PrepareToAbort() {
7140 OS::PrepareToAbort();
7141}
7142
7143} // namespace dart
7144