dart-sdk/runtime/vm/dart_api_impl.cc

7066 lines
246 KiB
C++
Raw Normal View History

// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "include/dart_api.h"
#include "include/dart_native_api.h"
[vm/bytecode] Bootstrapping VM from bytecode Previously, core snapshot was generated from AST (because --enable-interpreter/--use-bytecode-compiler was not specified when building core snapshot). As the result, CL https://dart.googlesource.com/sdk/+/da8cb470cc94830a98d49532e8d5d1a5b3d80f8b which declared libraries in bytecode also removed bytecode entirely from core snapshot in Dart SDK. This CL enables bytecode by default if --bytecode argument is specified for gn.py. This enables JIT compiler from bytecode (interpreter is still disabled by default but can be enabled using --enable-interpreter). Core snapshot and other snapshots now have bytecode. This change revealed a bunch of bugs which are fixed in this CL: * _Closure fields were treated as unboxing candidates which triggered assertion in LoadFieldTOS in interpreter. * Several places should load class declarations if they are not loaded yet. * Canonicalization of TypeRef objects which are not fully initialized may cause duplicate entries in the hash table of canonical TypeArguments. This triggers assertions when hash table is rehashed. The solution is to avoid canonicalization of non-root recursive types and recursive type arguments. Also, TypeRef::Canonicalize and TypeRef::Hash are reverted to assert and work only if type was set. * Native wrapper classes are eagerly stamped as type-finalized which caused assertion failures when reading their class declarations from bytecode. * When building flow graph for FFI trampolines kernel offset of library (which is now declared in bytecode) was queried. Added special case to Function::KernelDataProgramOffset(). * In interpreter-only mode with simulator (e.g. SIMARM64) if simulator is not called before code is interrupted with stack overflow check, simulator returns get_sp() = 0, which was treated as stack overflow. * test standalone_2/io/platform_resolved_executable_test.dart spawns sub-process but it didn't pass VM options. Change-Id: I81bc4f1a4c6725cfa246a435ebe5d8abe43abc67 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/107199 Commit-Queue: Alexander Markov <alexmarkov@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com> Reviewed-by: Régis Crelier <regis@google.com>
2019-06-26 18:25:26 +00:00
#include <memory>
#include <utility>
[vm/bytecode] Bootstrapping VM from bytecode Previously, core snapshot was generated from AST (because --enable-interpreter/--use-bytecode-compiler was not specified when building core snapshot). As the result, CL https://dart.googlesource.com/sdk/+/da8cb470cc94830a98d49532e8d5d1a5b3d80f8b which declared libraries in bytecode also removed bytecode entirely from core snapshot in Dart SDK. This CL enables bytecode by default if --bytecode argument is specified for gn.py. This enables JIT compiler from bytecode (interpreter is still disabled by default but can be enabled using --enable-interpreter). Core snapshot and other snapshots now have bytecode. This change revealed a bunch of bugs which are fixed in this CL: * _Closure fields were treated as unboxing candidates which triggered assertion in LoadFieldTOS in interpreter. * Several places should load class declarations if they are not loaded yet. * Canonicalization of TypeRef objects which are not fully initialized may cause duplicate entries in the hash table of canonical TypeArguments. This triggers assertions when hash table is rehashed. The solution is to avoid canonicalization of non-root recursive types and recursive type arguments. Also, TypeRef::Canonicalize and TypeRef::Hash are reverted to assert and work only if type was set. * Native wrapper classes are eagerly stamped as type-finalized which caused assertion failures when reading their class declarations from bytecode. * When building flow graph for FFI trampolines kernel offset of library (which is now declared in bytecode) was queried. Added special case to Function::KernelDataProgramOffset(). * In interpreter-only mode with simulator (e.g. SIMARM64) if simulator is not called before code is interrupted with stack overflow check, simulator returns get_sp() = 0, which was treated as stack overflow. * test standalone_2/io/platform_resolved_executable_test.dart spawns sub-process but it didn't pass VM options. Change-Id: I81bc4f1a4c6725cfa246a435ebe5d8abe43abc67 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/107199 Commit-Queue: Alexander Markov <alexmarkov@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com> Reviewed-by: Régis Crelier <regis@google.com>
2019-06-26 18:25:26 +00:00
#include "lib/stacktrace.h"
#include "platform/assert.h"
#include "platform/unicode.h"
#include "vm/app_snapshot.h"
#include "vm/class_finalizer.h"
#include "vm/compiler/jit/compiler.h"
#include "vm/dart.h"
#include "vm/dart_api_impl.h"
#include "vm/dart_api_message.h"
#include "vm/dart_api_state.h"
#include "vm/dart_entry.h"
#include "vm/debugger.h"
#include "vm/dwarf.h"
#include "vm/elf.h"
#include "vm/exceptions.h"
#include "vm/flags.h"
#include "vm/growable_array.h"
#include "vm/heap/verifier.h"
#include "vm/image_snapshot.h"
#include "vm/isolate_reload.h"
#include "vm/kernel_isolate.h"
#include "vm/lockers.h"
#include "vm/message.h"
#include "vm/message_handler.h"
#include "vm/message_snapshot.h"
#include "vm/native_entry.h"
#include "vm/native_symbol.h"
#include "vm/object.h"
#include "vm/object_store.h"
#include "vm/os.h"
#include "vm/os_thread.h"
#include "vm/port.h"
#include "vm/profiler.h"
#include "vm/profiler_service.h"
#include "vm/program_visitor.h"
#include "vm/resolver.h"
#include "vm/reusable_handles.h"
#include "vm/service.h"
#include "vm/service_event.h"
#include "vm/service_isolate.h"
#include "vm/stack_frame.h"
#include "vm/symbols.h"
#include "vm/tags.h"
#include "vm/thread_registry.h"
#include "vm/uri.h"
#include "vm/version.h"
#if !defined(DART_PRECOMPILED_RUNTIME)
#include "vm/compiler/aot/precompiler.h"
#include "vm/kernel_loader.h"
#endif // !defined(DART_PRECOMPILED_RUNTIME)
namespace dart {
// Facilitate quick access to the current zone once we have the current thread.
#define Z (T->zone())
DECLARE_FLAG(bool, print_class_table);
#if defined(DEBUG) && !defined(DART_PRECOMPILED_RUNTIME)
DEFINE_FLAG(bool,
check_function_fingerprints,
true,
"Check function fingerprints");
#endif // defined(DEBUG) && !defined(DART_PRECOMPILED_RUNTIME).
DEFINE_FLAG(bool,
verify_acquired_data,
false,
"Verify correct API acquire/release of typed data.");
DEFINE_FLAG(bool,
dump_tables,
false,
"Dump common hash tables before snapshotting.");
#define CHECK_ERROR_HANDLE(error) \
{ \
ErrorPtr err = (error); \
if (err != Error::null()) { \
return Api::NewHandle(T, err); \
} \
}
ThreadLocalKey Api::api_native_key_ = kUnsetThreadLocalKey;
Dart_Handle Api::true_handle_ = NULL;
Dart_Handle Api::false_handle_ = NULL;
Dart_Handle Api::null_handle_ = NULL;
Dart_Handle Api::empty_string_handle_ = NULL;
Dart_Handle Api::no_callbacks_error_handle_ = NULL;
Dart_Handle Api::unwind_in_progress_error_handle_ = NULL;
const char* CanonicalFunction(const char* func) {
if (strncmp(func, "dart::", 6) == 0) {
return func + 6;
} else {
return func;
}
}
#if defined(DEBUG)
// An object visitor which will iterate over all the function objects in the
// heap and check if the result type and parameter types are canonicalized
// or not. An assertion is raised if a type is not canonicalized.
class CheckFunctionTypesVisitor : public ObjectVisitor {
public:
explicit CheckFunctionTypesVisitor(Thread* thread)
: classHandle_(Class::Handle(thread->zone())),
funcHandle_(Function::Handle(thread->zone())),
typeHandle_(AbstractType::Handle(thread->zone())) {}
void VisitObject(ObjectPtr obj) {
if (obj->IsFunction()) {
funcHandle_ ^= obj;
classHandle_ ^= funcHandle_.Owner();
// Verify that the result type of a function is canonical or a
// TypeParameter.
typeHandle_ ^= funcHandle_.result_type();
ASSERT(typeHandle_.IsTypeParameter() || typeHandle_.IsCanonical());
// Verify that the types in the function signature are all canonical or
// a TypeParameter.
const intptr_t num_parameters = funcHandle_.NumParameters();
for (intptr_t i = 0; i < num_parameters; i++) {
typeHandle_ = funcHandle_.ParameterTypeAt(i);
ASSERT(typeHandle_.IsTypeParameter() || typeHandle_.IsCanonical());
}
}
}
private:
Class& classHandle_;
Function& funcHandle_;
AbstractType& typeHandle_;
};
#endif // #if defined(DEBUG).
static InstancePtr GetListInstance(Zone* zone, const Object& obj) {
if (obj.IsInstance()) {
ObjectStore* object_store = IsolateGroup::Current()->object_store();
const Type& list_rare_type =
Type::Handle(zone, object_store->non_nullable_list_rare_type());
ASSERT(!list_rare_type.IsNull());
const Instance& instance = Instance::Cast(obj);
const Class& obj_class = Class::Handle(zone, obj.clazz());
if (Class::IsSubtypeOf(obj_class, Object::null_type_arguments(),
[VM/nnbd] Do not check nullability of LHS too early in strong mode (fixes #41160). Nullability of left hand side in type test was checked too early, i.e. before handling FutureOr on the right hand side. The following tests began passing (in strong mode): standalone/io/addlatexhash_test was fixed (RuntimeError -> Pass) standalone/io/file_output_stream_test was fixed (RuntimeError -> Pass) standalone/io/file_stream_test was fixed (RuntimeError -> Pass) standalone/io/file_system_async_links_test was fixed (RuntimeError -> Pass) standalone/io/file_system_links_test was fixed (RuntimeError -> Pass) standalone/io/file_write_only_test was fixed (RuntimeError -> Pass) standalone/io/pipe_server_test/0 was fixed (RuntimeError -> Pass) standalone/io/pipe_server_test/1 was fixed (RuntimeError -> Pass) standalone/io/pipe_server_test/2 was fixed (RuntimeError -> Pass) standalone/io/pipe_server_test/3 was fixed (RuntimeError -> Pass) standalone/io/pipe_server_test/4 was fixed (RuntimeError -> Pass) standalone/io/pipe_server_test/5 was fixed (RuntimeError -> Pass) standalone/io/stream_pipe_test/0 was fixed (RuntimeError -> Pass) standalone/io/stream_pipe_test/1 was fixed (RuntimeError -> Pass) standalone/io/stream_pipe_test/2 was fixed (RuntimeError -> Pass) standalone/io/stream_pipe_test/3 was fixed (RuntimeError -> Pass) Change-Id: I855328f101382cf5f1af9119b396aa9d0cb14e40 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/140776 Commit-Queue: Régis Crelier <regis@google.com> Reviewed-by: Liam Appelbe <liama@google.com>
2020-03-25 20:26:26 +00:00
Nullability::kNonNullable, list_rare_type,
Heap::kNew)) {
return instance.ptr();
}
}
return Instance::null();
}
static InstancePtr GetMapInstance(Zone* zone, const Object& obj) {
if (obj.IsInstance()) {
ObjectStore* object_store = IsolateGroup::Current()->object_store();
const Type& map_rare_type =
Type::Handle(zone, object_store->non_nullable_map_rare_type());
ASSERT(!map_rare_type.IsNull());
const Instance& instance = Instance::Cast(obj);
const Class& obj_class = Class::Handle(zone, obj.clazz());
if (Class::IsSubtypeOf(obj_class, Object::null_type_arguments(),
[VM/nnbd] Do not check nullability of LHS too early in strong mode (fixes #41160). Nullability of left hand side in type test was checked too early, i.e. before handling FutureOr on the right hand side. The following tests began passing (in strong mode): standalone/io/addlatexhash_test was fixed (RuntimeError -> Pass) standalone/io/file_output_stream_test was fixed (RuntimeError -> Pass) standalone/io/file_stream_test was fixed (RuntimeError -> Pass) standalone/io/file_system_async_links_test was fixed (RuntimeError -> Pass) standalone/io/file_system_links_test was fixed (RuntimeError -> Pass) standalone/io/file_write_only_test was fixed (RuntimeError -> Pass) standalone/io/pipe_server_test/0 was fixed (RuntimeError -> Pass) standalone/io/pipe_server_test/1 was fixed (RuntimeError -> Pass) standalone/io/pipe_server_test/2 was fixed (RuntimeError -> Pass) standalone/io/pipe_server_test/3 was fixed (RuntimeError -> Pass) standalone/io/pipe_server_test/4 was fixed (RuntimeError -> Pass) standalone/io/pipe_server_test/5 was fixed (RuntimeError -> Pass) standalone/io/stream_pipe_test/0 was fixed (RuntimeError -> Pass) standalone/io/stream_pipe_test/1 was fixed (RuntimeError -> Pass) standalone/io/stream_pipe_test/2 was fixed (RuntimeError -> Pass) standalone/io/stream_pipe_test/3 was fixed (RuntimeError -> Pass) Change-Id: I855328f101382cf5f1af9119b396aa9d0cb14e40 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/140776 Commit-Queue: Régis Crelier <regis@google.com> Reviewed-by: Liam Appelbe <liama@google.com>
2020-03-25 20:26:26 +00:00
Nullability::kNonNullable, map_rare_type,
Heap::kNew)) {
return instance.ptr();
}
}
return Instance::null();
}
static bool IsCompiletimeErrorObject(Zone* zone, const Object& obj) {
#if defined(DART_PRECOMPILED_RUNTIME)
// All compile-time errors were handled at snapshot generation time and
// compiletime_error_class was removed.
return false;
#else
auto isolate_group = Thread::Current()->isolate_group();
const Class& error_class = Class::Handle(
zone, isolate_group->object_store()->compiletime_error_class());
ASSERT(!error_class.IsNull());
return (obj.GetClassId() == error_class.id());
#endif
}
Add a new API function to extract all the native arguments into an array passed in by the caller. This call can be used in DOM bindings patterns as follows: Old code - Dart_Handle exception = 0; { WebGL* receiver = DartDOMWrapper::receiver< WebGL >(args); unsigned srcRGB = DartUtilities::dartToUnsigned(args, 1, exception); if (exception) goto fail; unsigned dstRGB = DartUtilities::dartToUnsigned(args, 2, exception); if (exception) goto fail; unsigned srcAlpha = DartUtilities::dartToUnsigned(args, 3, exception); if (exception) goto fail; unsigned dstAlpha = DartUtilities::dartToUnsigned(args, 4, exception); if (exception) goto fail; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; } fail: Dart_ThrowException(exception); ASSERT_NOT_REACHED(); Proposed new code - /** * One time initialization code for setting up argument descriptors */ const int kNumArgs = 5; const int kNumNativeFields = 2; static const uint8_t native_arg_descriptor[kNumArgs] = { DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kNativeFields, 0), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 1), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 2), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 3), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 4), }; Dart_NativeArgument_Value native_args[kNumArgs]; intptr_t native_fields[kNumNativeFields]; native_args[0].as_native_fields.num_fields = kNumNativeFields; native_args[0].as_native_fields.values = native_fields; /** * Code executed for each invocation of the binding method */ Dart_Handle result = Dart_GetNativeArguments(args, kNumArgs, native_arg_descriptor, native_args); if (Dart_IsError(result)) { Dart_ThrowException(result); } WebGL* receiver = DartDOMWrapper::receiver< WebGL >(native_args[0].as_native_fields.values); unsigned srcRGB = native_args[1].as_uint32; unsigned dstRGB = native_args[2].as_uint32; unsigned srcAlpha = native_args[3].as_uint32; unsigned dstAlpha = native_args[4].as_uint32; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; R=iposva@google.com, vsm@google.com Review URL: https://codereview.chromium.org//282883002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@36464 260f80e4-7a28-3924-810f-c04153c831b5
2014-05-22 00:08:23 +00:00
static bool GetNativeStringArgument(NativeArguments* arguments,
int arg_index,
Dart_Handle* str,
void** peer) {
ASSERT(peer != NULL);
if (Api::StringGetPeerHelper(arguments, arg_index, peer)) {
*str = NULL;
return true;
}
Thread* thread = arguments->thread();
ASSERT(thread == Thread::Current());
Add a new API function to extract all the native arguments into an array passed in by the caller. This call can be used in DOM bindings patterns as follows: Old code - Dart_Handle exception = 0; { WebGL* receiver = DartDOMWrapper::receiver< WebGL >(args); unsigned srcRGB = DartUtilities::dartToUnsigned(args, 1, exception); if (exception) goto fail; unsigned dstRGB = DartUtilities::dartToUnsigned(args, 2, exception); if (exception) goto fail; unsigned srcAlpha = DartUtilities::dartToUnsigned(args, 3, exception); if (exception) goto fail; unsigned dstAlpha = DartUtilities::dartToUnsigned(args, 4, exception); if (exception) goto fail; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; } fail: Dart_ThrowException(exception); ASSERT_NOT_REACHED(); Proposed new code - /** * One time initialization code for setting up argument descriptors */ const int kNumArgs = 5; const int kNumNativeFields = 2; static const uint8_t native_arg_descriptor[kNumArgs] = { DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kNativeFields, 0), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 1), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 2), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 3), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 4), }; Dart_NativeArgument_Value native_args[kNumArgs]; intptr_t native_fields[kNumNativeFields]; native_args[0].as_native_fields.num_fields = kNumNativeFields; native_args[0].as_native_fields.values = native_fields; /** * Code executed for each invocation of the binding method */ Dart_Handle result = Dart_GetNativeArguments(args, kNumArgs, native_arg_descriptor, native_args); if (Dart_IsError(result)) { Dart_ThrowException(result); } WebGL* receiver = DartDOMWrapper::receiver< WebGL >(native_args[0].as_native_fields.values); unsigned srcRGB = native_args[1].as_uint32; unsigned dstRGB = native_args[2].as_uint32; unsigned srcAlpha = native_args[3].as_uint32; unsigned dstAlpha = native_args[4].as_uint32; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; R=iposva@google.com, vsm@google.com Review URL: https://codereview.chromium.org//282883002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@36464 260f80e4-7a28-3924-810f-c04153c831b5
2014-05-22 00:08:23 +00:00
*peer = NULL;
REUSABLE_OBJECT_HANDLESCOPE(thread);
Object& obj = thread->ObjectHandle();
Add a new API function to extract all the native arguments into an array passed in by the caller. This call can be used in DOM bindings patterns as follows: Old code - Dart_Handle exception = 0; { WebGL* receiver = DartDOMWrapper::receiver< WebGL >(args); unsigned srcRGB = DartUtilities::dartToUnsigned(args, 1, exception); if (exception) goto fail; unsigned dstRGB = DartUtilities::dartToUnsigned(args, 2, exception); if (exception) goto fail; unsigned srcAlpha = DartUtilities::dartToUnsigned(args, 3, exception); if (exception) goto fail; unsigned dstAlpha = DartUtilities::dartToUnsigned(args, 4, exception); if (exception) goto fail; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; } fail: Dart_ThrowException(exception); ASSERT_NOT_REACHED(); Proposed new code - /** * One time initialization code for setting up argument descriptors */ const int kNumArgs = 5; const int kNumNativeFields = 2; static const uint8_t native_arg_descriptor[kNumArgs] = { DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kNativeFields, 0), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 1), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 2), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 3), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 4), }; Dart_NativeArgument_Value native_args[kNumArgs]; intptr_t native_fields[kNumNativeFields]; native_args[0].as_native_fields.num_fields = kNumNativeFields; native_args[0].as_native_fields.values = native_fields; /** * Code executed for each invocation of the binding method */ Dart_Handle result = Dart_GetNativeArguments(args, kNumArgs, native_arg_descriptor, native_args); if (Dart_IsError(result)) { Dart_ThrowException(result); } WebGL* receiver = DartDOMWrapper::receiver< WebGL >(native_args[0].as_native_fields.values); unsigned srcRGB = native_args[1].as_uint32; unsigned dstRGB = native_args[2].as_uint32; unsigned srcAlpha = native_args[3].as_uint32; unsigned dstAlpha = native_args[4].as_uint32; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; R=iposva@google.com, vsm@google.com Review URL: https://codereview.chromium.org//282883002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@36464 260f80e4-7a28-3924-810f-c04153c831b5
2014-05-22 00:08:23 +00:00
obj = arguments->NativeArgAt(arg_index);
if (IsStringClassId(obj.GetClassId())) {
ASSERT(thread->api_top_scope() != NULL);
*str = Api::NewHandle(thread, obj.ptr());
Add a new API function to extract all the native arguments into an array passed in by the caller. This call can be used in DOM bindings patterns as follows: Old code - Dart_Handle exception = 0; { WebGL* receiver = DartDOMWrapper::receiver< WebGL >(args); unsigned srcRGB = DartUtilities::dartToUnsigned(args, 1, exception); if (exception) goto fail; unsigned dstRGB = DartUtilities::dartToUnsigned(args, 2, exception); if (exception) goto fail; unsigned srcAlpha = DartUtilities::dartToUnsigned(args, 3, exception); if (exception) goto fail; unsigned dstAlpha = DartUtilities::dartToUnsigned(args, 4, exception); if (exception) goto fail; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; } fail: Dart_ThrowException(exception); ASSERT_NOT_REACHED(); Proposed new code - /** * One time initialization code for setting up argument descriptors */ const int kNumArgs = 5; const int kNumNativeFields = 2; static const uint8_t native_arg_descriptor[kNumArgs] = { DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kNativeFields, 0), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 1), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 2), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 3), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 4), }; Dart_NativeArgument_Value native_args[kNumArgs]; intptr_t native_fields[kNumNativeFields]; native_args[0].as_native_fields.num_fields = kNumNativeFields; native_args[0].as_native_fields.values = native_fields; /** * Code executed for each invocation of the binding method */ Dart_Handle result = Dart_GetNativeArguments(args, kNumArgs, native_arg_descriptor, native_args); if (Dart_IsError(result)) { Dart_ThrowException(result); } WebGL* receiver = DartDOMWrapper::receiver< WebGL >(native_args[0].as_native_fields.values); unsigned srcRGB = native_args[1].as_uint32; unsigned dstRGB = native_args[2].as_uint32; unsigned srcAlpha = native_args[3].as_uint32; unsigned dstAlpha = native_args[4].as_uint32; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; R=iposva@google.com, vsm@google.com Review URL: https://codereview.chromium.org//282883002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@36464 260f80e4-7a28-3924-810f-c04153c831b5
2014-05-22 00:08:23 +00:00
return true;
}
if (obj.IsNull()) {
*str = Api::Null();
return true;
}
return false;
}
static bool GetNativeIntegerArgument(NativeArguments* arguments,
int arg_index,
int64_t* value) {
ASSERT(value != NULL);
return Api::GetNativeIntegerArgument(arguments, arg_index, value);
Add a new API function to extract all the native arguments into an array passed in by the caller. This call can be used in DOM bindings patterns as follows: Old code - Dart_Handle exception = 0; { WebGL* receiver = DartDOMWrapper::receiver< WebGL >(args); unsigned srcRGB = DartUtilities::dartToUnsigned(args, 1, exception); if (exception) goto fail; unsigned dstRGB = DartUtilities::dartToUnsigned(args, 2, exception); if (exception) goto fail; unsigned srcAlpha = DartUtilities::dartToUnsigned(args, 3, exception); if (exception) goto fail; unsigned dstAlpha = DartUtilities::dartToUnsigned(args, 4, exception); if (exception) goto fail; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; } fail: Dart_ThrowException(exception); ASSERT_NOT_REACHED(); Proposed new code - /** * One time initialization code for setting up argument descriptors */ const int kNumArgs = 5; const int kNumNativeFields = 2; static const uint8_t native_arg_descriptor[kNumArgs] = { DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kNativeFields, 0), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 1), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 2), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 3), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 4), }; Dart_NativeArgument_Value native_args[kNumArgs]; intptr_t native_fields[kNumNativeFields]; native_args[0].as_native_fields.num_fields = kNumNativeFields; native_args[0].as_native_fields.values = native_fields; /** * Code executed for each invocation of the binding method */ Dart_Handle result = Dart_GetNativeArguments(args, kNumArgs, native_arg_descriptor, native_args); if (Dart_IsError(result)) { Dart_ThrowException(result); } WebGL* receiver = DartDOMWrapper::receiver< WebGL >(native_args[0].as_native_fields.values); unsigned srcRGB = native_args[1].as_uint32; unsigned dstRGB = native_args[2].as_uint32; unsigned srcAlpha = native_args[3].as_uint32; unsigned dstAlpha = native_args[4].as_uint32; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; R=iposva@google.com, vsm@google.com Review URL: https://codereview.chromium.org//282883002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@36464 260f80e4-7a28-3924-810f-c04153c831b5
2014-05-22 00:08:23 +00:00
}
static bool GetNativeUnsignedIntegerArgument(NativeArguments* arguments,
int arg_index,
uint64_t* value) {
ASSERT(value != NULL);
int64_t arg_value = 0;
if (Api::GetNativeIntegerArgument(arguments, arg_index, &arg_value)) {
*value = static_cast<uint64_t>(arg_value);
return true;
}
return false;
}
static bool GetNativeDoubleArgument(NativeArguments* arguments,
int arg_index,
double* value) {
ASSERT(value != NULL);
return Api::GetNativeDoubleArgument(arguments, arg_index, value);
Add a new API function to extract all the native arguments into an array passed in by the caller. This call can be used in DOM bindings patterns as follows: Old code - Dart_Handle exception = 0; { WebGL* receiver = DartDOMWrapper::receiver< WebGL >(args); unsigned srcRGB = DartUtilities::dartToUnsigned(args, 1, exception); if (exception) goto fail; unsigned dstRGB = DartUtilities::dartToUnsigned(args, 2, exception); if (exception) goto fail; unsigned srcAlpha = DartUtilities::dartToUnsigned(args, 3, exception); if (exception) goto fail; unsigned dstAlpha = DartUtilities::dartToUnsigned(args, 4, exception); if (exception) goto fail; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; } fail: Dart_ThrowException(exception); ASSERT_NOT_REACHED(); Proposed new code - /** * One time initialization code for setting up argument descriptors */ const int kNumArgs = 5; const int kNumNativeFields = 2; static const uint8_t native_arg_descriptor[kNumArgs] = { DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kNativeFields, 0), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 1), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 2), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 3), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 4), }; Dart_NativeArgument_Value native_args[kNumArgs]; intptr_t native_fields[kNumNativeFields]; native_args[0].as_native_fields.num_fields = kNumNativeFields; native_args[0].as_native_fields.values = native_fields; /** * Code executed for each invocation of the binding method */ Dart_Handle result = Dart_GetNativeArguments(args, kNumArgs, native_arg_descriptor, native_args); if (Dart_IsError(result)) { Dart_ThrowException(result); } WebGL* receiver = DartDOMWrapper::receiver< WebGL >(native_args[0].as_native_fields.values); unsigned srcRGB = native_args[1].as_uint32; unsigned dstRGB = native_args[2].as_uint32; unsigned srcAlpha = native_args[3].as_uint32; unsigned dstAlpha = native_args[4].as_uint32; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; R=iposva@google.com, vsm@google.com Review URL: https://codereview.chromium.org//282883002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@36464 260f80e4-7a28-3924-810f-c04153c831b5
2014-05-22 00:08:23 +00:00
}
static Dart_Handle GetNativeFieldsOfArgument(NativeArguments* arguments,
int arg_index,
int num_fields,
intptr_t* field_values,
const char* current_func) {
ASSERT(field_values != NULL);
if (Api::GetNativeFieldsOfArgument(arguments, arg_index, num_fields,
Add a new API function to extract all the native arguments into an array passed in by the caller. This call can be used in DOM bindings patterns as follows: Old code - Dart_Handle exception = 0; { WebGL* receiver = DartDOMWrapper::receiver< WebGL >(args); unsigned srcRGB = DartUtilities::dartToUnsigned(args, 1, exception); if (exception) goto fail; unsigned dstRGB = DartUtilities::dartToUnsigned(args, 2, exception); if (exception) goto fail; unsigned srcAlpha = DartUtilities::dartToUnsigned(args, 3, exception); if (exception) goto fail; unsigned dstAlpha = DartUtilities::dartToUnsigned(args, 4, exception); if (exception) goto fail; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; } fail: Dart_ThrowException(exception); ASSERT_NOT_REACHED(); Proposed new code - /** * One time initialization code for setting up argument descriptors */ const int kNumArgs = 5; const int kNumNativeFields = 2; static const uint8_t native_arg_descriptor[kNumArgs] = { DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kNativeFields, 0), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 1), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 2), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 3), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 4), }; Dart_NativeArgument_Value native_args[kNumArgs]; intptr_t native_fields[kNumNativeFields]; native_args[0].as_native_fields.num_fields = kNumNativeFields; native_args[0].as_native_fields.values = native_fields; /** * Code executed for each invocation of the binding method */ Dart_Handle result = Dart_GetNativeArguments(args, kNumArgs, native_arg_descriptor, native_args); if (Dart_IsError(result)) { Dart_ThrowException(result); } WebGL* receiver = DartDOMWrapper::receiver< WebGL >(native_args[0].as_native_fields.values); unsigned srcRGB = native_args[1].as_uint32; unsigned dstRGB = native_args[2].as_uint32; unsigned srcAlpha = native_args[3].as_uint32; unsigned dstAlpha = native_args[4].as_uint32; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; R=iposva@google.com, vsm@google.com Review URL: https://codereview.chromium.org//282883002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@36464 260f80e4-7a28-3924-810f-c04153c831b5
2014-05-22 00:08:23 +00:00
field_values)) {
return Api::Success();
}
Thread* thread = arguments->thread();
ASSERT(thread == Thread::Current());
REUSABLE_OBJECT_HANDLESCOPE(thread);
Object& obj = thread->ObjectHandle();
Add a new API function to extract all the native arguments into an array passed in by the caller. This call can be used in DOM bindings patterns as follows: Old code - Dart_Handle exception = 0; { WebGL* receiver = DartDOMWrapper::receiver< WebGL >(args); unsigned srcRGB = DartUtilities::dartToUnsigned(args, 1, exception); if (exception) goto fail; unsigned dstRGB = DartUtilities::dartToUnsigned(args, 2, exception); if (exception) goto fail; unsigned srcAlpha = DartUtilities::dartToUnsigned(args, 3, exception); if (exception) goto fail; unsigned dstAlpha = DartUtilities::dartToUnsigned(args, 4, exception); if (exception) goto fail; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; } fail: Dart_ThrowException(exception); ASSERT_NOT_REACHED(); Proposed new code - /** * One time initialization code for setting up argument descriptors */ const int kNumArgs = 5; const int kNumNativeFields = 2; static const uint8_t native_arg_descriptor[kNumArgs] = { DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kNativeFields, 0), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 1), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 2), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 3), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 4), }; Dart_NativeArgument_Value native_args[kNumArgs]; intptr_t native_fields[kNumNativeFields]; native_args[0].as_native_fields.num_fields = kNumNativeFields; native_args[0].as_native_fields.values = native_fields; /** * Code executed for each invocation of the binding method */ Dart_Handle result = Dart_GetNativeArguments(args, kNumArgs, native_arg_descriptor, native_args); if (Dart_IsError(result)) { Dart_ThrowException(result); } WebGL* receiver = DartDOMWrapper::receiver< WebGL >(native_args[0].as_native_fields.values); unsigned srcRGB = native_args[1].as_uint32; unsigned dstRGB = native_args[2].as_uint32; unsigned srcAlpha = native_args[3].as_uint32; unsigned dstAlpha = native_args[4].as_uint32; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; R=iposva@google.com, vsm@google.com Review URL: https://codereview.chromium.org//282883002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@36464 260f80e4-7a28-3924-810f-c04153c831b5
2014-05-22 00:08:23 +00:00
obj = arguments->NativeArgAt(arg_index);
if (obj.IsNull()) {
memset(field_values, 0, (num_fields * sizeof(field_values[0])));
return Api::Success();
}
// We did not succeed in extracting the native fields report the
// appropriate error.
if (!obj.IsInstance()) {
return Api::NewError(
"%s expects argument at index '%d' to be of"
" type Instance.",
current_func, arg_index);
Add a new API function to extract all the native arguments into an array passed in by the caller. This call can be used in DOM bindings patterns as follows: Old code - Dart_Handle exception = 0; { WebGL* receiver = DartDOMWrapper::receiver< WebGL >(args); unsigned srcRGB = DartUtilities::dartToUnsigned(args, 1, exception); if (exception) goto fail; unsigned dstRGB = DartUtilities::dartToUnsigned(args, 2, exception); if (exception) goto fail; unsigned srcAlpha = DartUtilities::dartToUnsigned(args, 3, exception); if (exception) goto fail; unsigned dstAlpha = DartUtilities::dartToUnsigned(args, 4, exception); if (exception) goto fail; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; } fail: Dart_ThrowException(exception); ASSERT_NOT_REACHED(); Proposed new code - /** * One time initialization code for setting up argument descriptors */ const int kNumArgs = 5; const int kNumNativeFields = 2; static const uint8_t native_arg_descriptor[kNumArgs] = { DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kNativeFields, 0), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 1), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 2), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 3), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 4), }; Dart_NativeArgument_Value native_args[kNumArgs]; intptr_t native_fields[kNumNativeFields]; native_args[0].as_native_fields.num_fields = kNumNativeFields; native_args[0].as_native_fields.values = native_fields; /** * Code executed for each invocation of the binding method */ Dart_Handle result = Dart_GetNativeArguments(args, kNumArgs, native_arg_descriptor, native_args); if (Dart_IsError(result)) { Dart_ThrowException(result); } WebGL* receiver = DartDOMWrapper::receiver< WebGL >(native_args[0].as_native_fields.values); unsigned srcRGB = native_args[1].as_uint32; unsigned dstRGB = native_args[2].as_uint32; unsigned srcAlpha = native_args[3].as_uint32; unsigned dstAlpha = native_args[4].as_uint32; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; R=iposva@google.com, vsm@google.com Review URL: https://codereview.chromium.org//282883002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@36464 260f80e4-7a28-3924-810f-c04153c831b5
2014-05-22 00:08:23 +00:00
}
const Instance& instance = Instance::Cast(obj);
int field_count = instance.NumNativeFields();
ASSERT(num_fields != field_count);
return Api::NewError("%s: expected %d 'num_fields' but was passed in %d.",
current_func, field_count, num_fields);
Add a new API function to extract all the native arguments into an array passed in by the caller. This call can be used in DOM bindings patterns as follows: Old code - Dart_Handle exception = 0; { WebGL* receiver = DartDOMWrapper::receiver< WebGL >(args); unsigned srcRGB = DartUtilities::dartToUnsigned(args, 1, exception); if (exception) goto fail; unsigned dstRGB = DartUtilities::dartToUnsigned(args, 2, exception); if (exception) goto fail; unsigned srcAlpha = DartUtilities::dartToUnsigned(args, 3, exception); if (exception) goto fail; unsigned dstAlpha = DartUtilities::dartToUnsigned(args, 4, exception); if (exception) goto fail; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; } fail: Dart_ThrowException(exception); ASSERT_NOT_REACHED(); Proposed new code - /** * One time initialization code for setting up argument descriptors */ const int kNumArgs = 5; const int kNumNativeFields = 2; static const uint8_t native_arg_descriptor[kNumArgs] = { DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kNativeFields, 0), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 1), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 2), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 3), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 4), }; Dart_NativeArgument_Value native_args[kNumArgs]; intptr_t native_fields[kNumNativeFields]; native_args[0].as_native_fields.num_fields = kNumNativeFields; native_args[0].as_native_fields.values = native_fields; /** * Code executed for each invocation of the binding method */ Dart_Handle result = Dart_GetNativeArguments(args, kNumArgs, native_arg_descriptor, native_args); if (Dart_IsError(result)) { Dart_ThrowException(result); } WebGL* receiver = DartDOMWrapper::receiver< WebGL >(native_args[0].as_native_fields.values); unsigned srcRGB = native_args[1].as_uint32; unsigned dstRGB = native_args[2].as_uint32; unsigned srcAlpha = native_args[3].as_uint32; unsigned dstAlpha = native_args[4].as_uint32; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; R=iposva@google.com, vsm@google.com Review URL: https://codereview.chromium.org//282883002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@36464 260f80e4-7a28-3924-810f-c04153c831b5
2014-05-22 00:08:23 +00:00
}
static FunctionPtr FindCoreLibPrivateFunction(Zone* zone, const String& name) {
const Library& core_lib = Library::Handle(zone, Library::CoreLibrary());
ASSERT(!core_lib.IsNull());
const Function& function =
Function::Handle(zone, core_lib.LookupFunctionAllowPrivate(name));
ASSERT(!function.IsNull());
return function.ptr();
}
static ObjectPtr CallStatic1Arg(Zone* zone,
const String& name,
const Instance& arg0) {
const intptr_t kNumArgs = 1;
const Function& function =
Function::Handle(zone, FindCoreLibPrivateFunction(zone, name));
const Array& args = Array::Handle(zone, Array::New(kNumArgs));
args.SetAt(0, arg0);
return DartEntry::InvokeFunction(function, args);
}
static ObjectPtr CallStatic2Args(Zone* zone,
const String& name,
const Instance& arg0,
const Instance& arg1) {
const intptr_t kNumArgs = 2;
const Function& function =
Function::Handle(zone, FindCoreLibPrivateFunction(zone, name));
const Array& args = Array::Handle(zone, Array::New(kNumArgs));
args.SetAt(0, arg0);
args.SetAt(1, arg1);
return DartEntry::InvokeFunction(function, args);
}
static ObjectPtr CallStatic3Args(Zone* zone,
const String& name,
const Instance& arg0,
const Instance& arg1,
const Instance& arg2) {
const intptr_t kNumArgs = 3;
const Function& function =
Function::Handle(zone, FindCoreLibPrivateFunction(zone, name));
const Array& args = Array::Handle(Array::New(kNumArgs));
args.SetAt(0, arg0);
args.SetAt(1, arg1);
args.SetAt(2, arg2);
return DartEntry::InvokeFunction(function, args);
}
static const char* GetErrorString(Thread* thread, const Object& obj) {
// This function requires an API scope to be present.
if (obj.IsError()) {
ASSERT(thread->api_top_scope() != NULL);
const Error& error = Error::Cast(obj);
const char* str = error.ToErrorCString();
intptr_t len = strlen(str) + 1;
char* str_copy = Api::TopScope(thread)->zone()->Alloc<char>(len);
strncpy(str_copy, str, len);
// Strip a possible trailing '\n'.
if ((len > 1) && (str_copy[len - 2] == '\n')) {
str_copy[len - 2] = '\0';
}
return str_copy;
} else {
return "";
}
}
Dart_Handle Api::InitNewHandle(Thread* thread, ObjectPtr raw) {
LocalHandles* local_handles = Api::TopScope(thread)->local_handles();
ASSERT(local_handles != NULL);
LocalHandle* ref = local_handles->AllocateHandle();
ref->set_ptr(raw);
return ref->apiHandle();
}
Dart_Handle Api::NewHandle(Thread* thread, ObjectPtr raw) {
if (raw == Object::null()) {
return Null();
}
if (raw == Bool::True().ptr()) {
return True();
}
if (raw == Bool::False().ptr()) {
return False();
}
ASSERT(thread->execution_state() == Thread::kThreadInVM);
return InitNewHandle(thread, raw);
}
ObjectPtr Api::UnwrapHandle(Dart_Handle object) {
#if defined(DEBUG)
Thread* thread = Thread::Current();
ASSERT(thread->execution_state() == Thread::kThreadInVM);
ASSERT(thread->IsMutatorThread());
ASSERT(thread->isolate() != NULL);
ASSERT(FinalizablePersistentHandle::ptr_offset() == 0 &&
PersistentHandle::ptr_offset() == 0 && LocalHandle::ptr_offset() == 0);
#endif
return (reinterpret_cast<LocalHandle*>(object))->ptr();
}
#define DEFINE_UNWRAP(type) \
const type& Api::Unwrap##type##Handle(Zone* zone, Dart_Handle dart_handle) { \
const Object& obj = Object::Handle(zone, Api::UnwrapHandle(dart_handle)); \
if (obj.Is##type()) { \
return type::Cast(obj); \
} \
return type::Handle(zone); \
}
CLASS_LIST_FOR_HANDLES(DEFINE_UNWRAP)
#undef DEFINE_UNWRAP
const String& Api::UnwrapStringHandle(const ReusableObjectHandleScope& reuse,
Dart_Handle dart_handle) {
Object& ref = reuse.Handle();
ref = Api::UnwrapHandle(dart_handle);
if (ref.IsString()) {
return String::Cast(ref);
}
return Object::null_string();
}
const Instance& Api::UnwrapInstanceHandle(
const ReusableObjectHandleScope& reuse,
Dart_Handle dart_handle) {
Object& ref = reuse.Handle();
ref = Api::UnwrapHandle(dart_handle);
if (ref.IsInstance()) {
return Instance::Cast(ref);
}
return Object::null_instance();
}
Dart_Handle Api::CheckAndFinalizePendingClasses(Thread* thread) {
Isolate* isolate = thread->isolate();
if (!isolate->AllowClassFinalization()) {
// Class finalization is blocked for the isolate. Do nothing.
return Api::Success();
}
if (ClassFinalizer::ProcessPendingClasses()) {
return Api::Success();
}
ASSERT(thread->sticky_error() != Object::null());
return Api::NewHandle(thread, thread->sticky_error());
}
Dart_Isolate Api::CastIsolate(Isolate* isolate) {
return reinterpret_cast<Dart_Isolate>(isolate);
}
Dart_IsolateGroup Api::CastIsolateGroup(IsolateGroup* isolate_group) {
return reinterpret_cast<Dart_IsolateGroup>(isolate_group);
}
Dart_Handle Api::NewError(const char* format, ...) {
Thread* T = Thread::Current();
CHECK_API_SCOPE(T);
CHECK_CALLBACK_STATE(T);
// Ensure we transition safepoint state to VM if we are not already in
// that state.
TransitionToVM transition(T);
HANDLESCOPE(T);
va_list args;
va_start(args, format);
char* buffer = OS::VSCreate(Z, format, args);
va_end(args);
const String& message = String::Handle(Z, String::New(buffer));
return Api::NewHandle(T, ApiError::New(message));
}
Dart_Handle Api::NewArgumentError(const char* format, ...) {
Thread* T = Thread::Current();
CHECK_API_SCOPE(T);
CHECK_CALLBACK_STATE(T);
// Ensure we transition safepoint state to VM if we are not already in
// that state.
TransitionToVM transition(T);
HANDLESCOPE(T);
va_list args;
va_start(args, format);
char* buffer = OS::VSCreate(Z, format, args);
va_end(args);
const String& message = String::Handle(Z, String::New(buffer));
const Array& arguments = Array::Handle(Z, Array::New(1));
arguments.SetAt(0, message);
Object& error = Object::Handle(
Z, DartLibraryCalls::InstanceCreate(
Library::Handle(Z, Library::CoreLibrary()),
Symbols::ArgumentError(), Symbols::Dot(), arguments));
if (!error.IsError()) {
error = UnhandledException::New(Instance::Cast(error), Instance::Handle());
}
return Api::NewHandle(T, error.ptr());
}
bool Api::IsValid(Dart_Handle handle) {
Isolate* isolate = Isolate::Current();
Thread* thread = Thread::Current();
ASSERT(thread->IsMutatorThread());
CHECK_ISOLATE(isolate);
// Check against all of the handles in the current isolate as well as the
// read-only handles.
return thread->IsValidHandle(handle) ||
isolate->group()->api_state()->IsActivePersistentHandle(
reinterpret_cast<Dart_PersistentHandle>(handle)) ||
isolate->group()->api_state()->IsActiveWeakPersistentHandle(
reinterpret_cast<Dart_WeakPersistentHandle>(handle)) ||
Dart::IsReadOnlyApiHandle(handle) ||
Dart::IsReadOnlyHandle(reinterpret_cast<uword>(handle));
}
ApiLocalScope* Api::TopScope(Thread* thread) {
ASSERT(thread != NULL);
ApiLocalScope* scope = thread->api_top_scope();
ASSERT(scope != NULL);
return scope;
}
void Api::Init() {
if (api_native_key_ == kUnsetThreadLocalKey) {
api_native_key_ = OSThread::CreateThreadLocal();
}
ASSERT(api_native_key_ != kUnsetThreadLocalKey);
}
static Dart_Handle InitNewReadOnlyApiHandle(ObjectPtr raw) {
ASSERT(raw->untag()->InVMIsolateHeap());
LocalHandle* ref = Dart::AllocateReadOnlyApiHandle();
ref->set_ptr(raw);
return ref->apiHandle();
}
void Api::InitHandles() {
Isolate* isolate = Isolate::Current();
ASSERT(isolate != NULL);
ASSERT(isolate == Dart::vm_isolate());
ApiState* state = isolate->group()->api_state();
ASSERT(state != NULL);
ASSERT(true_handle_ == NULL);
true_handle_ = InitNewReadOnlyApiHandle(Bool::True().ptr());
ASSERT(false_handle_ == NULL);
false_handle_ = InitNewReadOnlyApiHandle(Bool::False().ptr());
ASSERT(null_handle_ == NULL);
null_handle_ = InitNewReadOnlyApiHandle(Object::null());
ASSERT(empty_string_handle_ == NULL);
empty_string_handle_ = InitNewReadOnlyApiHandle(Symbols::Empty().ptr());
ASSERT(no_callbacks_error_handle_ == NULL);
no_callbacks_error_handle_ =
InitNewReadOnlyApiHandle(Object::no_callbacks_error().ptr());
ASSERT(unwind_in_progress_error_handle_ == NULL);
unwind_in_progress_error_handle_ =
InitNewReadOnlyApiHandle(Object::unwind_in_progress_error().ptr());
}
void Api::Cleanup() {
true_handle_ = NULL;
false_handle_ = NULL;
null_handle_ = NULL;
empty_string_handle_ = NULL;
no_callbacks_error_handle_ = NULL;
unwind_in_progress_error_handle_ = NULL;
}
bool Api::StringGetPeerHelper(NativeArguments* arguments,
int arg_index,
void** peer) {
NoSafepointScope no_safepoint_scope;
ObjectPtr raw_obj = arguments->NativeArgAt(arg_index);
if (!raw_obj->IsHeapObject()) {
return false;
}
intptr_t cid = raw_obj->GetClassId();
if (cid == kExternalOneByteStringCid) {
ExternalOneByteStringPtr raw_string =
static_cast<ExternalOneByteStringPtr>(raw_obj);
*peer = raw_string->untag()->peer_;
return true;
}
if (cid == kOneByteStringCid || cid == kTwoByteStringCid) {
auto isolate_group = arguments->thread()->isolate_group();
*peer = isolate_group->heap()->GetPeer(raw_obj);
return (*peer != 0);
}
if (cid == kExternalTwoByteStringCid) {
ExternalTwoByteStringPtr raw_string =
static_cast<ExternalTwoByteStringPtr>(raw_obj);
*peer = raw_string->untag()->peer_;
return true;
}
return false;
}
bool Api::GetNativeReceiver(NativeArguments* arguments, intptr_t* value) {
NoSafepointScope no_safepoint_scope;
ObjectPtr raw_obj = arguments->NativeArg0();
if (raw_obj->IsHeapObject()) {
intptr_t cid = raw_obj->GetClassId();
if (cid >= kNumPredefinedCids) {
ASSERT(Instance::Cast(Object::Handle(raw_obj)).IsValidNativeIndex(0));
TypedDataPtr native_fields =
reinterpret_cast<CompressedTypedDataPtr*>(
UntaggedObject::ToAddr(raw_obj) + sizeof(UntaggedObject))
->Decompress(raw_obj->heap_base());
if (native_fields == TypedData::null()) {
*value = 0;
} else {
*value = *bit_cast<intptr_t*, uint8_t*>(native_fields->untag()->data());
}
return true;
}
}
return false;
}
bool Api::GetNativeBooleanArgument(NativeArguments* arguments,
int arg_index,
bool* value) {
NoSafepointScope no_safepoint_scope;
ObjectPtr raw_obj = arguments->NativeArgAt(arg_index);
if (raw_obj->IsHeapObject()) {
intptr_t cid = raw_obj->GetClassId();
if (cid == kBoolCid) {
*value = (raw_obj == Object::bool_true().ptr());
return true;
}
if (cid == kNullCid) {
*value = false;
return true;
}
}
return false;
}
Add a new API function to extract all the native arguments into an array passed in by the caller. This call can be used in DOM bindings patterns as follows: Old code - Dart_Handle exception = 0; { WebGL* receiver = DartDOMWrapper::receiver< WebGL >(args); unsigned srcRGB = DartUtilities::dartToUnsigned(args, 1, exception); if (exception) goto fail; unsigned dstRGB = DartUtilities::dartToUnsigned(args, 2, exception); if (exception) goto fail; unsigned srcAlpha = DartUtilities::dartToUnsigned(args, 3, exception); if (exception) goto fail; unsigned dstAlpha = DartUtilities::dartToUnsigned(args, 4, exception); if (exception) goto fail; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; } fail: Dart_ThrowException(exception); ASSERT_NOT_REACHED(); Proposed new code - /** * One time initialization code for setting up argument descriptors */ const int kNumArgs = 5; const int kNumNativeFields = 2; static const uint8_t native_arg_descriptor[kNumArgs] = { DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kNativeFields, 0), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 1), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 2), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 3), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 4), }; Dart_NativeArgument_Value native_args[kNumArgs]; intptr_t native_fields[kNumNativeFields]; native_args[0].as_native_fields.num_fields = kNumNativeFields; native_args[0].as_native_fields.values = native_fields; /** * Code executed for each invocation of the binding method */ Dart_Handle result = Dart_GetNativeArguments(args, kNumArgs, native_arg_descriptor, native_args); if (Dart_IsError(result)) { Dart_ThrowException(result); } WebGL* receiver = DartDOMWrapper::receiver< WebGL >(native_args[0].as_native_fields.values); unsigned srcRGB = native_args[1].as_uint32; unsigned dstRGB = native_args[2].as_uint32; unsigned srcAlpha = native_args[3].as_uint32; unsigned dstAlpha = native_args[4].as_uint32; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; R=iposva@google.com, vsm@google.com Review URL: https://codereview.chromium.org//282883002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@36464 260f80e4-7a28-3924-810f-c04153c831b5
2014-05-22 00:08:23 +00:00
bool Api::GetNativeIntegerArgument(NativeArguments* arguments,
int arg_index,
int64_t* value) {
NoSafepointScope no_safepoint_scope;
ObjectPtr raw_obj = arguments->NativeArgAt(arg_index);
Add a new API function to extract all the native arguments into an array passed in by the caller. This call can be used in DOM bindings patterns as follows: Old code - Dart_Handle exception = 0; { WebGL* receiver = DartDOMWrapper::receiver< WebGL >(args); unsigned srcRGB = DartUtilities::dartToUnsigned(args, 1, exception); if (exception) goto fail; unsigned dstRGB = DartUtilities::dartToUnsigned(args, 2, exception); if (exception) goto fail; unsigned srcAlpha = DartUtilities::dartToUnsigned(args, 3, exception); if (exception) goto fail; unsigned dstAlpha = DartUtilities::dartToUnsigned(args, 4, exception); if (exception) goto fail; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; } fail: Dart_ThrowException(exception); ASSERT_NOT_REACHED(); Proposed new code - /** * One time initialization code for setting up argument descriptors */ const int kNumArgs = 5; const int kNumNativeFields = 2; static const uint8_t native_arg_descriptor[kNumArgs] = { DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kNativeFields, 0), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 1), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 2), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 3), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 4), }; Dart_NativeArgument_Value native_args[kNumArgs]; intptr_t native_fields[kNumNativeFields]; native_args[0].as_native_fields.num_fields = kNumNativeFields; native_args[0].as_native_fields.values = native_fields; /** * Code executed for each invocation of the binding method */ Dart_Handle result = Dart_GetNativeArguments(args, kNumArgs, native_arg_descriptor, native_args); if (Dart_IsError(result)) { Dart_ThrowException(result); } WebGL* receiver = DartDOMWrapper::receiver< WebGL >(native_args[0].as_native_fields.values); unsigned srcRGB = native_args[1].as_uint32; unsigned dstRGB = native_args[2].as_uint32; unsigned srcAlpha = native_args[3].as_uint32; unsigned dstAlpha = native_args[4].as_uint32; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; R=iposva@google.com, vsm@google.com Review URL: https://codereview.chromium.org//282883002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@36464 260f80e4-7a28-3924-810f-c04153c831b5
2014-05-22 00:08:23 +00:00
if (raw_obj->IsHeapObject()) {
intptr_t cid = raw_obj->GetClassId();
if (cid == kMintCid) {
*value = static_cast<MintPtr>(raw_obj)->untag()->value_;
Add a new API function to extract all the native arguments into an array passed in by the caller. This call can be used in DOM bindings patterns as follows: Old code - Dart_Handle exception = 0; { WebGL* receiver = DartDOMWrapper::receiver< WebGL >(args); unsigned srcRGB = DartUtilities::dartToUnsigned(args, 1, exception); if (exception) goto fail; unsigned dstRGB = DartUtilities::dartToUnsigned(args, 2, exception); if (exception) goto fail; unsigned srcAlpha = DartUtilities::dartToUnsigned(args, 3, exception); if (exception) goto fail; unsigned dstAlpha = DartUtilities::dartToUnsigned(args, 4, exception); if (exception) goto fail; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; } fail: Dart_ThrowException(exception); ASSERT_NOT_REACHED(); Proposed new code - /** * One time initialization code for setting up argument descriptors */ const int kNumArgs = 5; const int kNumNativeFields = 2; static const uint8_t native_arg_descriptor[kNumArgs] = { DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kNativeFields, 0), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 1), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 2), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 3), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 4), }; Dart_NativeArgument_Value native_args[kNumArgs]; intptr_t native_fields[kNumNativeFields]; native_args[0].as_native_fields.num_fields = kNumNativeFields; native_args[0].as_native_fields.values = native_fields; /** * Code executed for each invocation of the binding method */ Dart_Handle result = Dart_GetNativeArguments(args, kNumArgs, native_arg_descriptor, native_args); if (Dart_IsError(result)) { Dart_ThrowException(result); } WebGL* receiver = DartDOMWrapper::receiver< WebGL >(native_args[0].as_native_fields.values); unsigned srcRGB = native_args[1].as_uint32; unsigned dstRGB = native_args[2].as_uint32; unsigned srcAlpha = native_args[3].as_uint32; unsigned dstAlpha = native_args[4].as_uint32; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; R=iposva@google.com, vsm@google.com Review URL: https://codereview.chromium.org//282883002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@36464 260f80e4-7a28-3924-810f-c04153c831b5
2014-05-22 00:08:23 +00:00
return true;
}
return false;
}
*value = Smi::Value(static_cast<SmiPtr>(raw_obj));
Add a new API function to extract all the native arguments into an array passed in by the caller. This call can be used in DOM bindings patterns as follows: Old code - Dart_Handle exception = 0; { WebGL* receiver = DartDOMWrapper::receiver< WebGL >(args); unsigned srcRGB = DartUtilities::dartToUnsigned(args, 1, exception); if (exception) goto fail; unsigned dstRGB = DartUtilities::dartToUnsigned(args, 2, exception); if (exception) goto fail; unsigned srcAlpha = DartUtilities::dartToUnsigned(args, 3, exception); if (exception) goto fail; unsigned dstAlpha = DartUtilities::dartToUnsigned(args, 4, exception); if (exception) goto fail; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; } fail: Dart_ThrowException(exception); ASSERT_NOT_REACHED(); Proposed new code - /** * One time initialization code for setting up argument descriptors */ const int kNumArgs = 5; const int kNumNativeFields = 2; static const uint8_t native_arg_descriptor[kNumArgs] = { DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kNativeFields, 0), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 1), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 2), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 3), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 4), }; Dart_NativeArgument_Value native_args[kNumArgs]; intptr_t native_fields[kNumNativeFields]; native_args[0].as_native_fields.num_fields = kNumNativeFields; native_args[0].as_native_fields.values = native_fields; /** * Code executed for each invocation of the binding method */ Dart_Handle result = Dart_GetNativeArguments(args, kNumArgs, native_arg_descriptor, native_args); if (Dart_IsError(result)) { Dart_ThrowException(result); } WebGL* receiver = DartDOMWrapper::receiver< WebGL >(native_args[0].as_native_fields.values); unsigned srcRGB = native_args[1].as_uint32; unsigned dstRGB = native_args[2].as_uint32; unsigned srcAlpha = native_args[3].as_uint32; unsigned dstAlpha = native_args[4].as_uint32; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; R=iposva@google.com, vsm@google.com Review URL: https://codereview.chromium.org//282883002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@36464 260f80e4-7a28-3924-810f-c04153c831b5
2014-05-22 00:08:23 +00:00
return true;
}
bool Api::GetNativeDoubleArgument(NativeArguments* arguments,
int arg_index,
double* value) {
NoSafepointScope no_safepoint_scope;
ObjectPtr raw_obj = arguments->NativeArgAt(arg_index);
Add a new API function to extract all the native arguments into an array passed in by the caller. This call can be used in DOM bindings patterns as follows: Old code - Dart_Handle exception = 0; { WebGL* receiver = DartDOMWrapper::receiver< WebGL >(args); unsigned srcRGB = DartUtilities::dartToUnsigned(args, 1, exception); if (exception) goto fail; unsigned dstRGB = DartUtilities::dartToUnsigned(args, 2, exception); if (exception) goto fail; unsigned srcAlpha = DartUtilities::dartToUnsigned(args, 3, exception); if (exception) goto fail; unsigned dstAlpha = DartUtilities::dartToUnsigned(args, 4, exception); if (exception) goto fail; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; } fail: Dart_ThrowException(exception); ASSERT_NOT_REACHED(); Proposed new code - /** * One time initialization code for setting up argument descriptors */ const int kNumArgs = 5; const int kNumNativeFields = 2; static const uint8_t native_arg_descriptor[kNumArgs] = { DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kNativeFields, 0), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 1), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 2), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 3), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 4), }; Dart_NativeArgument_Value native_args[kNumArgs]; intptr_t native_fields[kNumNativeFields]; native_args[0].as_native_fields.num_fields = kNumNativeFields; native_args[0].as_native_fields.values = native_fields; /** * Code executed for each invocation of the binding method */ Dart_Handle result = Dart_GetNativeArguments(args, kNumArgs, native_arg_descriptor, native_args); if (Dart_IsError(result)) { Dart_ThrowException(result); } WebGL* receiver = DartDOMWrapper::receiver< WebGL >(native_args[0].as_native_fields.values); unsigned srcRGB = native_args[1].as_uint32; unsigned dstRGB = native_args[2].as_uint32; unsigned srcAlpha = native_args[3].as_uint32; unsigned dstAlpha = native_args[4].as_uint32; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; R=iposva@google.com, vsm@google.com Review URL: https://codereview.chromium.org//282883002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@36464 260f80e4-7a28-3924-810f-c04153c831b5
2014-05-22 00:08:23 +00:00
if (raw_obj->IsHeapObject()) {
intptr_t cid = raw_obj->GetClassId();
if (cid == kDoubleCid) {
*value = static_cast<DoublePtr>(raw_obj)->untag()->value_;
Add a new API function to extract all the native arguments into an array passed in by the caller. This call can be used in DOM bindings patterns as follows: Old code - Dart_Handle exception = 0; { WebGL* receiver = DartDOMWrapper::receiver< WebGL >(args); unsigned srcRGB = DartUtilities::dartToUnsigned(args, 1, exception); if (exception) goto fail; unsigned dstRGB = DartUtilities::dartToUnsigned(args, 2, exception); if (exception) goto fail; unsigned srcAlpha = DartUtilities::dartToUnsigned(args, 3, exception); if (exception) goto fail; unsigned dstAlpha = DartUtilities::dartToUnsigned(args, 4, exception); if (exception) goto fail; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; } fail: Dart_ThrowException(exception); ASSERT_NOT_REACHED(); Proposed new code - /** * One time initialization code for setting up argument descriptors */ const int kNumArgs = 5; const int kNumNativeFields = 2; static const uint8_t native_arg_descriptor[kNumArgs] = { DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kNativeFields, 0), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 1), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 2), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 3), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 4), }; Dart_NativeArgument_Value native_args[kNumArgs]; intptr_t native_fields[kNumNativeFields]; native_args[0].as_native_fields.num_fields = kNumNativeFields; native_args[0].as_native_fields.values = native_fields; /** * Code executed for each invocation of the binding method */ Dart_Handle result = Dart_GetNativeArguments(args, kNumArgs, native_arg_descriptor, native_args); if (Dart_IsError(result)) { Dart_ThrowException(result); } WebGL* receiver = DartDOMWrapper::receiver< WebGL >(native_args[0].as_native_fields.values); unsigned srcRGB = native_args[1].as_uint32; unsigned dstRGB = native_args[2].as_uint32; unsigned srcAlpha = native_args[3].as_uint32; unsigned dstAlpha = native_args[4].as_uint32; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; R=iposva@google.com, vsm@google.com Review URL: https://codereview.chromium.org//282883002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@36464 260f80e4-7a28-3924-810f-c04153c831b5
2014-05-22 00:08:23 +00:00
return true;
}
if (cid == kMintCid) {
*value =
static_cast<double>(static_cast<MintPtr>(raw_obj)->untag()->value_);
Add a new API function to extract all the native arguments into an array passed in by the caller. This call can be used in DOM bindings patterns as follows: Old code - Dart_Handle exception = 0; { WebGL* receiver = DartDOMWrapper::receiver< WebGL >(args); unsigned srcRGB = DartUtilities::dartToUnsigned(args, 1, exception); if (exception) goto fail; unsigned dstRGB = DartUtilities::dartToUnsigned(args, 2, exception); if (exception) goto fail; unsigned srcAlpha = DartUtilities::dartToUnsigned(args, 3, exception); if (exception) goto fail; unsigned dstAlpha = DartUtilities::dartToUnsigned(args, 4, exception); if (exception) goto fail; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; } fail: Dart_ThrowException(exception); ASSERT_NOT_REACHED(); Proposed new code - /** * One time initialization code for setting up argument descriptors */ const int kNumArgs = 5; const int kNumNativeFields = 2; static const uint8_t native_arg_descriptor[kNumArgs] = { DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kNativeFields, 0), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 1), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 2), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 3), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 4), }; Dart_NativeArgument_Value native_args[kNumArgs]; intptr_t native_fields[kNumNativeFields]; native_args[0].as_native_fields.num_fields = kNumNativeFields; native_args[0].as_native_fields.values = native_fields; /** * Code executed for each invocation of the binding method */ Dart_Handle result = Dart_GetNativeArguments(args, kNumArgs, native_arg_descriptor, native_args); if (Dart_IsError(result)) { Dart_ThrowException(result); } WebGL* receiver = DartDOMWrapper::receiver< WebGL >(native_args[0].as_native_fields.values); unsigned srcRGB = native_args[1].as_uint32; unsigned dstRGB = native_args[2].as_uint32; unsigned srcAlpha = native_args[3].as_uint32; unsigned dstAlpha = native_args[4].as_uint32; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; R=iposva@google.com, vsm@google.com Review URL: https://codereview.chromium.org//282883002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@36464 260f80e4-7a28-3924-810f-c04153c831b5
2014-05-22 00:08:23 +00:00
return true;
}
return false;
}
*value = static_cast<double>(Smi::Value(static_cast<SmiPtr>(raw_obj)));
Add a new API function to extract all the native arguments into an array passed in by the caller. This call can be used in DOM bindings patterns as follows: Old code - Dart_Handle exception = 0; { WebGL* receiver = DartDOMWrapper::receiver< WebGL >(args); unsigned srcRGB = DartUtilities::dartToUnsigned(args, 1, exception); if (exception) goto fail; unsigned dstRGB = DartUtilities::dartToUnsigned(args, 2, exception); if (exception) goto fail; unsigned srcAlpha = DartUtilities::dartToUnsigned(args, 3, exception); if (exception) goto fail; unsigned dstAlpha = DartUtilities::dartToUnsigned(args, 4, exception); if (exception) goto fail; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; } fail: Dart_ThrowException(exception); ASSERT_NOT_REACHED(); Proposed new code - /** * One time initialization code for setting up argument descriptors */ const int kNumArgs = 5; const int kNumNativeFields = 2; static const uint8_t native_arg_descriptor[kNumArgs] = { DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kNativeFields, 0), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 1), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 2), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 3), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 4), }; Dart_NativeArgument_Value native_args[kNumArgs]; intptr_t native_fields[kNumNativeFields]; native_args[0].as_native_fields.num_fields = kNumNativeFields; native_args[0].as_native_fields.values = native_fields; /** * Code executed for each invocation of the binding method */ Dart_Handle result = Dart_GetNativeArguments(args, kNumArgs, native_arg_descriptor, native_args); if (Dart_IsError(result)) { Dart_ThrowException(result); } WebGL* receiver = DartDOMWrapper::receiver< WebGL >(native_args[0].as_native_fields.values); unsigned srcRGB = native_args[1].as_uint32; unsigned dstRGB = native_args[2].as_uint32; unsigned srcAlpha = native_args[3].as_uint32; unsigned dstAlpha = native_args[4].as_uint32; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; R=iposva@google.com, vsm@google.com Review URL: https://codereview.chromium.org//282883002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@36464 260f80e4-7a28-3924-810f-c04153c831b5
2014-05-22 00:08:23 +00:00
return true;
}
bool Api::GetNativeFieldsOfArgument(NativeArguments* arguments,
int arg_index,
int num_fields,
intptr_t* field_values) {
NoSafepointScope no_safepoint_scope;
ObjectPtr raw_obj = arguments->NativeArgAt(arg_index);
intptr_t cid = raw_obj->GetClassIdMayBeSmi();
int class_num_fields = arguments->thread()
->isolate_group()
->class_table()
->At(cid)
->untag()
->num_native_fields_;
if (num_fields != class_num_fields) {
// No native fields or mismatched native field count.
return false;
Add a new API function to extract all the native arguments into an array passed in by the caller. This call can be used in DOM bindings patterns as follows: Old code - Dart_Handle exception = 0; { WebGL* receiver = DartDOMWrapper::receiver< WebGL >(args); unsigned srcRGB = DartUtilities::dartToUnsigned(args, 1, exception); if (exception) goto fail; unsigned dstRGB = DartUtilities::dartToUnsigned(args, 2, exception); if (exception) goto fail; unsigned srcAlpha = DartUtilities::dartToUnsigned(args, 3, exception); if (exception) goto fail; unsigned dstAlpha = DartUtilities::dartToUnsigned(args, 4, exception); if (exception) goto fail; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; } fail: Dart_ThrowException(exception); ASSERT_NOT_REACHED(); Proposed new code - /** * One time initialization code for setting up argument descriptors */ const int kNumArgs = 5; const int kNumNativeFields = 2; static const uint8_t native_arg_descriptor[kNumArgs] = { DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kNativeFields, 0), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 1), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 2), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 3), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 4), }; Dart_NativeArgument_Value native_args[kNumArgs]; intptr_t native_fields[kNumNativeFields]; native_args[0].as_native_fields.num_fields = kNumNativeFields; native_args[0].as_native_fields.values = native_fields; /** * Code executed for each invocation of the binding method */ Dart_Handle result = Dart_GetNativeArguments(args, kNumArgs, native_arg_descriptor, native_args); if (Dart_IsError(result)) { Dart_ThrowException(result); } WebGL* receiver = DartDOMWrapper::receiver< WebGL >(native_args[0].as_native_fields.values); unsigned srcRGB = native_args[1].as_uint32; unsigned dstRGB = native_args[2].as_uint32; unsigned srcAlpha = native_args[3].as_uint32; unsigned dstAlpha = native_args[4].as_uint32; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; R=iposva@google.com, vsm@google.com Review URL: https://codereview.chromium.org//282883002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@36464 260f80e4-7a28-3924-810f-c04153c831b5
2014-05-22 00:08:23 +00:00
}
TypedDataPtr native_fields =
reinterpret_cast<CompressedTypedDataPtr*>(
UntaggedObject::ToAddr(raw_obj) + sizeof(UntaggedObject))
->Decompress(raw_obj->heap_base());
if (native_fields == TypedData::null()) {
// Native fields not initialized.
memset(field_values, 0, (num_fields * sizeof(field_values[0])));
return true;
}
ASSERT(class_num_fields == Smi::Value(native_fields->untag()->length()));
intptr_t* native_values =
reinterpret_cast<intptr_t*>(native_fields->untag()->data());
memmove(field_values, native_values, (num_fields * sizeof(field_values[0])));
return true;
Add a new API function to extract all the native arguments into an array passed in by the caller. This call can be used in DOM bindings patterns as follows: Old code - Dart_Handle exception = 0; { WebGL* receiver = DartDOMWrapper::receiver< WebGL >(args); unsigned srcRGB = DartUtilities::dartToUnsigned(args, 1, exception); if (exception) goto fail; unsigned dstRGB = DartUtilities::dartToUnsigned(args, 2, exception); if (exception) goto fail; unsigned srcAlpha = DartUtilities::dartToUnsigned(args, 3, exception); if (exception) goto fail; unsigned dstAlpha = DartUtilities::dartToUnsigned(args, 4, exception); if (exception) goto fail; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; } fail: Dart_ThrowException(exception); ASSERT_NOT_REACHED(); Proposed new code - /** * One time initialization code for setting up argument descriptors */ const int kNumArgs = 5; const int kNumNativeFields = 2; static const uint8_t native_arg_descriptor[kNumArgs] = { DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kNativeFields, 0), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 1), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 2), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 3), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 4), }; Dart_NativeArgument_Value native_args[kNumArgs]; intptr_t native_fields[kNumNativeFields]; native_args[0].as_native_fields.num_fields = kNumNativeFields; native_args[0].as_native_fields.values = native_fields; /** * Code executed for each invocation of the binding method */ Dart_Handle result = Dart_GetNativeArguments(args, kNumArgs, native_arg_descriptor, native_args); if (Dart_IsError(result)) { Dart_ThrowException(result); } WebGL* receiver = DartDOMWrapper::receiver< WebGL >(native_args[0].as_native_fields.values); unsigned srcRGB = native_args[1].as_uint32; unsigned dstRGB = native_args[2].as_uint32; unsigned srcAlpha = native_args[3].as_uint32; unsigned dstAlpha = native_args[4].as_uint32; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; R=iposva@google.com, vsm@google.com Review URL: https://codereview.chromium.org//282883002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@36464 260f80e4-7a28-3924-810f-c04153c831b5
2014-05-22 00:08:23 +00:00
}
void Api::SetWeakHandleReturnValue(NativeArguments* args,
Dart_WeakPersistentHandle retval) {
args->SetReturnUnsafe(FinalizablePersistentHandle::Cast(retval)->ptr());
}
PersistentHandle* PersistentHandle::Cast(Dart_PersistentHandle handle) {
ASSERT(IsolateGroup::Current()->api_state()->IsValidPersistentHandle(handle));
return reinterpret_cast<PersistentHandle*>(handle);
}
FinalizablePersistentHandle* FinalizablePersistentHandle::Cast(
Dart_WeakPersistentHandle handle) {
#if defined(DEBUG)
ApiState* state = IsolateGroup::Current()->api_state();
ASSERT(state->IsValidWeakPersistentHandle(handle));
#endif
return reinterpret_cast<FinalizablePersistentHandle*>(handle);
}
FinalizablePersistentHandle* FinalizablePersistentHandle::Cast(
Dart_FinalizableHandle handle) {
#if defined(DEBUG)
ApiState* state = IsolateGroup::Current()->api_state();
ASSERT(state->IsValidFinalizableHandle(handle));
#endif
return reinterpret_cast<FinalizablePersistentHandle*>(handle);
}
void FinalizablePersistentHandle::Finalize(
IsolateGroup* isolate_group,
FinalizablePersistentHandle* handle) {
if (!handle->ptr()->IsHeapObject()) {
return; // Free handle.
}
[vm] Native API: Make Dart_NewWeakPersistentHandle not auto delete Changes Dart_NewWeakPersistentHandle to no longer auto delete the weak persistent handle. Changes the signatures of WeakPersistentHandleFinalizers to no longer have access to the handle. Flutter PR: https://github.com/flutter/engine/pull/19843 g3 presubmit: cl/318028238 Issue: https://github.com/dart-lang/sdk/issues/42312 TEST=runtime/vm/dart_api_impl_test.cc Change-Id: I3f77db9954d9486759f903b78c03a494f73c68ba Cq-Include-Trybots:dart/try:vm-ffi-android-debug-arm-try,vm-ffi-android-debug-arm64-try,app-kernel-linux-debug-x64-try,vm-kernel-linux-debug-ia32-try,vm-kernel-win-debug-x64-try,vm-kernel-win-debug-ia32-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-asan-linux-release-x64-try,vm-kernel-msan-linux-release-x64-try,vm-kernel-precomp-msan-linux-release-x64-try,vm-kernel-linux-release-simarm-try,vm-kernel-linux-release-simarm64-try,vm-kernel-precomp-android-release-arm_x64-try,vm-kernel-precomp-obfuscate-linux-release-x64-try,dart-sdk-linux-try,analyzer-analysis-server-linux-try,analyzer-linux-release-try,front-end-linux-release-x64-try,vm-kernel-precomp-win-release-x64-try,vm-kernel-mac-debug-x64-try,vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-nnbd-linux-debug-x64-try,analyzer-nnbd-linux-release-try,front-end-nnbd-linux-release-x64-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/151525 Commit-Queue: Daco Harkes <dacoharkes@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com>
2020-11-03 10:27:44 +00:00
Dart_HandleFinalizer callback = handle->callback();
ASSERT(callback != NULL);
void* peer = handle->peer();
ApiState* state = isolate_group->api_state();
ASSERT(state != NULL);
[vm] Native API: Make Dart_NewWeakPersistentHandle not auto delete Changes Dart_NewWeakPersistentHandle to no longer auto delete the weak persistent handle. Changes the signatures of WeakPersistentHandleFinalizers to no longer have access to the handle. Flutter PR: https://github.com/flutter/engine/pull/19843 g3 presubmit: cl/318028238 Issue: https://github.com/dart-lang/sdk/issues/42312 TEST=runtime/vm/dart_api_impl_test.cc Change-Id: I3f77db9954d9486759f903b78c03a494f73c68ba Cq-Include-Trybots:dart/try:vm-ffi-android-debug-arm-try,vm-ffi-android-debug-arm64-try,app-kernel-linux-debug-x64-try,vm-kernel-linux-debug-ia32-try,vm-kernel-win-debug-x64-try,vm-kernel-win-debug-ia32-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-asan-linux-release-x64-try,vm-kernel-msan-linux-release-x64-try,vm-kernel-precomp-msan-linux-release-x64-try,vm-kernel-linux-release-simarm-try,vm-kernel-linux-release-simarm64-try,vm-kernel-precomp-android-release-arm_x64-try,vm-kernel-precomp-obfuscate-linux-release-x64-try,dart-sdk-linux-try,analyzer-analysis-server-linux-try,analyzer-linux-release-try,front-end-linux-release-x64-try,vm-kernel-precomp-win-release-x64-try,vm-kernel-mac-debug-x64-try,vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-nnbd-linux-debug-x64-try,analyzer-nnbd-linux-release-try,front-end-nnbd-linux-release-x64-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/151525 Commit-Queue: Daco Harkes <dacoharkes@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com>
2020-11-03 10:27:44 +00:00
if (!handle->auto_delete()) {
// Clear handle before running finalizer, finalizer can free the handle.
state->ClearWeakPersistentHandle(handle);
}
[vm] Native API: Make Dart_NewWeakPersistentHandle not auto delete Changes Dart_NewWeakPersistentHandle to no longer auto delete the weak persistent handle. Changes the signatures of WeakPersistentHandleFinalizers to no longer have access to the handle. Flutter PR: https://github.com/flutter/engine/pull/19843 g3 presubmit: cl/318028238 Issue: https://github.com/dart-lang/sdk/issues/42312 TEST=runtime/vm/dart_api_impl_test.cc Change-Id: I3f77db9954d9486759f903b78c03a494f73c68ba Cq-Include-Trybots:dart/try:vm-ffi-android-debug-arm-try,vm-ffi-android-debug-arm64-try,app-kernel-linux-debug-x64-try,vm-kernel-linux-debug-ia32-try,vm-kernel-win-debug-x64-try,vm-kernel-win-debug-ia32-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-asan-linux-release-x64-try,vm-kernel-msan-linux-release-x64-try,vm-kernel-precomp-msan-linux-release-x64-try,vm-kernel-linux-release-simarm-try,vm-kernel-linux-release-simarm64-try,vm-kernel-precomp-android-release-arm_x64-try,vm-kernel-precomp-obfuscate-linux-release-x64-try,dart-sdk-linux-try,analyzer-analysis-server-linux-try,analyzer-linux-release-try,front-end-linux-release-x64-try,vm-kernel-precomp-win-release-x64-try,vm-kernel-mac-debug-x64-try,vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-nnbd-linux-debug-x64-try,analyzer-nnbd-linux-release-try,front-end-nnbd-linux-release-x64-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/151525 Commit-Queue: Daco Harkes <dacoharkes@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com>
2020-11-03 10:27:44 +00:00
(*callback)(isolate_group->embedder_data(), peer);
if (handle->auto_delete()) {
state->FreeWeakPersistentHandle(handle);
}
}
// --- Handles ---
DART_EXPORT bool Dart_IsError(Dart_Handle handle) {
Thread* thread = Thread::Current();
TransitionNativeToVM transition(thread);
return Api::IsError(handle);
}
DART_EXPORT void Dart_KillIsolate(Dart_Isolate handle) {
Isolate* isolate = reinterpret_cast<Isolate*>(handle);
CHECK_ISOLATE(isolate);
Isolate::KillIfExists(isolate, Isolate::kKillMsg);
}
DART_EXPORT bool Dart_IsApiError(Dart_Handle object) {
Thread* thread = Thread::Current();
TransitionNativeToVM transition(thread);
return Api::ClassId(object) == kApiErrorCid;
}
DART_EXPORT bool Dart_IsUnhandledExceptionError(Dart_Handle object) {
Thread* thread = Thread::Current();
TransitionNativeToVM transition(thread);
return Api::ClassId(object) == kUnhandledExceptionCid;
}
DART_EXPORT bool Dart_IsCompilationError(Dart_Handle object) {
if (::Dart_IsUnhandledExceptionError(object)) {
DARTSCOPE(Thread::Current());
const UnhandledException& error =
UnhandledException::Cast(Object::Handle(Z, Api::UnwrapHandle(object)));
const Instance& exc = Instance::Handle(Z, error.exception());
return IsCompiletimeErrorObject(Z, exc);
}
Thread* thread = Thread::Current();
TransitionNativeToVM transition(thread);
return Api::ClassId(object) == kLanguageErrorCid;
}
DART_EXPORT bool Dart_IsFatalError(Dart_Handle object) {
Thread* thread = Thread::Current();
TransitionNativeToVM transition(thread);
return Api::ClassId(object) == kUnwindErrorCid;
}
DART_EXPORT const char* Dart_GetError(Dart_Handle handle) {
DARTSCOPE(Thread::Current());
API_TIMELINE_DURATION(T);
const Object& obj = Object::Handle(Z, Api::UnwrapHandle(handle));
return GetErrorString(T, obj);
}
DART_EXPORT bool Dart_ErrorHasException(Dart_Handle handle) {
DARTSCOPE(Thread::Current());
const Object& obj = Object::Handle(Z, Api::UnwrapHandle(handle));
return obj.IsUnhandledException();
}
DART_EXPORT Dart_Handle Dart_ErrorGetException(Dart_Handle handle) {
DARTSCOPE(Thread::Current());
const Object& obj = Object::Handle(Z, Api::UnwrapHandle(handle));
if (obj.IsUnhandledException()) {
const UnhandledException& error = UnhandledException::Cast(obj);
return Api::NewHandle(T, error.exception());
} else if (obj.IsError()) {
return Api::NewError("This error is not an unhandled exception error.");
} else {
return Api::NewError("Can only get exceptions from error handles.");
}
}
DART_EXPORT Dart_Handle Dart_ErrorGetStackTrace(Dart_Handle handle) {
DARTSCOPE(Thread::Current());
const Object& obj = Object::Handle(Z, Api::UnwrapHandle(handle));
if (obj.IsUnhandledException()) {
const UnhandledException& error = UnhandledException::Cast(obj);
return Api::NewHandle(T, error.stacktrace());
} else if (obj.IsError()) {
return Api::NewError("This error is not an unhandled exception error.");
} else {
return Api::NewError("Can only get stacktraces from error handles.");
}
}
DART_EXPORT Dart_Handle Dart_NewApiError(const char* error) {
DARTSCOPE(Thread::Current());
CHECK_CALLBACK_STATE(T);
const String& message = String::Handle(Z, String::New(error));
return Api::NewHandle(T, ApiError::New(message));
}
DART_EXPORT Dart_Handle Dart_NewCompilationError(const char* error) {
DARTSCOPE(Thread::Current());
CHECK_CALLBACK_STATE(T);
const String& message = String::Handle(Z, String::New(error));
return Api::NewHandle(T, LanguageError::New(message));
}
DART_EXPORT Dart_Handle Dart_NewUnhandledExceptionError(Dart_Handle exception) {
DARTSCOPE(Thread::Current());
CHECK_CALLBACK_STATE(T);
Instance& obj = Instance::Handle(Z);
intptr_t class_id = Api::ClassId(exception);
if ((class_id == kApiErrorCid) || (class_id == kLanguageErrorCid)) {
const Object& excp = Object::Handle(Z, Api::UnwrapHandle(exception));
obj = String::New(GetErrorString(T, excp));
} else {
obj = Api::UnwrapInstanceHandle(Z, exception).ptr();
if (obj.IsNull()) {
RETURN_TYPE_ERROR(Z, exception, Instance);
}
}
const StackTrace& stacktrace = StackTrace::Handle(Z);
return Api::NewHandle(T, UnhandledException::New(obj, stacktrace));
}
DART_EXPORT void Dart_PropagateError(Dart_Handle handle) {
Thread* thread = Thread::Current();
CHECK_ISOLATE(thread->isolate());
TransitionNativeToVM transition(thread);
const Object& obj = Object::Handle(thread->zone(), Api::UnwrapHandle(handle));
if (!obj.IsError()) {
FATAL1(
"%s expects argument 'handle' to be an error handle. "
"Did you forget to check Dart_IsError first?",
CURRENT_FUNC);
}
if (thread->top_exit_frame_info() == 0) {
// There are no dart frames on the stack so it would be illegal to
// propagate an error here.
FATAL("No Dart frames on stack, cannot propagate error.");
}
// Unwind all the API scopes till the exit frame before propagating.
const Error* error;
{
// We need to preserve the error object across the destruction of zones
// when the ApiScopes are unwound. By using NoSafepointScope, we can ensure
// that GC won't touch the raw error object before creating a valid
// handle for it in the surviving zone.
NoSafepointScope no_safepoint;
ErrorPtr raw_error = Api::UnwrapErrorHandle(thread->zone(), handle).ptr();
thread->UnwindScopes(thread->top_exit_frame_info());
// Note that thread's zone is different here than at the beginning of this
// function.
error = &Error::Handle(thread->zone(), raw_error);
}
Exceptions::PropagateError(*error);
UNREACHABLE();
}
DART_EXPORT Dart_Handle Dart_ToString(Dart_Handle object) {
DARTSCOPE(Thread::Current());
const Object& obj = Object::Handle(Z, Api::UnwrapHandle(object));
if (obj.IsString()) {
return Api::NewHandle(T, obj.ptr());
} else if (obj.IsInstance()) {
CHECK_CALLBACK_STATE(T);
const Instance& receiver = Instance::Cast(obj);
return Api::NewHandle(T, DartLibraryCalls::ToString(receiver));
} else {
CHECK_CALLBACK_STATE(T);
// This is a VM internal object. Call the C++ method of printing.
return Api::NewHandle(T, String::New(obj.ToCString()));
}
}
DART_EXPORT bool Dart_IdentityEquals(Dart_Handle obj1, Dart_Handle obj2) {
DARTSCOPE(Thread::Current());
{
NoSafepointScope no_safepoint_scope;
if (Api::UnwrapHandle(obj1) == Api::UnwrapHandle(obj2)) {
return true;
}
}
const Object& object1 = Object::Handle(Z, Api::UnwrapHandle(obj1));
const Object& object2 = Object::Handle(Z, Api::UnwrapHandle(obj2));
if (object1.IsInstance() && object2.IsInstance()) {
return Instance::Cast(object1).IsIdenticalTo(Instance::Cast(object2));
}
return false;
}
DART_EXPORT Dart_Handle
Dart_HandleFromPersistent(Dart_PersistentHandle object) {
Thread* thread = Thread::Current();
Isolate* isolate = thread->isolate();
CHECK_ISOLATE(isolate);
ApiState* state = isolate->group()->api_state();
ASSERT(state != NULL);
TransitionNativeToVM transition(thread);
NoSafepointScope no_safepoint_scope;
PersistentHandle* ref = PersistentHandle::Cast(object);
return Api::NewHandle(thread, ref->ptr());
}
DART_EXPORT Dart_Handle
Dart_HandleFromWeakPersistent(Dart_WeakPersistentHandle object) {
Thread* thread = Thread::Current();
Isolate* isolate = thread->isolate();
CHECK_ISOLATE(isolate);
ApiState* state = isolate->group()->api_state();
ASSERT(state != NULL);
TransitionNativeToVM transition(thread);
NoSafepointScope no_safepoint_scope;
FinalizablePersistentHandle* weak_ref =
FinalizablePersistentHandle::Cast(object);
[vm] Native API: Make Dart_NewWeakPersistentHandle not auto delete Changes Dart_NewWeakPersistentHandle to no longer auto delete the weak persistent handle. Changes the signatures of WeakPersistentHandleFinalizers to no longer have access to the handle. Flutter PR: https://github.com/flutter/engine/pull/19843 g3 presubmit: cl/318028238 Issue: https://github.com/dart-lang/sdk/issues/42312 TEST=runtime/vm/dart_api_impl_test.cc Change-Id: I3f77db9954d9486759f903b78c03a494f73c68ba Cq-Include-Trybots:dart/try:vm-ffi-android-debug-arm-try,vm-ffi-android-debug-arm64-try,app-kernel-linux-debug-x64-try,vm-kernel-linux-debug-ia32-try,vm-kernel-win-debug-x64-try,vm-kernel-win-debug-ia32-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-asan-linux-release-x64-try,vm-kernel-msan-linux-release-x64-try,vm-kernel-precomp-msan-linux-release-x64-try,vm-kernel-linux-release-simarm-try,vm-kernel-linux-release-simarm64-try,vm-kernel-precomp-android-release-arm_x64-try,vm-kernel-precomp-obfuscate-linux-release-x64-try,dart-sdk-linux-try,analyzer-analysis-server-linux-try,analyzer-linux-release-try,front-end-linux-release-x64-try,vm-kernel-precomp-win-release-x64-try,vm-kernel-mac-debug-x64-try,vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-nnbd-linux-debug-x64-try,analyzer-nnbd-linux-release-try,front-end-nnbd-linux-release-x64-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/151525 Commit-Queue: Daco Harkes <dacoharkes@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com>
2020-11-03 10:27:44 +00:00
if (weak_ref->IsFinalizedNotFreed()) {
return Dart_Null();
}
return Api::NewHandle(thread, weak_ref->ptr());
}
static Dart_Handle HandleFromFinalizable(Dart_FinalizableHandle object) {
Thread* thread = Thread::Current();
Isolate* isolate = thread->isolate();
CHECK_ISOLATE(isolate);
ApiState* state = isolate->group()->api_state();
ASSERT(state != NULL);
TransitionNativeToVM transition(thread);
NoSafepointScope no_safepoint_scope;
FinalizablePersistentHandle* weak_ref =
FinalizablePersistentHandle::Cast(object);
return Api::NewHandle(thread, weak_ref->ptr());
}
DART_EXPORT Dart_PersistentHandle Dart_NewPersistentHandle(Dart_Handle object) {
DARTSCOPE(Thread::Current());
Isolate* I = T->isolate();
ApiState* state = I->group()->api_state();
ASSERT(state != NULL);
const Object& old_ref = Object::Handle(Z, Api::UnwrapHandle(object));
PersistentHandle* new_ref = state->AllocatePersistentHandle();
new_ref->set_ptr(old_ref);
return new_ref->apiHandle();
}
DART_EXPORT void Dart_SetPersistentHandle(Dart_PersistentHandle obj1,
Dart_Handle obj2) {
DARTSCOPE(Thread::Current());
Isolate* I = T->isolate();
ApiState* state = I->group()->api_state();
ASSERT(state != NULL);
ASSERT(state->IsValidPersistentHandle(obj1));
const Object& obj2_ref = Object::Handle(Z, Api::UnwrapHandle(obj2));
PersistentHandle* obj1_ref = PersistentHandle::Cast(obj1);
obj1_ref->set_ptr(obj2_ref);
}
static bool IsFfiCompound(Thread* T, const Object& obj) {
Rereland "[vm/ffi] Disallow `Pointer`s and structs in finalizers and expandos" `Dart_NewWeakPersistentHandle` and `Dart_NewFinalizableHandle` in `dart_api.h` do no longer accept `Pointer`s and subtypes of `Struct`s as values passed in to the `object` parameter. Expandos no longer accept `Pointer`s and subtypes of `Struct`s as values passed in to the `object` parameter. Cleans up unused object_store->ffi_struct_class. Reland 1: Allow importing `dart:ffi` from `dart:core` with `--enable-ffi=false`. Reland 2: Allow the new `_Compound` class to extend `NativeType`. (This got triggered in this CL on the build because of the import from `dart:core`.) Closes: https://github.com/dart-lang/sdk/issues/45071 Breaking change: https://github.com/dart-lang/sdk/issues/45072 TEST=vm/cc/DartAPI_FinalizableHandleErrors TEST=vm/cc/DartAPI_WeakPersistentHandleErrors TEST=tests/ffi(_2)/expando_test.dart Change-Id: I133278e16bd75cd2bb6234e7ddf042ffa0a54fd6 Cq-Include-Trybots: luci.dart.try:dart-sdk-linux-try,dart-sdk-mac-try,dart-sdk-win-try,vm-ffi-android-debug-arm-try,vm-ffi-android-debug-arm64-try,vm-kernel-asan-linux-release-x64-try,vm-kernel-mac-debug-x64-try,vm-kernel-linux-debug-ia32-try,vm-kernel-linux-debug-x64-try,vm-kernel-nnbd-linux-debug-x64-try,vm-kernel-nnbd-linux-debug-ia32-try,vm-kernel-nnbd-mac-release-x64-try,vm-kernel-nnbd-win-debug-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-debug-simarm_x64-try,vm-kernel-precomp-nnbd-linux-debug-x64-try,vm-kernel-precomp-win-release-x64-try,vm-kernel-reload-linux-debug-x64-try,vm-kernel-reload-rollback-linux-debug-x64-try,vm-kernel-win-debug-x64-try,vm-kernel-win-debug-ia32-try,vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-precomp-obfuscate-linux-release-x64-try,vm-kernel-msan-linux-release-x64-try,vm-kernel-precomp-msan-linux-release-x64-try,vm-kernel-precomp-android-release-arm_x64-try,analyzer-analysis-server-linux-try,vm-kernel-precomp-linux-debug-x64c-try,vm-kernel-linux-debug-x64c-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/195079 Reviewed-by: Martin Kustermann <kustermann@google.com> Commit-Queue: Daco Harkes <dacoharkes@google.com>
2021-04-14 12:07:18 +00:00
if (obj.IsNull()) {
return false;
}
// CFE guarantees we can only have direct subclasses of `Struct` and `Union`
Rereland "[vm/ffi] Disallow `Pointer`s and structs in finalizers and expandos" `Dart_NewWeakPersistentHandle` and `Dart_NewFinalizableHandle` in `dart_api.h` do no longer accept `Pointer`s and subtypes of `Struct`s as values passed in to the `object` parameter. Expandos no longer accept `Pointer`s and subtypes of `Struct`s as values passed in to the `object` parameter. Cleans up unused object_store->ffi_struct_class. Reland 1: Allow importing `dart:ffi` from `dart:core` with `--enable-ffi=false`. Reland 2: Allow the new `_Compound` class to extend `NativeType`. (This got triggered in this CL on the build because of the import from `dart:core`.) Closes: https://github.com/dart-lang/sdk/issues/45071 Breaking change: https://github.com/dart-lang/sdk/issues/45072 TEST=vm/cc/DartAPI_FinalizableHandleErrors TEST=vm/cc/DartAPI_WeakPersistentHandleErrors TEST=tests/ffi(_2)/expando_test.dart Change-Id: I133278e16bd75cd2bb6234e7ddf042ffa0a54fd6 Cq-Include-Trybots: luci.dart.try:dart-sdk-linux-try,dart-sdk-mac-try,dart-sdk-win-try,vm-ffi-android-debug-arm-try,vm-ffi-android-debug-arm64-try,vm-kernel-asan-linux-release-x64-try,vm-kernel-mac-debug-x64-try,vm-kernel-linux-debug-ia32-try,vm-kernel-linux-debug-x64-try,vm-kernel-nnbd-linux-debug-x64-try,vm-kernel-nnbd-linux-debug-ia32-try,vm-kernel-nnbd-mac-release-x64-try,vm-kernel-nnbd-win-debug-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-debug-simarm_x64-try,vm-kernel-precomp-nnbd-linux-debug-x64-try,vm-kernel-precomp-win-release-x64-try,vm-kernel-reload-linux-debug-x64-try,vm-kernel-reload-rollback-linux-debug-x64-try,vm-kernel-win-debug-x64-try,vm-kernel-win-debug-ia32-try,vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-precomp-obfuscate-linux-release-x64-try,vm-kernel-msan-linux-release-x64-try,vm-kernel-precomp-msan-linux-release-x64-try,vm-kernel-precomp-android-release-arm_x64-try,analyzer-analysis-server-linux-try,vm-kernel-precomp-linux-debug-x64c-try,vm-kernel-linux-debug-x64c-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/195079 Reviewed-by: Martin Kustermann <kustermann@google.com> Commit-Queue: Daco Harkes <dacoharkes@google.com>
2021-04-14 12:07:18 +00:00
// (no implementations or indirect subclasses are allowed).
const auto& klass = Class::Handle(Z, obj.clazz());
const auto& super_klass = Class::Handle(Z, klass.SuperClass());
if (super_klass.IsNull()) {
// This means klass is Object.
return false;
}
if (super_klass.Name() != Symbols::Struct().ptr() &&
super_klass.Name() != Symbols::Union().ptr()) {
Rereland "[vm/ffi] Disallow `Pointer`s and structs in finalizers and expandos" `Dart_NewWeakPersistentHandle` and `Dart_NewFinalizableHandle` in `dart_api.h` do no longer accept `Pointer`s and subtypes of `Struct`s as values passed in to the `object` parameter. Expandos no longer accept `Pointer`s and subtypes of `Struct`s as values passed in to the `object` parameter. Cleans up unused object_store->ffi_struct_class. Reland 1: Allow importing `dart:ffi` from `dart:core` with `--enable-ffi=false`. Reland 2: Allow the new `_Compound` class to extend `NativeType`. (This got triggered in this CL on the build because of the import from `dart:core`.) Closes: https://github.com/dart-lang/sdk/issues/45071 Breaking change: https://github.com/dart-lang/sdk/issues/45072 TEST=vm/cc/DartAPI_FinalizableHandleErrors TEST=vm/cc/DartAPI_WeakPersistentHandleErrors TEST=tests/ffi(_2)/expando_test.dart Change-Id: I133278e16bd75cd2bb6234e7ddf042ffa0a54fd6 Cq-Include-Trybots: luci.dart.try:dart-sdk-linux-try,dart-sdk-mac-try,dart-sdk-win-try,vm-ffi-android-debug-arm-try,vm-ffi-android-debug-arm64-try,vm-kernel-asan-linux-release-x64-try,vm-kernel-mac-debug-x64-try,vm-kernel-linux-debug-ia32-try,vm-kernel-linux-debug-x64-try,vm-kernel-nnbd-linux-debug-x64-try,vm-kernel-nnbd-linux-debug-ia32-try,vm-kernel-nnbd-mac-release-x64-try,vm-kernel-nnbd-win-debug-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-debug-simarm_x64-try,vm-kernel-precomp-nnbd-linux-debug-x64-try,vm-kernel-precomp-win-release-x64-try,vm-kernel-reload-linux-debug-x64-try,vm-kernel-reload-rollback-linux-debug-x64-try,vm-kernel-win-debug-x64-try,vm-kernel-win-debug-ia32-try,vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-precomp-obfuscate-linux-release-x64-try,vm-kernel-msan-linux-release-x64-try,vm-kernel-precomp-msan-linux-release-x64-try,vm-kernel-precomp-android-release-arm_x64-try,analyzer-analysis-server-linux-try,vm-kernel-precomp-linux-debug-x64c-try,vm-kernel-linux-debug-x64c-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/195079 Reviewed-by: Martin Kustermann <kustermann@google.com> Commit-Queue: Daco Harkes <dacoharkes@google.com>
2021-04-14 12:07:18 +00:00
return false;
}
const auto& library = Library::Handle(Z, super_klass.library());
return library.url() == Symbols::DartFfi().ptr();
}
static Dart_WeakPersistentHandle AllocateWeakPersistentHandle(
Thread* thread,
const Object& ref,
void* peer,
intptr_t external_allocation_size,
[vm] Native API: Make Dart_NewWeakPersistentHandle not auto delete Changes Dart_NewWeakPersistentHandle to no longer auto delete the weak persistent handle. Changes the signatures of WeakPersistentHandleFinalizers to no longer have access to the handle. Flutter PR: https://github.com/flutter/engine/pull/19843 g3 presubmit: cl/318028238 Issue: https://github.com/dart-lang/sdk/issues/42312 TEST=runtime/vm/dart_api_impl_test.cc Change-Id: I3f77db9954d9486759f903b78c03a494f73c68ba Cq-Include-Trybots:dart/try:vm-ffi-android-debug-arm-try,vm-ffi-android-debug-arm64-try,app-kernel-linux-debug-x64-try,vm-kernel-linux-debug-ia32-try,vm-kernel-win-debug-x64-try,vm-kernel-win-debug-ia32-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-asan-linux-release-x64-try,vm-kernel-msan-linux-release-x64-try,vm-kernel-precomp-msan-linux-release-x64-try,vm-kernel-linux-release-simarm-try,vm-kernel-linux-release-simarm64-try,vm-kernel-precomp-android-release-arm_x64-try,vm-kernel-precomp-obfuscate-linux-release-x64-try,dart-sdk-linux-try,analyzer-analysis-server-linux-try,analyzer-linux-release-try,front-end-linux-release-x64-try,vm-kernel-precomp-win-release-x64-try,vm-kernel-mac-debug-x64-try,vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-nnbd-linux-debug-x64-try,analyzer-nnbd-linux-release-try,front-end-nnbd-linux-release-x64-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/151525 Commit-Queue: Daco Harkes <dacoharkes@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com>
2020-11-03 10:27:44 +00:00
Dart_HandleFinalizer callback) {
if (!ref.ptr()->IsHeapObject()) {
return NULL;
}
Rereland "[vm/ffi] Disallow `Pointer`s and structs in finalizers and expandos" `Dart_NewWeakPersistentHandle` and `Dart_NewFinalizableHandle` in `dart_api.h` do no longer accept `Pointer`s and subtypes of `Struct`s as values passed in to the `object` parameter. Expandos no longer accept `Pointer`s and subtypes of `Struct`s as values passed in to the `object` parameter. Cleans up unused object_store->ffi_struct_class. Reland 1: Allow importing `dart:ffi` from `dart:core` with `--enable-ffi=false`. Reland 2: Allow the new `_Compound` class to extend `NativeType`. (This got triggered in this CL on the build because of the import from `dart:core`.) Closes: https://github.com/dart-lang/sdk/issues/45071 Breaking change: https://github.com/dart-lang/sdk/issues/45072 TEST=vm/cc/DartAPI_FinalizableHandleErrors TEST=vm/cc/DartAPI_WeakPersistentHandleErrors TEST=tests/ffi(_2)/expando_test.dart Change-Id: I133278e16bd75cd2bb6234e7ddf042ffa0a54fd6 Cq-Include-Trybots: luci.dart.try:dart-sdk-linux-try,dart-sdk-mac-try,dart-sdk-win-try,vm-ffi-android-debug-arm-try,vm-ffi-android-debug-arm64-try,vm-kernel-asan-linux-release-x64-try,vm-kernel-mac-debug-x64-try,vm-kernel-linux-debug-ia32-try,vm-kernel-linux-debug-x64-try,vm-kernel-nnbd-linux-debug-x64-try,vm-kernel-nnbd-linux-debug-ia32-try,vm-kernel-nnbd-mac-release-x64-try,vm-kernel-nnbd-win-debug-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-debug-simarm_x64-try,vm-kernel-precomp-nnbd-linux-debug-x64-try,vm-kernel-precomp-win-release-x64-try,vm-kernel-reload-linux-debug-x64-try,vm-kernel-reload-rollback-linux-debug-x64-try,vm-kernel-win-debug-x64-try,vm-kernel-win-debug-ia32-try,vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-precomp-obfuscate-linux-release-x64-try,vm-kernel-msan-linux-release-x64-try,vm-kernel-precomp-msan-linux-release-x64-try,vm-kernel-precomp-android-release-arm_x64-try,analyzer-analysis-server-linux-try,vm-kernel-precomp-linux-debug-x64c-try,vm-kernel-linux-debug-x64c-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/195079 Reviewed-by: Martin Kustermann <kustermann@google.com> Commit-Queue: Daco Harkes <dacoharkes@google.com>
2021-04-14 12:07:18 +00:00
if (ref.IsPointer()) {
return NULL;
}
if (IsFfiCompound(thread, ref)) {
Rereland "[vm/ffi] Disallow `Pointer`s and structs in finalizers and expandos" `Dart_NewWeakPersistentHandle` and `Dart_NewFinalizableHandle` in `dart_api.h` do no longer accept `Pointer`s and subtypes of `Struct`s as values passed in to the `object` parameter. Expandos no longer accept `Pointer`s and subtypes of `Struct`s as values passed in to the `object` parameter. Cleans up unused object_store->ffi_struct_class. Reland 1: Allow importing `dart:ffi` from `dart:core` with `--enable-ffi=false`. Reland 2: Allow the new `_Compound` class to extend `NativeType`. (This got triggered in this CL on the build because of the import from `dart:core`.) Closes: https://github.com/dart-lang/sdk/issues/45071 Breaking change: https://github.com/dart-lang/sdk/issues/45072 TEST=vm/cc/DartAPI_FinalizableHandleErrors TEST=vm/cc/DartAPI_WeakPersistentHandleErrors TEST=tests/ffi(_2)/expando_test.dart Change-Id: I133278e16bd75cd2bb6234e7ddf042ffa0a54fd6 Cq-Include-Trybots: luci.dart.try:dart-sdk-linux-try,dart-sdk-mac-try,dart-sdk-win-try,vm-ffi-android-debug-arm-try,vm-ffi-android-debug-arm64-try,vm-kernel-asan-linux-release-x64-try,vm-kernel-mac-debug-x64-try,vm-kernel-linux-debug-ia32-try,vm-kernel-linux-debug-x64-try,vm-kernel-nnbd-linux-debug-x64-try,vm-kernel-nnbd-linux-debug-ia32-try,vm-kernel-nnbd-mac-release-x64-try,vm-kernel-nnbd-win-debug-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-debug-simarm_x64-try,vm-kernel-precomp-nnbd-linux-debug-x64-try,vm-kernel-precomp-win-release-x64-try,vm-kernel-reload-linux-debug-x64-try,vm-kernel-reload-rollback-linux-debug-x64-try,vm-kernel-win-debug-x64-try,vm-kernel-win-debug-ia32-try,vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-precomp-obfuscate-linux-release-x64-try,vm-kernel-msan-linux-release-x64-try,vm-kernel-precomp-msan-linux-release-x64-try,vm-kernel-precomp-android-release-arm_x64-try,analyzer-analysis-server-linux-try,vm-kernel-precomp-linux-debug-x64c-try,vm-kernel-linux-debug-x64c-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/195079 Reviewed-by: Martin Kustermann <kustermann@google.com> Commit-Queue: Daco Harkes <dacoharkes@google.com>
2021-04-14 12:07:18 +00:00
return NULL;
}
FinalizablePersistentHandle* finalizable_ref =
FinalizablePersistentHandle::New(thread->isolate_group(), ref, peer,
callback, external_allocation_size,
[vm] Native API: Make Dart_NewWeakPersistentHandle not auto delete Changes Dart_NewWeakPersistentHandle to no longer auto delete the weak persistent handle. Changes the signatures of WeakPersistentHandleFinalizers to no longer have access to the handle. Flutter PR: https://github.com/flutter/engine/pull/19843 g3 presubmit: cl/318028238 Issue: https://github.com/dart-lang/sdk/issues/42312 TEST=runtime/vm/dart_api_impl_test.cc Change-Id: I3f77db9954d9486759f903b78c03a494f73c68ba Cq-Include-Trybots:dart/try:vm-ffi-android-debug-arm-try,vm-ffi-android-debug-arm64-try,app-kernel-linux-debug-x64-try,vm-kernel-linux-debug-ia32-try,vm-kernel-win-debug-x64-try,vm-kernel-win-debug-ia32-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-asan-linux-release-x64-try,vm-kernel-msan-linux-release-x64-try,vm-kernel-precomp-msan-linux-release-x64-try,vm-kernel-linux-release-simarm-try,vm-kernel-linux-release-simarm64-try,vm-kernel-precomp-android-release-arm_x64-try,vm-kernel-precomp-obfuscate-linux-release-x64-try,dart-sdk-linux-try,analyzer-analysis-server-linux-try,analyzer-linux-release-try,front-end-linux-release-x64-try,vm-kernel-precomp-win-release-x64-try,vm-kernel-mac-debug-x64-try,vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-nnbd-linux-debug-x64-try,analyzer-nnbd-linux-release-try,front-end-nnbd-linux-release-x64-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/151525 Commit-Queue: Daco Harkes <dacoharkes@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com>
2020-11-03 10:27:44 +00:00
/*auto_delete=*/false);
return finalizable_ref->ApiWeakPersistentHandle();
}
static Dart_WeakPersistentHandle AllocateWeakPersistentHandle(
Rereland "[vm/ffi] Disallow `Pointer`s and structs in finalizers and expandos" `Dart_NewWeakPersistentHandle` and `Dart_NewFinalizableHandle` in `dart_api.h` do no longer accept `Pointer`s and subtypes of `Struct`s as values passed in to the `object` parameter. Expandos no longer accept `Pointer`s and subtypes of `Struct`s as values passed in to the `object` parameter. Cleans up unused object_store->ffi_struct_class. Reland 1: Allow importing `dart:ffi` from `dart:core` with `--enable-ffi=false`. Reland 2: Allow the new `_Compound` class to extend `NativeType`. (This got triggered in this CL on the build because of the import from `dart:core`.) Closes: https://github.com/dart-lang/sdk/issues/45071 Breaking change: https://github.com/dart-lang/sdk/issues/45072 TEST=vm/cc/DartAPI_FinalizableHandleErrors TEST=vm/cc/DartAPI_WeakPersistentHandleErrors TEST=tests/ffi(_2)/expando_test.dart Change-Id: I133278e16bd75cd2bb6234e7ddf042ffa0a54fd6 Cq-Include-Trybots: luci.dart.try:dart-sdk-linux-try,dart-sdk-mac-try,dart-sdk-win-try,vm-ffi-android-debug-arm-try,vm-ffi-android-debug-arm64-try,vm-kernel-asan-linux-release-x64-try,vm-kernel-mac-debug-x64-try,vm-kernel-linux-debug-ia32-try,vm-kernel-linux-debug-x64-try,vm-kernel-nnbd-linux-debug-x64-try,vm-kernel-nnbd-linux-debug-ia32-try,vm-kernel-nnbd-mac-release-x64-try,vm-kernel-nnbd-win-debug-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-debug-simarm_x64-try,vm-kernel-precomp-nnbd-linux-debug-x64-try,vm-kernel-precomp-win-release-x64-try,vm-kernel-reload-linux-debug-x64-try,vm-kernel-reload-rollback-linux-debug-x64-try,vm-kernel-win-debug-x64-try,vm-kernel-win-debug-ia32-try,vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-precomp-obfuscate-linux-release-x64-try,vm-kernel-msan-linux-release-x64-try,vm-kernel-precomp-msan-linux-release-x64-try,vm-kernel-precomp-android-release-arm_x64-try,analyzer-analysis-server-linux-try,vm-kernel-precomp-linux-debug-x64c-try,vm-kernel-linux-debug-x64c-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/195079 Reviewed-by: Martin Kustermann <kustermann@google.com> Commit-Queue: Daco Harkes <dacoharkes@google.com>
2021-04-14 12:07:18 +00:00
Thread* T,
Dart_Handle object,
void* peer,
intptr_t external_allocation_size,
[vm] Native API: Make Dart_NewWeakPersistentHandle not auto delete Changes Dart_NewWeakPersistentHandle to no longer auto delete the weak persistent handle. Changes the signatures of WeakPersistentHandleFinalizers to no longer have access to the handle. Flutter PR: https://github.com/flutter/engine/pull/19843 g3 presubmit: cl/318028238 Issue: https://github.com/dart-lang/sdk/issues/42312 TEST=runtime/vm/dart_api_impl_test.cc Change-Id: I3f77db9954d9486759f903b78c03a494f73c68ba Cq-Include-Trybots:dart/try:vm-ffi-android-debug-arm-try,vm-ffi-android-debug-arm64-try,app-kernel-linux-debug-x64-try,vm-kernel-linux-debug-ia32-try,vm-kernel-win-debug-x64-try,vm-kernel-win-debug-ia32-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-asan-linux-release-x64-try,vm-kernel-msan-linux-release-x64-try,vm-kernel-precomp-msan-linux-release-x64-try,vm-kernel-linux-release-simarm-try,vm-kernel-linux-release-simarm64-try,vm-kernel-precomp-android-release-arm_x64-try,vm-kernel-precomp-obfuscate-linux-release-x64-try,dart-sdk-linux-try,analyzer-analysis-server-linux-try,analyzer-linux-release-try,front-end-linux-release-x64-try,vm-kernel-precomp-win-release-x64-try,vm-kernel-mac-debug-x64-try,vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-nnbd-linux-debug-x64-try,analyzer-nnbd-linux-release-try,front-end-nnbd-linux-release-x64-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/151525 Commit-Queue: Daco Harkes <dacoharkes@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com>
2020-11-03 10:27:44 +00:00
Dart_HandleFinalizer callback) {
Rereland "[vm/ffi] Disallow `Pointer`s and structs in finalizers and expandos" `Dart_NewWeakPersistentHandle` and `Dart_NewFinalizableHandle` in `dart_api.h` do no longer accept `Pointer`s and subtypes of `Struct`s as values passed in to the `object` parameter. Expandos no longer accept `Pointer`s and subtypes of `Struct`s as values passed in to the `object` parameter. Cleans up unused object_store->ffi_struct_class. Reland 1: Allow importing `dart:ffi` from `dart:core` with `--enable-ffi=false`. Reland 2: Allow the new `_Compound` class to extend `NativeType`. (This got triggered in this CL on the build because of the import from `dart:core`.) Closes: https://github.com/dart-lang/sdk/issues/45071 Breaking change: https://github.com/dart-lang/sdk/issues/45072 TEST=vm/cc/DartAPI_FinalizableHandleErrors TEST=vm/cc/DartAPI_WeakPersistentHandleErrors TEST=tests/ffi(_2)/expando_test.dart Change-Id: I133278e16bd75cd2bb6234e7ddf042ffa0a54fd6 Cq-Include-Trybots: luci.dart.try:dart-sdk-linux-try,dart-sdk-mac-try,dart-sdk-win-try,vm-ffi-android-debug-arm-try,vm-ffi-android-debug-arm64-try,vm-kernel-asan-linux-release-x64-try,vm-kernel-mac-debug-x64-try,vm-kernel-linux-debug-ia32-try,vm-kernel-linux-debug-x64-try,vm-kernel-nnbd-linux-debug-x64-try,vm-kernel-nnbd-linux-debug-ia32-try,vm-kernel-nnbd-mac-release-x64-try,vm-kernel-nnbd-win-debug-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-debug-simarm_x64-try,vm-kernel-precomp-nnbd-linux-debug-x64-try,vm-kernel-precomp-win-release-x64-try,vm-kernel-reload-linux-debug-x64-try,vm-kernel-reload-rollback-linux-debug-x64-try,vm-kernel-win-debug-x64-try,vm-kernel-win-debug-ia32-try,vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-precomp-obfuscate-linux-release-x64-try,vm-kernel-msan-linux-release-x64-try,vm-kernel-precomp-msan-linux-release-x64-try,vm-kernel-precomp-android-release-arm_x64-try,analyzer-analysis-server-linux-try,vm-kernel-precomp-linux-debug-x64c-try,vm-kernel-linux-debug-x64c-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/195079 Reviewed-by: Martin Kustermann <kustermann@google.com> Commit-Queue: Daco Harkes <dacoharkes@google.com>
2021-04-14 12:07:18 +00:00
const auto& ref = Object::Handle(Z, Api::UnwrapHandle(object));
return AllocateWeakPersistentHandle(T, ref, peer, external_allocation_size,
callback);
}
static Dart_FinalizableHandle AllocateFinalizableHandle(
Thread* thread,
const Object& ref,
void* peer,
intptr_t external_allocation_size,
Dart_HandleFinalizer callback) {
if (!ref.ptr()->IsHeapObject()) {
return NULL;
}
Rereland "[vm/ffi] Disallow `Pointer`s and structs in finalizers and expandos" `Dart_NewWeakPersistentHandle` and `Dart_NewFinalizableHandle` in `dart_api.h` do no longer accept `Pointer`s and subtypes of `Struct`s as values passed in to the `object` parameter. Expandos no longer accept `Pointer`s and subtypes of `Struct`s as values passed in to the `object` parameter. Cleans up unused object_store->ffi_struct_class. Reland 1: Allow importing `dart:ffi` from `dart:core` with `--enable-ffi=false`. Reland 2: Allow the new `_Compound` class to extend `NativeType`. (This got triggered in this CL on the build because of the import from `dart:core`.) Closes: https://github.com/dart-lang/sdk/issues/45071 Breaking change: https://github.com/dart-lang/sdk/issues/45072 TEST=vm/cc/DartAPI_FinalizableHandleErrors TEST=vm/cc/DartAPI_WeakPersistentHandleErrors TEST=tests/ffi(_2)/expando_test.dart Change-Id: I133278e16bd75cd2bb6234e7ddf042ffa0a54fd6 Cq-Include-Trybots: luci.dart.try:dart-sdk-linux-try,dart-sdk-mac-try,dart-sdk-win-try,vm-ffi-android-debug-arm-try,vm-ffi-android-debug-arm64-try,vm-kernel-asan-linux-release-x64-try,vm-kernel-mac-debug-x64-try,vm-kernel-linux-debug-ia32-try,vm-kernel-linux-debug-x64-try,vm-kernel-nnbd-linux-debug-x64-try,vm-kernel-nnbd-linux-debug-ia32-try,vm-kernel-nnbd-mac-release-x64-try,vm-kernel-nnbd-win-debug-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-debug-simarm_x64-try,vm-kernel-precomp-nnbd-linux-debug-x64-try,vm-kernel-precomp-win-release-x64-try,vm-kernel-reload-linux-debug-x64-try,vm-kernel-reload-rollback-linux-debug-x64-try,vm-kernel-win-debug-x64-try,vm-kernel-win-debug-ia32-try,vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-precomp-obfuscate-linux-release-x64-try,vm-kernel-msan-linux-release-x64-try,vm-kernel-precomp-msan-linux-release-x64-try,vm-kernel-precomp-android-release-arm_x64-try,analyzer-analysis-server-linux-try,vm-kernel-precomp-linux-debug-x64c-try,vm-kernel-linux-debug-x64c-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/195079 Reviewed-by: Martin Kustermann <kustermann@google.com> Commit-Queue: Daco Harkes <dacoharkes@google.com>
2021-04-14 12:07:18 +00:00
if (ref.IsPointer()) {
return NULL;
}
if (IsFfiCompound(thread, ref)) {
Rereland "[vm/ffi] Disallow `Pointer`s and structs in finalizers and expandos" `Dart_NewWeakPersistentHandle` and `Dart_NewFinalizableHandle` in `dart_api.h` do no longer accept `Pointer`s and subtypes of `Struct`s as values passed in to the `object` parameter. Expandos no longer accept `Pointer`s and subtypes of `Struct`s as values passed in to the `object` parameter. Cleans up unused object_store->ffi_struct_class. Reland 1: Allow importing `dart:ffi` from `dart:core` with `--enable-ffi=false`. Reland 2: Allow the new `_Compound` class to extend `NativeType`. (This got triggered in this CL on the build because of the import from `dart:core`.) Closes: https://github.com/dart-lang/sdk/issues/45071 Breaking change: https://github.com/dart-lang/sdk/issues/45072 TEST=vm/cc/DartAPI_FinalizableHandleErrors TEST=vm/cc/DartAPI_WeakPersistentHandleErrors TEST=tests/ffi(_2)/expando_test.dart Change-Id: I133278e16bd75cd2bb6234e7ddf042ffa0a54fd6 Cq-Include-Trybots: luci.dart.try:dart-sdk-linux-try,dart-sdk-mac-try,dart-sdk-win-try,vm-ffi-android-debug-arm-try,vm-ffi-android-debug-arm64-try,vm-kernel-asan-linux-release-x64-try,vm-kernel-mac-debug-x64-try,vm-kernel-linux-debug-ia32-try,vm-kernel-linux-debug-x64-try,vm-kernel-nnbd-linux-debug-x64-try,vm-kernel-nnbd-linux-debug-ia32-try,vm-kernel-nnbd-mac-release-x64-try,vm-kernel-nnbd-win-debug-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-debug-simarm_x64-try,vm-kernel-precomp-nnbd-linux-debug-x64-try,vm-kernel-precomp-win-release-x64-try,vm-kernel-reload-linux-debug-x64-try,vm-kernel-reload-rollback-linux-debug-x64-try,vm-kernel-win-debug-x64-try,vm-kernel-win-debug-ia32-try,vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-precomp-obfuscate-linux-release-x64-try,vm-kernel-msan-linux-release-x64-try,vm-kernel-precomp-msan-linux-release-x64-try,vm-kernel-precomp-android-release-arm_x64-try,analyzer-analysis-server-linux-try,vm-kernel-precomp-linux-debug-x64c-try,vm-kernel-linux-debug-x64c-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/195079 Reviewed-by: Martin Kustermann <kustermann@google.com> Commit-Queue: Daco Harkes <dacoharkes@google.com>
2021-04-14 12:07:18 +00:00
return NULL;
}
FinalizablePersistentHandle* finalizable_ref =
FinalizablePersistentHandle::New(thread->isolate_group(), ref, peer,
callback, external_allocation_size,
/*auto_delete=*/true);
return finalizable_ref->ApiFinalizableHandle();
}
static Dart_FinalizableHandle AllocateFinalizableHandle(
Rereland "[vm/ffi] Disallow `Pointer`s and structs in finalizers and expandos" `Dart_NewWeakPersistentHandle` and `Dart_NewFinalizableHandle` in `dart_api.h` do no longer accept `Pointer`s and subtypes of `Struct`s as values passed in to the `object` parameter. Expandos no longer accept `Pointer`s and subtypes of `Struct`s as values passed in to the `object` parameter. Cleans up unused object_store->ffi_struct_class. Reland 1: Allow importing `dart:ffi` from `dart:core` with `--enable-ffi=false`. Reland 2: Allow the new `_Compound` class to extend `NativeType`. (This got triggered in this CL on the build because of the import from `dart:core`.) Closes: https://github.com/dart-lang/sdk/issues/45071 Breaking change: https://github.com/dart-lang/sdk/issues/45072 TEST=vm/cc/DartAPI_FinalizableHandleErrors TEST=vm/cc/DartAPI_WeakPersistentHandleErrors TEST=tests/ffi(_2)/expando_test.dart Change-Id: I133278e16bd75cd2bb6234e7ddf042ffa0a54fd6 Cq-Include-Trybots: luci.dart.try:dart-sdk-linux-try,dart-sdk-mac-try,dart-sdk-win-try,vm-ffi-android-debug-arm-try,vm-ffi-android-debug-arm64-try,vm-kernel-asan-linux-release-x64-try,vm-kernel-mac-debug-x64-try,vm-kernel-linux-debug-ia32-try,vm-kernel-linux-debug-x64-try,vm-kernel-nnbd-linux-debug-x64-try,vm-kernel-nnbd-linux-debug-ia32-try,vm-kernel-nnbd-mac-release-x64-try,vm-kernel-nnbd-win-debug-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-debug-simarm_x64-try,vm-kernel-precomp-nnbd-linux-debug-x64-try,vm-kernel-precomp-win-release-x64-try,vm-kernel-reload-linux-debug-x64-try,vm-kernel-reload-rollback-linux-debug-x64-try,vm-kernel-win-debug-x64-try,vm-kernel-win-debug-ia32-try,vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-precomp-obfuscate-linux-release-x64-try,vm-kernel-msan-linux-release-x64-try,vm-kernel-precomp-msan-linux-release-x64-try,vm-kernel-precomp-android-release-arm_x64-try,analyzer-analysis-server-linux-try,vm-kernel-precomp-linux-debug-x64c-try,vm-kernel-linux-debug-x64c-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/195079 Reviewed-by: Martin Kustermann <kustermann@google.com> Commit-Queue: Daco Harkes <dacoharkes@google.com>
2021-04-14 12:07:18 +00:00
Thread* T,
Dart_Handle object,
void* peer,
intptr_t external_allocation_size,
Dart_HandleFinalizer callback) {
Rereland "[vm/ffi] Disallow `Pointer`s and structs in finalizers and expandos" `Dart_NewWeakPersistentHandle` and `Dart_NewFinalizableHandle` in `dart_api.h` do no longer accept `Pointer`s and subtypes of `Struct`s as values passed in to the `object` parameter. Expandos no longer accept `Pointer`s and subtypes of `Struct`s as values passed in to the `object` parameter. Cleans up unused object_store->ffi_struct_class. Reland 1: Allow importing `dart:ffi` from `dart:core` with `--enable-ffi=false`. Reland 2: Allow the new `_Compound` class to extend `NativeType`. (This got triggered in this CL on the build because of the import from `dart:core`.) Closes: https://github.com/dart-lang/sdk/issues/45071 Breaking change: https://github.com/dart-lang/sdk/issues/45072 TEST=vm/cc/DartAPI_FinalizableHandleErrors TEST=vm/cc/DartAPI_WeakPersistentHandleErrors TEST=tests/ffi(_2)/expando_test.dart Change-Id: I133278e16bd75cd2bb6234e7ddf042ffa0a54fd6 Cq-Include-Trybots: luci.dart.try:dart-sdk-linux-try,dart-sdk-mac-try,dart-sdk-win-try,vm-ffi-android-debug-arm-try,vm-ffi-android-debug-arm64-try,vm-kernel-asan-linux-release-x64-try,vm-kernel-mac-debug-x64-try,vm-kernel-linux-debug-ia32-try,vm-kernel-linux-debug-x64-try,vm-kernel-nnbd-linux-debug-x64-try,vm-kernel-nnbd-linux-debug-ia32-try,vm-kernel-nnbd-mac-release-x64-try,vm-kernel-nnbd-win-debug-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-debug-simarm_x64-try,vm-kernel-precomp-nnbd-linux-debug-x64-try,vm-kernel-precomp-win-release-x64-try,vm-kernel-reload-linux-debug-x64-try,vm-kernel-reload-rollback-linux-debug-x64-try,vm-kernel-win-debug-x64-try,vm-kernel-win-debug-ia32-try,vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-precomp-obfuscate-linux-release-x64-try,vm-kernel-msan-linux-release-x64-try,vm-kernel-precomp-msan-linux-release-x64-try,vm-kernel-precomp-android-release-arm_x64-try,analyzer-analysis-server-linux-try,vm-kernel-precomp-linux-debug-x64c-try,vm-kernel-linux-debug-x64c-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/195079 Reviewed-by: Martin Kustermann <kustermann@google.com> Commit-Queue: Daco Harkes <dacoharkes@google.com>
2021-04-14 12:07:18 +00:00
const auto& ref = Object::Handle(Z, Api::UnwrapHandle(object));
return AllocateFinalizableHandle(T, ref, peer, external_allocation_size,
callback);
}
DART_EXPORT Dart_WeakPersistentHandle
Dart_NewWeakPersistentHandle(Dart_Handle object,
void* peer,
intptr_t external_allocation_size,
[vm] Native API: Make Dart_NewWeakPersistentHandle not auto delete Changes Dart_NewWeakPersistentHandle to no longer auto delete the weak persistent handle. Changes the signatures of WeakPersistentHandleFinalizers to no longer have access to the handle. Flutter PR: https://github.com/flutter/engine/pull/19843 g3 presubmit: cl/318028238 Issue: https://github.com/dart-lang/sdk/issues/42312 TEST=runtime/vm/dart_api_impl_test.cc Change-Id: I3f77db9954d9486759f903b78c03a494f73c68ba Cq-Include-Trybots:dart/try:vm-ffi-android-debug-arm-try,vm-ffi-android-debug-arm64-try,app-kernel-linux-debug-x64-try,vm-kernel-linux-debug-ia32-try,vm-kernel-win-debug-x64-try,vm-kernel-win-debug-ia32-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-asan-linux-release-x64-try,vm-kernel-msan-linux-release-x64-try,vm-kernel-precomp-msan-linux-release-x64-try,vm-kernel-linux-release-simarm-try,vm-kernel-linux-release-simarm64-try,vm-kernel-precomp-android-release-arm_x64-try,vm-kernel-precomp-obfuscate-linux-release-x64-try,dart-sdk-linux-try,analyzer-analysis-server-linux-try,analyzer-linux-release-try,front-end-linux-release-x64-try,vm-kernel-precomp-win-release-x64-try,vm-kernel-mac-debug-x64-try,vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-nnbd-linux-debug-x64-try,analyzer-nnbd-linux-release-try,front-end-nnbd-linux-release-x64-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/151525 Commit-Queue: Daco Harkes <dacoharkes@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com>
2020-11-03 10:27:44 +00:00
Dart_HandleFinalizer callback) {
Rereland "[vm/ffi] Disallow `Pointer`s and structs in finalizers and expandos" `Dart_NewWeakPersistentHandle` and `Dart_NewFinalizableHandle` in `dart_api.h` do no longer accept `Pointer`s and subtypes of `Struct`s as values passed in to the `object` parameter. Expandos no longer accept `Pointer`s and subtypes of `Struct`s as values passed in to the `object` parameter. Cleans up unused object_store->ffi_struct_class. Reland 1: Allow importing `dart:ffi` from `dart:core` with `--enable-ffi=false`. Reland 2: Allow the new `_Compound` class to extend `NativeType`. (This got triggered in this CL on the build because of the import from `dart:core`.) Closes: https://github.com/dart-lang/sdk/issues/45071 Breaking change: https://github.com/dart-lang/sdk/issues/45072 TEST=vm/cc/DartAPI_FinalizableHandleErrors TEST=vm/cc/DartAPI_WeakPersistentHandleErrors TEST=tests/ffi(_2)/expando_test.dart Change-Id: I133278e16bd75cd2bb6234e7ddf042ffa0a54fd6 Cq-Include-Trybots: luci.dart.try:dart-sdk-linux-try,dart-sdk-mac-try,dart-sdk-win-try,vm-ffi-android-debug-arm-try,vm-ffi-android-debug-arm64-try,vm-kernel-asan-linux-release-x64-try,vm-kernel-mac-debug-x64-try,vm-kernel-linux-debug-ia32-try,vm-kernel-linux-debug-x64-try,vm-kernel-nnbd-linux-debug-x64-try,vm-kernel-nnbd-linux-debug-ia32-try,vm-kernel-nnbd-mac-release-x64-try,vm-kernel-nnbd-win-debug-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-debug-simarm_x64-try,vm-kernel-precomp-nnbd-linux-debug-x64-try,vm-kernel-precomp-win-release-x64-try,vm-kernel-reload-linux-debug-x64-try,vm-kernel-reload-rollback-linux-debug-x64-try,vm-kernel-win-debug-x64-try,vm-kernel-win-debug-ia32-try,vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-precomp-obfuscate-linux-release-x64-try,vm-kernel-msan-linux-release-x64-try,vm-kernel-precomp-msan-linux-release-x64-try,vm-kernel-precomp-android-release-arm_x64-try,analyzer-analysis-server-linux-try,vm-kernel-precomp-linux-debug-x64c-try,vm-kernel-linux-debug-x64c-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/195079 Reviewed-by: Martin Kustermann <kustermann@google.com> Commit-Queue: Daco Harkes <dacoharkes@google.com>
2021-04-14 12:07:18 +00:00
DARTSCOPE(Thread::Current());
if (callback == NULL) {
return NULL;
}
Rereland "[vm/ffi] Disallow `Pointer`s and structs in finalizers and expandos" `Dart_NewWeakPersistentHandle` and `Dart_NewFinalizableHandle` in `dart_api.h` do no longer accept `Pointer`s and subtypes of `Struct`s as values passed in to the `object` parameter. Expandos no longer accept `Pointer`s and subtypes of `Struct`s as values passed in to the `object` parameter. Cleans up unused object_store->ffi_struct_class. Reland 1: Allow importing `dart:ffi` from `dart:core` with `--enable-ffi=false`. Reland 2: Allow the new `_Compound` class to extend `NativeType`. (This got triggered in this CL on the build because of the import from `dart:core`.) Closes: https://github.com/dart-lang/sdk/issues/45071 Breaking change: https://github.com/dart-lang/sdk/issues/45072 TEST=vm/cc/DartAPI_FinalizableHandleErrors TEST=vm/cc/DartAPI_WeakPersistentHandleErrors TEST=tests/ffi(_2)/expando_test.dart Change-Id: I133278e16bd75cd2bb6234e7ddf042ffa0a54fd6 Cq-Include-Trybots: luci.dart.try:dart-sdk-linux-try,dart-sdk-mac-try,dart-sdk-win-try,vm-ffi-android-debug-arm-try,vm-ffi-android-debug-arm64-try,vm-kernel-asan-linux-release-x64-try,vm-kernel-mac-debug-x64-try,vm-kernel-linux-debug-ia32-try,vm-kernel-linux-debug-x64-try,vm-kernel-nnbd-linux-debug-x64-try,vm-kernel-nnbd-linux-debug-ia32-try,vm-kernel-nnbd-mac-release-x64-try,vm-kernel-nnbd-win-debug-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-debug-simarm_x64-try,vm-kernel-precomp-nnbd-linux-debug-x64-try,vm-kernel-precomp-win-release-x64-try,vm-kernel-reload-linux-debug-x64-try,vm-kernel-reload-rollback-linux-debug-x64-try,vm-kernel-win-debug-x64-try,vm-kernel-win-debug-ia32-try,vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-precomp-obfuscate-linux-release-x64-try,vm-kernel-msan-linux-release-x64-try,vm-kernel-precomp-msan-linux-release-x64-try,vm-kernel-precomp-android-release-arm_x64-try,analyzer-analysis-server-linux-try,vm-kernel-precomp-linux-debug-x64c-try,vm-kernel-linux-debug-x64c-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/195079 Reviewed-by: Martin Kustermann <kustermann@google.com> Commit-Queue: Daco Harkes <dacoharkes@google.com>
2021-04-14 12:07:18 +00:00
return AllocateWeakPersistentHandle(T, object, peer, external_allocation_size,
callback);
}
DART_EXPORT Dart_FinalizableHandle
Dart_NewFinalizableHandle(Dart_Handle object,
void* peer,
intptr_t external_allocation_size,
Dart_HandleFinalizer callback) {
Rereland "[vm/ffi] Disallow `Pointer`s and structs in finalizers and expandos" `Dart_NewWeakPersistentHandle` and `Dart_NewFinalizableHandle` in `dart_api.h` do no longer accept `Pointer`s and subtypes of `Struct`s as values passed in to the `object` parameter. Expandos no longer accept `Pointer`s and subtypes of `Struct`s as values passed in to the `object` parameter. Cleans up unused object_store->ffi_struct_class. Reland 1: Allow importing `dart:ffi` from `dart:core` with `--enable-ffi=false`. Reland 2: Allow the new `_Compound` class to extend `NativeType`. (This got triggered in this CL on the build because of the import from `dart:core`.) Closes: https://github.com/dart-lang/sdk/issues/45071 Breaking change: https://github.com/dart-lang/sdk/issues/45072 TEST=vm/cc/DartAPI_FinalizableHandleErrors TEST=vm/cc/DartAPI_WeakPersistentHandleErrors TEST=tests/ffi(_2)/expando_test.dart Change-Id: I133278e16bd75cd2bb6234e7ddf042ffa0a54fd6 Cq-Include-Trybots: luci.dart.try:dart-sdk-linux-try,dart-sdk-mac-try,dart-sdk-win-try,vm-ffi-android-debug-arm-try,vm-ffi-android-debug-arm64-try,vm-kernel-asan-linux-release-x64-try,vm-kernel-mac-debug-x64-try,vm-kernel-linux-debug-ia32-try,vm-kernel-linux-debug-x64-try,vm-kernel-nnbd-linux-debug-x64-try,vm-kernel-nnbd-linux-debug-ia32-try,vm-kernel-nnbd-mac-release-x64-try,vm-kernel-nnbd-win-debug-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-debug-simarm_x64-try,vm-kernel-precomp-nnbd-linux-debug-x64-try,vm-kernel-precomp-win-release-x64-try,vm-kernel-reload-linux-debug-x64-try,vm-kernel-reload-rollback-linux-debug-x64-try,vm-kernel-win-debug-x64-try,vm-kernel-win-debug-ia32-try,vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-precomp-obfuscate-linux-release-x64-try,vm-kernel-msan-linux-release-x64-try,vm-kernel-precomp-msan-linux-release-x64-try,vm-kernel-precomp-android-release-arm_x64-try,analyzer-analysis-server-linux-try,vm-kernel-precomp-linux-debug-x64c-try,vm-kernel-linux-debug-x64c-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/195079 Reviewed-by: Martin Kustermann <kustermann@google.com> Commit-Queue: Daco Harkes <dacoharkes@google.com>
2021-04-14 12:07:18 +00:00
DARTSCOPE(Thread::Current());
if (callback == nullptr) {
return nullptr;
}
Rereland "[vm/ffi] Disallow `Pointer`s and structs in finalizers and expandos" `Dart_NewWeakPersistentHandle` and `Dart_NewFinalizableHandle` in `dart_api.h` do no longer accept `Pointer`s and subtypes of `Struct`s as values passed in to the `object` parameter. Expandos no longer accept `Pointer`s and subtypes of `Struct`s as values passed in to the `object` parameter. Cleans up unused object_store->ffi_struct_class. Reland 1: Allow importing `dart:ffi` from `dart:core` with `--enable-ffi=false`. Reland 2: Allow the new `_Compound` class to extend `NativeType`. (This got triggered in this CL on the build because of the import from `dart:core`.) Closes: https://github.com/dart-lang/sdk/issues/45071 Breaking change: https://github.com/dart-lang/sdk/issues/45072 TEST=vm/cc/DartAPI_FinalizableHandleErrors TEST=vm/cc/DartAPI_WeakPersistentHandleErrors TEST=tests/ffi(_2)/expando_test.dart Change-Id: I133278e16bd75cd2bb6234e7ddf042ffa0a54fd6 Cq-Include-Trybots: luci.dart.try:dart-sdk-linux-try,dart-sdk-mac-try,dart-sdk-win-try,vm-ffi-android-debug-arm-try,vm-ffi-android-debug-arm64-try,vm-kernel-asan-linux-release-x64-try,vm-kernel-mac-debug-x64-try,vm-kernel-linux-debug-ia32-try,vm-kernel-linux-debug-x64-try,vm-kernel-nnbd-linux-debug-x64-try,vm-kernel-nnbd-linux-debug-ia32-try,vm-kernel-nnbd-mac-release-x64-try,vm-kernel-nnbd-win-debug-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-debug-simarm_x64-try,vm-kernel-precomp-nnbd-linux-debug-x64-try,vm-kernel-precomp-win-release-x64-try,vm-kernel-reload-linux-debug-x64-try,vm-kernel-reload-rollback-linux-debug-x64-try,vm-kernel-win-debug-x64-try,vm-kernel-win-debug-ia32-try,vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-precomp-obfuscate-linux-release-x64-try,vm-kernel-msan-linux-release-x64-try,vm-kernel-precomp-msan-linux-release-x64-try,vm-kernel-precomp-android-release-arm_x64-try,analyzer-analysis-server-linux-try,vm-kernel-precomp-linux-debug-x64c-try,vm-kernel-linux-debug-x64c-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/195079 Reviewed-by: Martin Kustermann <kustermann@google.com> Commit-Queue: Daco Harkes <dacoharkes@google.com>
2021-04-14 12:07:18 +00:00
return AllocateFinalizableHandle(T, object, peer, external_allocation_size,
callback);
}
DART_EXPORT void Dart_UpdateExternalSize(Dart_WeakPersistentHandle object,
intptr_t external_size) {
Thread* T = Thread::Current();
IsolateGroup* isolate_group = T->isolate_group();
CHECK_ISOLATE_GROUP(isolate_group);
TransitionToVM transition(T);
ApiState* state = isolate_group->api_state();
ASSERT(state != NULL);
ASSERT(state->IsActiveWeakPersistentHandle(object));
auto weak_ref = FinalizablePersistentHandle::Cast(object);
weak_ref->UpdateExternalSize(external_size, isolate_group);
}
DART_EXPORT void Dart_UpdateFinalizableExternalSize(
Dart_FinalizableHandle object,
Dart_Handle strong_ref_to_object,
intptr_t external_allocation_size) {
if (!::Dart_IdentityEquals(strong_ref_to_object,
HandleFromFinalizable(object))) {
FATAL1(
"%s expects arguments 'object' and 'strong_ref_to_object' to point to "
"the same object.",
CURRENT_FUNC);
}
auto wph_object = reinterpret_cast<Dart_WeakPersistentHandle>(object);
::Dart_UpdateExternalSize(wph_object, external_allocation_size);
}
DART_EXPORT void Dart_DeletePersistentHandle(Dart_PersistentHandle object) {
Thread* T = Thread::Current();
IsolateGroup* isolate_group = T->isolate_group();
CHECK_ISOLATE_GROUP(isolate_group);
TransitionToVM transition(T);
ApiState* state = isolate_group->api_state();
ASSERT(state != NULL);
ASSERT(state->IsActivePersistentHandle(object));
ASSERT(!Api::IsProtectedHandle(object));
if (!Api::IsProtectedHandle(object)) {
PersistentHandle* ref = PersistentHandle::Cast(object);
state->FreePersistentHandle(ref);
}
}
DART_EXPORT void Dart_DeleteWeakPersistentHandle(
Dart_WeakPersistentHandle object) {
Thread* T = Thread::Current();
IsolateGroup* isolate_group = T->isolate_group();
CHECK_ISOLATE_GROUP(isolate_group);
TransitionToVM transition(T);
ApiState* state = isolate_group->api_state();
ASSERT(state != NULL);
ASSERT(state->IsActiveWeakPersistentHandle(object));
auto weak_ref = FinalizablePersistentHandle::Cast(object);
weak_ref->EnsureFreedExternal(isolate_group);
state->FreeWeakPersistentHandle(weak_ref);
}
DART_EXPORT void Dart_DeleteFinalizableHandle(
Dart_FinalizableHandle object,
Dart_Handle strong_ref_to_object) {
if (!::Dart_IdentityEquals(strong_ref_to_object,
HandleFromFinalizable(object))) {
FATAL1(
"%s expects arguments 'object' and 'strong_ref_to_object' to point to "
"the same object.",
CURRENT_FUNC);
}
auto wph_object = reinterpret_cast<Dart_WeakPersistentHandle>(object);
::Dart_DeleteWeakPersistentHandle(wph_object);
}
// --- Initialization and Globals ---
DART_EXPORT const char* Dart_VersionString() {
return Version::String();
}
DART_EXPORT char* Dart_Initialize(Dart_InitializeParams* params) {
if (params == NULL) {
return Utils::StrDup(
"Dart_Initialize: "
"Dart_InitializeParams is null.");
}
if (params->version != DART_INITIALIZE_PARAMS_CURRENT_VERSION) {
return Utils::StrDup(
"Dart_Initialize: "
"Invalid Dart_InitializeParams version.");
}
return Dart::Init(params);
}
DART_EXPORT char* Dart_Cleanup() {
CHECK_NO_ISOLATE(Isolate::Current());
return Dart::Cleanup();
}
DART_EXPORT char* Dart_SetVMFlags(int argc, const char** argv) {
return Flags::ProcessCommandLineFlags(argc, argv);
}
DART_EXPORT bool Dart_IsVMFlagSet(const char* flag_name) {
return Flags::IsSet(flag_name);
}
#if !defined(PRODUCT)
#define VM_METRIC_API(type, variable, name, unit) \
DART_EXPORT int64_t Dart_VM##variable##Metric() { \
return vm_metric_##variable.Value(); \
}
VM_METRIC_LIST(VM_METRIC_API);
#undef VM_METRIC_API
#else // !defined(PRODUCT)
#define VM_METRIC_API(type, variable, name, unit) \
DART_EXPORT int64_t Dart_VM##variable##Metric() { return -1; }
VM_METRIC_LIST(VM_METRIC_API)
#undef VM_METRIC_API
#endif // !defined(PRODUCT)
#define ISOLATE_GROUP_METRIC_API(type, variable, name, unit) \
DART_EXPORT int64_t Dart_IsolateGroup##variable##Metric( \
Dart_IsolateGroup isolate_group) { \
if (isolate_group == nullptr) { \
FATAL1("%s expects argument 'isolate_group' to be non-null.", \
CURRENT_FUNC); \
} \
IsolateGroup* group = reinterpret_cast<IsolateGroup*>(isolate_group); \
return group->Get##variable##Metric()->Value(); \
}
ISOLATE_GROUP_METRIC_LIST(ISOLATE_GROUP_METRIC_API)
#undef ISOLATE_GROUP_METRIC_API
#if !defined(PRODUCT)
#define ISOLATE_METRIC_API(type, variable, name, unit) \
DART_EXPORT int64_t Dart_Isolate##variable##Metric(Dart_Isolate isolate) { \
if (isolate == NULL) { \
FATAL1("%s expects argument 'isolate' to be non-null.", CURRENT_FUNC); \
} \
Isolate* iso = reinterpret_cast<Isolate*>(isolate); \
return iso->Get##variable##Metric()->Value(); \
}
ISOLATE_METRIC_LIST(ISOLATE_METRIC_API)
#undef ISOLATE_METRIC_API
#else // !defined(PRODUCT)
#define ISOLATE_METRIC_API(type, variable, name, unit) \
DART_EXPORT int64_t Dart_Isolate##variable##Metric(Dart_Isolate isolate) { \
return -1; \
}
ISOLATE_METRIC_LIST(ISOLATE_METRIC_API)
#undef ISOLATE_METRIC_API
#endif // !defined(PRODUCT)
// --- Isolates ---
static Dart_Isolate CreateIsolate(IsolateGroup* group,
bool is_new_group,
const char* name,
Second attempt to reland "[vm/concurrency] Introduce concept of Isolate Groups" This reverts commit 3d14b75f972ca287cd892ff907cf04b22839af59. An Isolate Group (IG) is a collection of isolates which were spawned from the same source. This allows the VM to: * have a guarantee that all isolates within one IG can safely exchange structured objects (currently we rely on embedder for this guarantee) * hot-reload all isolates together (currently we only reload one isolate, leaving same-source isolates in inconsistent state) * make a shared heap for all isolates from the same IG, which paves the way for faster communication and sharing of immutable objects. All isolates within one IG will share the same IsolateGroupSource. **Embedder changes** This change makes breaking embedder API changes to support this new concept of Isolate Groups: The existing isolate lifecycle callbacks given to Dart_Initialize will become Isolate Group lifecycle callbacks. A new callback `initialize_isolate` callback will be added which can initialize a new isolate within an existing IG. Existing embedders can be updated by performing the following renames Dart_CreateIsolate -> Dart_CreateIsolateGroup Dart_IsolateCreateCallback -> Dart_IsolateGroupCreateCallback Dart_IsolateCleanupCallback -> Dart_IsolateGroupShutdownCallback Dart_CreateIsolateFromKernel -> Dart_CreateIsolateGroupFromKernel Dart_CurrentIsolateData -> Dart_CurrentIsolateGroupData Dart_IsolateData -> Dart_IsolateGroupData Dart_GetNativeIsolateData -> Dart_GetNativeIsolateGroupData Dart_InitializeParams.create -> Dart_InitializeParams.create_group Dart_InitializeParams.cleanup -> Dart_InitializeParams.shutdown_group Dart_InitializeParams.shutdown -> Dart_InitializeParams.shutdown_isolate By default `Isolate.spawn` will cause the creation of a new IG. Though an embedder can opt-into supporting multiple isolates within one IG by providing a callback to the newly added `Dart_InitializeParams.initialize_isolate`. The responsibility of this new callback is to initialize an existing isolate (which was setup by re-using source code from the spawning isolate - i.e. the one which used `Isolate.spawn`) by setting native resolvers, initializing global state, etc. Issue https://github.com/dart-lang/sdk/issues/36648 Issue https://github.com/dart-lang/sdk/issues/36097 Original review: https://dart-review.googlesource.com/c/sdk/+/105241 Difference to original review: * Give each isolate it's own [Loader] (for now) * Sort classes during initialization for spawned isolates if app-jit is used (to match main isolate) * Fix IsolateData memory leak if isolate startup fails Difference to first reland(Patchset 2): * Fix typo where memory was freed twice. Change-Id: Ib1c83fe83b629cd50ae6af90ee99fdd44da882d4 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/108367 Commit-Queue: Alexander Aprelev <aam@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com>
2019-07-08 23:49:05 +00:00
void* isolate_data,
char** error) {
CHECK_NO_ISOLATE(Isolate::Current());
auto source = group->source();
Isolate* I = Dart::CreateIsolate(name, source->flags, group);
if (I == NULL) {
if (error != NULL) {
*error = Utils::StrDup("Isolate creation failed");
}
return reinterpret_cast<Dart_Isolate>(NULL);
}
Thread* T = Thread::Current();
bool success = false;
{
StackZone zone(T);
// We enter an API scope here as InitializeIsolate could compile some
// bootstrap library files which call out to a tag handler that may create
// Api Handles when an error is encountered.
T->EnterApiScope();
const Error& error_obj = Error::Handle(
Z, Dart::InitializeIsolate(
source->snapshot_data, source->snapshot_instructions,
source->kernel_buffer, source->kernel_buffer_size,
is_new_group ? nullptr : group, isolate_data));
if (error_obj.IsNull()) {
#if defined(DEBUG) && !defined(DART_PRECOMPILED_RUNTIME)
if (FLAG_check_function_fingerprints && !FLAG_precompiled_mode) {
Library::CheckFunctionFingerprints();
}
#endif // defined(DEBUG) && !defined(DART_PRECOMPILED_RUNTIME).
success = true;
} else if (error != NULL) {
*error = Utils::StrDup(error_obj.ToErrorCString());
}
// We exit the API scope entered above.
T->ExitApiScope();
}
if (success) {
// A Thread structure has been associated to the thread, we do the
// safepoint transition explicitly here instead of using the
// TransitionXXX scope objects as the reverse transition happens
// outside this scope in Dart_ShutdownIsolate/Dart_ExitIsolate.
T->set_execution_state(Thread::kThreadInNative);
T->EnterSafepoint();
if (error != NULL) {
*error = NULL;
}
return Api::CastIsolate(I);
}
Dart::ShutdownIsolate();
return reinterpret_cast<Dart_Isolate>(NULL);
}
static bool IsServiceOrKernelIsolateName(const char* name) {
if (ServiceIsolate::NameEquals(name)) {
ASSERT(!ServiceIsolate::Exists());
return true;
}
#if !defined(DART_PRECOMPILED_RUNTIME)
if (KernelIsolate::NameEquals(name)) {
ASSERT(!KernelIsolate::Exists());
return true;
}
#endif // !defined(DART_PRECOMPILED_RUNTIME)
return false;
}
Isolate* CreateWithinExistingIsolateGroup(IsolateGroup* group,
const char* name,
char** error) {
Second attempt to reland "[vm/concurrency] Introduce concept of Isolate Groups" This reverts commit 3d14b75f972ca287cd892ff907cf04b22839af59. An Isolate Group (IG) is a collection of isolates which were spawned from the same source. This allows the VM to: * have a guarantee that all isolates within one IG can safely exchange structured objects (currently we rely on embedder for this guarantee) * hot-reload all isolates together (currently we only reload one isolate, leaving same-source isolates in inconsistent state) * make a shared heap for all isolates from the same IG, which paves the way for faster communication and sharing of immutable objects. All isolates within one IG will share the same IsolateGroupSource. **Embedder changes** This change makes breaking embedder API changes to support this new concept of Isolate Groups: The existing isolate lifecycle callbacks given to Dart_Initialize will become Isolate Group lifecycle callbacks. A new callback `initialize_isolate` callback will be added which can initialize a new isolate within an existing IG. Existing embedders can be updated by performing the following renames Dart_CreateIsolate -> Dart_CreateIsolateGroup Dart_IsolateCreateCallback -> Dart_IsolateGroupCreateCallback Dart_IsolateCleanupCallback -> Dart_IsolateGroupShutdownCallback Dart_CreateIsolateFromKernel -> Dart_CreateIsolateGroupFromKernel Dart_CurrentIsolateData -> Dart_CurrentIsolateGroupData Dart_IsolateData -> Dart_IsolateGroupData Dart_GetNativeIsolateData -> Dart_GetNativeIsolateGroupData Dart_InitializeParams.create -> Dart_InitializeParams.create_group Dart_InitializeParams.cleanup -> Dart_InitializeParams.shutdown_group Dart_InitializeParams.shutdown -> Dart_InitializeParams.shutdown_isolate By default `Isolate.spawn` will cause the creation of a new IG. Though an embedder can opt-into supporting multiple isolates within one IG by providing a callback to the newly added `Dart_InitializeParams.initialize_isolate`. The responsibility of this new callback is to initialize an existing isolate (which was setup by re-using source code from the spawning isolate - i.e. the one which used `Isolate.spawn`) by setting native resolvers, initializing global state, etc. Issue https://github.com/dart-lang/sdk/issues/36648 Issue https://github.com/dart-lang/sdk/issues/36097 Original review: https://dart-review.googlesource.com/c/sdk/+/105241 Difference to original review: * Give each isolate it's own [Loader] (for now) * Sort classes during initialization for spawned isolates if app-jit is used (to match main isolate) * Fix IsolateData memory leak if isolate startup fails Difference to first reland(Patchset 2): * Fix typo where memory was freed twice. Change-Id: Ib1c83fe83b629cd50ae6af90ee99fdd44da882d4 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/108367 Commit-Queue: Alexander Aprelev <aam@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com>
2019-07-08 23:49:05 +00:00
API_TIMELINE_DURATION(Thread::Current());
CHECK_NO_ISOLATE(Isolate::Current());
auto spawning_group = group;
Second attempt to reland "[vm/concurrency] Introduce concept of Isolate Groups" This reverts commit 3d14b75f972ca287cd892ff907cf04b22839af59. An Isolate Group (IG) is a collection of isolates which were spawned from the same source. This allows the VM to: * have a guarantee that all isolates within one IG can safely exchange structured objects (currently we rely on embedder for this guarantee) * hot-reload all isolates together (currently we only reload one isolate, leaving same-source isolates in inconsistent state) * make a shared heap for all isolates from the same IG, which paves the way for faster communication and sharing of immutable objects. All isolates within one IG will share the same IsolateGroupSource. **Embedder changes** This change makes breaking embedder API changes to support this new concept of Isolate Groups: The existing isolate lifecycle callbacks given to Dart_Initialize will become Isolate Group lifecycle callbacks. A new callback `initialize_isolate` callback will be added which can initialize a new isolate within an existing IG. Existing embedders can be updated by performing the following renames Dart_CreateIsolate -> Dart_CreateIsolateGroup Dart_IsolateCreateCallback -> Dart_IsolateGroupCreateCallback Dart_IsolateCleanupCallback -> Dart_IsolateGroupShutdownCallback Dart_CreateIsolateFromKernel -> Dart_CreateIsolateGroupFromKernel Dart_CurrentIsolateData -> Dart_CurrentIsolateGroupData Dart_IsolateData -> Dart_IsolateGroupData Dart_GetNativeIsolateData -> Dart_GetNativeIsolateGroupData Dart_InitializeParams.create -> Dart_InitializeParams.create_group Dart_InitializeParams.cleanup -> Dart_InitializeParams.shutdown_group Dart_InitializeParams.shutdown -> Dart_InitializeParams.shutdown_isolate By default `Isolate.spawn` will cause the creation of a new IG. Though an embedder can opt-into supporting multiple isolates within one IG by providing a callback to the newly added `Dart_InitializeParams.initialize_isolate`. The responsibility of this new callback is to initialize an existing isolate (which was setup by re-using source code from the spawning isolate - i.e. the one which used `Isolate.spawn`) by setting native resolvers, initializing global state, etc. Issue https://github.com/dart-lang/sdk/issues/36648 Issue https://github.com/dart-lang/sdk/issues/36097 Original review: https://dart-review.googlesource.com/c/sdk/+/105241 Difference to original review: * Give each isolate it's own [Loader] (for now) * Sort classes during initialization for spawned isolates if app-jit is used (to match main isolate) * Fix IsolateData memory leak if isolate startup fails Difference to first reland(Patchset 2): * Fix typo where memory was freed twice. Change-Id: Ib1c83fe83b629cd50ae6af90ee99fdd44da882d4 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/108367 Commit-Queue: Alexander Aprelev <aam@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com>
2019-07-08 23:49:05 +00:00
Isolate* isolate = reinterpret_cast<Isolate*>(
CreateIsolate(spawning_group, /*is_new_group=*/false, name,
/*isolate_data=*/nullptr, error));
Second attempt to reland "[vm/concurrency] Introduce concept of Isolate Groups" This reverts commit 3d14b75f972ca287cd892ff907cf04b22839af59. An Isolate Group (IG) is a collection of isolates which were spawned from the same source. This allows the VM to: * have a guarantee that all isolates within one IG can safely exchange structured objects (currently we rely on embedder for this guarantee) * hot-reload all isolates together (currently we only reload one isolate, leaving same-source isolates in inconsistent state) * make a shared heap for all isolates from the same IG, which paves the way for faster communication and sharing of immutable objects. All isolates within one IG will share the same IsolateGroupSource. **Embedder changes** This change makes breaking embedder API changes to support this new concept of Isolate Groups: The existing isolate lifecycle callbacks given to Dart_Initialize will become Isolate Group lifecycle callbacks. A new callback `initialize_isolate` callback will be added which can initialize a new isolate within an existing IG. Existing embedders can be updated by performing the following renames Dart_CreateIsolate -> Dart_CreateIsolateGroup Dart_IsolateCreateCallback -> Dart_IsolateGroupCreateCallback Dart_IsolateCleanupCallback -> Dart_IsolateGroupShutdownCallback Dart_CreateIsolateFromKernel -> Dart_CreateIsolateGroupFromKernel Dart_CurrentIsolateData -> Dart_CurrentIsolateGroupData Dart_IsolateData -> Dart_IsolateGroupData Dart_GetNativeIsolateData -> Dart_GetNativeIsolateGroupData Dart_InitializeParams.create -> Dart_InitializeParams.create_group Dart_InitializeParams.cleanup -> Dart_InitializeParams.shutdown_group Dart_InitializeParams.shutdown -> Dart_InitializeParams.shutdown_isolate By default `Isolate.spawn` will cause the creation of a new IG. Though an embedder can opt-into supporting multiple isolates within one IG by providing a callback to the newly added `Dart_InitializeParams.initialize_isolate`. The responsibility of this new callback is to initialize an existing isolate (which was setup by re-using source code from the spawning isolate - i.e. the one which used `Isolate.spawn`) by setting native resolvers, initializing global state, etc. Issue https://github.com/dart-lang/sdk/issues/36648 Issue https://github.com/dart-lang/sdk/issues/36097 Original review: https://dart-review.googlesource.com/c/sdk/+/105241 Difference to original review: * Give each isolate it's own [Loader] (for now) * Sort classes during initialization for spawned isolates if app-jit is used (to match main isolate) * Fix IsolateData memory leak if isolate startup fails Difference to first reland(Patchset 2): * Fix typo where memory was freed twice. Change-Id: Ib1c83fe83b629cd50ae6af90ee99fdd44da882d4 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/108367 Commit-Queue: Alexander Aprelev <aam@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com>
2019-07-08 23:49:05 +00:00
if (isolate == nullptr) return nullptr;
auto source = spawning_group->source();
ASSERT(isolate->source() == source);
Second attempt to reland "[vm/concurrency] Introduce concept of Isolate Groups" This reverts commit 3d14b75f972ca287cd892ff907cf04b22839af59. An Isolate Group (IG) is a collection of isolates which were spawned from the same source. This allows the VM to: * have a guarantee that all isolates within one IG can safely exchange structured objects (currently we rely on embedder for this guarantee) * hot-reload all isolates together (currently we only reload one isolate, leaving same-source isolates in inconsistent state) * make a shared heap for all isolates from the same IG, which paves the way for faster communication and sharing of immutable objects. All isolates within one IG will share the same IsolateGroupSource. **Embedder changes** This change makes breaking embedder API changes to support this new concept of Isolate Groups: The existing isolate lifecycle callbacks given to Dart_Initialize will become Isolate Group lifecycle callbacks. A new callback `initialize_isolate` callback will be added which can initialize a new isolate within an existing IG. Existing embedders can be updated by performing the following renames Dart_CreateIsolate -> Dart_CreateIsolateGroup Dart_IsolateCreateCallback -> Dart_IsolateGroupCreateCallback Dart_IsolateCleanupCallback -> Dart_IsolateGroupShutdownCallback Dart_CreateIsolateFromKernel -> Dart_CreateIsolateGroupFromKernel Dart_CurrentIsolateData -> Dart_CurrentIsolateGroupData Dart_IsolateData -> Dart_IsolateGroupData Dart_GetNativeIsolateData -> Dart_GetNativeIsolateGroupData Dart_InitializeParams.create -> Dart_InitializeParams.create_group Dart_InitializeParams.cleanup -> Dart_InitializeParams.shutdown_group Dart_InitializeParams.shutdown -> Dart_InitializeParams.shutdown_isolate By default `Isolate.spawn` will cause the creation of a new IG. Though an embedder can opt-into supporting multiple isolates within one IG by providing a callback to the newly added `Dart_InitializeParams.initialize_isolate`. The responsibility of this new callback is to initialize an existing isolate (which was setup by re-using source code from the spawning isolate - i.e. the one which used `Isolate.spawn`) by setting native resolvers, initializing global state, etc. Issue https://github.com/dart-lang/sdk/issues/36648 Issue https://github.com/dart-lang/sdk/issues/36097 Original review: https://dart-review.googlesource.com/c/sdk/+/105241 Difference to original review: * Give each isolate it's own [Loader] (for now) * Sort classes during initialization for spawned isolates if app-jit is used (to match main isolate) * Fix IsolateData memory leak if isolate startup fails Difference to first reland(Patchset 2): * Fix typo where memory was freed twice. Change-Id: Ib1c83fe83b629cd50ae6af90ee99fdd44da882d4 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/108367 Commit-Queue: Alexander Aprelev <aam@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com>
2019-07-08 23:49:05 +00:00
return isolate;
}
DART_EXPORT void Dart_IsolateFlagsInitialize(Dart_IsolateFlags* flags) {
Isolate::FlagsInitialize(flags);
}
DART_EXPORT Dart_Isolate
Second attempt to reland "[vm/concurrency] Introduce concept of Isolate Groups" This reverts commit 3d14b75f972ca287cd892ff907cf04b22839af59. An Isolate Group (IG) is a collection of isolates which were spawned from the same source. This allows the VM to: * have a guarantee that all isolates within one IG can safely exchange structured objects (currently we rely on embedder for this guarantee) * hot-reload all isolates together (currently we only reload one isolate, leaving same-source isolates in inconsistent state) * make a shared heap for all isolates from the same IG, which paves the way for faster communication and sharing of immutable objects. All isolates within one IG will share the same IsolateGroupSource. **Embedder changes** This change makes breaking embedder API changes to support this new concept of Isolate Groups: The existing isolate lifecycle callbacks given to Dart_Initialize will become Isolate Group lifecycle callbacks. A new callback `initialize_isolate` callback will be added which can initialize a new isolate within an existing IG. Existing embedders can be updated by performing the following renames Dart_CreateIsolate -> Dart_CreateIsolateGroup Dart_IsolateCreateCallback -> Dart_IsolateGroupCreateCallback Dart_IsolateCleanupCallback -> Dart_IsolateGroupShutdownCallback Dart_CreateIsolateFromKernel -> Dart_CreateIsolateGroupFromKernel Dart_CurrentIsolateData -> Dart_CurrentIsolateGroupData Dart_IsolateData -> Dart_IsolateGroupData Dart_GetNativeIsolateData -> Dart_GetNativeIsolateGroupData Dart_InitializeParams.create -> Dart_InitializeParams.create_group Dart_InitializeParams.cleanup -> Dart_InitializeParams.shutdown_group Dart_InitializeParams.shutdown -> Dart_InitializeParams.shutdown_isolate By default `Isolate.spawn` will cause the creation of a new IG. Though an embedder can opt-into supporting multiple isolates within one IG by providing a callback to the newly added `Dart_InitializeParams.initialize_isolate`. The responsibility of this new callback is to initialize an existing isolate (which was setup by re-using source code from the spawning isolate - i.e. the one which used `Isolate.spawn`) by setting native resolvers, initializing global state, etc. Issue https://github.com/dart-lang/sdk/issues/36648 Issue https://github.com/dart-lang/sdk/issues/36097 Original review: https://dart-review.googlesource.com/c/sdk/+/105241 Difference to original review: * Give each isolate it's own [Loader] (for now) * Sort classes during initialization for spawned isolates if app-jit is used (to match main isolate) * Fix IsolateData memory leak if isolate startup fails Difference to first reland(Patchset 2): * Fix typo where memory was freed twice. Change-Id: Ib1c83fe83b629cd50ae6af90ee99fdd44da882d4 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/108367 Commit-Queue: Alexander Aprelev <aam@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com>
2019-07-08 23:49:05 +00:00
Dart_CreateIsolateGroup(const char* script_uri,
const char* name,
const uint8_t* snapshot_data,
const uint8_t* snapshot_instructions,
Dart_IsolateFlags* flags,
void* isolate_group_data,
void* isolate_data,
char** error) {
API_TIMELINE_DURATION(Thread::Current());
Second attempt to reland "[vm/concurrency] Introduce concept of Isolate Groups" This reverts commit 3d14b75f972ca287cd892ff907cf04b22839af59. An Isolate Group (IG) is a collection of isolates which were spawned from the same source. This allows the VM to: * have a guarantee that all isolates within one IG can safely exchange structured objects (currently we rely on embedder for this guarantee) * hot-reload all isolates together (currently we only reload one isolate, leaving same-source isolates in inconsistent state) * make a shared heap for all isolates from the same IG, which paves the way for faster communication and sharing of immutable objects. All isolates within one IG will share the same IsolateGroupSource. **Embedder changes** This change makes breaking embedder API changes to support this new concept of Isolate Groups: The existing isolate lifecycle callbacks given to Dart_Initialize will become Isolate Group lifecycle callbacks. A new callback `initialize_isolate` callback will be added which can initialize a new isolate within an existing IG. Existing embedders can be updated by performing the following renames Dart_CreateIsolate -> Dart_CreateIsolateGroup Dart_IsolateCreateCallback -> Dart_IsolateGroupCreateCallback Dart_IsolateCleanupCallback -> Dart_IsolateGroupShutdownCallback Dart_CreateIsolateFromKernel -> Dart_CreateIsolateGroupFromKernel Dart_CurrentIsolateData -> Dart_CurrentIsolateGroupData Dart_IsolateData -> Dart_IsolateGroupData Dart_GetNativeIsolateData -> Dart_GetNativeIsolateGroupData Dart_InitializeParams.create -> Dart_InitializeParams.create_group Dart_InitializeParams.cleanup -> Dart_InitializeParams.shutdown_group Dart_InitializeParams.shutdown -> Dart_InitializeParams.shutdown_isolate By default `Isolate.spawn` will cause the creation of a new IG. Though an embedder can opt-into supporting multiple isolates within one IG by providing a callback to the newly added `Dart_InitializeParams.initialize_isolate`. The responsibility of this new callback is to initialize an existing isolate (which was setup by re-using source code from the spawning isolate - i.e. the one which used `Isolate.spawn`) by setting native resolvers, initializing global state, etc. Issue https://github.com/dart-lang/sdk/issues/36648 Issue https://github.com/dart-lang/sdk/issues/36097 Original review: https://dart-review.googlesource.com/c/sdk/+/105241 Difference to original review: * Give each isolate it's own [Loader] (for now) * Sort classes during initialization for spawned isolates if app-jit is used (to match main isolate) * Fix IsolateData memory leak if isolate startup fails Difference to first reland(Patchset 2): * Fix typo where memory was freed twice. Change-Id: Ib1c83fe83b629cd50ae6af90ee99fdd44da882d4 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/108367 Commit-Queue: Alexander Aprelev <aam@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com>
2019-07-08 23:49:05 +00:00
Dart_IsolateFlags api_flags;
if (flags == nullptr) {
Isolate::FlagsInitialize(&api_flags);
flags = &api_flags;
}
const char* non_null_name = name == nullptr ? "isolate" : name;
std::unique_ptr<IsolateGroupSource> source(
new IsolateGroupSource(script_uri, non_null_name, snapshot_data,
snapshot_instructions, nullptr, -1, *flags));
auto group = new IsolateGroup(std::move(source), isolate_group_data, *flags);
group->CreateHeap(
/*is_vm_isolate=*/false, IsServiceOrKernelIsolateName(non_null_name));
IsolateGroup::RegisterIsolateGroup(group);
Dart_Isolate isolate = CreateIsolate(group, /*is_new_group=*/true,
non_null_name, isolate_data, error);
if (isolate != nullptr) {
group->set_initial_spawn_successful();
Second attempt to reland "[vm/concurrency] Introduce concept of Isolate Groups" This reverts commit 3d14b75f972ca287cd892ff907cf04b22839af59. An Isolate Group (IG) is a collection of isolates which were spawned from the same source. This allows the VM to: * have a guarantee that all isolates within one IG can safely exchange structured objects (currently we rely on embedder for this guarantee) * hot-reload all isolates together (currently we only reload one isolate, leaving same-source isolates in inconsistent state) * make a shared heap for all isolates from the same IG, which paves the way for faster communication and sharing of immutable objects. All isolates within one IG will share the same IsolateGroupSource. **Embedder changes** This change makes breaking embedder API changes to support this new concept of Isolate Groups: The existing isolate lifecycle callbacks given to Dart_Initialize will become Isolate Group lifecycle callbacks. A new callback `initialize_isolate` callback will be added which can initialize a new isolate within an existing IG. Existing embedders can be updated by performing the following renames Dart_CreateIsolate -> Dart_CreateIsolateGroup Dart_IsolateCreateCallback -> Dart_IsolateGroupCreateCallback Dart_IsolateCleanupCallback -> Dart_IsolateGroupShutdownCallback Dart_CreateIsolateFromKernel -> Dart_CreateIsolateGroupFromKernel Dart_CurrentIsolateData -> Dart_CurrentIsolateGroupData Dart_IsolateData -> Dart_IsolateGroupData Dart_GetNativeIsolateData -> Dart_GetNativeIsolateGroupData Dart_InitializeParams.create -> Dart_InitializeParams.create_group Dart_InitializeParams.cleanup -> Dart_InitializeParams.shutdown_group Dart_InitializeParams.shutdown -> Dart_InitializeParams.shutdown_isolate By default `Isolate.spawn` will cause the creation of a new IG. Though an embedder can opt-into supporting multiple isolates within one IG by providing a callback to the newly added `Dart_InitializeParams.initialize_isolate`. The responsibility of this new callback is to initialize an existing isolate (which was setup by re-using source code from the spawning isolate - i.e. the one which used `Isolate.spawn`) by setting native resolvers, initializing global state, etc. Issue https://github.com/dart-lang/sdk/issues/36648 Issue https://github.com/dart-lang/sdk/issues/36097 Original review: https://dart-review.googlesource.com/c/sdk/+/105241 Difference to original review: * Give each isolate it's own [Loader] (for now) * Sort classes during initialization for spawned isolates if app-jit is used (to match main isolate) * Fix IsolateData memory leak if isolate startup fails Difference to first reland(Patchset 2): * Fix typo where memory was freed twice. Change-Id: Ib1c83fe83b629cd50ae6af90ee99fdd44da882d4 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/108367 Commit-Queue: Alexander Aprelev <aam@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com>
2019-07-08 23:49:05 +00:00
}
return isolate;
}
DART_EXPORT Dart_Isolate
Second attempt to reland "[vm/concurrency] Introduce concept of Isolate Groups" This reverts commit 3d14b75f972ca287cd892ff907cf04b22839af59. An Isolate Group (IG) is a collection of isolates which were spawned from the same source. This allows the VM to: * have a guarantee that all isolates within one IG can safely exchange structured objects (currently we rely on embedder for this guarantee) * hot-reload all isolates together (currently we only reload one isolate, leaving same-source isolates in inconsistent state) * make a shared heap for all isolates from the same IG, which paves the way for faster communication and sharing of immutable objects. All isolates within one IG will share the same IsolateGroupSource. **Embedder changes** This change makes breaking embedder API changes to support this new concept of Isolate Groups: The existing isolate lifecycle callbacks given to Dart_Initialize will become Isolate Group lifecycle callbacks. A new callback `initialize_isolate` callback will be added which can initialize a new isolate within an existing IG. Existing embedders can be updated by performing the following renames Dart_CreateIsolate -> Dart_CreateIsolateGroup Dart_IsolateCreateCallback -> Dart_IsolateGroupCreateCallback Dart_IsolateCleanupCallback -> Dart_IsolateGroupShutdownCallback Dart_CreateIsolateFromKernel -> Dart_CreateIsolateGroupFromKernel Dart_CurrentIsolateData -> Dart_CurrentIsolateGroupData Dart_IsolateData -> Dart_IsolateGroupData Dart_GetNativeIsolateData -> Dart_GetNativeIsolateGroupData Dart_InitializeParams.create -> Dart_InitializeParams.create_group Dart_InitializeParams.cleanup -> Dart_InitializeParams.shutdown_group Dart_InitializeParams.shutdown -> Dart_InitializeParams.shutdown_isolate By default `Isolate.spawn` will cause the creation of a new IG. Though an embedder can opt-into supporting multiple isolates within one IG by providing a callback to the newly added `Dart_InitializeParams.initialize_isolate`. The responsibility of this new callback is to initialize an existing isolate (which was setup by re-using source code from the spawning isolate - i.e. the one which used `Isolate.spawn`) by setting native resolvers, initializing global state, etc. Issue https://github.com/dart-lang/sdk/issues/36648 Issue https://github.com/dart-lang/sdk/issues/36097 Original review: https://dart-review.googlesource.com/c/sdk/+/105241 Difference to original review: * Give each isolate it's own [Loader] (for now) * Sort classes during initialization for spawned isolates if app-jit is used (to match main isolate) * Fix IsolateData memory leak if isolate startup fails Difference to first reland(Patchset 2): * Fix typo where memory was freed twice. Change-Id: Ib1c83fe83b629cd50ae6af90ee99fdd44da882d4 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/108367 Commit-Queue: Alexander Aprelev <aam@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com>
2019-07-08 23:49:05 +00:00
Dart_CreateIsolateGroupFromKernel(const char* script_uri,
const char* name,
const uint8_t* kernel_buffer,
intptr_t kernel_buffer_size,
Dart_IsolateFlags* flags,
void* isolate_group_data,
void* isolate_data,
char** error) {
API_TIMELINE_DURATION(Thread::Current());
Second attempt to reland "[vm/concurrency] Introduce concept of Isolate Groups" This reverts commit 3d14b75f972ca287cd892ff907cf04b22839af59. An Isolate Group (IG) is a collection of isolates which were spawned from the same source. This allows the VM to: * have a guarantee that all isolates within one IG can safely exchange structured objects (currently we rely on embedder for this guarantee) * hot-reload all isolates together (currently we only reload one isolate, leaving same-source isolates in inconsistent state) * make a shared heap for all isolates from the same IG, which paves the way for faster communication and sharing of immutable objects. All isolates within one IG will share the same IsolateGroupSource. **Embedder changes** This change makes breaking embedder API changes to support this new concept of Isolate Groups: The existing isolate lifecycle callbacks given to Dart_Initialize will become Isolate Group lifecycle callbacks. A new callback `initialize_isolate` callback will be added which can initialize a new isolate within an existing IG. Existing embedders can be updated by performing the following renames Dart_CreateIsolate -> Dart_CreateIsolateGroup Dart_IsolateCreateCallback -> Dart_IsolateGroupCreateCallback Dart_IsolateCleanupCallback -> Dart_IsolateGroupShutdownCallback Dart_CreateIsolateFromKernel -> Dart_CreateIsolateGroupFromKernel Dart_CurrentIsolateData -> Dart_CurrentIsolateGroupData Dart_IsolateData -> Dart_IsolateGroupData Dart_GetNativeIsolateData -> Dart_GetNativeIsolateGroupData Dart_InitializeParams.create -> Dart_InitializeParams.create_group Dart_InitializeParams.cleanup -> Dart_InitializeParams.shutdown_group Dart_InitializeParams.shutdown -> Dart_InitializeParams.shutdown_isolate By default `Isolate.spawn` will cause the creation of a new IG. Though an embedder can opt-into supporting multiple isolates within one IG by providing a callback to the newly added `Dart_InitializeParams.initialize_isolate`. The responsibility of this new callback is to initialize an existing isolate (which was setup by re-using source code from the spawning isolate - i.e. the one which used `Isolate.spawn`) by setting native resolvers, initializing global state, etc. Issue https://github.com/dart-lang/sdk/issues/36648 Issue https://github.com/dart-lang/sdk/issues/36097 Original review: https://dart-review.googlesource.com/c/sdk/+/105241 Difference to original review: * Give each isolate it's own [Loader] (for now) * Sort classes during initialization for spawned isolates if app-jit is used (to match main isolate) * Fix IsolateData memory leak if isolate startup fails Difference to first reland(Patchset 2): * Fix typo where memory was freed twice. Change-Id: Ib1c83fe83b629cd50ae6af90ee99fdd44da882d4 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/108367 Commit-Queue: Alexander Aprelev <aam@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com>
2019-07-08 23:49:05 +00:00
Dart_IsolateFlags api_flags;
if (flags == nullptr) {
Isolate::FlagsInitialize(&api_flags);
flags = &api_flags;
}
const char* non_null_name = name == nullptr ? "isolate" : name;
std::shared_ptr<IsolateGroupSource> source(
new IsolateGroupSource(script_uri, non_null_name, nullptr, nullptr,
kernel_buffer, kernel_buffer_size, *flags));
auto group = new IsolateGroup(source, isolate_group_data, *flags);
IsolateGroup::RegisterIsolateGroup(group);
group->CreateHeap(
/*is_vm_isolate=*/false, IsServiceOrKernelIsolateName(non_null_name));
Dart_Isolate isolate = CreateIsolate(group, /*is_new_group=*/true,
non_null_name, isolate_data, error);
if (isolate != nullptr) {
group->set_initial_spawn_successful();
Second attempt to reland "[vm/concurrency] Introduce concept of Isolate Groups" This reverts commit 3d14b75f972ca287cd892ff907cf04b22839af59. An Isolate Group (IG) is a collection of isolates which were spawned from the same source. This allows the VM to: * have a guarantee that all isolates within one IG can safely exchange structured objects (currently we rely on embedder for this guarantee) * hot-reload all isolates together (currently we only reload one isolate, leaving same-source isolates in inconsistent state) * make a shared heap for all isolates from the same IG, which paves the way for faster communication and sharing of immutable objects. All isolates within one IG will share the same IsolateGroupSource. **Embedder changes** This change makes breaking embedder API changes to support this new concept of Isolate Groups: The existing isolate lifecycle callbacks given to Dart_Initialize will become Isolate Group lifecycle callbacks. A new callback `initialize_isolate` callback will be added which can initialize a new isolate within an existing IG. Existing embedders can be updated by performing the following renames Dart_CreateIsolate -> Dart_CreateIsolateGroup Dart_IsolateCreateCallback -> Dart_IsolateGroupCreateCallback Dart_IsolateCleanupCallback -> Dart_IsolateGroupShutdownCallback Dart_CreateIsolateFromKernel -> Dart_CreateIsolateGroupFromKernel Dart_CurrentIsolateData -> Dart_CurrentIsolateGroupData Dart_IsolateData -> Dart_IsolateGroupData Dart_GetNativeIsolateData -> Dart_GetNativeIsolateGroupData Dart_InitializeParams.create -> Dart_InitializeParams.create_group Dart_InitializeParams.cleanup -> Dart_InitializeParams.shutdown_group Dart_InitializeParams.shutdown -> Dart_InitializeParams.shutdown_isolate By default `Isolate.spawn` will cause the creation of a new IG. Though an embedder can opt-into supporting multiple isolates within one IG by providing a callback to the newly added `Dart_InitializeParams.initialize_isolate`. The responsibility of this new callback is to initialize an existing isolate (which was setup by re-using source code from the spawning isolate - i.e. the one which used `Isolate.spawn`) by setting native resolvers, initializing global state, etc. Issue https://github.com/dart-lang/sdk/issues/36648 Issue https://github.com/dart-lang/sdk/issues/36097 Original review: https://dart-review.googlesource.com/c/sdk/+/105241 Difference to original review: * Give each isolate it's own [Loader] (for now) * Sort classes during initialization for spawned isolates if app-jit is used (to match main isolate) * Fix IsolateData memory leak if isolate startup fails Difference to first reland(Patchset 2): * Fix typo where memory was freed twice. Change-Id: Ib1c83fe83b629cd50ae6af90ee99fdd44da882d4 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/108367 Commit-Queue: Alexander Aprelev <aam@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com>
2019-07-08 23:49:05 +00:00
}
return isolate;
}
[vm/concurrency] Add Dart_CreateLightweightIsolate/Dart_RunLoopAsync APIs Dart_CreateLightweightIsolate API: This API can be used by embedders to create a lightweight isolate (inside an existing isolate group). It is the analogous to Dart_CreateIsolateGroup - though taking a parent isolate as parameter (inside whose IG we create a new isolate) instead of taking kernel/snapshot data. Right now this API works on AOT and returns an error in JIT, both cases are covered by the test. Dart_RunLoopAsync: The API can be used by embedders to transfer ownership of an isolate to the VM, which will take care of running the message handling loop and shuts the isolate down once the last receive port has been closed. It does allow listening to error/exit events generated by the message loop implementation as well as allows setting errors-are-fatal, effectively the same event-loop related parameters from the `Isolate.spawn()` API, just in Dart. It's the embedders responsibility to first launch initial dart code which will take care of responding to events (i.e. directly/indirectly open a receive port) - otherwise the isolate cannot be talked to and would immediately shut down. Since our vm/cc tests do support running in AOT, we use a hybrid approach to test the functionality: We let a normal Dart test call a small C wrapper using FFI, to create a lightweight isolate, run it on a new thread and join that thread. TEST=vm/dart{,_2}/isolates/dart_api_create_lightweight_isolate_test Issue https://github.com/dart-lang/sdk/issues/36097 Closes https://github.com/dart-lang/sdk/issues/44088 Change-Id: Id77ba928793fdb517f6cb7e8130df98a0366ddd6 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/170983 Commit-Queue: Martin Kustermann <kustermann@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com> Reviewed-by: Alexander Aprelev <aam@google.com>
2020-11-12 10:22:16 +00:00
DART_EXPORT Dart_Isolate
Dart_CreateIsolateInGroup(Dart_Isolate group_member,
const char* name,
Dart_IsolateShutdownCallback shutdown_callback,
Dart_IsolateCleanupCallback cleanup_callback,
void* child_isolate_data,
char** error) {
CHECK_NO_ISOLATE(Isolate::Current());
auto member = reinterpret_cast<Isolate*>(group_member);
if (member->IsScheduled()) {
FATAL("The given member isolate (%s) must not have been entered.",
member->name());
}
*error = nullptr;
Isolate* isolate;
isolate = CreateWithinExistingIsolateGroup(member->group(), name, error);
[vm/concurrency] Add Dart_CreateLightweightIsolate/Dart_RunLoopAsync APIs Dart_CreateLightweightIsolate API: This API can be used by embedders to create a lightweight isolate (inside an existing isolate group). It is the analogous to Dart_CreateIsolateGroup - though taking a parent isolate as parameter (inside whose IG we create a new isolate) instead of taking kernel/snapshot data. Right now this API works on AOT and returns an error in JIT, both cases are covered by the test. Dart_RunLoopAsync: The API can be used by embedders to transfer ownership of an isolate to the VM, which will take care of running the message handling loop and shuts the isolate down once the last receive port has been closed. It does allow listening to error/exit events generated by the message loop implementation as well as allows setting errors-are-fatal, effectively the same event-loop related parameters from the `Isolate.spawn()` API, just in Dart. It's the embedders responsibility to first launch initial dart code which will take care of responding to events (i.e. directly/indirectly open a receive port) - otherwise the isolate cannot be talked to and would immediately shut down. Since our vm/cc tests do support running in AOT, we use a hybrid approach to test the functionality: We let a normal Dart test call a small C wrapper using FFI, to create a lightweight isolate, run it on a new thread and join that thread. TEST=vm/dart{,_2}/isolates/dart_api_create_lightweight_isolate_test Issue https://github.com/dart-lang/sdk/issues/36097 Closes https://github.com/dart-lang/sdk/issues/44088 Change-Id: Id77ba928793fdb517f6cb7e8130df98a0366ddd6 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/170983 Commit-Queue: Martin Kustermann <kustermann@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com> Reviewed-by: Alexander Aprelev <aam@google.com>
2020-11-12 10:22:16 +00:00
if (isolate != nullptr) {
isolate->set_origin_id(member->origin_id());
isolate->set_init_callback_data(child_isolate_data);
isolate->set_on_shutdown_callback(shutdown_callback);
isolate->set_on_cleanup_callback(cleanup_callback);
}
return Api::CastIsolate(isolate);
}
DART_EXPORT void Dart_ShutdownIsolate() {
Thread* T = Thread::Current();
auto I = T->isolate();
CHECK_ISOLATE(I);
// The Thread structure is disassociated from the isolate, we do the
// safepoint transition explicitly here instead of using the TransitionXXX
// scope objects as the original transition happened outside this scope in
Second attempt to reland "[vm/concurrency] Introduce concept of Isolate Groups" This reverts commit 3d14b75f972ca287cd892ff907cf04b22839af59. An Isolate Group (IG) is a collection of isolates which were spawned from the same source. This allows the VM to: * have a guarantee that all isolates within one IG can safely exchange structured objects (currently we rely on embedder for this guarantee) * hot-reload all isolates together (currently we only reload one isolate, leaving same-source isolates in inconsistent state) * make a shared heap for all isolates from the same IG, which paves the way for faster communication and sharing of immutable objects. All isolates within one IG will share the same IsolateGroupSource. **Embedder changes** This change makes breaking embedder API changes to support this new concept of Isolate Groups: The existing isolate lifecycle callbacks given to Dart_Initialize will become Isolate Group lifecycle callbacks. A new callback `initialize_isolate` callback will be added which can initialize a new isolate within an existing IG. Existing embedders can be updated by performing the following renames Dart_CreateIsolate -> Dart_CreateIsolateGroup Dart_IsolateCreateCallback -> Dart_IsolateGroupCreateCallback Dart_IsolateCleanupCallback -> Dart_IsolateGroupShutdownCallback Dart_CreateIsolateFromKernel -> Dart_CreateIsolateGroupFromKernel Dart_CurrentIsolateData -> Dart_CurrentIsolateGroupData Dart_IsolateData -> Dart_IsolateGroupData Dart_GetNativeIsolateData -> Dart_GetNativeIsolateGroupData Dart_InitializeParams.create -> Dart_InitializeParams.create_group Dart_InitializeParams.cleanup -> Dart_InitializeParams.shutdown_group Dart_InitializeParams.shutdown -> Dart_InitializeParams.shutdown_isolate By default `Isolate.spawn` will cause the creation of a new IG. Though an embedder can opt-into supporting multiple isolates within one IG by providing a callback to the newly added `Dart_InitializeParams.initialize_isolate`. The responsibility of this new callback is to initialize an existing isolate (which was setup by re-using source code from the spawning isolate - i.e. the one which used `Isolate.spawn`) by setting native resolvers, initializing global state, etc. Issue https://github.com/dart-lang/sdk/issues/36648 Issue https://github.com/dart-lang/sdk/issues/36097 Original review: https://dart-review.googlesource.com/c/sdk/+/105241 Difference to original review: * Give each isolate it's own [Loader] (for now) * Sort classes during initialization for spawned isolates if app-jit is used (to match main isolate) * Fix IsolateData memory leak if isolate startup fails Difference to first reland(Patchset 2): * Fix typo where memory was freed twice. Change-Id: Ib1c83fe83b629cd50ae6af90ee99fdd44da882d4 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/108367 Commit-Queue: Alexander Aprelev <aam@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com>
2019-07-08 23:49:05 +00:00
// Dart_EnterIsolate/Dart_CreateIsolateGroup.
ASSERT(T->execution_state() == Thread::kThreadInNative);
T->ExitSafepoint();
T->set_execution_state(Thread::kThreadInVM);
I->WaitForOutstandingSpawns();
// Release any remaining API scopes.
ApiLocalScope* scope = T->api_top_scope();
while (scope != NULL) {
ApiLocalScope* previous = scope->previous();
delete scope;
scope = previous;
}
T->set_api_top_scope(NULL);
{
StackZone zone(T);
HandleScope handle_scope(T);
#if defined(DEBUG)
if (T->isolate()->origin_id() == 0) {
T->isolate_group()->ValidateConstants();
}
#endif
Dart::RunShutdownCallback();
}
Dart::ShutdownIsolate();
}
DART_EXPORT Dart_Isolate Dart_CurrentIsolate() {
return Api::CastIsolate(Isolate::Current());
}
DART_EXPORT void* Dart_CurrentIsolateData() {
Isolate* isolate = Isolate::Current();
CHECK_ISOLATE(isolate);
NoSafepointScope no_safepoint_scope;
return isolate->init_callback_data();
}
DART_EXPORT void* Dart_IsolateData(Dart_Isolate isolate) {
if (isolate == NULL) {
FATAL1("%s expects argument 'isolate' to be non-null.", CURRENT_FUNC);
}
Second attempt to reland "[vm/concurrency] Introduce concept of Isolate Groups" This reverts commit 3d14b75f972ca287cd892ff907cf04b22839af59. An Isolate Group (IG) is a collection of isolates which were spawned from the same source. This allows the VM to: * have a guarantee that all isolates within one IG can safely exchange structured objects (currently we rely on embedder for this guarantee) * hot-reload all isolates together (currently we only reload one isolate, leaving same-source isolates in inconsistent state) * make a shared heap for all isolates from the same IG, which paves the way for faster communication and sharing of immutable objects. All isolates within one IG will share the same IsolateGroupSource. **Embedder changes** This change makes breaking embedder API changes to support this new concept of Isolate Groups: The existing isolate lifecycle callbacks given to Dart_Initialize will become Isolate Group lifecycle callbacks. A new callback `initialize_isolate` callback will be added which can initialize a new isolate within an existing IG. Existing embedders can be updated by performing the following renames Dart_CreateIsolate -> Dart_CreateIsolateGroup Dart_IsolateCreateCallback -> Dart_IsolateGroupCreateCallback Dart_IsolateCleanupCallback -> Dart_IsolateGroupShutdownCallback Dart_CreateIsolateFromKernel -> Dart_CreateIsolateGroupFromKernel Dart_CurrentIsolateData -> Dart_CurrentIsolateGroupData Dart_IsolateData -> Dart_IsolateGroupData Dart_GetNativeIsolateData -> Dart_GetNativeIsolateGroupData Dart_InitializeParams.create -> Dart_InitializeParams.create_group Dart_InitializeParams.cleanup -> Dart_InitializeParams.shutdown_group Dart_InitializeParams.shutdown -> Dart_InitializeParams.shutdown_isolate By default `Isolate.spawn` will cause the creation of a new IG. Though an embedder can opt-into supporting multiple isolates within one IG by providing a callback to the newly added `Dart_InitializeParams.initialize_isolate`. The responsibility of this new callback is to initialize an existing isolate (which was setup by re-using source code from the spawning isolate - i.e. the one which used `Isolate.spawn`) by setting native resolvers, initializing global state, etc. Issue https://github.com/dart-lang/sdk/issues/36648 Issue https://github.com/dart-lang/sdk/issues/36097 Original review: https://dart-review.googlesource.com/c/sdk/+/105241 Difference to original review: * Give each isolate it's own [Loader] (for now) * Sort classes during initialization for spawned isolates if app-jit is used (to match main isolate) * Fix IsolateData memory leak if isolate startup fails Difference to first reland(Patchset 2): * Fix typo where memory was freed twice. Change-Id: Ib1c83fe83b629cd50ae6af90ee99fdd44da882d4 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/108367 Commit-Queue: Alexander Aprelev <aam@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com>
2019-07-08 23:49:05 +00:00
// TODO(http://dartbug.com/16615): Validate isolate parameter.
return reinterpret_cast<Isolate*>(isolate)->init_callback_data();
}
DART_EXPORT Dart_IsolateGroup Dart_CurrentIsolateGroup() {
return Api::CastIsolateGroup(IsolateGroup::Current());
}
Second attempt to reland "[vm/concurrency] Introduce concept of Isolate Groups" This reverts commit 3d14b75f972ca287cd892ff907cf04b22839af59. An Isolate Group (IG) is a collection of isolates which were spawned from the same source. This allows the VM to: * have a guarantee that all isolates within one IG can safely exchange structured objects (currently we rely on embedder for this guarantee) * hot-reload all isolates together (currently we only reload one isolate, leaving same-source isolates in inconsistent state) * make a shared heap for all isolates from the same IG, which paves the way for faster communication and sharing of immutable objects. All isolates within one IG will share the same IsolateGroupSource. **Embedder changes** This change makes breaking embedder API changes to support this new concept of Isolate Groups: The existing isolate lifecycle callbacks given to Dart_Initialize will become Isolate Group lifecycle callbacks. A new callback `initialize_isolate` callback will be added which can initialize a new isolate within an existing IG. Existing embedders can be updated by performing the following renames Dart_CreateIsolate -> Dart_CreateIsolateGroup Dart_IsolateCreateCallback -> Dart_IsolateGroupCreateCallback Dart_IsolateCleanupCallback -> Dart_IsolateGroupShutdownCallback Dart_CreateIsolateFromKernel -> Dart_CreateIsolateGroupFromKernel Dart_CurrentIsolateData -> Dart_CurrentIsolateGroupData Dart_IsolateData -> Dart_IsolateGroupData Dart_GetNativeIsolateData -> Dart_GetNativeIsolateGroupData Dart_InitializeParams.create -> Dart_InitializeParams.create_group Dart_InitializeParams.cleanup -> Dart_InitializeParams.shutdown_group Dart_InitializeParams.shutdown -> Dart_InitializeParams.shutdown_isolate By default `Isolate.spawn` will cause the creation of a new IG. Though an embedder can opt-into supporting multiple isolates within one IG by providing a callback to the newly added `Dart_InitializeParams.initialize_isolate`. The responsibility of this new callback is to initialize an existing isolate (which was setup by re-using source code from the spawning isolate - i.e. the one which used `Isolate.spawn`) by setting native resolvers, initializing global state, etc. Issue https://github.com/dart-lang/sdk/issues/36648 Issue https://github.com/dart-lang/sdk/issues/36097 Original review: https://dart-review.googlesource.com/c/sdk/+/105241 Difference to original review: * Give each isolate it's own [Loader] (for now) * Sort classes during initialization for spawned isolates if app-jit is used (to match main isolate) * Fix IsolateData memory leak if isolate startup fails Difference to first reland(Patchset 2): * Fix typo where memory was freed twice. Change-Id: Ib1c83fe83b629cd50ae6af90ee99fdd44da882d4 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/108367 Commit-Queue: Alexander Aprelev <aam@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com>
2019-07-08 23:49:05 +00:00
DART_EXPORT void* Dart_CurrentIsolateGroupData() {
IsolateGroup* isolate_group = IsolateGroup::Current();
CHECK_ISOLATE_GROUP(isolate_group);
Second attempt to reland "[vm/concurrency] Introduce concept of Isolate Groups" This reverts commit 3d14b75f972ca287cd892ff907cf04b22839af59. An Isolate Group (IG) is a collection of isolates which were spawned from the same source. This allows the VM to: * have a guarantee that all isolates within one IG can safely exchange structured objects (currently we rely on embedder for this guarantee) * hot-reload all isolates together (currently we only reload one isolate, leaving same-source isolates in inconsistent state) * make a shared heap for all isolates from the same IG, which paves the way for faster communication and sharing of immutable objects. All isolates within one IG will share the same IsolateGroupSource. **Embedder changes** This change makes breaking embedder API changes to support this new concept of Isolate Groups: The existing isolate lifecycle callbacks given to Dart_Initialize will become Isolate Group lifecycle callbacks. A new callback `initialize_isolate` callback will be added which can initialize a new isolate within an existing IG. Existing embedders can be updated by performing the following renames Dart_CreateIsolate -> Dart_CreateIsolateGroup Dart_IsolateCreateCallback -> Dart_IsolateGroupCreateCallback Dart_IsolateCleanupCallback -> Dart_IsolateGroupShutdownCallback Dart_CreateIsolateFromKernel -> Dart_CreateIsolateGroupFromKernel Dart_CurrentIsolateData -> Dart_CurrentIsolateGroupData Dart_IsolateData -> Dart_IsolateGroupData Dart_GetNativeIsolateData -> Dart_GetNativeIsolateGroupData Dart_InitializeParams.create -> Dart_InitializeParams.create_group Dart_InitializeParams.cleanup -> Dart_InitializeParams.shutdown_group Dart_InitializeParams.shutdown -> Dart_InitializeParams.shutdown_isolate By default `Isolate.spawn` will cause the creation of a new IG. Though an embedder can opt-into supporting multiple isolates within one IG by providing a callback to the newly added `Dart_InitializeParams.initialize_isolate`. The responsibility of this new callback is to initialize an existing isolate (which was setup by re-using source code from the spawning isolate - i.e. the one which used `Isolate.spawn`) by setting native resolvers, initializing global state, etc. Issue https://github.com/dart-lang/sdk/issues/36648 Issue https://github.com/dart-lang/sdk/issues/36097 Original review: https://dart-review.googlesource.com/c/sdk/+/105241 Difference to original review: * Give each isolate it's own [Loader] (for now) * Sort classes during initialization for spawned isolates if app-jit is used (to match main isolate) * Fix IsolateData memory leak if isolate startup fails Difference to first reland(Patchset 2): * Fix typo where memory was freed twice. Change-Id: Ib1c83fe83b629cd50ae6af90ee99fdd44da882d4 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/108367 Commit-Queue: Alexander Aprelev <aam@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com>
2019-07-08 23:49:05 +00:00
NoSafepointScope no_safepoint_scope;
return isolate_group->embedder_data();
Second attempt to reland "[vm/concurrency] Introduce concept of Isolate Groups" This reverts commit 3d14b75f972ca287cd892ff907cf04b22839af59. An Isolate Group (IG) is a collection of isolates which were spawned from the same source. This allows the VM to: * have a guarantee that all isolates within one IG can safely exchange structured objects (currently we rely on embedder for this guarantee) * hot-reload all isolates together (currently we only reload one isolate, leaving same-source isolates in inconsistent state) * make a shared heap for all isolates from the same IG, which paves the way for faster communication and sharing of immutable objects. All isolates within one IG will share the same IsolateGroupSource. **Embedder changes** This change makes breaking embedder API changes to support this new concept of Isolate Groups: The existing isolate lifecycle callbacks given to Dart_Initialize will become Isolate Group lifecycle callbacks. A new callback `initialize_isolate` callback will be added which can initialize a new isolate within an existing IG. Existing embedders can be updated by performing the following renames Dart_CreateIsolate -> Dart_CreateIsolateGroup Dart_IsolateCreateCallback -> Dart_IsolateGroupCreateCallback Dart_IsolateCleanupCallback -> Dart_IsolateGroupShutdownCallback Dart_CreateIsolateFromKernel -> Dart_CreateIsolateGroupFromKernel Dart_CurrentIsolateData -> Dart_CurrentIsolateGroupData Dart_IsolateData -> Dart_IsolateGroupData Dart_GetNativeIsolateData -> Dart_GetNativeIsolateGroupData Dart_InitializeParams.create -> Dart_InitializeParams.create_group Dart_InitializeParams.cleanup -> Dart_InitializeParams.shutdown_group Dart_InitializeParams.shutdown -> Dart_InitializeParams.shutdown_isolate By default `Isolate.spawn` will cause the creation of a new IG. Though an embedder can opt-into supporting multiple isolates within one IG by providing a callback to the newly added `Dart_InitializeParams.initialize_isolate`. The responsibility of this new callback is to initialize an existing isolate (which was setup by re-using source code from the spawning isolate - i.e. the one which used `Isolate.spawn`) by setting native resolvers, initializing global state, etc. Issue https://github.com/dart-lang/sdk/issues/36648 Issue https://github.com/dart-lang/sdk/issues/36097 Original review: https://dart-review.googlesource.com/c/sdk/+/105241 Difference to original review: * Give each isolate it's own [Loader] (for now) * Sort classes during initialization for spawned isolates if app-jit is used (to match main isolate) * Fix IsolateData memory leak if isolate startup fails Difference to first reland(Patchset 2): * Fix typo where memory was freed twice. Change-Id: Ib1c83fe83b629cd50ae6af90ee99fdd44da882d4 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/108367 Commit-Queue: Alexander Aprelev <aam@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com>
2019-07-08 23:49:05 +00:00
}
DART_EXPORT Dart_IsolateGroupId Dart_CurrentIsolateGroupId() {
IsolateGroup* isolate_group = IsolateGroup::Current();
CHECK_ISOLATE_GROUP(isolate_group);
return isolate_group->id();
}
Second attempt to reland "[vm/concurrency] Introduce concept of Isolate Groups" This reverts commit 3d14b75f972ca287cd892ff907cf04b22839af59. An Isolate Group (IG) is a collection of isolates which were spawned from the same source. This allows the VM to: * have a guarantee that all isolates within one IG can safely exchange structured objects (currently we rely on embedder for this guarantee) * hot-reload all isolates together (currently we only reload one isolate, leaving same-source isolates in inconsistent state) * make a shared heap for all isolates from the same IG, which paves the way for faster communication and sharing of immutable objects. All isolates within one IG will share the same IsolateGroupSource. **Embedder changes** This change makes breaking embedder API changes to support this new concept of Isolate Groups: The existing isolate lifecycle callbacks given to Dart_Initialize will become Isolate Group lifecycle callbacks. A new callback `initialize_isolate` callback will be added which can initialize a new isolate within an existing IG. Existing embedders can be updated by performing the following renames Dart_CreateIsolate -> Dart_CreateIsolateGroup Dart_IsolateCreateCallback -> Dart_IsolateGroupCreateCallback Dart_IsolateCleanupCallback -> Dart_IsolateGroupShutdownCallback Dart_CreateIsolateFromKernel -> Dart_CreateIsolateGroupFromKernel Dart_CurrentIsolateData -> Dart_CurrentIsolateGroupData Dart_IsolateData -> Dart_IsolateGroupData Dart_GetNativeIsolateData -> Dart_GetNativeIsolateGroupData Dart_InitializeParams.create -> Dart_InitializeParams.create_group Dart_InitializeParams.cleanup -> Dart_InitializeParams.shutdown_group Dart_InitializeParams.shutdown -> Dart_InitializeParams.shutdown_isolate By default `Isolate.spawn` will cause the creation of a new IG. Though an embedder can opt-into supporting multiple isolates within one IG by providing a callback to the newly added `Dart_InitializeParams.initialize_isolate`. The responsibility of this new callback is to initialize an existing isolate (which was setup by re-using source code from the spawning isolate - i.e. the one which used `Isolate.spawn`) by setting native resolvers, initializing global state, etc. Issue https://github.com/dart-lang/sdk/issues/36648 Issue https://github.com/dart-lang/sdk/issues/36097 Original review: https://dart-review.googlesource.com/c/sdk/+/105241 Difference to original review: * Give each isolate it's own [Loader] (for now) * Sort classes during initialization for spawned isolates if app-jit is used (to match main isolate) * Fix IsolateData memory leak if isolate startup fails Difference to first reland(Patchset 2): * Fix typo where memory was freed twice. Change-Id: Ib1c83fe83b629cd50ae6af90ee99fdd44da882d4 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/108367 Commit-Queue: Alexander Aprelev <aam@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com>
2019-07-08 23:49:05 +00:00
DART_EXPORT void* Dart_IsolateGroupData(Dart_Isolate isolate) {
if (isolate == NULL) {
FATAL1("%s expects argument 'isolate' to be non-null.", CURRENT_FUNC);
}
// TODO(http://dartbug.com/16615): Validate isolate parameter.
return reinterpret_cast<Isolate*>(isolate)->group()->embedder_data();
}
DART_EXPORT Dart_Handle Dart_DebugName() {
DARTSCOPE(Thread::Current());
Isolate* I = T->isolate();
return Api::NewHandle(
T, String::NewFormatted("(%" Pd64 ") '%s'",
static_cast<int64_t>(I->main_port()), I->name()));
}
DART_EXPORT const char* Dart_IsolateServiceId(Dart_Isolate isolate) {
if (isolate == NULL) {
FATAL1("%s expects argument 'isolate' to be non-null.", CURRENT_FUNC);
}
Second attempt to reland "[vm/concurrency] Introduce concept of Isolate Groups" This reverts commit 3d14b75f972ca287cd892ff907cf04b22839af59. An Isolate Group (IG) is a collection of isolates which were spawned from the same source. This allows the VM to: * have a guarantee that all isolates within one IG can safely exchange structured objects (currently we rely on embedder for this guarantee) * hot-reload all isolates together (currently we only reload one isolate, leaving same-source isolates in inconsistent state) * make a shared heap for all isolates from the same IG, which paves the way for faster communication and sharing of immutable objects. All isolates within one IG will share the same IsolateGroupSource. **Embedder changes** This change makes breaking embedder API changes to support this new concept of Isolate Groups: The existing isolate lifecycle callbacks given to Dart_Initialize will become Isolate Group lifecycle callbacks. A new callback `initialize_isolate` callback will be added which can initialize a new isolate within an existing IG. Existing embedders can be updated by performing the following renames Dart_CreateIsolate -> Dart_CreateIsolateGroup Dart_IsolateCreateCallback -> Dart_IsolateGroupCreateCallback Dart_IsolateCleanupCallback -> Dart_IsolateGroupShutdownCallback Dart_CreateIsolateFromKernel -> Dart_CreateIsolateGroupFromKernel Dart_CurrentIsolateData -> Dart_CurrentIsolateGroupData Dart_IsolateData -> Dart_IsolateGroupData Dart_GetNativeIsolateData -> Dart_GetNativeIsolateGroupData Dart_InitializeParams.create -> Dart_InitializeParams.create_group Dart_InitializeParams.cleanup -> Dart_InitializeParams.shutdown_group Dart_InitializeParams.shutdown -> Dart_InitializeParams.shutdown_isolate By default `Isolate.spawn` will cause the creation of a new IG. Though an embedder can opt-into supporting multiple isolates within one IG by providing a callback to the newly added `Dart_InitializeParams.initialize_isolate`. The responsibility of this new callback is to initialize an existing isolate (which was setup by re-using source code from the spawning isolate - i.e. the one which used `Isolate.spawn`) by setting native resolvers, initializing global state, etc. Issue https://github.com/dart-lang/sdk/issues/36648 Issue https://github.com/dart-lang/sdk/issues/36097 Original review: https://dart-review.googlesource.com/c/sdk/+/105241 Difference to original review: * Give each isolate it's own [Loader] (for now) * Sort classes during initialization for spawned isolates if app-jit is used (to match main isolate) * Fix IsolateData memory leak if isolate startup fails Difference to first reland(Patchset 2): * Fix typo where memory was freed twice. Change-Id: Ib1c83fe83b629cd50ae6af90ee99fdd44da882d4 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/108367 Commit-Queue: Alexander Aprelev <aam@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com>
2019-07-08 23:49:05 +00:00
// TODO(http://dartbug.com/16615): Validate isolate parameter.
Isolate* I = reinterpret_cast<Isolate*>(isolate);
int64_t main_port = static_cast<int64_t>(I->main_port());
return OS::SCreate(NULL, "isolates/%" Pd64, main_port);
}
DART_EXPORT void Dart_EnterIsolate(Dart_Isolate isolate) {
CHECK_NO_ISOLATE(Isolate::Current());
Second attempt to reland "[vm/concurrency] Introduce concept of Isolate Groups" This reverts commit 3d14b75f972ca287cd892ff907cf04b22839af59. An Isolate Group (IG) is a collection of isolates which were spawned from the same source. This allows the VM to: * have a guarantee that all isolates within one IG can safely exchange structured objects (currently we rely on embedder for this guarantee) * hot-reload all isolates together (currently we only reload one isolate, leaving same-source isolates in inconsistent state) * make a shared heap for all isolates from the same IG, which paves the way for faster communication and sharing of immutable objects. All isolates within one IG will share the same IsolateGroupSource. **Embedder changes** This change makes breaking embedder API changes to support this new concept of Isolate Groups: The existing isolate lifecycle callbacks given to Dart_Initialize will become Isolate Group lifecycle callbacks. A new callback `initialize_isolate` callback will be added which can initialize a new isolate within an existing IG. Existing embedders can be updated by performing the following renames Dart_CreateIsolate -> Dart_CreateIsolateGroup Dart_IsolateCreateCallback -> Dart_IsolateGroupCreateCallback Dart_IsolateCleanupCallback -> Dart_IsolateGroupShutdownCallback Dart_CreateIsolateFromKernel -> Dart_CreateIsolateGroupFromKernel Dart_CurrentIsolateData -> Dart_CurrentIsolateGroupData Dart_IsolateData -> Dart_IsolateGroupData Dart_GetNativeIsolateData -> Dart_GetNativeIsolateGroupData Dart_InitializeParams.create -> Dart_InitializeParams.create_group Dart_InitializeParams.cleanup -> Dart_InitializeParams.shutdown_group Dart_InitializeParams.shutdown -> Dart_InitializeParams.shutdown_isolate By default `Isolate.spawn` will cause the creation of a new IG. Though an embedder can opt-into supporting multiple isolates within one IG by providing a callback to the newly added `Dart_InitializeParams.initialize_isolate`. The responsibility of this new callback is to initialize an existing isolate (which was setup by re-using source code from the spawning isolate - i.e. the one which used `Isolate.spawn`) by setting native resolvers, initializing global state, etc. Issue https://github.com/dart-lang/sdk/issues/36648 Issue https://github.com/dart-lang/sdk/issues/36097 Original review: https://dart-review.googlesource.com/c/sdk/+/105241 Difference to original review: * Give each isolate it's own [Loader] (for now) * Sort classes during initialization for spawned isolates if app-jit is used (to match main isolate) * Fix IsolateData memory leak if isolate startup fails Difference to first reland(Patchset 2): * Fix typo where memory was freed twice. Change-Id: Ib1c83fe83b629cd50ae6af90ee99fdd44da882d4 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/108367 Commit-Queue: Alexander Aprelev <aam@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com>
2019-07-08 23:49:05 +00:00
// TODO(http://dartbug.com/16615): Validate isolate parameter.
Isolate* iso = reinterpret_cast<Isolate*>(isolate);
if (!Thread::EnterIsolate(iso)) {
if (iso->IsScheduled()) {
FATAL(
"Isolate %s is already scheduled on mutator thread %p, "
"failed to schedule from os thread 0x%" Px "\n",
iso->name(), iso->scheduled_mutator_thread(),
OSThread::ThreadIdToIntPtr(OSThread::GetCurrentThreadId()));
} else {
FATAL("Unable to enter isolate %s as Dart VM is shutting down",
iso->name());
}
}
// A Thread structure has been associated to the thread, we do the
// safepoint transition explicitly here instead of using the
// TransitionXXX scope objects as the reverse transition happens
// outside this scope in Dart_ExitIsolate/Dart_ShutdownIsolate.
Thread* T = Thread::Current();
T->set_execution_state(Thread::kThreadInNative);
T->EnterSafepoint();
}
DART_EXPORT void Dart_StartProfiling() {
#if !defined(PRODUCT)
if (!FLAG_profiler) {
FLAG_profiler = true;
Profiler::Init();
}
#endif // !defined(PRODUCT)
}
DART_EXPORT void Dart_StopProfiling() {
#if !defined(PRODUCT)
if (FLAG_profiler) {
Profiler::Cleanup();
FLAG_profiler = false;
}
#endif // !defined(PRODUCT)
}
DART_EXPORT void Dart_ThreadDisableProfiling() {
OSThread* os_thread = OSThread::Current();
if (os_thread == NULL) {
return;
}
os_thread->DisableThreadInterrupts();
}
DART_EXPORT void Dart_ThreadEnableProfiling() {
OSThread* os_thread = OSThread::Current();
if (os_thread == NULL) {
return;
}
os_thread->EnableThreadInterrupts();
}
DART_EXPORT void Dart_AddSymbols(const char* dso_name,
void* buffer,
intptr_t buffer_size) {
NativeSymbolResolver::AddSymbols(dso_name, buffer, buffer_size);
}
DART_EXPORT bool Dart_WriteProfileToTimeline(Dart_Port main_port,
char** error) {
#if defined(PRODUCT)
return false;
#else
if (!FLAG_profiler) {
if (error != NULL) {
*error = Utils::StrDup("The profiler is not running.");
}
return false;
}
const intptr_t kBufferLength = 512;
char method[kBufferLength];
// clang-format off
intptr_t method_length = snprintf(method, kBufferLength, "{"
"\"jsonrpc\": \"2.0\","
"\"method\": \"_writeCpuProfileTimeline\","
"\"id\": \"\","
"\"params\": {"
" \"isolateId\": \"isolates/%" Pd64 "\","
" \"tags\": \"None\""
"}"
"}", main_port);
// clang-format on
ASSERT(method_length <= kBufferLength);
char* response = NULL;
intptr_t response_length;
bool success = Dart_InvokeVMServiceMethod(
reinterpret_cast<uint8_t*>(method), method_length,
reinterpret_cast<uint8_t**>(&response), &response_length, error);
free(response);
return success;
#endif
}
DART_EXPORT bool Dart_ShouldPauseOnStart() {
#if defined(PRODUCT)
return false;
#else
Isolate* isolate = Isolate::Current();
CHECK_ISOLATE(isolate);
NoSafepointScope no_safepoint_scope;
return isolate->message_handler()->should_pause_on_start();
#endif
}
DART_EXPORT void Dart_SetShouldPauseOnStart(bool should_pause) {
#if defined(PRODUCT)
if (should_pause) {
FATAL1("%s(true) is not supported in a PRODUCT build", CURRENT_FUNC);
}
#else
Isolate* isolate = Isolate::Current();
CHECK_ISOLATE(isolate);
NoSafepointScope no_safepoint_scope;
if (isolate->is_runnable()) {
FATAL1("%s expects the current isolate to not be runnable yet.",
CURRENT_FUNC);
}
isolate->message_handler()->set_should_pause_on_start(should_pause);
#endif
}
DART_EXPORT bool Dart_IsPausedOnStart() {
#if defined(PRODUCT)
return false;
#else
Isolate* isolate = Isolate::Current();
CHECK_ISOLATE(isolate);
NoSafepointScope no_safepoint_scope;
return isolate->message_handler()->is_paused_on_start();
#endif
}
DART_EXPORT void Dart_SetPausedOnStart(bool paused) {
#if defined(PRODUCT)
if (paused) {
FATAL1("%s(true) is not supported in a PRODUCT build", CURRENT_FUNC);
}
#else
Isolate* isolate = Isolate::Current();
CHECK_ISOLATE(isolate);
NoSafepointScope no_safepoint_scope;
if (isolate->message_handler()->is_paused_on_start() != paused) {
isolate->message_handler()->PausedOnStart(paused);
}
#endif
}
DART_EXPORT bool Dart_ShouldPauseOnExit() {
#if defined(PRODUCT)
return false;
#else
Isolate* isolate = Isolate::Current();
CHECK_ISOLATE(isolate);
NoSafepointScope no_safepoint_scope;
return isolate->message_handler()->should_pause_on_exit();
#endif
}
DART_EXPORT void Dart_SetShouldPauseOnExit(bool should_pause) {
#if defined(PRODUCT)
if (should_pause) {
FATAL1("%s(true) is not supported in a PRODUCT build", CURRENT_FUNC);
}
#else
Isolate* isolate = Isolate::Current();
CHECK_ISOLATE(isolate);
NoSafepointScope no_safepoint_scope;
isolate->message_handler()->set_should_pause_on_exit(should_pause);
#endif
}
DART_EXPORT bool Dart_IsPausedOnExit() {
#if defined(PRODUCT)
return false;
#else
Isolate* isolate = Isolate::Current();
CHECK_ISOLATE(isolate);
NoSafepointScope no_safepoint_scope;
return isolate->message_handler()->is_paused_on_exit();
#endif
}
DART_EXPORT void Dart_SetPausedOnExit(bool paused) {
#if defined(PRODUCT)
if (paused) {
FATAL1("%s(true) is not supported in a PRODUCT build", CURRENT_FUNC);
}
#else
Isolate* isolate = Isolate::Current();
CHECK_ISOLATE(isolate);
NoSafepointScope no_safepoint_scope;
if (isolate->message_handler()->is_paused_on_exit() != paused) {
isolate->message_handler()->PausedOnExit(paused);
}
#endif
}
Revert "[vm] Cleanup Dart_Get/Set/HasStickyError API and use isolate's sticky error only as a backup for thread's sticky error" This reverts commit b10f17960890b053a5c1ac9303e0f9332fc8bd17. Reason for revert: failed service/* tests Original change's description: > [vm] Cleanup Dart_Get/Set/HasStickyError API and use isolate's sticky error only as a backup for thread's sticky error > > Both thread and isolate have sticky error fields. Dart API was using > isolate's sticky error, while Dart code was using thread's sticky error. > There was a one-way move of a thread's sticky error into isolate > when thread was unscheduled. > > This causes a problem as error in the isolate may go unnoticed and > repeated unscheduling/re-scheduling might end up overwriting the error > in the isolate (which triggers the assertion). > > To solve this problem, this CL: > * Cleans up Dart API which manipulates isolate's sticky error, so > isolate's sticky error is never set directly. > * When sceduling an isolate to a thread, sticky error is moved back from > isolate (if any). > > With this changes, thread's sticky error is always used if thread is running, > and isolate's sticky error is only used to hold sticky error while > isolate has no thread. > > Fixes https://github.com/dart-lang/sdk/issues/35590 > > Change-Id: I99b128cac363ca2df75f6e64c083b1ec36c866ce > Reviewed-on: https://dart-review.googlesource.com/c/89442 > Reviewed-by: Ryan Macnak <rmacnak@google.com> > Commit-Queue: Alexander Markov <alexmarkov@google.com> TBR=rmacnak@google.com,alexmarkov@google.com,zra@google.com,asiva@google.com Change-Id: I15874575b6b8ddca618741c59c21d4e692c4dcab No-Presubmit: true No-Tree-Checks: true No-Try: true Reviewed-on: https://dart-review.googlesource.com/c/90127 Reviewed-by: Alexander Markov <alexmarkov@google.com> Commit-Queue: Alexander Markov <alexmarkov@google.com>
2019-01-18 01:41:18 +00:00
DART_EXPORT void Dart_SetStickyError(Dart_Handle error) {
Thread* thread = Thread::Current();
DARTSCOPE(thread);
Isolate* isolate = thread->isolate();
CHECK_ISOLATE(isolate);
NoSafepointScope no_safepoint_scope;
const Error& error_handle = Api::UnwrapErrorHandle(Z, error);
if ((isolate->sticky_error() != Error::null()) &&
(error_handle.ptr() != Object::null())) {
Revert "[vm] Cleanup Dart_Get/Set/HasStickyError API and use isolate's sticky error only as a backup for thread's sticky error" This reverts commit b10f17960890b053a5c1ac9303e0f9332fc8bd17. Reason for revert: failed service/* tests Original change's description: > [vm] Cleanup Dart_Get/Set/HasStickyError API and use isolate's sticky error only as a backup for thread's sticky error > > Both thread and isolate have sticky error fields. Dart API was using > isolate's sticky error, while Dart code was using thread's sticky error. > There was a one-way move of a thread's sticky error into isolate > when thread was unscheduled. > > This causes a problem as error in the isolate may go unnoticed and > repeated unscheduling/re-scheduling might end up overwriting the error > in the isolate (which triggers the assertion). > > To solve this problem, this CL: > * Cleans up Dart API which manipulates isolate's sticky error, so > isolate's sticky error is never set directly. > * When sceduling an isolate to a thread, sticky error is moved back from > isolate (if any). > > With this changes, thread's sticky error is always used if thread is running, > and isolate's sticky error is only used to hold sticky error while > isolate has no thread. > > Fixes https://github.com/dart-lang/sdk/issues/35590 > > Change-Id: I99b128cac363ca2df75f6e64c083b1ec36c866ce > Reviewed-on: https://dart-review.googlesource.com/c/89442 > Reviewed-by: Ryan Macnak <rmacnak@google.com> > Commit-Queue: Alexander Markov <alexmarkov@google.com> TBR=rmacnak@google.com,alexmarkov@google.com,zra@google.com,asiva@google.com Change-Id: I15874575b6b8ddca618741c59c21d4e692c4dcab No-Presubmit: true No-Tree-Checks: true No-Try: true Reviewed-on: https://dart-review.googlesource.com/c/90127 Reviewed-by: Alexander Markov <alexmarkov@google.com> Commit-Queue: Alexander Markov <alexmarkov@google.com>
2019-01-18 01:41:18 +00:00
FATAL1("%s expects there to be no sticky error.", CURRENT_FUNC);
}
if (!error_handle.IsUnhandledException() &&
(error_handle.ptr() != Object::null())) {
Revert "[vm] Cleanup Dart_Get/Set/HasStickyError API and use isolate's sticky error only as a backup for thread's sticky error" This reverts commit b10f17960890b053a5c1ac9303e0f9332fc8bd17. Reason for revert: failed service/* tests Original change's description: > [vm] Cleanup Dart_Get/Set/HasStickyError API and use isolate's sticky error only as a backup for thread's sticky error > > Both thread and isolate have sticky error fields. Dart API was using > isolate's sticky error, while Dart code was using thread's sticky error. > There was a one-way move of a thread's sticky error into isolate > when thread was unscheduled. > > This causes a problem as error in the isolate may go unnoticed and > repeated unscheduling/re-scheduling might end up overwriting the error > in the isolate (which triggers the assertion). > > To solve this problem, this CL: > * Cleans up Dart API which manipulates isolate's sticky error, so > isolate's sticky error is never set directly. > * When sceduling an isolate to a thread, sticky error is moved back from > isolate (if any). > > With this changes, thread's sticky error is always used if thread is running, > and isolate's sticky error is only used to hold sticky error while > isolate has no thread. > > Fixes https://github.com/dart-lang/sdk/issues/35590 > > Change-Id: I99b128cac363ca2df75f6e64c083b1ec36c866ce > Reviewed-on: https://dart-review.googlesource.com/c/89442 > Reviewed-by: Ryan Macnak <rmacnak@google.com> > Commit-Queue: Alexander Markov <alexmarkov@google.com> TBR=rmacnak@google.com,alexmarkov@google.com,zra@google.com,asiva@google.com Change-Id: I15874575b6b8ddca618741c59c21d4e692c4dcab No-Presubmit: true No-Tree-Checks: true No-Try: true Reviewed-on: https://dart-review.googlesource.com/c/90127 Reviewed-by: Alexander Markov <alexmarkov@google.com> Commit-Queue: Alexander Markov <alexmarkov@google.com>
2019-01-18 01:41:18 +00:00
FATAL1("%s expects the error to be an unhandled exception error or null.",
CURRENT_FUNC);
}
isolate->SetStickyError(error_handle.ptr());
Revert "[vm] Cleanup Dart_Get/Set/HasStickyError API and use isolate's sticky error only as a backup for thread's sticky error" This reverts commit b10f17960890b053a5c1ac9303e0f9332fc8bd17. Reason for revert: failed service/* tests Original change's description: > [vm] Cleanup Dart_Get/Set/HasStickyError API and use isolate's sticky error only as a backup for thread's sticky error > > Both thread and isolate have sticky error fields. Dart API was using > isolate's sticky error, while Dart code was using thread's sticky error. > There was a one-way move of a thread's sticky error into isolate > when thread was unscheduled. > > This causes a problem as error in the isolate may go unnoticed and > repeated unscheduling/re-scheduling might end up overwriting the error > in the isolate (which triggers the assertion). > > To solve this problem, this CL: > * Cleans up Dart API which manipulates isolate's sticky error, so > isolate's sticky error is never set directly. > * When sceduling an isolate to a thread, sticky error is moved back from > isolate (if any). > > With this changes, thread's sticky error is always used if thread is running, > and isolate's sticky error is only used to hold sticky error while > isolate has no thread. > > Fixes https://github.com/dart-lang/sdk/issues/35590 > > Change-Id: I99b128cac363ca2df75f6e64c083b1ec36c866ce > Reviewed-on: https://dart-review.googlesource.com/c/89442 > Reviewed-by: Ryan Macnak <rmacnak@google.com> > Commit-Queue: Alexander Markov <alexmarkov@google.com> TBR=rmacnak@google.com,alexmarkov@google.com,zra@google.com,asiva@google.com Change-Id: I15874575b6b8ddca618741c59c21d4e692c4dcab No-Presubmit: true No-Tree-Checks: true No-Try: true Reviewed-on: https://dart-review.googlesource.com/c/90127 Reviewed-by: Alexander Markov <alexmarkov@google.com> Commit-Queue: Alexander Markov <alexmarkov@google.com>
2019-01-18 01:41:18 +00:00
}
DART_EXPORT bool Dart_HasStickyError() {
Thread* T = Thread::Current();
Isolate* isolate = T->isolate();
CHECK_ISOLATE(isolate);
NoSafepointScope no_safepoint_scope;
return isolate->sticky_error() != Error::null();
}
DART_EXPORT Dart_Handle Dart_GetStickyError() {
Thread* T = Thread::Current();
Isolate* I = T->isolate();
CHECK_ISOLATE(I);
{
NoSafepointScope no_safepoint_scope;
if (I->sticky_error() == Error::null()) {
return Api::Null();
}
Revert "[vm] Cleanup Dart_Get/Set/HasStickyError API and use isolate's sticky error only as a backup for thread's sticky error" This reverts commit b10f17960890b053a5c1ac9303e0f9332fc8bd17. Reason for revert: failed service/* tests Original change's description: > [vm] Cleanup Dart_Get/Set/HasStickyError API and use isolate's sticky error only as a backup for thread's sticky error > > Both thread and isolate have sticky error fields. Dart API was using > isolate's sticky error, while Dart code was using thread's sticky error. > There was a one-way move of a thread's sticky error into isolate > when thread was unscheduled. > > This causes a problem as error in the isolate may go unnoticed and > repeated unscheduling/re-scheduling might end up overwriting the error > in the isolate (which triggers the assertion). > > To solve this problem, this CL: > * Cleans up Dart API which manipulates isolate's sticky error, so > isolate's sticky error is never set directly. > * When sceduling an isolate to a thread, sticky error is moved back from > isolate (if any). > > With this changes, thread's sticky error is always used if thread is running, > and isolate's sticky error is only used to hold sticky error while > isolate has no thread. > > Fixes https://github.com/dart-lang/sdk/issues/35590 > > Change-Id: I99b128cac363ca2df75f6e64c083b1ec36c866ce > Reviewed-on: https://dart-review.googlesource.com/c/89442 > Reviewed-by: Ryan Macnak <rmacnak@google.com> > Commit-Queue: Alexander Markov <alexmarkov@google.com> TBR=rmacnak@google.com,alexmarkov@google.com,zra@google.com,asiva@google.com Change-Id: I15874575b6b8ddca618741c59c21d4e692c4dcab No-Presubmit: true No-Tree-Checks: true No-Try: true Reviewed-on: https://dart-review.googlesource.com/c/90127 Reviewed-by: Alexander Markov <alexmarkov@google.com> Commit-Queue: Alexander Markov <alexmarkov@google.com>
2019-01-18 01:41:18 +00:00
}
TransitionNativeToVM transition(T);
return Api::NewHandle(T, I->sticky_error());
Revert "[vm] Cleanup Dart_Get/Set/HasStickyError API and use isolate's sticky error only as a backup for thread's sticky error" This reverts commit b10f17960890b053a5c1ac9303e0f9332fc8bd17. Reason for revert: failed service/* tests Original change's description: > [vm] Cleanup Dart_Get/Set/HasStickyError API and use isolate's sticky error only as a backup for thread's sticky error > > Both thread and isolate have sticky error fields. Dart API was using > isolate's sticky error, while Dart code was using thread's sticky error. > There was a one-way move of a thread's sticky error into isolate > when thread was unscheduled. > > This causes a problem as error in the isolate may go unnoticed and > repeated unscheduling/re-scheduling might end up overwriting the error > in the isolate (which triggers the assertion). > > To solve this problem, this CL: > * Cleans up Dart API which manipulates isolate's sticky error, so > isolate's sticky error is never set directly. > * When sceduling an isolate to a thread, sticky error is moved back from > isolate (if any). > > With this changes, thread's sticky error is always used if thread is running, > and isolate's sticky error is only used to hold sticky error while > isolate has no thread. > > Fixes https://github.com/dart-lang/sdk/issues/35590 > > Change-Id: I99b128cac363ca2df75f6e64c083b1ec36c866ce > Reviewed-on: https://dart-review.googlesource.com/c/89442 > Reviewed-by: Ryan Macnak <rmacnak@google.com> > Commit-Queue: Alexander Markov <alexmarkov@google.com> TBR=rmacnak@google.com,alexmarkov@google.com,zra@google.com,asiva@google.com Change-Id: I15874575b6b8ddca618741c59c21d4e692c4dcab No-Presubmit: true No-Tree-Checks: true No-Try: true Reviewed-on: https://dart-review.googlesource.com/c/90127 Reviewed-by: Alexander Markov <alexmarkov@google.com> Commit-Queue: Alexander Markov <alexmarkov@google.com>
2019-01-18 01:41:18 +00:00
}
DART_EXPORT void Dart_NotifyIdle(int64_t deadline) {
Thread* T = Thread::Current();
CHECK_ISOLATE(T->isolate());
API_TIMELINE_BEGIN_END(T);
TransitionNativeToVM transition(T);
T->isolate()->group()->idle_time_handler()->NotifyIdle(deadline);
}
DART_EXPORT void Dart_NotifyLowMemory() {
API_TIMELINE_BEGIN_END(Thread::Current());
SemiSpace::ClearCache();
Zone::ClearCache();
// For each isolate's global variables, we might also clear:
// - RegExp backtracking stack (both bytecode and compiled versions)
// - String -> RegExp cache
// - BigInt division/remainder cache
// - double.toString cache
// But cache invalidation code might be larger than the expected size of some
// caches.
}
DART_EXPORT Dart_PerformanceMode
Dart_SetPerformanceMode(Dart_PerformanceMode mode) {
Thread* T = Thread::Current();
CHECK_ISOLATE(T->isolate());
TransitionNativeToVM transition(T);
return T->heap()->SetMode(mode);
}
DART_EXPORT void Dart_ExitIsolate() {
Thread* T = Thread::Current();
CHECK_ISOLATE(T->isolate());
// The Thread structure is disassociated from the isolate, we do the
// safepoint transition explicitly here instead of using the TransitionXXX
// scope objects as the original transition happened outside this scope in
Second attempt to reland "[vm/concurrency] Introduce concept of Isolate Groups" This reverts commit 3d14b75f972ca287cd892ff907cf04b22839af59. An Isolate Group (IG) is a collection of isolates which were spawned from the same source. This allows the VM to: * have a guarantee that all isolates within one IG can safely exchange structured objects (currently we rely on embedder for this guarantee) * hot-reload all isolates together (currently we only reload one isolate, leaving same-source isolates in inconsistent state) * make a shared heap for all isolates from the same IG, which paves the way for faster communication and sharing of immutable objects. All isolates within one IG will share the same IsolateGroupSource. **Embedder changes** This change makes breaking embedder API changes to support this new concept of Isolate Groups: The existing isolate lifecycle callbacks given to Dart_Initialize will become Isolate Group lifecycle callbacks. A new callback `initialize_isolate` callback will be added which can initialize a new isolate within an existing IG. Existing embedders can be updated by performing the following renames Dart_CreateIsolate -> Dart_CreateIsolateGroup Dart_IsolateCreateCallback -> Dart_IsolateGroupCreateCallback Dart_IsolateCleanupCallback -> Dart_IsolateGroupShutdownCallback Dart_CreateIsolateFromKernel -> Dart_CreateIsolateGroupFromKernel Dart_CurrentIsolateData -> Dart_CurrentIsolateGroupData Dart_IsolateData -> Dart_IsolateGroupData Dart_GetNativeIsolateData -> Dart_GetNativeIsolateGroupData Dart_InitializeParams.create -> Dart_InitializeParams.create_group Dart_InitializeParams.cleanup -> Dart_InitializeParams.shutdown_group Dart_InitializeParams.shutdown -> Dart_InitializeParams.shutdown_isolate By default `Isolate.spawn` will cause the creation of a new IG. Though an embedder can opt-into supporting multiple isolates within one IG by providing a callback to the newly added `Dart_InitializeParams.initialize_isolate`. The responsibility of this new callback is to initialize an existing isolate (which was setup by re-using source code from the spawning isolate - i.e. the one which used `Isolate.spawn`) by setting native resolvers, initializing global state, etc. Issue https://github.com/dart-lang/sdk/issues/36648 Issue https://github.com/dart-lang/sdk/issues/36097 Original review: https://dart-review.googlesource.com/c/sdk/+/105241 Difference to original review: * Give each isolate it's own [Loader] (for now) * Sort classes during initialization for spawned isolates if app-jit is used (to match main isolate) * Fix IsolateData memory leak if isolate startup fails Difference to first reland(Patchset 2): * Fix typo where memory was freed twice. Change-Id: Ib1c83fe83b629cd50ae6af90ee99fdd44da882d4 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/108367 Commit-Queue: Alexander Aprelev <aam@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com>
2019-07-08 23:49:05 +00:00
// Dart_EnterIsolate/Dart_CreateIsolateGroup.
ASSERT(T->execution_state() == Thread::kThreadInNative);
T->ExitSafepoint();
T->set_execution_state(Thread::kThreadInVM);
Thread::ExitIsolate();
}
DART_EXPORT Dart_Handle
Dart_CreateSnapshot(uint8_t** vm_snapshot_data_buffer,
intptr_t* vm_snapshot_data_size,
uint8_t** isolate_snapshot_data_buffer,
intptr_t* isolate_snapshot_data_size,
bool is_core) {
#if defined(DART_PRECOMPILED_RUNTIME)
return Api::NewError("Cannot create snapshots on an AOT runtime.");
#else
DARTSCOPE(Thread::Current());
API_TIMELINE_DURATION(T);
[vm] Consolidate the *WriteStream hierarchy. All *WriteStream classes are now part of the same hierarchy: class BaseWriteStream : ValueObject; Base class for all *WriteStreams. Provides all the methods from the old WriteStream except for buffer() and SetPosition() (relegated to NonStreamingWriteStreams). Has one pure virtual method Realloc that must be overridden by concrete subclasses. class NonStreamingWriteStream : BaseWriteStream; Base class for all *WriteStreams where the entire stream is available at all times (i.e., no flushing to an external sink). Extends the public BaseWriteStream API with buffer() (for accessing the stream contents) and SetPosition() (for changing the current stream pointer to the given absolute position in the stream). class MallocWriteStream : NonStreamingWriteStream; Uses realloc to reallocate the internal buffer. Almost the same as the old WriteStream, except that it only takes an initial size. Adds one public method Steal() for taking ownership of the current buffer contents (after which the buffer is reset to an empty state). Instead of passing a pointer to a buffer, the internal buffer must be accessed via either Steal() or buffer(), which allows access to the current stream contents without changing ownership or resetting the stream. The internal buffer is freed on stream destruction. class ZoneWriteStream: NonStreamingWriteStream; Takes a zone and reallocates the internal buffer in that zone. No additional public methods beyond those available from NonStreamingWriteStream. class StreamingWriteStream : BaseWriteStream; Uses realloc to reallocate the internal buffer. Generally same as before, where the contents of the stream are periodically flushed using Dart_StreamingWriteCallback. Since it extends BaseWriteStream, there are now more methods available for writing data to the stream than just Print/VPrint/WriteBytes. Since portions of the stream may be flushed and thus no longer in the internal buffer, does not provide access to the contents of the stream or a way to reposition the current stream pointer. Flushes any unflushed data and frees the internal buffer on stream destruction. Also refactor things so that write streams are passed to appropriate recipients, instead of the recipients taking arguments they only used to create a WriteStream internally. Thus, recipients now can just specify the appropriate base class for the public API used: * BaseWriteStream for just writing to the stream, or * NonStreamingWriteStream if re-positioning or the stream contents are needed. Change-Id: I419096ecd9331483d168b079fca55b69ef397f15 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/164080 Commit-Queue: Tess Strickland <sstrickl@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com>
2020-09-23 21:05:59 +00:00
if (vm_snapshot_data_buffer != nullptr) {
CHECK_NULL(vm_snapshot_data_size);
}
CHECK_NULL(isolate_snapshot_data_buffer);
CHECK_NULL(isolate_snapshot_data_size);
// Finalize all classes if needed.
Dart_Handle state = Api::CheckAndFinalizePendingClasses(T);
if (Api::IsError(state)) {
return state;
}
NoBackgroundCompilerScope no_bg_compiler(T);
#if defined(DEBUG)
T->isolate_group()->heap()->CollectAllGarbage(GCReason::kDebugging);
{
HeapIterationScope iteration(T);
CheckFunctionTypesVisitor check_canonical(T);
iteration.IterateObjects(&check_canonical);
}
#endif // #if defined(DEBUG)
[vm] Consolidate the *WriteStream hierarchy. All *WriteStream classes are now part of the same hierarchy: class BaseWriteStream : ValueObject; Base class for all *WriteStreams. Provides all the methods from the old WriteStream except for buffer() and SetPosition() (relegated to NonStreamingWriteStreams). Has one pure virtual method Realloc that must be overridden by concrete subclasses. class NonStreamingWriteStream : BaseWriteStream; Base class for all *WriteStreams where the entire stream is available at all times (i.e., no flushing to an external sink). Extends the public BaseWriteStream API with buffer() (for accessing the stream contents) and SetPosition() (for changing the current stream pointer to the given absolute position in the stream). class MallocWriteStream : NonStreamingWriteStream; Uses realloc to reallocate the internal buffer. Almost the same as the old WriteStream, except that it only takes an initial size. Adds one public method Steal() for taking ownership of the current buffer contents (after which the buffer is reset to an empty state). Instead of passing a pointer to a buffer, the internal buffer must be accessed via either Steal() or buffer(), which allows access to the current stream contents without changing ownership or resetting the stream. The internal buffer is freed on stream destruction. class ZoneWriteStream: NonStreamingWriteStream; Takes a zone and reallocates the internal buffer in that zone. No additional public methods beyond those available from NonStreamingWriteStream. class StreamingWriteStream : BaseWriteStream; Uses realloc to reallocate the internal buffer. Generally same as before, where the contents of the stream are periodically flushed using Dart_StreamingWriteCallback. Since it extends BaseWriteStream, there are now more methods available for writing data to the stream than just Print/VPrint/WriteBytes. Since portions of the stream may be flushed and thus no longer in the internal buffer, does not provide access to the contents of the stream or a way to reposition the current stream pointer. Flushes any unflushed data and frees the internal buffer on stream destruction. Also refactor things so that write streams are passed to appropriate recipients, instead of the recipients taking arguments they only used to create a WriteStream internally. Thus, recipients now can just specify the appropriate base class for the public API used: * BaseWriteStream for just writing to the stream, or * NonStreamingWriteStream if re-positioning or the stream contents are needed. Change-Id: I419096ecd9331483d168b079fca55b69ef397f15 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/164080 Commit-Queue: Tess Strickland <sstrickl@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com>
2020-09-23 21:05:59 +00:00
ZoneWriteStream vm_snapshot_data(Api::TopScope(T)->zone(),
FullSnapshotWriter::kInitialSize);
ZoneWriteStream isolate_snapshot_data(Api::TopScope(T)->zone(),
FullSnapshotWriter::kInitialSize);
const Snapshot::Kind snapshot_kind =
is_core ? Snapshot::kFullCore : Snapshot::kFull;
[vm] Consolidate the *WriteStream hierarchy. All *WriteStream classes are now part of the same hierarchy: class BaseWriteStream : ValueObject; Base class for all *WriteStreams. Provides all the methods from the old WriteStream except for buffer() and SetPosition() (relegated to NonStreamingWriteStreams). Has one pure virtual method Realloc that must be overridden by concrete subclasses. class NonStreamingWriteStream : BaseWriteStream; Base class for all *WriteStreams where the entire stream is available at all times (i.e., no flushing to an external sink). Extends the public BaseWriteStream API with buffer() (for accessing the stream contents) and SetPosition() (for changing the current stream pointer to the given absolute position in the stream). class MallocWriteStream : NonStreamingWriteStream; Uses realloc to reallocate the internal buffer. Almost the same as the old WriteStream, except that it only takes an initial size. Adds one public method Steal() for taking ownership of the current buffer contents (after which the buffer is reset to an empty state). Instead of passing a pointer to a buffer, the internal buffer must be accessed via either Steal() or buffer(), which allows access to the current stream contents without changing ownership or resetting the stream. The internal buffer is freed on stream destruction. class ZoneWriteStream: NonStreamingWriteStream; Takes a zone and reallocates the internal buffer in that zone. No additional public methods beyond those available from NonStreamingWriteStream. class StreamingWriteStream : BaseWriteStream; Uses realloc to reallocate the internal buffer. Generally same as before, where the contents of the stream are periodically flushed using Dart_StreamingWriteCallback. Since it extends BaseWriteStream, there are now more methods available for writing data to the stream than just Print/VPrint/WriteBytes. Since portions of the stream may be flushed and thus no longer in the internal buffer, does not provide access to the contents of the stream or a way to reposition the current stream pointer. Flushes any unflushed data and frees the internal buffer on stream destruction. Also refactor things so that write streams are passed to appropriate recipients, instead of the recipients taking arguments they only used to create a WriteStream internally. Thus, recipients now can just specify the appropriate base class for the public API used: * BaseWriteStream for just writing to the stream, or * NonStreamingWriteStream if re-positioning or the stream contents are needed. Change-Id: I419096ecd9331483d168b079fca55b69ef397f15 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/164080 Commit-Queue: Tess Strickland <sstrickl@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com>
2020-09-23 21:05:59 +00:00
FullSnapshotWriter writer(
snapshot_kind, &vm_snapshot_data, &isolate_snapshot_data,
[vm] Consolidate the *WriteStream hierarchy. All *WriteStream classes are now part of the same hierarchy: class BaseWriteStream : ValueObject; Base class for all *WriteStreams. Provides all the methods from the old WriteStream except for buffer() and SetPosition() (relegated to NonStreamingWriteStreams). Has one pure virtual method Realloc that must be overridden by concrete subclasses. class NonStreamingWriteStream : BaseWriteStream; Base class for all *WriteStreams where the entire stream is available at all times (i.e., no flushing to an external sink). Extends the public BaseWriteStream API with buffer() (for accessing the stream contents) and SetPosition() (for changing the current stream pointer to the given absolute position in the stream). class MallocWriteStream : NonStreamingWriteStream; Uses realloc to reallocate the internal buffer. Almost the same as the old WriteStream, except that it only takes an initial size. Adds one public method Steal() for taking ownership of the current buffer contents (after which the buffer is reset to an empty state). Instead of passing a pointer to a buffer, the internal buffer must be accessed via either Steal() or buffer(), which allows access to the current stream contents without changing ownership or resetting the stream. The internal buffer is freed on stream destruction. class ZoneWriteStream: NonStreamingWriteStream; Takes a zone and reallocates the internal buffer in that zone. No additional public methods beyond those available from NonStreamingWriteStream. class StreamingWriteStream : BaseWriteStream; Uses realloc to reallocate the internal buffer. Generally same as before, where the contents of the stream are periodically flushed using Dart_StreamingWriteCallback. Since it extends BaseWriteStream, there are now more methods available for writing data to the stream than just Print/VPrint/WriteBytes. Since portions of the stream may be flushed and thus no longer in the internal buffer, does not provide access to the contents of the stream or a way to reposition the current stream pointer. Flushes any unflushed data and frees the internal buffer on stream destruction. Also refactor things so that write streams are passed to appropriate recipients, instead of the recipients taking arguments they only used to create a WriteStream internally. Thus, recipients now can just specify the appropriate base class for the public API used: * BaseWriteStream for just writing to the stream, or * NonStreamingWriteStream if re-positioning or the stream contents are needed. Change-Id: I419096ecd9331483d168b079fca55b69ef397f15 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/164080 Commit-Queue: Tess Strickland <sstrickl@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com>
2020-09-23 21:05:59 +00:00
nullptr /* vm_image_writer */, nullptr /* isolate_image_writer */);
writer.WriteFullSnapshot();
[vm] Consolidate the *WriteStream hierarchy. All *WriteStream classes are now part of the same hierarchy: class BaseWriteStream : ValueObject; Base class for all *WriteStreams. Provides all the methods from the old WriteStream except for buffer() and SetPosition() (relegated to NonStreamingWriteStreams). Has one pure virtual method Realloc that must be overridden by concrete subclasses. class NonStreamingWriteStream : BaseWriteStream; Base class for all *WriteStreams where the entire stream is available at all times (i.e., no flushing to an external sink). Extends the public BaseWriteStream API with buffer() (for accessing the stream contents) and SetPosition() (for changing the current stream pointer to the given absolute position in the stream). class MallocWriteStream : NonStreamingWriteStream; Uses realloc to reallocate the internal buffer. Almost the same as the old WriteStream, except that it only takes an initial size. Adds one public method Steal() for taking ownership of the current buffer contents (after which the buffer is reset to an empty state). Instead of passing a pointer to a buffer, the internal buffer must be accessed via either Steal() or buffer(), which allows access to the current stream contents without changing ownership or resetting the stream. The internal buffer is freed on stream destruction. class ZoneWriteStream: NonStreamingWriteStream; Takes a zone and reallocates the internal buffer in that zone. No additional public methods beyond those available from NonStreamingWriteStream. class StreamingWriteStream : BaseWriteStream; Uses realloc to reallocate the internal buffer. Generally same as before, where the contents of the stream are periodically flushed using Dart_StreamingWriteCallback. Since it extends BaseWriteStream, there are now more methods available for writing data to the stream than just Print/VPrint/WriteBytes. Since portions of the stream may be flushed and thus no longer in the internal buffer, does not provide access to the contents of the stream or a way to reposition the current stream pointer. Flushes any unflushed data and frees the internal buffer on stream destruction. Also refactor things so that write streams are passed to appropriate recipients, instead of the recipients taking arguments they only used to create a WriteStream internally. Thus, recipients now can just specify the appropriate base class for the public API used: * BaseWriteStream for just writing to the stream, or * NonStreamingWriteStream if re-positioning or the stream contents are needed. Change-Id: I419096ecd9331483d168b079fca55b69ef397f15 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/164080 Commit-Queue: Tess Strickland <sstrickl@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com>
2020-09-23 21:05:59 +00:00
if (vm_snapshot_data_buffer != nullptr) {
*vm_snapshot_data_buffer = vm_snapshot_data.buffer();
*vm_snapshot_data_size = writer.VmIsolateSnapshotSize();
}
[vm] Consolidate the *WriteStream hierarchy. All *WriteStream classes are now part of the same hierarchy: class BaseWriteStream : ValueObject; Base class for all *WriteStreams. Provides all the methods from the old WriteStream except for buffer() and SetPosition() (relegated to NonStreamingWriteStreams). Has one pure virtual method Realloc that must be overridden by concrete subclasses. class NonStreamingWriteStream : BaseWriteStream; Base class for all *WriteStreams where the entire stream is available at all times (i.e., no flushing to an external sink). Extends the public BaseWriteStream API with buffer() (for accessing the stream contents) and SetPosition() (for changing the current stream pointer to the given absolute position in the stream). class MallocWriteStream : NonStreamingWriteStream; Uses realloc to reallocate the internal buffer. Almost the same as the old WriteStream, except that it only takes an initial size. Adds one public method Steal() for taking ownership of the current buffer contents (after which the buffer is reset to an empty state). Instead of passing a pointer to a buffer, the internal buffer must be accessed via either Steal() or buffer(), which allows access to the current stream contents without changing ownership or resetting the stream. The internal buffer is freed on stream destruction. class ZoneWriteStream: NonStreamingWriteStream; Takes a zone and reallocates the internal buffer in that zone. No additional public methods beyond those available from NonStreamingWriteStream. class StreamingWriteStream : BaseWriteStream; Uses realloc to reallocate the internal buffer. Generally same as before, where the contents of the stream are periodically flushed using Dart_StreamingWriteCallback. Since it extends BaseWriteStream, there are now more methods available for writing data to the stream than just Print/VPrint/WriteBytes. Since portions of the stream may be flushed and thus no longer in the internal buffer, does not provide access to the contents of the stream or a way to reposition the current stream pointer. Flushes any unflushed data and frees the internal buffer on stream destruction. Also refactor things so that write streams are passed to appropriate recipients, instead of the recipients taking arguments they only used to create a WriteStream internally. Thus, recipients now can just specify the appropriate base class for the public API used: * BaseWriteStream for just writing to the stream, or * NonStreamingWriteStream if re-positioning or the stream contents are needed. Change-Id: I419096ecd9331483d168b079fca55b69ef397f15 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/164080 Commit-Queue: Tess Strickland <sstrickl@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com>
2020-09-23 21:05:59 +00:00
*isolate_snapshot_data_buffer = isolate_snapshot_data.buffer();
*isolate_snapshot_data_size = writer.IsolateSnapshotSize();
return Api::Success();
#endif
}
DART_EXPORT bool Dart_IsKernel(const uint8_t* buffer, intptr_t buffer_size) {
if (buffer_size < 4) {
return false;
}
return (buffer[0] == 0x90) && (buffer[1] == 0xab) && (buffer[2] == 0xcd) &&
(buffer[3] == 0xef);
}
DART_EXPORT char* Dart_IsolateMakeRunnable(Dart_Isolate isolate) {
CHECK_NO_ISOLATE(Isolate::Current());
API_TIMELINE_DURATION(Thread::Current());
if (isolate == NULL) {
FATAL1("%s expects argument 'isolate' to be non-null.", CURRENT_FUNC);
}
// TODO(16615): Validate isolate parameter.
[vm/concurrency] Fix inconsistency in Dart's spawn implementation When Dart invokes Isolate.spawn the Dart VM calls out to the embedder to create an isolate (group) or initialize it (in case of lightweight isolates). * If the embedder doesn't implement this functionality or fails to perform the creation/initialization, it will signal this failure via the return value it gives to the VM in the call back implementation (i.e. Dart_InitializeParams.create_group and Dart_InitializeParams.initialize_isolate}). * If the embeder sucessfully completed it's work, the VM owns the isolate after the embedder call returns. The VM is then responsible for running it. It is an undocumented invariant atm that the embedder is responsible to make the isolate runnable if it signals the VM that isolate was sucessfully created/initialized. => If it does not do that, we have effectively an isolate leak. => Though right now seemingly all of our embedders to that correctly. To avoid this unintentional isolate leak we make the isolate runnable ourselves if embedder callback was successful but did not make it runnable itself. => This also avoids unnecessary ceremony code in the embedders that look like this: Dart_ExitIsolate(); Dart_IsolateMakeRunnable(child); Dart_EnterIsolate(child); The implementation of `Dart_IsolateMakeRunnable()` had an untested and unused code path that caused running the isolate (on a thread pool). This is not documented and can lead to bugs because often the embedders enter the isolate right after making it runnable (e.g. above code sequence) - which would be racing with the spawned message handler thread. => Furtunately our embedders are well behaved and make the isolate runnable during the callback. => As a safeguard we'll make `Dart_IsolateMakeRunnable()` return an error if it's called outside the callback (which we can detect by the presense of a spawn state) Issue https://github.com/dart-lang/sdk/issues/44088 Issue https://github.com/dart-lang/sdk/issues/36097 TEST=Changes internal details of implementation which is already covered by tests. Change-Id: Ieef316cc0807d99f2fcb1fbd56bbc9c41e904ba8 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/170882 Commit-Queue: Martin Kustermann <kustermann@google.com> Reviewed-by: Alexander Aprelev <aam@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com>
2020-11-12 08:49:38 +00:00
const char* error = reinterpret_cast<Isolate*>(isolate)->MakeRunnable();
if (error != nullptr) {
return Utils::StrDup(error);
}
[vm/concurrency] Fix inconsistency in Dart's spawn implementation When Dart invokes Isolate.spawn the Dart VM calls out to the embedder to create an isolate (group) or initialize it (in case of lightweight isolates). * If the embedder doesn't implement this functionality or fails to perform the creation/initialization, it will signal this failure via the return value it gives to the VM in the call back implementation (i.e. Dart_InitializeParams.create_group and Dart_InitializeParams.initialize_isolate}). * If the embeder sucessfully completed it's work, the VM owns the isolate after the embedder call returns. The VM is then responsible for running it. It is an undocumented invariant atm that the embedder is responsible to make the isolate runnable if it signals the VM that isolate was sucessfully created/initialized. => If it does not do that, we have effectively an isolate leak. => Though right now seemingly all of our embedders to that correctly. To avoid this unintentional isolate leak we make the isolate runnable ourselves if embedder callback was successful but did not make it runnable itself. => This also avoids unnecessary ceremony code in the embedders that look like this: Dart_ExitIsolate(); Dart_IsolateMakeRunnable(child); Dart_EnterIsolate(child); The implementation of `Dart_IsolateMakeRunnable()` had an untested and unused code path that caused running the isolate (on a thread pool). This is not documented and can lead to bugs because often the embedders enter the isolate right after making it runnable (e.g. above code sequence) - which would be racing with the spawned message handler thread. => Furtunately our embedders are well behaved and make the isolate runnable during the callback. => As a safeguard we'll make `Dart_IsolateMakeRunnable()` return an error if it's called outside the callback (which we can detect by the presense of a spawn state) Issue https://github.com/dart-lang/sdk/issues/44088 Issue https://github.com/dart-lang/sdk/issues/36097 TEST=Changes internal details of implementation which is already covered by tests. Change-Id: Ieef316cc0807d99f2fcb1fbd56bbc9c41e904ba8 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/170882 Commit-Queue: Martin Kustermann <kustermann@google.com> Reviewed-by: Alexander Aprelev <aam@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com>
2020-11-12 08:49:38 +00:00
return nullptr;
}
// --- Messages and Ports ---
DART_EXPORT void Dart_SetMessageNotifyCallback(
Dart_MessageNotifyCallback message_notify_callback) {
Allow embedders to provide custom message delivery for an isolate. ============== Added Dart_SetPostMessageCallback and Dart_SetClosePortCallback. These allow the embedder to provide custom message/port behavior for their application. The vm provides standard implementations that work with the standard run loop. Added Dart_HandleMessage, which processes one message on the current isolate. Embedders can use this to write their own message processing loops. Rewrote code to use this internally. Added Isolate::StandardRunLoop() to share code between Dart_RunLoop and lib/isolate.cc Changed the interface to PortMap::PostMessage. PostMessage is now agnostic to message delivery mechanism. Note that PortMap is now out of the "ReceiveMessage" business entirely. Moved MessageQueue and friends out to message_queue.cc/h. Moved the monitor from the Isolate into the MessageQueue. No need for outsiders to mess. Added MessageQueue::Wait. Moved monitor locking from PortMap into MessageQueue itself, which was easier for me to reason about. Wrote some tests. Removed PortMessage::Handle. The code turned into Dart_HandleMessage. Regularized the nomenclature around ports. Type is now always Dart_Port instead of intptr_t. Variables end in _port instead of _id. Use the term "dest" instead of "target" or "send". Added a family of new tests to port_test. Added EXPECT_NE to the test framework. Review URL: http://codereview.chromium.org//8297004 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@516 260f80e4-7a28-3924-810f-c04153c831b5
2011-10-18 17:54:07 +00:00
Isolate* isolate = Isolate::Current();
CHECK_ISOLATE(isolate);
{
NoSafepointScope no_safepoint_scope;
isolate->set_message_notify_callback(message_notify_callback);
}
if (message_notify_callback != nullptr && isolate->HasPendingMessages()) {
::Dart_ExitIsolate();
// If a new handler gets installed and there are pending messages in the
// queue (e.g. OOB messages for doing vm service work) we need to notify
// the newly registered callback, otherwise the embedder might never get
// notified about the pending messages.
message_notify_callback(Api::CastIsolate(isolate));
::Dart_EnterIsolate(Api::CastIsolate(isolate));
}
Allow embedders to provide custom message delivery for an isolate. ============== Added Dart_SetPostMessageCallback and Dart_SetClosePortCallback. These allow the embedder to provide custom message/port behavior for their application. The vm provides standard implementations that work with the standard run loop. Added Dart_HandleMessage, which processes one message on the current isolate. Embedders can use this to write their own message processing loops. Rewrote code to use this internally. Added Isolate::StandardRunLoop() to share code between Dart_RunLoop and lib/isolate.cc Changed the interface to PortMap::PostMessage. PostMessage is now agnostic to message delivery mechanism. Note that PortMap is now out of the "ReceiveMessage" business entirely. Moved MessageQueue and friends out to message_queue.cc/h. Moved the monitor from the Isolate into the MessageQueue. No need for outsiders to mess. Added MessageQueue::Wait. Moved monitor locking from PortMap into MessageQueue itself, which was easier for me to reason about. Wrote some tests. Removed PortMessage::Handle. The code turned into Dart_HandleMessage. Regularized the nomenclature around ports. Type is now always Dart_Port instead of intptr_t. Variables end in _port instead of _id. Use the term "dest" instead of "target" or "send". Added a family of new tests to port_test. Added EXPECT_NE to the test framework. Review URL: http://codereview.chromium.org//8297004 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@516 260f80e4-7a28-3924-810f-c04153c831b5
2011-10-18 17:54:07 +00:00
}
DART_EXPORT Dart_MessageNotifyCallback Dart_GetMessageNotifyCallback() {
Isolate* isolate = Isolate::Current();
CHECK_ISOLATE(isolate);
NoSafepointScope no_safepoint_scope;
return isolate->message_notify_callback();
}
struct RunLoopData {
Monitor* monitor;
bool done;
};
static void RunLoopDone(uword param) {
RunLoopData* data = reinterpret_cast<RunLoopData*>(param);
ASSERT(data->monitor != NULL);
MonitorLocker ml(data->monitor);
data->done = true;
ml.Notify();
}
DART_EXPORT Dart_Handle Dart_RunLoop() {
Isolate* I;
bool result;
{
Thread* T = Thread::Current();
I = T->isolate();
CHECK_API_SCOPE(T);
CHECK_CALLBACK_STATE(T);
}
API_TIMELINE_BEGIN_END(Thread::Current());
// The message handler run loop does not expect to have a current isolate
// so we exit the isolate here and enter it again after the runloop is done.
::Dart_ExitIsolate();
{
Monitor monitor;
MonitorLocker ml(&monitor);
RunLoopData data;
data.monitor = &monitor;
data.done = false;
result =
I->message_handler()->Run(I->group()->thread_pool(), NULL, RunLoopDone,
reinterpret_cast<uword>(&data));
if (result) {
while (!data.done) {
ml.Wait();
}
}
}
::Dart_EnterIsolate(Api::CastIsolate(I));
if (!result) {
Thread* T = Thread::Current();
TransitionNativeToVM transition(T);
return Api::NewError("Run method in isolate message handler failed");
} else if (I->sticky_error() != Object::null()) {
Thread* T = Thread::Current();
Revert "[vm] Cleanup Dart_Get/Set/HasStickyError API and use isolate's sticky error only as a backup for thread's sticky error" This reverts commit b10f17960890b053a5c1ac9303e0f9332fc8bd17. Reason for revert: failed service/* tests Original change's description: > [vm] Cleanup Dart_Get/Set/HasStickyError API and use isolate's sticky error only as a backup for thread's sticky error > > Both thread and isolate have sticky error fields. Dart API was using > isolate's sticky error, while Dart code was using thread's sticky error. > There was a one-way move of a thread's sticky error into isolate > when thread was unscheduled. > > This causes a problem as error in the isolate may go unnoticed and > repeated unscheduling/re-scheduling might end up overwriting the error > in the isolate (which triggers the assertion). > > To solve this problem, this CL: > * Cleans up Dart API which manipulates isolate's sticky error, so > isolate's sticky error is never set directly. > * When sceduling an isolate to a thread, sticky error is moved back from > isolate (if any). > > With this changes, thread's sticky error is always used if thread is running, > and isolate's sticky error is only used to hold sticky error while > isolate has no thread. > > Fixes https://github.com/dart-lang/sdk/issues/35590 > > Change-Id: I99b128cac363ca2df75f6e64c083b1ec36c866ce > Reviewed-on: https://dart-review.googlesource.com/c/89442 > Reviewed-by: Ryan Macnak <rmacnak@google.com> > Commit-Queue: Alexander Markov <alexmarkov@google.com> TBR=rmacnak@google.com,alexmarkov@google.com,zra@google.com,asiva@google.com Change-Id: I15874575b6b8ddca618741c59c21d4e692c4dcab No-Presubmit: true No-Tree-Checks: true No-Try: true Reviewed-on: https://dart-review.googlesource.com/c/90127 Reviewed-by: Alexander Markov <alexmarkov@google.com> Commit-Queue: Alexander Markov <alexmarkov@google.com>
2019-01-18 01:41:18 +00:00
TransitionNativeToVM transition(T);
return Api::NewHandle(T, I->StealStickyError());
}
if (FLAG_print_class_table) {
HANDLESCOPE(Thread::Current());
I->group()->class_table()->Print();
}
return Api::Success();
}
[vm/concurrency] Add Dart_CreateLightweightIsolate/Dart_RunLoopAsync APIs Dart_CreateLightweightIsolate API: This API can be used by embedders to create a lightweight isolate (inside an existing isolate group). It is the analogous to Dart_CreateIsolateGroup - though taking a parent isolate as parameter (inside whose IG we create a new isolate) instead of taking kernel/snapshot data. Right now this API works on AOT and returns an error in JIT, both cases are covered by the test. Dart_RunLoopAsync: The API can be used by embedders to transfer ownership of an isolate to the VM, which will take care of running the message handling loop and shuts the isolate down once the last receive port has been closed. It does allow listening to error/exit events generated by the message loop implementation as well as allows setting errors-are-fatal, effectively the same event-loop related parameters from the `Isolate.spawn()` API, just in Dart. It's the embedders responsibility to first launch initial dart code which will take care of responding to events (i.e. directly/indirectly open a receive port) - otherwise the isolate cannot be talked to and would immediately shut down. Since our vm/cc tests do support running in AOT, we use a hybrid approach to test the functionality: We let a normal Dart test call a small C wrapper using FFI, to create a lightweight isolate, run it on a new thread and join that thread. TEST=vm/dart{,_2}/isolates/dart_api_create_lightweight_isolate_test Issue https://github.com/dart-lang/sdk/issues/36097 Closes https://github.com/dart-lang/sdk/issues/44088 Change-Id: Id77ba928793fdb517f6cb7e8130df98a0366ddd6 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/170983 Commit-Queue: Martin Kustermann <kustermann@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com> Reviewed-by: Alexander Aprelev <aam@google.com>
2020-11-12 10:22:16 +00:00
DART_EXPORT bool Dart_RunLoopAsync(bool errors_are_fatal,
Dart_Port on_error_port,
Dart_Port on_exit_port,
char** error) {
auto thread = Thread::Current();
auto isolate = thread->isolate();
CHECK_ISOLATE(isolate);
*error = nullptr;
if (thread->api_top_scope() != nullptr) {
*error = Utils::StrDup("There must not be an active api scope.");
return false;
}
if (!isolate->is_runnable()) {
const char* error_msg = isolate->MakeRunnable();
if (error_msg != nullptr) {
*error = Utils::StrDup(error_msg);
return false;
}
}
isolate->SetErrorsFatal(errors_are_fatal);
if (on_error_port != ILLEGAL_PORT || on_exit_port != ILLEGAL_PORT) {
auto thread = Thread::Current();
TransitionNativeToVM transition(thread);
StackZone zone(thread);
if (on_error_port != ILLEGAL_PORT) {
const auto& port =
SendPort::Handle(thread->zone(), SendPort::New(on_error_port));
isolate->AddErrorListener(port);
}
if (on_exit_port != ILLEGAL_PORT) {
const auto& port =
SendPort::Handle(thread->zone(), SendPort::New(on_exit_port));
isolate->AddExitListener(port, Instance::null_instance());
}
}
Dart_ExitIsolate();
isolate->Run();
[vm/concurrency] Add Dart_CreateLightweightIsolate/Dart_RunLoopAsync APIs Dart_CreateLightweightIsolate API: This API can be used by embedders to create a lightweight isolate (inside an existing isolate group). It is the analogous to Dart_CreateIsolateGroup - though taking a parent isolate as parameter (inside whose IG we create a new isolate) instead of taking kernel/snapshot data. Right now this API works on AOT and returns an error in JIT, both cases are covered by the test. Dart_RunLoopAsync: The API can be used by embedders to transfer ownership of an isolate to the VM, which will take care of running the message handling loop and shuts the isolate down once the last receive port has been closed. It does allow listening to error/exit events generated by the message loop implementation as well as allows setting errors-are-fatal, effectively the same event-loop related parameters from the `Isolate.spawn()` API, just in Dart. It's the embedders responsibility to first launch initial dart code which will take care of responding to events (i.e. directly/indirectly open a receive port) - otherwise the isolate cannot be talked to and would immediately shut down. Since our vm/cc tests do support running in AOT, we use a hybrid approach to test the functionality: We let a normal Dart test call a small C wrapper using FFI, to create a lightweight isolate, run it on a new thread and join that thread. TEST=vm/dart{,_2}/isolates/dart_api_create_lightweight_isolate_test Issue https://github.com/dart-lang/sdk/issues/36097 Closes https://github.com/dart-lang/sdk/issues/44088 Change-Id: Id77ba928793fdb517f6cb7e8130df98a0366ddd6 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/170983 Commit-Queue: Martin Kustermann <kustermann@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com> Reviewed-by: Alexander Aprelev <aam@google.com>
2020-11-12 10:22:16 +00:00
return true;
}
DART_EXPORT Dart_Handle Dart_HandleMessage() {
Thread* T = Thread::Current();
Isolate* I = T->isolate();
CHECK_API_SCOPE(T);
CHECK_CALLBACK_STATE(T);
API_TIMELINE_BEGIN_END(T);
TransitionNativeToVM transition(T);
if (I->message_handler()->HandleNextMessage() != MessageHandler::kOK) {
return Api::NewHandle(T, T->StealStickyError());
}
return Api::Success();
Allow embedders to provide custom message delivery for an isolate. ============== Added Dart_SetPostMessageCallback and Dart_SetClosePortCallback. These allow the embedder to provide custom message/port behavior for their application. The vm provides standard implementations that work with the standard run loop. Added Dart_HandleMessage, which processes one message on the current isolate. Embedders can use this to write their own message processing loops. Rewrote code to use this internally. Added Isolate::StandardRunLoop() to share code between Dart_RunLoop and lib/isolate.cc Changed the interface to PortMap::PostMessage. PostMessage is now agnostic to message delivery mechanism. Note that PortMap is now out of the "ReceiveMessage" business entirely. Moved MessageQueue and friends out to message_queue.cc/h. Moved the monitor from the Isolate into the MessageQueue. No need for outsiders to mess. Added MessageQueue::Wait. Moved monitor locking from PortMap into MessageQueue itself, which was easier for me to reason about. Wrote some tests. Removed PortMessage::Handle. The code turned into Dart_HandleMessage. Regularized the nomenclature around ports. Type is now always Dart_Port instead of intptr_t. Variables end in _port instead of _id. Use the term "dest" instead of "target" or "send". Added a family of new tests to port_test. Added EXPECT_NE to the test framework. Review URL: http://codereview.chromium.org//8297004 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@516 260f80e4-7a28-3924-810f-c04153c831b5
2011-10-18 17:54:07 +00:00
}
DART_EXPORT Dart_Handle Dart_WaitForEvent(int64_t timeout_millis) {
Thread* T = Thread::Current();
Isolate* I = T->isolate();
CHECK_API_SCOPE(T);
CHECK_CALLBACK_STATE(T);
API_TIMELINE_BEGIN_END(T);
TransitionNativeToVM transition(T);
if (I->message_notify_callback() != NULL) {
return Api::NewError("waitForEventSync is not supported by this embedder");
}
Object& result =
Object::Handle(Z, DartLibraryCalls::EnsureScheduleImmediate());
if (result.IsError()) {
return Api::NewHandle(T, result.ptr());
}
// Drain the microtask queue. Propagate any errors to the entry frame.
result = DartLibraryCalls::DrainMicrotaskQueue();
if (result.IsError()) {
// Persist the error across unwiding scopes before propagating.
const Error* error;
{
NoSafepointScope no_safepoint;
ErrorPtr raw_error = Error::Cast(result).ptr();
T->UnwindScopes(T->top_exit_frame_info());
error = &Error::Handle(T->zone(), raw_error);
}
Exceptions::PropagateToEntry(*error);
UNREACHABLE();
return Api::NewError("Unreachable");
}
// Block to wait for messages and then handle them. Propagate any errors to
// the entry frame.
if (I->message_handler()->PauseAndHandleAllMessages(timeout_millis) !=
MessageHandler::kOK) {
// Persist the error across unwiding scopes before propagating.
const Error* error;
{
NoSafepointScope no_safepoint;
ErrorPtr raw_error = T->StealStickyError();
T->UnwindScopes(T->top_exit_frame_info());
error = &Error::Handle(T->zone(), raw_error);
}
Exceptions::PropagateToEntry(*error);
UNREACHABLE();
return Api::NewError("Unreachable");
}
return Api::Success();
}
DART_EXPORT bool Dart_HandleServiceMessages() {
#if defined(PRODUCT)
return true;
#else
Thread* T = Thread::Current();
Isolate* I = T->isolate();
CHECK_API_SCOPE(T);
CHECK_CALLBACK_STATE(T);
API_TIMELINE_DURATION(T);
TransitionNativeToVM transition(T);
ASSERT(I->GetAndClearResumeRequest() == false);
MessageHandler::MessageStatus status =
I->message_handler()->HandleOOBMessages();
bool resume = I->GetAndClearResumeRequest();
return (status != MessageHandler::kOK) || resume;
#endif
}
DART_EXPORT bool Dart_HasServiceMessages() {
#if defined(PRODUCT)
return false;
#else
Isolate* isolate = Isolate::Current();
ASSERT(isolate);
NoSafepointScope no_safepoint_scope;
return isolate->message_handler()->HasOOBMessages();
#endif
}
Add a mid-sized integration test for the Dart Embedding Api which demonstrates how to create a custom isolate abstraction. In this test, we use an event queue to share a single thread among our custom isolates. Add a callback which allows embedders to see when a port is created. Not sure if I should keep this or not. New apis: Dart_CreatePort() -- allocates a port id and adds a port->isolate mapping. Dart_IsolateHasActivePorts() -- does the current isolate have open ports? (this name a bit awkward...) Bail out of PortMap::ClosePorts() early if there are no open ports. This suppresses calls to the close_port_callback when there are no open ports. Use DART_CHECK_VALID to provide better error output when the test lib has errors. ------------------------- Sample output of the test: -- (isolate=0x815600) Constructing isolate -- Enter: CustomIsolateImpl_start -- -- Adding port (7111) -> isolate (0x830800) -- -- Adding StartEvent to queue -- -- Exit: CustomIsolateImpl_start -- -- Adding port (7112) -> isolate (0x815600) -- -- Posting message dest(7111) reply(0) -- -- Adding MessageEvent to queue -- -- Starting event loop -- >> StartEvent with isolate(0x830800)-- -- (isolate=0x830800) Running isolateMain $$ MessageEvent with dest port 7111-- -- (isolate=0x830800) Received: 42 -- Posting message dest(7112) reply(0) -- -- Adding MessageEvent to queue -- $$ MessageEvent with dest port 7112-- -- Closing port (7112) -- -- Adding ShutdownEvent to queue -- -- (isolate=0x815600) Received: 43 << ShutdownEvent with isolate(0x815600)-- -- Finished event loop -- Review URL: http://codereview.chromium.org//8588040 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@1906 260f80e4-7a28-3924-810f-c04153c831b5
2011-11-29 21:55:13 +00:00
DART_EXPORT bool Dart_HasLivePorts() {
Isolate* isolate = Isolate::Current();
ASSERT(isolate);
NoSafepointScope no_safepoint_scope;
return isolate->message_handler()->HasLivePorts();
Add a mid-sized integration test for the Dart Embedding Api which demonstrates how to create a custom isolate abstraction. In this test, we use an event queue to share a single thread among our custom isolates. Add a callback which allows embedders to see when a port is created. Not sure if I should keep this or not. New apis: Dart_CreatePort() -- allocates a port id and adds a port->isolate mapping. Dart_IsolateHasActivePorts() -- does the current isolate have open ports? (this name a bit awkward...) Bail out of PortMap::ClosePorts() early if there are no open ports. This suppresses calls to the close_port_callback when there are no open ports. Use DART_CHECK_VALID to provide better error output when the test lib has errors. ------------------------- Sample output of the test: -- (isolate=0x815600) Constructing isolate -- Enter: CustomIsolateImpl_start -- -- Adding port (7111) -> isolate (0x830800) -- -- Adding StartEvent to queue -- -- Exit: CustomIsolateImpl_start -- -- Adding port (7112) -> isolate (0x815600) -- -- Posting message dest(7111) reply(0) -- -- Adding MessageEvent to queue -- -- Starting event loop -- >> StartEvent with isolate(0x830800)-- -- (isolate=0x830800) Running isolateMain $$ MessageEvent with dest port 7111-- -- (isolate=0x830800) Received: 42 -- Posting message dest(7112) reply(0) -- -- Adding MessageEvent to queue -- $$ MessageEvent with dest port 7112-- -- Closing port (7112) -- -- Adding ShutdownEvent to queue -- -- (isolate=0x815600) Received: 43 << ShutdownEvent with isolate(0x815600)-- -- Finished event loop -- Review URL: http://codereview.chromium.org//8588040 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@1906 260f80e4-7a28-3924-810f-c04153c831b5
2011-11-29 21:55:13 +00:00
}
DART_EXPORT bool Dart_Post(Dart_Port port_id, Dart_Handle handle) {
DARTSCOPE(Thread::Current());
API_TIMELINE_DURATION(T);
NoSafepointScope no_safepoint_scope;
if (port_id == ILLEGAL_PORT) {
return false;
}
const Object& object = Object::Handle(Z, Api::UnwrapHandle(handle));
return PortMap::PostMessage(WriteMessage(/* can_send_any_object */ false,
/* same_group */ false, object,
port_id, Message::kNormalPriority));
Add a mid-sized integration test for the Dart Embedding Api which demonstrates how to create a custom isolate abstraction. In this test, we use an event queue to share a single thread among our custom isolates. Add a callback which allows embedders to see when a port is created. Not sure if I should keep this or not. New apis: Dart_CreatePort() -- allocates a port id and adds a port->isolate mapping. Dart_IsolateHasActivePorts() -- does the current isolate have open ports? (this name a bit awkward...) Bail out of PortMap::ClosePorts() early if there are no open ports. This suppresses calls to the close_port_callback when there are no open ports. Use DART_CHECK_VALID to provide better error output when the test lib has errors. ------------------------- Sample output of the test: -- (isolate=0x815600) Constructing isolate -- Enter: CustomIsolateImpl_start -- -- Adding port (7111) -> isolate (0x830800) -- -- Adding StartEvent to queue -- -- Exit: CustomIsolateImpl_start -- -- Adding port (7112) -> isolate (0x815600) -- -- Posting message dest(7111) reply(0) -- -- Adding MessageEvent to queue -- -- Starting event loop -- >> StartEvent with isolate(0x830800)-- -- (isolate=0x830800) Running isolateMain $$ MessageEvent with dest port 7111-- -- (isolate=0x830800) Received: 42 -- Posting message dest(7112) reply(0) -- -- Adding MessageEvent to queue -- $$ MessageEvent with dest port 7112-- -- Closing port (7112) -- -- Adding ShutdownEvent to queue -- -- (isolate=0x815600) Received: 43 << ShutdownEvent with isolate(0x815600)-- -- Finished event loop -- Review URL: http://codereview.chromium.org//8588040 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@1906 260f80e4-7a28-3924-810f-c04153c831b5
2011-11-29 21:55:13 +00:00
}
DART_EXPORT Dart_Handle Dart_NewSendPort(Dart_Port port_id) {
DARTSCOPE(Thread::Current());
CHECK_CALLBACK_STATE(T);
if (port_id == ILLEGAL_PORT) {
return Api::NewError("%s: illegal port_id %" Pd64 ".", CURRENT_FUNC,
port_id);
}
return Api::NewHandle(T, SendPort::New(port_id));
Add a mid-sized integration test for the Dart Embedding Api which demonstrates how to create a custom isolate abstraction. In this test, we use an event queue to share a single thread among our custom isolates. Add a callback which allows embedders to see when a port is created. Not sure if I should keep this or not. New apis: Dart_CreatePort() -- allocates a port id and adds a port->isolate mapping. Dart_IsolateHasActivePorts() -- does the current isolate have open ports? (this name a bit awkward...) Bail out of PortMap::ClosePorts() early if there are no open ports. This suppresses calls to the close_port_callback when there are no open ports. Use DART_CHECK_VALID to provide better error output when the test lib has errors. ------------------------- Sample output of the test: -- (isolate=0x815600) Constructing isolate -- Enter: CustomIsolateImpl_start -- -- Adding port (7111) -> isolate (0x830800) -- -- Adding StartEvent to queue -- -- Exit: CustomIsolateImpl_start -- -- Adding port (7112) -> isolate (0x815600) -- -- Posting message dest(7111) reply(0) -- -- Adding MessageEvent to queue -- -- Starting event loop -- >> StartEvent with isolate(0x830800)-- -- (isolate=0x830800) Running isolateMain $$ MessageEvent with dest port 7111-- -- (isolate=0x830800) Received: 42 -- Posting message dest(7112) reply(0) -- -- Adding MessageEvent to queue -- $$ MessageEvent with dest port 7112-- -- Closing port (7112) -- -- Adding ShutdownEvent to queue -- -- (isolate=0x815600) Received: 43 << ShutdownEvent with isolate(0x815600)-- -- Finished event loop -- Review URL: http://codereview.chromium.org//8588040 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@1906 260f80e4-7a28-3924-810f-c04153c831b5
2011-11-29 21:55:13 +00:00
}
DART_EXPORT Dart_Handle Dart_SendPortGetId(Dart_Handle port,
Dart_Port* port_id) {
DARTSCOPE(Thread::Current());
CHECK_CALLBACK_STATE(T);
API_TIMELINE_DURATION(T);
const SendPort& send_port = Api::UnwrapSendPortHandle(Z, port);
if (send_port.IsNull()) {
RETURN_TYPE_ERROR(Z, port, SendPort);
}
if (port_id == NULL) {
RETURN_NULL_ERROR(port_id);
}
*port_id = send_port.Id();
return Api::Success();
}
Add a mid-sized integration test for the Dart Embedding Api which demonstrates how to create a custom isolate abstraction. In this test, we use an event queue to share a single thread among our custom isolates. Add a callback which allows embedders to see when a port is created. Not sure if I should keep this or not. New apis: Dart_CreatePort() -- allocates a port id and adds a port->isolate mapping. Dart_IsolateHasActivePorts() -- does the current isolate have open ports? (this name a bit awkward...) Bail out of PortMap::ClosePorts() early if there are no open ports. This suppresses calls to the close_port_callback when there are no open ports. Use DART_CHECK_VALID to provide better error output when the test lib has errors. ------------------------- Sample output of the test: -- (isolate=0x815600) Constructing isolate -- Enter: CustomIsolateImpl_start -- -- Adding port (7111) -> isolate (0x830800) -- -- Adding StartEvent to queue -- -- Exit: CustomIsolateImpl_start -- -- Adding port (7112) -> isolate (0x815600) -- -- Posting message dest(7111) reply(0) -- -- Adding MessageEvent to queue -- -- Starting event loop -- >> StartEvent with isolate(0x830800)-- -- (isolate=0x830800) Running isolateMain $$ MessageEvent with dest port 7111-- -- (isolate=0x830800) Received: 42 -- Posting message dest(7112) reply(0) -- -- Adding MessageEvent to queue -- $$ MessageEvent with dest port 7112-- -- Closing port (7112) -- -- Adding ShutdownEvent to queue -- -- (isolate=0x815600) Received: 43 << ShutdownEvent with isolate(0x815600)-- -- Finished event loop -- Review URL: http://codereview.chromium.org//8588040 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@1906 260f80e4-7a28-3924-810f-c04153c831b5
2011-11-29 21:55:13 +00:00
DART_EXPORT Dart_Port Dart_GetMainPortId() {
Isolate* isolate = Isolate::Current();
CHECK_ISOLATE(isolate);
Add a mid-sized integration test for the Dart Embedding Api which demonstrates how to create a custom isolate abstraction. In this test, we use an event queue to share a single thread among our custom isolates. Add a callback which allows embedders to see when a port is created. Not sure if I should keep this or not. New apis: Dart_CreatePort() -- allocates a port id and adds a port->isolate mapping. Dart_IsolateHasActivePorts() -- does the current isolate have open ports? (this name a bit awkward...) Bail out of PortMap::ClosePorts() early if there are no open ports. This suppresses calls to the close_port_callback when there are no open ports. Use DART_CHECK_VALID to provide better error output when the test lib has errors. ------------------------- Sample output of the test: -- (isolate=0x815600) Constructing isolate -- Enter: CustomIsolateImpl_start -- -- Adding port (7111) -> isolate (0x830800) -- -- Adding StartEvent to queue -- -- Exit: CustomIsolateImpl_start -- -- Adding port (7112) -> isolate (0x815600) -- -- Posting message dest(7111) reply(0) -- -- Adding MessageEvent to queue -- -- Starting event loop -- >> StartEvent with isolate(0x830800)-- -- (isolate=0x830800) Running isolateMain $$ MessageEvent with dest port 7111-- -- (isolate=0x830800) Received: 42 -- Posting message dest(7112) reply(0) -- -- Adding MessageEvent to queue -- $$ MessageEvent with dest port 7112-- -- Closing port (7112) -- -- Adding ShutdownEvent to queue -- -- (isolate=0x815600) Received: 43 << ShutdownEvent with isolate(0x815600)-- -- Finished event loop -- Review URL: http://codereview.chromium.org//8588040 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@1906 260f80e4-7a28-3924-810f-c04153c831b5
2011-11-29 21:55:13 +00:00
return isolate->main_port();
}
// --- Scopes ----
DART_EXPORT void Dart_EnterScope() {
Thread* thread = Thread::Current();
Isolate* isolate = thread->isolate();
CHECK_ISOLATE(isolate);
TransitionNativeToVM transition(thread);
thread->EnterApiScope();
}
DART_EXPORT void Dart_ExitScope() {
Thread* thread = Thread::Current();
CHECK_API_SCOPE(thread);
TransitionNativeToVM transition(thread);
thread->ExitApiScope();
}
DART_EXPORT uint8_t* Dart_ScopeAllocate(intptr_t size) {
Zone* zone;
Thread* thread = Thread::Current();
if (thread != NULL) {
ApiLocalScope* scope = thread->api_top_scope();
zone = scope->zone();
} else {
ApiNativeScope* scope = ApiNativeScope::Current();
if (scope == NULL) return NULL;
zone = scope->zone();
}
return reinterpret_cast<uint8_t*>(zone->AllocUnsafe(size));
}
// --- Objects ----
DART_EXPORT Dart_Handle Dart_Null() {
ASSERT(Isolate::Current() != NULL);
return Api::Null();
}
DART_EXPORT bool Dart_IsNull(Dart_Handle object) {
TransitionNativeToVM transition(Thread::Current());
return Api::UnwrapHandle(object) == Object::null();
}
DART_EXPORT Dart_Handle Dart_EmptyString() {
ASSERT(Isolate::Current() != NULL);
return Api::EmptyString();
}
DART_EXPORT Dart_Handle Dart_TypeDynamic() {
DARTSCOPE(Thread::Current());
CHECK_CALLBACK_STATE(T);
API_TIMELINE_DURATION(T);
return Api::NewHandle(T, Type::DynamicType());
}
DART_EXPORT Dart_Handle Dart_TypeVoid() {
DARTSCOPE(Thread::Current());
CHECK_CALLBACK_STATE(T);
API_TIMELINE_DURATION(T);
return Api::NewHandle(T, Type::VoidType());
}
DART_EXPORT Dart_Handle Dart_TypeNever() {
DARTSCOPE(Thread::Current());
CHECK_CALLBACK_STATE(T);
API_TIMELINE_DURATION(T);
return Api::NewHandle(T, Type::NeverType());
}
DART_EXPORT Dart_Handle Dart_ObjectEquals(Dart_Handle obj1,
Dart_Handle obj2,
bool* value) {
DARTSCOPE(Thread::Current());
CHECK_CALLBACK_STATE(T);
const Instance& expected =
Instance::CheckedHandle(Z, Api::UnwrapHandle(obj1));
const Instance& actual = Instance::CheckedHandle(Z, Api::UnwrapHandle(obj2));
const Object& result =
Object::Handle(Z, DartLibraryCalls::Equals(expected, actual));
if (result.IsBool()) {
*value = Bool::Cast(result).value();
return Api::Success();
} else if (result.IsError()) {
return Api::NewHandle(T, result.ptr());
} else {
return Api::NewError("Expected boolean result from ==");
}
}
// Assumes type is non-null.
static bool InstanceIsType(const Thread* thread,
const Instance& instance,
const Type& type) {
ASSERT(!type.IsNull());
CHECK_CALLBACK_STATE(thread);
return instance.IsInstanceOf(type, Object::null_type_arguments(),
Object::null_type_arguments());
}
DART_EXPORT Dart_Handle Dart_ObjectIsType(Dart_Handle object,
Dart_Handle type,
bool* value) {
DARTSCOPE(Thread::Current());
const Type& type_obj = Api::UnwrapTypeHandle(Z, type);
if (type_obj.IsNull()) {
*value = false;
RETURN_TYPE_ERROR(Z, type, Type);
}
if (!type_obj.IsFinalized()) {
return Api::NewError(
"%s expects argument 'type' to be a fully resolved type.",
CURRENT_FUNC);
}
if (object == Api::Null()) {
*value = false;
return Api::Success();
}
const Instance& instance = Api::UnwrapInstanceHandle(Z, object);
if (instance.IsNull()) {
*value = false;
RETURN_TYPE_ERROR(Z, object, Instance);
}
*value = InstanceIsType(T, instance, type_obj);
return Api::Success();
}
DART_EXPORT bool Dart_IsInstance(Dart_Handle object) {
Thread* thread = Thread::Current();
CHECK_ISOLATE(thread->isolate());
TransitionNativeToVM transition(thread);
REUSABLE_OBJECT_HANDLESCOPE(thread);
Object& ref = thread->ObjectHandle();
ref = Api::UnwrapHandle(object);
return ref.IsInstance();
}
DART_EXPORT bool Dart_IsNumber(Dart_Handle object) {
Thread* thread = Thread::Current();
CHECK_ISOLATE(thread->isolate());
TransitionNativeToVM transition(thread);
return IsNumberClassId(Api::ClassId(object));
}
DART_EXPORT bool Dart_IsInteger(Dart_Handle object) {
Thread* thread = Thread::Current();
CHECK_ISOLATE(thread->isolate());
TransitionNativeToVM transition(thread);
return IsIntegerClassId(Api::ClassId(object));
}
DART_EXPORT bool Dart_IsDouble(Dart_Handle object) {
Thread* thread = Thread::Current();
CHECK_ISOLATE(thread->isolate());
TransitionNativeToVM transition(thread);
return Api::ClassId(object) == kDoubleCid;
}
DART_EXPORT bool Dart_IsBoolean(Dart_Handle object) {
Thread* thread = Thread::Current();
CHECK_ISOLATE(thread->isolate());
TransitionNativeToVM transition(thread);
return Api::ClassId(object) == kBoolCid;
}
DART_EXPORT bool Dart_IsString(Dart_Handle object) {
Thread* thread = Thread::Current();
CHECK_ISOLATE(thread->isolate());
TransitionNativeToVM transition(thread);
return IsStringClassId(Api::ClassId(object));
}
DART_EXPORT bool Dart_IsStringLatin1(Dart_Handle object) {
Thread* thread = Thread::Current();
CHECK_ISOLATE(thread->isolate());
TransitionNativeToVM transition(thread);
return IsOneByteStringClassId(Api::ClassId(object));
}
DART_EXPORT bool Dart_IsExternalString(Dart_Handle object) {
Thread* thread = Thread::Current();
CHECK_ISOLATE(thread->isolate());
TransitionNativeToVM transition(thread);
return IsExternalStringClassId(Api::ClassId(object));
}
DART_EXPORT bool Dart_IsList(Dart_Handle object) {
DARTSCOPE(Thread::Current());
if (IsBuiltinListClassId(Api::ClassId(object))) {
return true;
}
const Object& obj = Object::Handle(Z, Api::UnwrapHandle(object));
return GetListInstance(Z, obj) != Instance::null();
}
DART_EXPORT bool Dart_IsMap(Dart_Handle object) {
DARTSCOPE(Thread::Current());
const Object& obj = Object::Handle(Z, Api::UnwrapHandle(object));
return GetMapInstance(Z, obj) != Instance::null();
}
DART_EXPORT bool Dart_IsLibrary(Dart_Handle object) {
Thread* thread = Thread::Current();
CHECK_ISOLATE(thread->isolate());
TransitionNativeToVM transition(thread);
return Api::ClassId(object) == kLibraryCid;
}
DART_EXPORT bool Dart_IsType(Dart_Handle handle) {
Thread* thread = Thread::Current();
CHECK_ISOLATE(thread->isolate());
TransitionNativeToVM transition(thread);
return IsTypeClassId(Api::ClassId(handle));
}
DART_EXPORT bool Dart_IsFunction(Dart_Handle handle) {
Thread* thread = Thread::Current();
CHECK_ISOLATE(thread->isolate());
TransitionNativeToVM transition(thread);
return Api::ClassId(handle) == kFunctionCid;
}
DART_EXPORT bool Dart_IsVariable(Dart_Handle handle) {
Thread* thread = Thread::Current();
CHECK_ISOLATE(thread->isolate());
TransitionNativeToVM transition(thread);
return Api::ClassId(handle) == kFieldCid;
}
DART_EXPORT bool Dart_IsTypeVariable(Dart_Handle handle) {
Thread* thread = Thread::Current();
CHECK_ISOLATE(thread->isolate());
TransitionNativeToVM transition(thread);
return Api::ClassId(handle) == kTypeParameterCid;
}
DART_EXPORT bool Dart_IsClosure(Dart_Handle object) {
Thread* thread = Thread::Current();
CHECK_ISOLATE(thread->isolate());
TransitionNativeToVM transition(thread);
return Api::ClassId(object) == kClosureCid;
}
DART_EXPORT bool Dart_IsTearOff(Dart_Handle object) {
DARTSCOPE(Thread::Current());
API_TIMELINE_DURATION(T);
const Object& obj = Object::Handle(Z, Api::UnwrapHandle(object));
if (obj.IsClosure()) {
const Closure& closure = Closure::Cast(obj);
const Function& func = Function::Handle(Z, closure.function());
return func.IsImplicitClosureFunction();
}
return false;
}
DART_EXPORT bool Dart_IsTypedData(Dart_Handle handle) {
Thread* thread = Thread::Current();
CHECK_ISOLATE(thread->isolate());
TransitionNativeToVM transition(thread);
intptr_t cid = Api::ClassId(handle);
return IsTypedDataClassId(cid) || IsExternalTypedDataClassId(cid) ||
IsTypedDataViewClassId(cid);
}
DART_EXPORT bool Dart_IsByteBuffer(Dart_Handle handle) {
Thread* thread = Thread::Current();
CHECK_ISOLATE(thread->isolate());
TransitionNativeToVM transition(thread);
return Api::ClassId(handle) == kByteBufferCid;
}
DART_EXPORT bool Dart_IsFuture(Dart_Handle handle) {
DARTSCOPE(Thread::Current());
API_TIMELINE_DURATION(T);
const Object& obj = Object::Handle(Z, Api::UnwrapHandle(handle));
if (obj.IsInstance()) {
ObjectStore* object_store = T->isolate_group()->object_store();
const Type& future_rare_type =
Type::Handle(Z, object_store->non_nullable_future_rare_type());
ASSERT(!future_rare_type.IsNull());
const Class& obj_class = Class::Handle(Z, obj.clazz());
bool is_future = Class::IsSubtypeOf(
[VM/nnbd] Do not check nullability of LHS too early in strong mode (fixes #41160). Nullability of left hand side in type test was checked too early, i.e. before handling FutureOr on the right hand side. The following tests began passing (in strong mode): standalone/io/addlatexhash_test was fixed (RuntimeError -> Pass) standalone/io/file_output_stream_test was fixed (RuntimeError -> Pass) standalone/io/file_stream_test was fixed (RuntimeError -> Pass) standalone/io/file_system_async_links_test was fixed (RuntimeError -> Pass) standalone/io/file_system_links_test was fixed (RuntimeError -> Pass) standalone/io/file_write_only_test was fixed (RuntimeError -> Pass) standalone/io/pipe_server_test/0 was fixed (RuntimeError -> Pass) standalone/io/pipe_server_test/1 was fixed (RuntimeError -> Pass) standalone/io/pipe_server_test/2 was fixed (RuntimeError -> Pass) standalone/io/pipe_server_test/3 was fixed (RuntimeError -> Pass) standalone/io/pipe_server_test/4 was fixed (RuntimeError -> Pass) standalone/io/pipe_server_test/5 was fixed (RuntimeError -> Pass) standalone/io/stream_pipe_test/0 was fixed (RuntimeError -> Pass) standalone/io/stream_pipe_test/1 was fixed (RuntimeError -> Pass) standalone/io/stream_pipe_test/2 was fixed (RuntimeError -> Pass) standalone/io/stream_pipe_test/3 was fixed (RuntimeError -> Pass) Change-Id: I855328f101382cf5f1af9119b396aa9d0cb14e40 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/140776 Commit-Queue: Régis Crelier <regis@google.com> Reviewed-by: Liam Appelbe <liama@google.com>
2020-03-25 20:26:26 +00:00
obj_class, Object::null_type_arguments(), Nullability::kNonNullable,
future_rare_type, Heap::kNew);
return is_future;
}
return false;
}
// --- Instances ----
DART_EXPORT Dart_Handle Dart_InstanceGetType(Dart_Handle instance) {
DARTSCOPE(Thread::Current());
API_TIMELINE_DURATION(T);
auto isolate_group = T->isolate_group();
const Object& obj = Object::Handle(Z, Api::UnwrapHandle(instance));
if (obj.IsNull()) {
return Api::NewHandle(T, isolate_group->object_store()->null_type());
}
if (!obj.IsInstance()) {
RETURN_TYPE_ERROR(Z, instance, Instance);
}
const AbstractType& type =
AbstractType::Handle(Instance::Cast(obj).GetType(Heap::kNew));
return Api::NewHandle(T, type.Canonicalize(T, nullptr));
}
DART_EXPORT Dart_Handle Dart_FunctionName(Dart_Handle function) {
DARTSCOPE(Thread::Current());
const Function& func = Api::UnwrapFunctionHandle(Z, function);
if (func.IsNull()) {
RETURN_TYPE_ERROR(Z, function, Function);
}
return Api::NewHandle(T, func.UserVisibleName());
}
DART_EXPORT Dart_Handle Dart_ClassName(Dart_Handle cls_type) {
DARTSCOPE(Thread::Current());
const Type& type_obj = Api::UnwrapTypeHandle(Z, cls_type);
if (type_obj.IsNull()) {
RETURN_TYPE_ERROR(Z, cls_type, Type);
}
const Class& klass = Class::Handle(Z, type_obj.type_class());
if (klass.IsNull()) {
return Api::NewError(
"cls_type must be a Type object which represents a Class.");
}
return Api::NewHandle(T, klass.UserVisibleName());
}
DART_EXPORT Dart_Handle Dart_FunctionOwner(Dart_Handle function) {
DARTSCOPE(Thread::Current());
const Function& func = Api::UnwrapFunctionHandle(Z, function);
if (func.IsNull()) {
RETURN_TYPE_ERROR(Z, function, Function);
}
if (func.IsNonImplicitClosureFunction()) {
FunctionPtr parent_function = func.parent_function();
return Api::NewHandle(T, parent_function);
}
const Class& owner = Class::Handle(Z, func.Owner());
ASSERT(!owner.IsNull());
if (owner.IsTopLevel()) {
// Top-level functions are implemented as members of a hidden class. We hide
// that class here and instead answer the library.
#if defined(DEBUG)
const Library& lib = Library::Handle(Z, owner.library());
if (lib.IsNull()) {
ASSERT(owner.IsDynamicClass() || owner.IsVoidClass() ||
owner.IsNeverClass());
}
#endif
return Api::NewHandle(T, owner.library());
} else {
return Api::NewHandle(T, owner.RareType());
}
}
DART_EXPORT Dart_Handle Dart_FunctionIsStatic(Dart_Handle function,
bool* is_static) {
DARTSCOPE(Thread::Current());
if (is_static == NULL) {
RETURN_NULL_ERROR(is_static);
}
const Function& func = Api::UnwrapFunctionHandle(Z, function);
if (func.IsNull()) {
RETURN_TYPE_ERROR(Z, function, Function);
}
*is_static = func.is_static();
return Api::Success();
}
DART_EXPORT Dart_Handle Dart_ClosureFunction(Dart_Handle closure) {
DARTSCOPE(Thread::Current());
const Instance& closure_obj = Api::UnwrapInstanceHandle(Z, closure);
if (closure_obj.IsNull() || !closure_obj.IsClosure()) {
RETURN_TYPE_ERROR(Z, closure, Instance);
}
ASSERT(ClassFinalizer::AllClassesFinalized());
FunctionPtr rf = Closure::Cast(closure_obj).function();
return Api::NewHandle(T, rf);
}
DART_EXPORT Dart_Handle Dart_ClassLibrary(Dart_Handle cls_type) {
DARTSCOPE(Thread::Current());
const Type& type_obj = Api::UnwrapTypeHandle(Z, cls_type);
const Class& klass = Class::Handle(Z, type_obj.type_class());
if (klass.IsNull()) {
return Api::NewError(
"cls_type must be a Type object which represents a Class.");
}
const Library& library = Library::Handle(klass.library());
if (library.IsNull()) {
return Dart_Null();
}
return Api::NewHandle(Thread::Current(), library.ptr());
}
// --- Numbers, Integers and Doubles ----
DART_EXPORT Dart_Handle Dart_IntegerFitsIntoInt64(Dart_Handle integer,
bool* fits) {
// Fast path for Smis and Mints.
Thread* thread = Thread::Current();
API_TIMELINE_DURATION(thread);
Isolate* isolate = thread->isolate();
CHECK_ISOLATE(isolate);
if (Api::IsSmi(integer)) {
*fits = true;
return Api::Success();
}
// Slow path for mints and type error.
DARTSCOPE(thread);
if (Api::ClassId(integer) == kMintCid) {
*fits = true;
return Api::Success();
}
const Integer& int_obj = Api::UnwrapIntegerHandle(Z, integer);
ASSERT(int_obj.IsNull());
RETURN_TYPE_ERROR(Z, integer, Integer);
}
DART_EXPORT Dart_Handle Dart_IntegerFitsIntoUint64(Dart_Handle integer,
bool* fits) {
// Fast path for Smis.
Thread* thread = Thread::Current();
Isolate* isolate = thread->isolate();
CHECK_ISOLATE(isolate);
API_TIMELINE_DURATION(thread);
if (Api::IsSmi(integer)) {
*fits = (Api::SmiValue(integer) >= 0);
return Api::Success();
}
// Slow path for Mints.
DARTSCOPE(thread);
const Integer& int_obj = Api::UnwrapIntegerHandle(Z, integer);
if (int_obj.IsNull()) {
RETURN_TYPE_ERROR(Z, integer, Integer);
}
ASSERT(int_obj.IsMint());
*fits = !int_obj.IsNegative();
return Api::Success();
}
DART_EXPORT Dart_Handle Dart_NewInteger(int64_t value) {
// Fast path for Smis.
Thread* thread = Thread::Current();
Isolate* isolate = thread->isolate();
CHECK_ISOLATE(isolate);
API_TIMELINE_DURATION(thread);
DARTSCOPE(thread);
CHECK_CALLBACK_STATE(thread);
return Api::NewHandle(thread, Integer::New(value));
}
DART_EXPORT Dart_Handle Dart_NewIntegerFromUint64(uint64_t value) {
DARTSCOPE(Thread::Current());
CHECK_CALLBACK_STATE(T);
API_TIMELINE_DURATION(T);
if (Integer::IsValueInRange(value)) {
return Api::NewHandle(T, Integer::NewFromUint64(value));
}
return Api::NewError("%s: Cannot create Dart integer from value %" Pu64,
CURRENT_FUNC, value);
}
DART_EXPORT Dart_Handle Dart_NewIntegerFromHexCString(const char* str) {
DARTSCOPE(Thread::Current());
CHECK_CALLBACK_STATE(T);
API_TIMELINE_DURATION(T);
const String& str_obj = String::Handle(Z, String::New(str));
IntegerPtr integer = Integer::New(str_obj);
if (integer == Integer::null()) {
return Api::NewError("%s: Cannot create Dart integer from string %s",
CURRENT_FUNC, str);
}
return Api::NewHandle(T, integer);
}
DART_EXPORT Dart_Handle Dart_IntegerToInt64(Dart_Handle integer,
int64_t* value) {
// Fast path for Smis.
Thread* thread = Thread::Current();
Isolate* isolate = thread->isolate();
CHECK_ISOLATE(isolate);
if (Api::IsSmi(integer)) {
*value = Api::SmiValue(integer);
return Api::Success();
}
// Slow path for Mints.
DARTSCOPE(thread);
const Integer& int_obj = Api::UnwrapIntegerHandle(Z, integer);
if (int_obj.IsNull()) {
RETURN_TYPE_ERROR(Z, integer, Integer);
}
ASSERT(int_obj.IsMint());
*value = int_obj.AsInt64Value();
return Api::Success();
}
DART_EXPORT Dart_Handle Dart_IntegerToUint64(Dart_Handle integer,
uint64_t* value) {
// Fast path for Smis.
Thread* thread = Thread::Current();
Isolate* isolate = thread->isolate();
CHECK_ISOLATE(isolate);
if (Api::IsSmi(integer)) {
intptr_t smi_value = Api::SmiValue(integer);
if (smi_value >= 0) {
*value = smi_value;
return Api::Success();
}
}
// Slow path for Mints.
DARTSCOPE(thread);
const Integer& int_obj = Api::UnwrapIntegerHandle(Z, integer);
if (int_obj.IsNull()) {
RETURN_TYPE_ERROR(Z, integer, Integer);
}
if (int_obj.IsSmi()) {
ASSERT(int_obj.IsNegative());
} else {
ASSERT(int_obj.IsMint());
if (!int_obj.IsNegative()) {
*value = int_obj.AsInt64Value();
return Api::Success();
}
}
return Api::NewError("%s: Integer %s cannot be represented as a uint64_t.",
CURRENT_FUNC, int_obj.ToCString());
}
DART_EXPORT Dart_Handle Dart_IntegerToHexCString(Dart_Handle integer,
const char** value) {
DARTSCOPE(Thread::Current());
API_TIMELINE_DURATION(T);
const Integer& int_obj = Api::UnwrapIntegerHandle(Z, integer);
if (int_obj.IsNull()) {
RETURN_TYPE_ERROR(Z, integer, Integer);
}
Zone* scope_zone = Api::TopScope(Thread::Current())->zone();
*value = int_obj.ToHexCString(scope_zone);
return Api::Success();
}
DART_EXPORT Dart_Handle Dart_NewDouble(double value) {
DARTSCOPE(Thread::Current());
CHECK_CALLBACK_STATE(T);
return Api::NewHandle(T, Double::New(value));
}
DART_EXPORT Dart_Handle Dart_DoubleValue(Dart_Handle double_obj,
double* value) {
DARTSCOPE(Thread::Current());
const Double& obj = Api::UnwrapDoubleHandle(Z, double_obj);
if (obj.IsNull()) {
RETURN_TYPE_ERROR(Z, double_obj, Double);
}
*value = obj.value();
return Api::Success();
}
DART_EXPORT Dart_Handle Dart_GetStaticMethodClosure(Dart_Handle library,
Dart_Handle cls_type,
Dart_Handle function_name) {
DARTSCOPE(Thread::Current());
const Library& lib = Api::UnwrapLibraryHandle(Z, library);
if (lib.IsNull()) {
RETURN_TYPE_ERROR(Z, library, Library);
}
const Type& type_obj = Api::UnwrapTypeHandle(Z, cls_type);
if (type_obj.IsNull()) {
RETURN_TYPE_ERROR(Z, cls_type, Type);
}
const Class& klass = Class::Handle(Z, type_obj.type_class());
if (klass.IsNull()) {
return Api::NewError(
"cls_type must be a Type object which represents a Class");
}
const auto& error = klass.EnsureIsFinalized(Thread::Current());
if (error != Error::null()) {
return Api::NewHandle(T, error);
}
const String& func_name = Api::UnwrapStringHandle(Z, function_name);
if (func_name.IsNull()) {
RETURN_TYPE_ERROR(Z, function_name, String);
}
Function& func =
Function::Handle(Z, klass.LookupStaticFunctionAllowPrivate(func_name));
if (func.IsNull()) {
return Dart_Null();
}
if (!func.is_static()) {
return Api::NewError("function_name must refer to a static method.");
}
if (func.kind() != UntaggedFunction::kRegularFunction) {
return Api::NewError(
"function_name must be the name of a regular function.");
}
func = func.ImplicitClosureFunction();
if (func.IsNull()) {
return Dart_Null();
}
return Api::NewHandle(T, func.ImplicitStaticClosure());
}
// --- Booleans ----
DART_EXPORT Dart_Handle Dart_True() {
ASSERT(Isolate::Current() != NULL);
return Api::True();
}
DART_EXPORT Dart_Handle Dart_False() {
ASSERT(Isolate::Current() != NULL);
return Api::False();
}
DART_EXPORT Dart_Handle Dart_NewBoolean(bool value) {
Isolate* isolate = Isolate::Current();
CHECK_ISOLATE(isolate);
return value ? Api::True() : Api::False();
}
DART_EXPORT Dart_Handle Dart_BooleanValue(Dart_Handle boolean_obj,
bool* value) {
DARTSCOPE(Thread::Current());
const Bool& obj = Api::UnwrapBoolHandle(Z, boolean_obj);
if (obj.IsNull()) {
RETURN_TYPE_ERROR(Z, boolean_obj, Bool);
}
*value = obj.value();
return Api::Success();
}
// --- Strings ---
DART_EXPORT Dart_Handle Dart_StringLength(Dart_Handle str, intptr_t* len) {
Thread* thread = Thread::Current();
DARTSCOPE(thread);
{
ReusableObjectHandleScope reused_obj_handle(thread);
const String& str_obj = Api::UnwrapStringHandle(reused_obj_handle, str);
if (!str_obj.IsNull()) {
*len = str_obj.Length();
return Api::Success();
}
}
RETURN_TYPE_ERROR(thread->zone(), str, String);
}
DART_EXPORT Dart_Handle Dart_NewStringFromCString(const char* str) {
DARTSCOPE(Thread::Current());
API_TIMELINE_DURATION(T);
if (str == NULL) {
RETURN_NULL_ERROR(str);
}
CHECK_CALLBACK_STATE(T);
return Api::NewHandle(T, String::New(str));
}
DART_EXPORT Dart_Handle Dart_NewStringFromUTF8(const uint8_t* utf8_array,
intptr_t length) {
DARTSCOPE(Thread::Current());
API_TIMELINE_DURATION(T);
if (utf8_array == NULL && length != 0) {
RETURN_NULL_ERROR(utf8_array);
}
CHECK_LENGTH(length, String::kMaxElements);
if (!Utf8::IsValid(utf8_array, length)) {
return Api::NewError("%s expects argument 'str' to be valid UTF-8.",
CURRENT_FUNC);
}
CHECK_CALLBACK_STATE(T);
return Api::NewHandle(T, String::FromUTF8(utf8_array, length));
}
DART_EXPORT Dart_Handle Dart_NewStringFromUTF16(const uint16_t* utf16_array,
intptr_t length) {
DARTSCOPE(Thread::Current());
if (utf16_array == NULL && length != 0) {
RETURN_NULL_ERROR(utf16_array);
}
CHECK_LENGTH(length, String::kMaxElements);
CHECK_CALLBACK_STATE(T);
return Api::NewHandle(T, String::FromUTF16(utf16_array, length));
}
DART_EXPORT Dart_Handle Dart_NewStringFromUTF32(const int32_t* utf32_array,
intptr_t length) {
DARTSCOPE(Thread::Current());
API_TIMELINE_DURATION(T);
if (utf32_array == NULL && length != 0) {
RETURN_NULL_ERROR(utf32_array);
}
CHECK_LENGTH(length, String::kMaxElements);
CHECK_CALLBACK_STATE(T);
return Api::NewHandle(T, String::FromUTF32(utf32_array, length));
}
DART_EXPORT Dart_Handle
Dart_NewExternalLatin1String(const uint8_t* latin1_array,
intptr_t length,
void* peer,
intptr_t external_allocation_size,
[vm] Native API: Make Dart_NewWeakPersistentHandle not auto delete Changes Dart_NewWeakPersistentHandle to no longer auto delete the weak persistent handle. Changes the signatures of WeakPersistentHandleFinalizers to no longer have access to the handle. Flutter PR: https://github.com/flutter/engine/pull/19843 g3 presubmit: cl/318028238 Issue: https://github.com/dart-lang/sdk/issues/42312 TEST=runtime/vm/dart_api_impl_test.cc Change-Id: I3f77db9954d9486759f903b78c03a494f73c68ba Cq-Include-Trybots:dart/try:vm-ffi-android-debug-arm-try,vm-ffi-android-debug-arm64-try,app-kernel-linux-debug-x64-try,vm-kernel-linux-debug-ia32-try,vm-kernel-win-debug-x64-try,vm-kernel-win-debug-ia32-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-asan-linux-release-x64-try,vm-kernel-msan-linux-release-x64-try,vm-kernel-precomp-msan-linux-release-x64-try,vm-kernel-linux-release-simarm-try,vm-kernel-linux-release-simarm64-try,vm-kernel-precomp-android-release-arm_x64-try,vm-kernel-precomp-obfuscate-linux-release-x64-try,dart-sdk-linux-try,analyzer-analysis-server-linux-try,analyzer-linux-release-try,front-end-linux-release-x64-try,vm-kernel-precomp-win-release-x64-try,vm-kernel-mac-debug-x64-try,vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-nnbd-linux-debug-x64-try,analyzer-nnbd-linux-release-try,front-end-nnbd-linux-release-x64-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/151525 Commit-Queue: Daco Harkes <dacoharkes@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com>
2020-11-03 10:27:44 +00:00
Dart_HandleFinalizer callback) {
DARTSCOPE(Thread::Current());
API_TIMELINE_DURATION(T);
if (latin1_array == NULL && length != 0) {
RETURN_NULL_ERROR(latin1_array);
}
if (callback == NULL) {
RETURN_NULL_ERROR(callback);
}
CHECK_LENGTH(length, String::kMaxElements);
CHECK_CALLBACK_STATE(T);
return Api::NewHandle(
T,
String::NewExternal(latin1_array, length, peer, external_allocation_size,
[vm/isolate] Add TransferableTypedData class that allows low-cost passing of Uint8List between isolates. TransferableTypedData instances are one-use kind of thing: once receiver materializes it, it can't be used again, once sender sends it out to an isolate, sender can't send it to different isolate. Example of use: sender isolate: ``` Future<TransferableTypedData> consolidateHttpClientResponseBytes(HttpClientResponse response) { final completer = Completer<TransferableTypedData>(); final chunks = <Uint8List>[]; response.listen((List<int> chunk) { chunks.add(chunk); }, onDone: () { completer.complete(TransferableTypedData.fromList(chunks)); }); return completer.future; } ... sendPort.send(await consolidateHttpClientResponseBytes(response)); ``` receiver isolate: ``` RawReceivePort port = RawReceivePort((TransferableTypedData transferable) { Uint8List content = transferable.materialize().asUint8List(); ... }); ``` 31959[tr] and 31960[tr] tests were inspired by dartbug.com/31959, dartbug.com/31960 that this CL attempts to address: ``` ╰─➤ out/ReleaseX64/dart 31960.dart sending... 163ms for round-trip sending... 81ms for round-trip sending... 20ms for round-trip sending... 14ms for round-trip sending... 20ms for round-trip sending... 14ms for round-trip ``` (notice no "since last checking" pauses") vs ``` ╰─➤ out/ReleaseX64/dart 31960.dart sending... 154ms since last checkin 174ms for round-trip sending... 68ms since last checkin 9ms since last checkin 171ms for round-trip sending... 13ms since last checkin 108ms for round-trip sending... 14ms since last checkin 108ms for round-trip sending... 14ms since last checkin 107ms for round-trip ``` Change-Id: I0fcb5ce285394f498c3f1db4414204531f98199d Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/99623 Commit-Queue: Alexander Aprelev <aam@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com> Reviewed-by: Lasse R.H. Nielsen <lrn@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com>
2019-06-06 19:49:07 +00:00
callback, T->heap()->SpaceForExternal(length)));
}
DART_EXPORT Dart_Handle
Dart_NewExternalUTF16String(const uint16_t* utf16_array,
intptr_t length,
void* peer,
intptr_t external_allocation_size,
[vm] Native API: Make Dart_NewWeakPersistentHandle not auto delete Changes Dart_NewWeakPersistentHandle to no longer auto delete the weak persistent handle. Changes the signatures of WeakPersistentHandleFinalizers to no longer have access to the handle. Flutter PR: https://github.com/flutter/engine/pull/19843 g3 presubmit: cl/318028238 Issue: https://github.com/dart-lang/sdk/issues/42312 TEST=runtime/vm/dart_api_impl_test.cc Change-Id: I3f77db9954d9486759f903b78c03a494f73c68ba Cq-Include-Trybots:dart/try:vm-ffi-android-debug-arm-try,vm-ffi-android-debug-arm64-try,app-kernel-linux-debug-x64-try,vm-kernel-linux-debug-ia32-try,vm-kernel-win-debug-x64-try,vm-kernel-win-debug-ia32-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-asan-linux-release-x64-try,vm-kernel-msan-linux-release-x64-try,vm-kernel-precomp-msan-linux-release-x64-try,vm-kernel-linux-release-simarm-try,vm-kernel-linux-release-simarm64-try,vm-kernel-precomp-android-release-arm_x64-try,vm-kernel-precomp-obfuscate-linux-release-x64-try,dart-sdk-linux-try,analyzer-analysis-server-linux-try,analyzer-linux-release-try,front-end-linux-release-x64-try,vm-kernel-precomp-win-release-x64-try,vm-kernel-mac-debug-x64-try,vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-nnbd-linux-debug-x64-try,analyzer-nnbd-linux-release-try,front-end-nnbd-linux-release-x64-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/151525 Commit-Queue: Daco Harkes <dacoharkes@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com>
2020-11-03 10:27:44 +00:00
Dart_HandleFinalizer callback) {
DARTSCOPE(Thread::Current());
if (utf16_array == NULL && length != 0) {
RETURN_NULL_ERROR(utf16_array);
}
if (callback == NULL) {
RETURN_NULL_ERROR(callback);
}
CHECK_LENGTH(length, String::kMaxElements);
CHECK_CALLBACK_STATE(T);
intptr_t bytes = length * sizeof(*utf16_array);
return Api::NewHandle(
T,
String::NewExternal(utf16_array, length, peer, external_allocation_size,
[vm/isolate] Add TransferableTypedData class that allows low-cost passing of Uint8List between isolates. TransferableTypedData instances are one-use kind of thing: once receiver materializes it, it can't be used again, once sender sends it out to an isolate, sender can't send it to different isolate. Example of use: sender isolate: ``` Future<TransferableTypedData> consolidateHttpClientResponseBytes(HttpClientResponse response) { final completer = Completer<TransferableTypedData>(); final chunks = <Uint8List>[]; response.listen((List<int> chunk) { chunks.add(chunk); }, onDone: () { completer.complete(TransferableTypedData.fromList(chunks)); }); return completer.future; } ... sendPort.send(await consolidateHttpClientResponseBytes(response)); ``` receiver isolate: ``` RawReceivePort port = RawReceivePort((TransferableTypedData transferable) { Uint8List content = transferable.materialize().asUint8List(); ... }); ``` 31959[tr] and 31960[tr] tests were inspired by dartbug.com/31959, dartbug.com/31960 that this CL attempts to address: ``` ╰─➤ out/ReleaseX64/dart 31960.dart sending... 163ms for round-trip sending... 81ms for round-trip sending... 20ms for round-trip sending... 14ms for round-trip sending... 20ms for round-trip sending... 14ms for round-trip ``` (notice no "since last checking" pauses") vs ``` ╰─➤ out/ReleaseX64/dart 31960.dart sending... 154ms since last checkin 174ms for round-trip sending... 68ms since last checkin 9ms since last checkin 171ms for round-trip sending... 13ms since last checkin 108ms for round-trip sending... 14ms since last checkin 108ms for round-trip sending... 14ms since last checkin 107ms for round-trip ``` Change-Id: I0fcb5ce285394f498c3f1db4414204531f98199d Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/99623 Commit-Queue: Alexander Aprelev <aam@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com> Reviewed-by: Lasse R.H. Nielsen <lrn@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com>
2019-06-06 19:49:07 +00:00
callback, T->heap()->SpaceForExternal(bytes)));
}
DART_EXPORT Dart_Handle Dart_StringToCString(Dart_Handle object,
const char** cstr) {
DARTSCOPE(Thread::Current());
API_TIMELINE_DURATION(T);
if (cstr == NULL) {
RETURN_NULL_ERROR(cstr);
}
const String& str_obj = Api::UnwrapStringHandle(Z, object);
if (str_obj.IsNull()) {
RETURN_TYPE_ERROR(Z, object, String);
}
intptr_t string_length = Utf8::Length(str_obj);
char* res = Api::TopScope(T)->zone()->Alloc<char>(string_length + 1);
if (res == NULL) {
return Api::NewError("Unable to allocate memory");
}
const char* string_value = str_obj.ToCString();
memmove(res, string_value, string_length + 1);
ASSERT(res[string_length] == '\0');
*cstr = res;
return Api::Success();
}
DART_EXPORT Dart_Handle Dart_StringToUTF8(Dart_Handle str,
uint8_t** utf8_array,
intptr_t* length) {
DARTSCOPE(Thread::Current());
API_TIMELINE_DURATION(T);
if (utf8_array == NULL) {
RETURN_NULL_ERROR(utf8_array);
}
if (length == NULL) {
RETURN_NULL_ERROR(length);
}
const String& str_obj = Api::UnwrapStringHandle(Z, str);
if (str_obj.IsNull()) {
RETURN_TYPE_ERROR(Z, str, String);
}
intptr_t str_len = Utf8::Length(str_obj);
*utf8_array = Api::TopScope(T)->zone()->Alloc<uint8_t>(str_len);
if (*utf8_array == NULL) {
return Api::NewError("Unable to allocate memory");
}
str_obj.ToUTF8(*utf8_array, str_len);
*length = str_len;
return Api::Success();
}
DART_EXPORT Dart_Handle Dart_StringToLatin1(Dart_Handle str,
uint8_t* latin1_array,
intptr_t* length) {
DARTSCOPE(Thread::Current());
API_TIMELINE_DURATION(T);
if (latin1_array == NULL) {
RETURN_NULL_ERROR(latin1_array);
}
if (length == NULL) {
RETURN_NULL_ERROR(length);
}
const String& str_obj = Api::UnwrapStringHandle(Z, str);
if (str_obj.IsNull() || !str_obj.IsOneByteString()) {
RETURN_TYPE_ERROR(Z, str, String);
}
intptr_t str_len = str_obj.Length();
intptr_t copy_len = (str_len > *length) ? *length : str_len;
// We have already asserted that the string object is a Latin-1 string
// so we can copy the characters over using a simple loop.
for (intptr_t i = 0; i < copy_len; i++) {
latin1_array[i] = str_obj.CharAt(i);
}
*length = copy_len;
return Api::Success();
}
DART_EXPORT Dart_Handle Dart_StringToUTF16(Dart_Handle str,
uint16_t* utf16_array,
intptr_t* length) {
DARTSCOPE(Thread::Current());
API_TIMELINE_DURATION(T);
const String& str_obj = Api::UnwrapStringHandle(Z, str);
if (str_obj.IsNull()) {
RETURN_TYPE_ERROR(Z, str, String);
}
intptr_t str_len = str_obj.Length();
intptr_t copy_len = (str_len > *length) ? *length : str_len;
for (intptr_t i = 0; i < copy_len; i++) {
utf16_array[i] = str_obj.CharAt(i);
}
*length = copy_len;
return Api::Success();
}
DART_EXPORT Dart_Handle Dart_StringStorageSize(Dart_Handle str,
intptr_t* size) {
Thread* thread = Thread::Current();
CHECK_ISOLATE(thread->isolate());
TransitionNativeToVM transition(thread);
if (size == NULL) {
RETURN_NULL_ERROR(size);
}
{
ReusableObjectHandleScope reused_obj_handle(thread);
const String& str_obj = Api::UnwrapStringHandle(reused_obj_handle, str);
if (!str_obj.IsNull()) {
*size = (str_obj.Length() * str_obj.CharSize());
return Api::Success();
}
}
RETURN_TYPE_ERROR(thread->zone(), str, String);
}
DART_EXPORT Dart_Handle Dart_StringGetProperties(Dart_Handle object,
intptr_t* char_size,
intptr_t* str_len,
void** peer) {
Thread* thread = Thread::Current();
CHECK_ISOLATE(thread->isolate());
TransitionNativeToVM transition(thread);
{
ReusableObjectHandleScope reused_obj_handle(thread);
const String& str = Api::UnwrapStringHandle(reused_obj_handle, object);
if (!str.IsNull()) {
if (str.IsExternal()) {
*peer = str.GetPeer();
ASSERT(*peer != NULL);
} else {
NoSafepointScope no_safepoint_scope;
*peer = thread->heap()->GetPeer(str.ptr());
}
*char_size = str.CharSize();
*str_len = str.Length();
return Api::Success();
}
}
RETURN_TYPE_ERROR(thread->zone(), object, String);
}
// --- Lists ---
DART_EXPORT Dart_Handle Dart_NewList(intptr_t length) {
return Dart_NewListOf(Dart_CoreType_Dynamic, length);
}
static TypeArgumentsPtr TypeArgumentsForElementType(
ObjectStore* store,
Dart_CoreType_Id element_type_id) {
switch (element_type_id) {
case Dart_CoreType_Dynamic:
return TypeArguments::null();
case Dart_CoreType_Int:
return store->type_argument_legacy_int();
case Dart_CoreType_String:
return store->type_argument_legacy_string();
}
UNREACHABLE();
return TypeArguments::null();
}
DART_EXPORT Dart_Handle Dart_NewListOf(Dart_CoreType_Id element_type_id,
intptr_t length) {
DARTSCOPE(Thread::Current());
if (T->isolate_group()->null_safety() &&
element_type_id != Dart_CoreType_Dynamic) {
return Api::NewError(
"Cannot use legacy types with --sound-null-safety enabled. "
"Use Dart_NewListOfType or Dart_NewListOfTypeFilled instead.");
}
CHECK_LENGTH(length, Array::kMaxElements);
CHECK_CALLBACK_STATE(T);
const Array& arr = Array::Handle(Z, Array::New(length));
if (element_type_id != Dart_CoreType_Dynamic) {
arr.SetTypeArguments(TypeArguments::Handle(
Z, TypeArgumentsForElementType(T->isolate_group()->object_store(),
element_type_id)));
}
return Api::NewHandle(T, arr.ptr());
}
static bool CanTypeContainNull(const Type& type) {
return (type.nullability() == Nullability::kLegacy) ||
(type.nullability() == Nullability::kNullable);
}
DART_EXPORT Dart_Handle Dart_NewListOfType(Dart_Handle element_type,
intptr_t length) {
DARTSCOPE(Thread::Current());
CHECK_LENGTH(length, Array::kMaxElements);
CHECK_CALLBACK_STATE(T);
const Type& type = Api::UnwrapTypeHandle(Z, element_type);
if (type.IsNull()) {
RETURN_TYPE_ERROR(Z, element_type, Type);
}
if (!type.IsFinalized()) {
return Api::NewError(
"%s expects argument 'type' to be a fully resolved type.",
CURRENT_FUNC);
}
if ((length > 0) && !CanTypeContainNull(type)) {
return Api::NewError("%s expects argument 'type' to be a nullable type.",
CURRENT_FUNC);
}
return Api::NewHandle(T, Array::New(length, type));
}
DART_EXPORT Dart_Handle Dart_NewListOfTypeFilled(Dart_Handle element_type,
Dart_Handle fill_object,
intptr_t length) {
DARTSCOPE(Thread::Current());
CHECK_LENGTH(length, Array::kMaxElements);
CHECK_CALLBACK_STATE(T);
const Type& type = Api::UnwrapTypeHandle(Z, element_type);
if (type.IsNull()) {
RETURN_TYPE_ERROR(Z, element_type, Type);
}
if (!type.IsFinalized()) {
return Api::NewError(
"%s expects argument 'type' to be a fully resolved type.",
CURRENT_FUNC);
}
const Instance& instance = Api::UnwrapInstanceHandle(Z, fill_object);
if (!instance.IsNull() && !InstanceIsType(T, instance, type)) {
return Api::NewError(
"%s expects argument 'fill_object' to have the same type as "
"'element_type'.",
CURRENT_FUNC);
}
if ((length > 0) && instance.IsNull() && !CanTypeContainNull(type)) {
return Api::NewError(
"%s expects argument 'fill_object' to be non-null for a non-nullable "
"'element_type'.",
CURRENT_FUNC);
}
Array& arr = Array::Handle(Z, Array::New(length, type));
for (intptr_t i = 0; i < arr.Length(); ++i) {
arr.SetAt(i, instance);
}
return Api::NewHandle(T, arr.ptr());
}
#define GET_LIST_LENGTH(zone, type, obj, len) \
type& array = type::Handle(zone); \
array ^= obj.ptr(); \
*len = array.Length(); \
return Api::Success();
DART_EXPORT Dart_Handle Dart_ListLength(Dart_Handle list, intptr_t* len) {
DARTSCOPE(Thread::Current());
const Object& obj = Object::Handle(Z, Api::UnwrapHandle(list));
if (obj.IsError()) {
// Pass through errors.
return list;
}
if (obj.IsTypedDataBase()) {
GET_LIST_LENGTH(Z, TypedDataBase, obj, len);
}
if (obj.IsArray()) {
GET_LIST_LENGTH(Z, Array, obj, len);
}
if (obj.IsGrowableObjectArray()) {
GET_LIST_LENGTH(Z, GrowableObjectArray, obj, len);
}
CHECK_CALLBACK_STATE(T);
// Now check and handle a dart object that implements the List interface.
const Instance& instance = Instance::Handle(Z, GetListInstance(Z, obj));
if (instance.IsNull()) {
return Api::NewArgumentError(
"Object does not implement the List interface");
}
const Object& retval =
Object::Handle(Z, CallStatic1Arg(Z, Symbols::_listLength(), instance));
if (retval.IsSmi()) {
*len = Smi::Cast(retval).Value();
return Api::Success();
} else if (retval.IsMint()) {
int64_t mint_value = Mint::Cast(retval).value();
if (mint_value >= kIntptrMin && mint_value <= kIntptrMax) {
*len = static_cast<intptr_t>(mint_value);
return Api::Success();
}
return Api::NewError(
"Length of List object is greater than the "
"maximum value that 'len' parameter can hold");
} else if (retval.IsError()) {
return Api::NewHandle(T, retval.ptr());
} else {
return Api::NewError("Length of List object is not an integer");
}
}
#define GET_LIST_ELEMENT(thread, type, obj, index) \
const type& array_obj = type::Cast(obj); \
if ((index >= 0) && (index < array_obj.Length())) { \
return Api::NewHandle(thread, array_obj.At(index)); \
} \
return Api::NewError("Invalid index passed in to access list element");
DART_EXPORT Dart_Handle Dart_ListGetAt(Dart_Handle list, intptr_t index) {
DARTSCOPE(Thread::Current());
const Object& obj = Object::Handle(Z, Api::UnwrapHandle(list));
if (obj.IsArray()) {
GET_LIST_ELEMENT(T, Array, obj, index);
} else if (obj.IsGrowableObjectArray()) {
GET_LIST_ELEMENT(T, GrowableObjectArray, obj, index);
} else if (obj.IsError()) {
return list;
} else {
CHECK_CALLBACK_STATE(T);
// Check and handle a dart object that implements the List interface.
const Instance& instance = Instance::Handle(Z, GetListInstance(Z, obj));
if (!instance.IsNull()) {
return Api::NewHandle(
T, CallStatic2Args(Z, Symbols::_listGetAt(), instance,
Instance::Handle(Z, Integer::New(index))));
}
return Api::NewArgumentError(
"Object does not implement the 'List' interface");
}
}
#define GET_LIST_RANGE(thread, type, obj, offset, length) \
const type& array_obj = type::Cast(obj); \
if ((offset >= 0) && (offset + length <= array_obj.Length())) { \
for (intptr_t index = 0; index < length; ++index) { \
result[index] = Api::NewHandle(thread, array_obj.At(index + offset)); \
} \
return Api::Success(); \
} \
return Api::NewError("Invalid offset/length passed in to access list");
DART_EXPORT Dart_Handle Dart_ListGetRange(Dart_Handle list,
intptr_t offset,
intptr_t length,
Dart_Handle* result) {
DARTSCOPE(Thread::Current());
if (result == NULL) {
RETURN_NULL_ERROR(result);
}
const Object& obj = Object::Handle(Z, Api::UnwrapHandle(list));
if (obj.IsArray()) {
GET_LIST_RANGE(T, Array, obj, offset, length);
} else if (obj.IsGrowableObjectArray()) {
GET_LIST_RANGE(T, GrowableObjectArray, obj, offset, length);
} else if (obj.IsError()) {
return list;
} else {
CHECK_CALLBACK_STATE(T);
// Check and handle a dart object that implements the List interface.
const Instance& instance = Instance::Handle(Z, GetListInstance(Z, obj));
if (!instance.IsNull()) {
const intptr_t kNumArgs = 2;
const Function& function = Function::Handle(
Z, FindCoreLibPrivateFunction(Z, Symbols::_listGetAt()));
const Array& args = Array::Handle(Z, Array::New(kNumArgs));
args.SetAt(0, instance);
Instance& index = Instance::Handle(Z);
for (intptr_t i = 0; i < length; ++i) {
index = Integer::New(i);
args.SetAt(1, index);
Dart_Handle value =
Api::NewHandle(T, DartEntry::InvokeFunction(function, args));
if (Api::IsError(value)) return value;
result[i] = value;
}
return Api::Success();
}
return Api::NewArgumentError(
"Object does not implement the 'List' interface");
}
}
#define SET_LIST_ELEMENT(type, obj, index, value) \
const type& array = type::Cast(obj); \
const Object& value_obj = Object::Handle(Z, Api::UnwrapHandle(value)); \
if (!value_obj.IsNull() && !value_obj.IsInstance()) { \
RETURN_TYPE_ERROR(Z, value, Instance); \
} \
if ((index >= 0) && (index < array.Length())) { \
array.SetAt(index, value_obj); \
return Api::Success(); \
} \
return Api::NewError("Invalid index passed in to set list element");
DART_EXPORT Dart_Handle Dart_ListSetAt(Dart_Handle list,
intptr_t index,
Dart_Handle value) {
DARTSCOPE(Thread::Current());
const Object& obj = Object::Handle(Z, Api::UnwrapHandle(list));
// If the list is immutable we call into Dart for the indexed setter to
// get the unsupported operation exception as the result.
if (obj.IsArray() && !Array::Cast(obj).IsImmutable()) {
SET_LIST_ELEMENT(Array, obj, index, value);
} else if (obj.IsGrowableObjectArray()) {
SET_LIST_ELEMENT(GrowableObjectArray, obj, index, value);
} else if (obj.IsError()) {
return list;
} else {
CHECK_CALLBACK_STATE(T);
// Check and handle a dart object that implements the List interface.
const Instance& instance = Instance::Handle(Z, GetListInstance(Z, obj));
if (!instance.IsNull()) {
const Integer& index_obj = Integer::Handle(Z, Integer::New(index));
const Object& value_obj = Object::Handle(Z, Api::UnwrapHandle(value));
if (!value_obj.IsNull() && !value_obj.IsInstance()) {
RETURN_TYPE_ERROR(Z, value, Instance);
}
return Api::NewHandle(
T, CallStatic3Args(Z, Symbols::_listSetAt(), instance, index_obj,
Instance::Cast(value_obj)));
}
return Api::NewArgumentError(
"Object does not implement the 'List' interface");
}
}
static ObjectPtr ResolveConstructor(const char* current_func,
const Class& cls,
const String& class_name,
const String& dotted_name,
int num_args);
static ObjectPtr ThrowArgumentError(const char* exception_message) {
Thread* thread = Thread::Current();
Zone* zone = thread->zone();
// Lookup the class ArgumentError in dart:core.
const String& lib_url = String::Handle(String::New("dart:core"));
const String& class_name = String::Handle(String::New("ArgumentError"));
const Library& lib =
Library::Handle(zone, Library::LookupLibrary(thread, lib_url));
if (lib.IsNull()) {
const String& message = String::Handle(String::NewFormatted(
"%s: library '%s' not found.", CURRENT_FUNC, lib_url.ToCString()));
return ApiError::New(message);
}
const Class& cls =
Class::Handle(zone, lib.LookupClassAllowPrivate(class_name));
ASSERT(!cls.IsNull());
Object& result = Object::Handle(zone);
String& dot_name = String::Handle(String::New("."));
String& constr_name = String::Handle(String::Concat(class_name, dot_name));
result = ResolveConstructor(CURRENT_FUNC, cls, class_name, constr_name, 1);
if (result.IsError()) return result.ptr();
ASSERT(result.IsFunction());
Function& constructor = Function::Handle(zone);
constructor ^= result.ptr();
if (!constructor.IsGenerativeConstructor()) {
const String& message = String::Handle(
String::NewFormatted("%s: class '%s' is not a constructor.",
CURRENT_FUNC, class_name.ToCString()));
return ApiError::New(message);
}
Instance& exception = Instance::Handle(zone);
exception = Instance::New(cls);
const Array& args = Array::Handle(zone, Array::New(2));
args.SetAt(0, exception);
args.SetAt(1, String::Handle(String::New(exception_message)));
result = DartEntry::InvokeFunction(constructor, args);
if (result.IsError()) return result.ptr();
ASSERT(result.IsNull());
if (thread->top_exit_frame_info() == 0) {
// There are no dart frames on the stack so it would be illegal to
// throw an exception here.
const String& message = String::Handle(
String::New("No Dart frames on stack, cannot throw exception"));
return ApiError::New(message);
}
// Unwind all the API scopes till the exit frame before throwing an
// exception.
const Instance* saved_exception;
{
NoSafepointScope no_safepoint;
InstancePtr raw_exception = exception.ptr();
thread->UnwindScopes(thread->top_exit_frame_info());
saved_exception = &Instance::Handle(raw_exception);
}
Exceptions::Throw(thread, *saved_exception);
const String& message =
String::Handle(String::New("Exception was not thrown, internal error"));
return ApiError::New(message);
}
// TODO(sgjesse): value should always be smaller then 0xff. Add error handling.
#define GET_LIST_ELEMENT_AS_BYTES(type, obj, native_array, offset, length) \
const type& array = type::Cast(obj); \
if (Utils::RangeCheck(offset, length, array.Length())) { \
Object& element = Object::Handle(Z); \
for (int i = 0; i < length; i++) { \
element = array.At(offset + i); \
if (!element.IsInteger()) { \
return Api::NewHandle( \
T, ThrowArgumentError("List contains non-int elements")); \
} \
const Integer& integer = Integer::Cast(element); \
native_array[i] = static_cast<uint8_t>(integer.AsInt64Value() & 0xff); \
ASSERT(integer.AsInt64Value() <= 0xff); \
} \
return Api::Success(); \
} \
return Api::NewError("Invalid length passed in to access array elements");
DART_EXPORT Dart_Handle Dart_ListGetAsBytes(Dart_Handle list,
intptr_t offset,
uint8_t* native_array,
intptr_t length) {
DARTSCOPE(Thread::Current());
const Object& obj = Object::Handle(Z, Api::UnwrapHandle(list));
if (obj.IsTypedDataBase()) {
const TypedDataBase& array = TypedDataBase::Cast(obj);
if (array.ElementSizeInBytes() == 1) {
if (Utils::RangeCheck(offset, length, array.Length())) {
NoSafepointScope no_safepoint;
memmove(native_array,
reinterpret_cast<uint8_t*>(array.DataAddr(offset)), length);
return Api::Success();
}
return Api::NewError("Invalid length passed in to access list elements");
}
}
if (obj.IsArray()) {
GET_LIST_ELEMENT_AS_BYTES(Array, obj, native_array, offset, length);
}
if (obj.IsGrowableObjectArray()) {
GET_LIST_ELEMENT_AS_BYTES(GrowableObjectArray, obj, native_array, offset,
length);
}
if (obj.IsError()) {
return list;
}
CHECK_CALLBACK_STATE(T);
// Check and handle a dart object that implements the List interface.
const Instance& instance = Instance::Handle(Z, GetListInstance(Z, obj));
if (!instance.IsNull()) {
const int kNumArgs = 2;
const Function& function = Function::Handle(
Z, FindCoreLibPrivateFunction(Z, Symbols::_listGetAt()));
Object& result = Object::Handle(Z);
Integer& intobj = Integer::Handle(Z);
const Array& args = Array::Handle(Z, Array::New(kNumArgs));
args.SetAt(0, instance); // Set up the receiver as the first argument.
for (int i = 0; i < length; i++) {
HANDLESCOPE(T);
intobj = Integer::New(offset + i);
args.SetAt(1, intobj);
result = DartEntry::InvokeFunction(function, args);
if (result.IsError()) {
return Api::NewHandle(T, result.ptr());
}
if (!result.IsInteger()) {
return Api::NewError(
"%s expects the argument 'list' to be "
"a List of int",
CURRENT_FUNC);
}
const Integer& integer_result = Integer::Cast(result);
ASSERT(integer_result.AsInt64Value() <= 0xff);
// TODO(hpayer): value should always be smaller then 0xff. Add error
// handling.
native_array[i] =
static_cast<uint8_t>(integer_result.AsInt64Value() & 0xff);
}
return Api::Success();
}
return Api::NewArgumentError(
"Object does not implement the 'List' interface");
}
#define SET_LIST_ELEMENT_AS_BYTES(type, obj, native_array, offset, length) \
const type& array = type::Cast(obj); \
Integer& integer = Integer::Handle(Z); \
if (Utils::RangeCheck(offset, length, array.Length())) { \
for (int i = 0; i < length; i++) { \
integer = Integer::New(native_array[i]); \
array.SetAt(offset + i, integer); \
} \
return Api::Success(); \
} \
return Api::NewError("Invalid length passed in to set array elements");
DART_EXPORT Dart_Handle Dart_ListSetAsBytes(Dart_Handle list,
intptr_t offset,
const uint8_t* native_array,
intptr_t length) {
DARTSCOPE(Thread::Current());
const Object& obj = Object::Handle(Z, Api::UnwrapHandle(list));
if (obj.IsTypedDataBase()) {
const TypedDataBase& array = TypedDataBase::Cast(obj);
if (array.ElementSizeInBytes() == 1) {
if (Utils::RangeCheck(offset, length, array.Length())) {
NoSafepointScope no_safepoint;
memmove(reinterpret_cast<uint8_t*>(array.DataAddr(offset)),
native_array, length);
return Api::Success();
}
return Api::NewError("Invalid length passed in to access list elements");
}
}
if (obj.IsArray() && !Array::Cast(obj).IsImmutable()) {
// If the list is immutable we call into Dart for the indexed setter to
// get the unsupported operation exception as the result.
SET_LIST_ELEMENT_AS_BYTES(Array, obj, native_array, offset, length);
}
if (obj.IsGrowableObjectArray()) {
SET_LIST_ELEMENT_AS_BYTES(GrowableObjectArray, obj, native_array, offset,
length);
}
if (obj.IsError()) {
return list;
}
CHECK_CALLBACK_STATE(T);
// Check and handle a dart object that implements the List interface.
const Instance& instance = Instance::Handle(Z, GetListInstance(Z, obj));
if (!instance.IsNull()) {
const int kNumArgs = 3;
const Function& function = Function::Handle(
Z, FindCoreLibPrivateFunction(Z, Symbols::_listSetAt()));
Integer& indexobj = Integer::Handle(Z);
Integer& valueobj = Integer::Handle(Z);
const Array& args = Array::Handle(Z, Array::New(kNumArgs));
args.SetAt(0, instance); // Set up the receiver as the first argument.
for (int i = 0; i < length; i++) {
indexobj = Integer::New(offset + i);
valueobj = Integer::New(native_array[i]);
args.SetAt(1, indexobj);
args.SetAt(2, valueobj);
const Object& result =
Object::Handle(Z, DartEntry::InvokeFunction(function, args));
if (result.IsError()) {
return Api::NewHandle(T, result.ptr());
}
}
return Api::Success();
}
return Api::NewArgumentError(
"Object does not implement the 'List' interface");
}
// --- Maps ---
DART_EXPORT Dart_Handle Dart_MapGetAt(Dart_Handle map, Dart_Handle key) {
DARTSCOPE(Thread::Current());
CHECK_CALLBACK_STATE(T);
const Object& obj = Object::Handle(Z, Api::UnwrapHandle(map));
const Instance& instance = Instance::Handle(Z, GetMapInstance(Z, obj));
if (!instance.IsNull()) {
const Object& key_obj = Object::Handle(Api::UnwrapHandle(key));
if (!(key_obj.IsInstance() || key_obj.IsNull())) {
return Api::NewError("Key is not an instance");
}
return Api::NewHandle(T, CallStatic2Args(Z, Symbols::_mapGet(), instance,
Instance::Cast(key_obj)));
}
return Api::NewArgumentError("Object does not implement the 'Map' interface");
}
DART_EXPORT Dart_Handle Dart_MapContainsKey(Dart_Handle map, Dart_Handle key) {
DARTSCOPE(Thread::Current());
CHECK_CALLBACK_STATE(T);
const Object& obj = Object::Handle(Z, Api::UnwrapHandle(map));
const Instance& instance = Instance::Handle(Z, GetMapInstance(Z, obj));
if (!instance.IsNull()) {
const Object& key_obj = Object::Handle(Z, Api::UnwrapHandle(key));
if (!(key_obj.IsInstance() || key_obj.IsNull())) {
return Api::NewError("Key is not an instance");
}
return Api::NewHandle(
T, CallStatic2Args(Z, Symbols::_mapContainsKey(), instance,
Instance::Cast(key_obj)));
}
return Api::NewArgumentError("Object does not implement the 'Map' interface");
}
DART_EXPORT Dart_Handle Dart_MapKeys(Dart_Handle map) {
DARTSCOPE(Thread::Current());
CHECK_CALLBACK_STATE(T);
Object& obj = Object::Handle(Z, Api::UnwrapHandle(map));
Instance& instance = Instance::Handle(Z, GetMapInstance(Z, obj));
if (!instance.IsNull()) {
return Api::NewHandle(T, CallStatic1Arg(Z, Symbols::_mapKeys(), instance));
}
return Api::NewArgumentError("Object does not implement the 'Map' interface");
}
// --- Typed Data ---
// Helper method to get the type of a TypedData object.
static Dart_TypedData_Type GetType(intptr_t class_id) {
Dart_TypedData_Type type;
switch (class_id) {
case kByteDataViewCid:
type = Dart_TypedData_kByteData;
break;
case kTypedDataInt8ArrayCid:
case kTypedDataInt8ArrayViewCid:
case kExternalTypedDataInt8ArrayCid:
type = Dart_TypedData_kInt8;
break;
case kTypedDataUint8ArrayCid:
case kTypedDataUint8ArrayViewCid:
case kExternalTypedDataUint8ArrayCid:
type = Dart_TypedData_kUint8;
break;
case kTypedDataUint8ClampedArrayCid:
case kTypedDataUint8ClampedArrayViewCid:
case kExternalTypedDataUint8ClampedArrayCid:
type = Dart_TypedData_kUint8Clamped;
break;
case kTypedDataInt16ArrayCid:
case kTypedDataInt16ArrayViewCid:
case kExternalTypedDataInt16ArrayCid:
type = Dart_TypedData_kInt16;
break;
case kTypedDataUint16ArrayCid:
case kTypedDataUint16ArrayViewCid:
case kExternalTypedDataUint16ArrayCid:
type = Dart_TypedData_kUint16;
break;
case kTypedDataInt32ArrayCid:
case kTypedDataInt32ArrayViewCid:
case kExternalTypedDataInt32ArrayCid:
type = Dart_TypedData_kInt32;
break;
case kTypedDataUint32ArrayCid:
case kTypedDataUint32ArrayViewCid:
case kExternalTypedDataUint32ArrayCid:
type = Dart_TypedData_kUint32;
break;
case kTypedDataInt64ArrayCid:
case kTypedDataInt64ArrayViewCid:
case kExternalTypedDataInt64ArrayCid:
type = Dart_TypedData_kInt64;
break;
case kTypedDataUint64ArrayCid:
case kTypedDataUint64ArrayViewCid:
case kExternalTypedDataUint64ArrayCid:
type = Dart_TypedData_kUint64;
break;
case kTypedDataFloat32ArrayCid:
case kTypedDataFloat32ArrayViewCid:
case kExternalTypedDataFloat32ArrayCid:
type = Dart_TypedData_kFloat32;
break;
case kTypedDataFloat64ArrayCid:
case kTypedDataFloat64ArrayViewCid:
case kExternalTypedDataFloat64ArrayCid:
type = Dart_TypedData_kFloat64;
break;
case kTypedDataInt32x4ArrayCid:
case kTypedDataInt32x4ArrayViewCid:
case kExternalTypedDataInt32x4ArrayCid:
type = Dart_TypedData_kInt32x4;
break;
case kTypedDataFloat32x4ArrayCid:
case kTypedDataFloat32x4ArrayViewCid:
case kExternalTypedDataFloat32x4ArrayCid:
type = Dart_TypedData_kFloat32x4;
break;
case kTypedDataFloat64x2ArrayCid:
case kTypedDataFloat64x2ArrayViewCid:
case kExternalTypedDataFloat64x2ArrayCid:
type = Dart_TypedData_kFloat64x2;
break;
default:
type = Dart_TypedData_kInvalid;
break;
}
return type;
}
DART_EXPORT Dart_TypedData_Type Dart_GetTypeOfTypedData(Dart_Handle object) {
Thread* thread = Thread::Current();
API_TIMELINE_DURATION(thread);
TransitionNativeToVM transition(thread);
intptr_t class_id = Api::ClassId(object);
if (IsTypedDataClassId(class_id) || IsTypedDataViewClassId(class_id)) {
return GetType(class_id);
}
return Dart_TypedData_kInvalid;
}
DART_EXPORT Dart_TypedData_Type
Dart_GetTypeOfExternalTypedData(Dart_Handle object) {
Thread* thread = Thread::Current();
API_TIMELINE_DURATION(thread);
TransitionNativeToVM transition(thread);
intptr_t class_id = Api::ClassId(object);
if (IsExternalTypedDataClassId(class_id)) {
return GetType(class_id);
}
if (IsTypedDataViewClassId(class_id)) {
// Check if data object of the view is external.
Zone* zone = thread->zone();
const auto& view_obj = Api::UnwrapTypedDataViewHandle(zone, object);
ASSERT(!view_obj.IsNull());
const auto& data_obj = Instance::Handle(zone, view_obj.typed_data());
if (ExternalTypedData::IsExternalTypedData(data_obj)) {
return GetType(class_id);
}
}
return Dart_TypedData_kInvalid;
}
static ObjectPtr GetByteDataConstructor(Thread* thread,
const String& constructor_name,
intptr_t num_args) {
const Library& lib = Library::Handle(
thread->isolate_group()->object_store()->typed_data_library());
ASSERT(!lib.IsNull());
const Class& cls = Class::Handle(
thread->zone(), lib.LookupClassAllowPrivate(Symbols::ByteData()));
ASSERT(!cls.IsNull());
return ResolveConstructor(CURRENT_FUNC, cls, Symbols::ByteData(),
constructor_name, num_args);
}
static Dart_Handle NewByteData(Thread* thread, intptr_t length) {
CHECK_LENGTH(length, TypedData::MaxElements(kTypedDataInt8ArrayCid));
Zone* zone = thread->zone();
Object& result = Object::Handle(zone);
result = GetByteDataConstructor(thread, Symbols::ByteDataDot(), 1);
ASSERT(!result.IsNull());
ASSERT(result.IsFunction());
const Function& factory = Function::Cast(result);
ASSERT(!factory.IsGenerativeConstructor());
// Create the argument list.
const Array& args = Array::Handle(zone, Array::New(2));
// Factories get type arguments.
args.SetAt(0, Object::null_type_arguments());
args.SetAt(1, Smi::Handle(zone, Smi::New(length)));
// Invoke the constructor and return the new object.
result = DartEntry::InvokeFunction(factory, args);
ASSERT(result.IsInstance() || result.IsNull() || result.IsError());
return Api::NewHandle(thread, result.ptr());
}
static Dart_Handle NewTypedData(Thread* thread, intptr_t cid, intptr_t length) {
CHECK_LENGTH(length, TypedData::MaxElements(cid));
return Api::NewHandle(thread, TypedData::New(cid, length));
}
[vm] Native API: Make Dart_NewWeakPersistentHandle not auto delete Changes Dart_NewWeakPersistentHandle to no longer auto delete the weak persistent handle. Changes the signatures of WeakPersistentHandleFinalizers to no longer have access to the handle. Flutter PR: https://github.com/flutter/engine/pull/19843 g3 presubmit: cl/318028238 Issue: https://github.com/dart-lang/sdk/issues/42312 TEST=runtime/vm/dart_api_impl_test.cc Change-Id: I3f77db9954d9486759f903b78c03a494f73c68ba Cq-Include-Trybots:dart/try:vm-ffi-android-debug-arm-try,vm-ffi-android-debug-arm64-try,app-kernel-linux-debug-x64-try,vm-kernel-linux-debug-ia32-try,vm-kernel-win-debug-x64-try,vm-kernel-win-debug-ia32-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-asan-linux-release-x64-try,vm-kernel-msan-linux-release-x64-try,vm-kernel-precomp-msan-linux-release-x64-try,vm-kernel-linux-release-simarm-try,vm-kernel-linux-release-simarm64-try,vm-kernel-precomp-android-release-arm_x64-try,vm-kernel-precomp-obfuscate-linux-release-x64-try,dart-sdk-linux-try,analyzer-analysis-server-linux-try,analyzer-linux-release-try,front-end-linux-release-x64-try,vm-kernel-precomp-win-release-x64-try,vm-kernel-mac-debug-x64-try,vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-nnbd-linux-debug-x64-try,analyzer-nnbd-linux-release-try,front-end-nnbd-linux-release-x64-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/151525 Commit-Queue: Daco Harkes <dacoharkes@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com>
2020-11-03 10:27:44 +00:00
static Dart_Handle NewExternalTypedData(Thread* thread,
intptr_t cid,
void* data,
intptr_t length,
void* peer,
intptr_t external_allocation_size,
Dart_HandleFinalizer callback) {
CHECK_LENGTH(length, ExternalTypedData::MaxElements(cid));
Zone* zone = thread->zone();
intptr_t bytes = length * ExternalTypedData::ElementSizeInBytes(cid);
auto& cls =
Class::Handle(zone, thread->isolate_group()->class_table()->At(cid));
[vm] Reland "Remove non-covariant checks from closure bodies (part 1)" Also relands the followup CLs: "Perform non-covariant checks when dynamically invoking callables." "Use AreValidArguments so that names are checked as well." Original description of first CL: This change only affects compilation when running in non-precompiled mode with --no-lazy-dispatchers enabled. Instead of always compiling in non-covariant checks, even for closures not called dynamically, remove the non-covariant checks from the closure and instead do the non-covariant checks for dynamic calls during the NoSuchMethodForCallStub fallback by calling Function::DoArgumentTypesMatch. Adds two overloads for Function::DoArgumentTypesMatch, one which takes a function type argument vector and one which takes neither an instantiator type argument vector or a function type argument vector. For the versions that are not explicitly passed a type argument vector, an appropriate one is constructed using the arguments. If there is not enough information in the arguments, then we fall back to assuming the empty type argument vector for the instantiator case and instantiating to bounds in the function type argument case. Fixes Function::DoArgumentTypesMatch to handle generic functions and to check arguments appropriately according to the active null safety mode. For generic functions, the provided or resulting function type vector has non-covariant checks performed against the type parameter bounds. This change uncovered one test that was incorrectly passing in strong mode, see https://github.com/dart-lang/sdk/issues/42688 for details. Original description of second CL: The VM only does this when the callable function does not expect dynamic invocations. Otherwise, performing the checks would be redundant, as the function body already contains the appropriate non-covariant checks. Third CL had no additional description. Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-debug-x64-try,vm-dartkb-linux-release-x64-try,vm-kernel-reload-linux-release-x64-try, vm-kernel-reload-rollback-linux-debug-x64-try Bug: https://github.com/dart-lang/sdk/issues/40813 Change-Id: I1a3e9c1865103a8d716e1cad814267caffaaadf2 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/154688 Reviewed-by: Martin Kustermann <kustermann@google.com>
2020-07-21 10:00:41 +00:00
auto& result = Object::Handle(zone, cls.EnsureIsAllocateFinalized(thread));
if (result.IsError()) {
return Api::NewHandle(thread, result.ptr());
[vm] Reland "Remove non-covariant checks from closure bodies (part 1)" Also relands the followup CLs: "Perform non-covariant checks when dynamically invoking callables." "Use AreValidArguments so that names are checked as well." Original description of first CL: This change only affects compilation when running in non-precompiled mode with --no-lazy-dispatchers enabled. Instead of always compiling in non-covariant checks, even for closures not called dynamically, remove the non-covariant checks from the closure and instead do the non-covariant checks for dynamic calls during the NoSuchMethodForCallStub fallback by calling Function::DoArgumentTypesMatch. Adds two overloads for Function::DoArgumentTypesMatch, one which takes a function type argument vector and one which takes neither an instantiator type argument vector or a function type argument vector. For the versions that are not explicitly passed a type argument vector, an appropriate one is constructed using the arguments. If there is not enough information in the arguments, then we fall back to assuming the empty type argument vector for the instantiator case and instantiating to bounds in the function type argument case. Fixes Function::DoArgumentTypesMatch to handle generic functions and to check arguments appropriately according to the active null safety mode. For generic functions, the provided or resulting function type vector has non-covariant checks performed against the type parameter bounds. This change uncovered one test that was incorrectly passing in strong mode, see https://github.com/dart-lang/sdk/issues/42688 for details. Original description of second CL: The VM only does this when the callable function does not expect dynamic invocations. Otherwise, performing the checks would be redundant, as the function body already contains the appropriate non-covariant checks. Third CL had no additional description. Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-debug-x64-try,vm-dartkb-linux-release-x64-try,vm-kernel-reload-linux-release-x64-try, vm-kernel-reload-rollback-linux-debug-x64-try Bug: https://github.com/dart-lang/sdk/issues/40813 Change-Id: I1a3e9c1865103a8d716e1cad814267caffaaadf2 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/154688 Reviewed-by: Martin Kustermann <kustermann@google.com>
2020-07-21 10:00:41 +00:00
}
result = ExternalTypedData::New(cid, reinterpret_cast<uint8_t*>(data), length,
thread->heap()->SpaceForExternal(bytes));
if (callback != nullptr) {
[vm] Native API: Make Dart_NewWeakPersistentHandle not auto delete Changes Dart_NewWeakPersistentHandle to no longer auto delete the weak persistent handle. Changes the signatures of WeakPersistentHandleFinalizers to no longer have access to the handle. Flutter PR: https://github.com/flutter/engine/pull/19843 g3 presubmit: cl/318028238 Issue: https://github.com/dart-lang/sdk/issues/42312 TEST=runtime/vm/dart_api_impl_test.cc Change-Id: I3f77db9954d9486759f903b78c03a494f73c68ba Cq-Include-Trybots:dart/try:vm-ffi-android-debug-arm-try,vm-ffi-android-debug-arm64-try,app-kernel-linux-debug-x64-try,vm-kernel-linux-debug-ia32-try,vm-kernel-win-debug-x64-try,vm-kernel-win-debug-ia32-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-asan-linux-release-x64-try,vm-kernel-msan-linux-release-x64-try,vm-kernel-precomp-msan-linux-release-x64-try,vm-kernel-linux-release-simarm-try,vm-kernel-linux-release-simarm64-try,vm-kernel-precomp-android-release-arm_x64-try,vm-kernel-precomp-obfuscate-linux-release-x64-try,dart-sdk-linux-try,analyzer-analysis-server-linux-try,analyzer-linux-release-try,front-end-linux-release-x64-try,vm-kernel-precomp-win-release-x64-try,vm-kernel-mac-debug-x64-try,vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-nnbd-linux-debug-x64-try,analyzer-nnbd-linux-release-try,front-end-nnbd-linux-release-x64-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/151525 Commit-Queue: Daco Harkes <dacoharkes@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com>
2020-11-03 10:27:44 +00:00
AllocateFinalizableHandle(thread, result, peer, external_allocation_size,
callback);
}
return Api::NewHandle(thread, result.ptr());
}
[vm] Native API: Make Dart_NewWeakPersistentHandle not auto delete Changes Dart_NewWeakPersistentHandle to no longer auto delete the weak persistent handle. Changes the signatures of WeakPersistentHandleFinalizers to no longer have access to the handle. Flutter PR: https://github.com/flutter/engine/pull/19843 g3 presubmit: cl/318028238 Issue: https://github.com/dart-lang/sdk/issues/42312 TEST=runtime/vm/dart_api_impl_test.cc Change-Id: I3f77db9954d9486759f903b78c03a494f73c68ba Cq-Include-Trybots:dart/try:vm-ffi-android-debug-arm-try,vm-ffi-android-debug-arm64-try,app-kernel-linux-debug-x64-try,vm-kernel-linux-debug-ia32-try,vm-kernel-win-debug-x64-try,vm-kernel-win-debug-ia32-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-asan-linux-release-x64-try,vm-kernel-msan-linux-release-x64-try,vm-kernel-precomp-msan-linux-release-x64-try,vm-kernel-linux-release-simarm-try,vm-kernel-linux-release-simarm64-try,vm-kernel-precomp-android-release-arm_x64-try,vm-kernel-precomp-obfuscate-linux-release-x64-try,dart-sdk-linux-try,analyzer-analysis-server-linux-try,analyzer-linux-release-try,front-end-linux-release-x64-try,vm-kernel-precomp-win-release-x64-try,vm-kernel-mac-debug-x64-try,vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-nnbd-linux-debug-x64-try,analyzer-nnbd-linux-release-try,front-end-nnbd-linux-release-x64-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/151525 Commit-Queue: Daco Harkes <dacoharkes@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com>
2020-11-03 10:27:44 +00:00
static Dart_Handle NewExternalByteData(Thread* thread,
void* data,
intptr_t length,
void* peer,
intptr_t external_allocation_size,
Dart_HandleFinalizer callback) {
Zone* zone = thread->zone();
Dart_Handle ext_data =
NewExternalTypedData(thread, kExternalTypedDataUint8ArrayCid, data,
length, peer, external_allocation_size, callback);
if (Api::IsError(ext_data)) {
return ext_data;
}
Object& result = Object::Handle(zone);
result = GetByteDataConstructor(thread, Symbols::ByteDataDot_view(), 3);
ASSERT(!result.IsNull());
ASSERT(result.IsFunction());
const Function& factory = Function::Cast(result);
ASSERT(!factory.IsGenerativeConstructor());
// Create the argument list.
const intptr_t num_args = 3;
const Array& args = Array::Handle(zone, Array::New(num_args + 1));
// Factories get type arguments.
args.SetAt(0, Object::null_type_arguments());
const ExternalTypedData& array =
Api::UnwrapExternalTypedDataHandle(zone, ext_data);
args.SetAt(1, array);
Smi& smi = Smi::Handle(zone);
smi = Smi::New(0);
args.SetAt(2, smi);
smi = Smi::New(length);
args.SetAt(3, smi);
// Invoke the constructor and return the new object.
result = DartEntry::InvokeFunction(factory, args);
ASSERT(result.IsNull() || result.IsInstance() || result.IsError());
return Api::NewHandle(thread, result.ptr());
}
DART_EXPORT Dart_Handle Dart_NewTypedData(Dart_TypedData_Type type,
intptr_t length) {
DARTSCOPE(Thread::Current());
CHECK_CALLBACK_STATE(T);
switch (type) {
case Dart_TypedData_kByteData:
return NewByteData(T, length);
case Dart_TypedData_kInt8:
return NewTypedData(T, kTypedDataInt8ArrayCid, length);
case Dart_TypedData_kUint8:
return NewTypedData(T, kTypedDataUint8ArrayCid, length);
case Dart_TypedData_kUint8Clamped:
return NewTypedData(T, kTypedDataUint8ClampedArrayCid, length);
case Dart_TypedData_kInt16:
return NewTypedData(T, kTypedDataInt16ArrayCid, length);
case Dart_TypedData_kUint16:
return NewTypedData(T, kTypedDataUint16ArrayCid, length);
case Dart_TypedData_kInt32:
return NewTypedData(T, kTypedDataInt32ArrayCid, length);
case Dart_TypedData_kUint32:
return NewTypedData(T, kTypedDataUint32ArrayCid, length);
case Dart_TypedData_kInt64:
return NewTypedData(T, kTypedDataInt64ArrayCid, length);
case Dart_TypedData_kUint64:
return NewTypedData(T, kTypedDataUint64ArrayCid, length);
case Dart_TypedData_kFloat32:
return NewTypedData(T, kTypedDataFloat32ArrayCid, length);
case Dart_TypedData_kFloat64:
return NewTypedData(T, kTypedDataFloat64ArrayCid, length);
case Dart_TypedData_kInt32x4:
return NewTypedData(T, kTypedDataInt32x4ArrayCid, length);
case Dart_TypedData_kFloat32x4:
return NewTypedData(T, kTypedDataFloat32x4ArrayCid, length);
case Dart_TypedData_kFloat64x2:
return NewTypedData(T, kTypedDataFloat64x2ArrayCid, length);
default:
return Api::NewError("%s expects argument 'type' to be of 'TypedData'",
CURRENT_FUNC);
}
UNREACHABLE();
return Api::Null();
}
DART_EXPORT Dart_Handle Dart_NewExternalTypedData(Dart_TypedData_Type type,
void* data,
intptr_t length) {
return Dart_NewExternalTypedDataWithFinalizer(type, data, length, NULL, 0,
NULL);
}
[vm] Native API: Make Dart_NewWeakPersistentHandle not auto delete Changes Dart_NewWeakPersistentHandle to no longer auto delete the weak persistent handle. Changes the signatures of WeakPersistentHandleFinalizers to no longer have access to the handle. Flutter PR: https://github.com/flutter/engine/pull/19843 g3 presubmit: cl/318028238 Issue: https://github.com/dart-lang/sdk/issues/42312 TEST=runtime/vm/dart_api_impl_test.cc Change-Id: I3f77db9954d9486759f903b78c03a494f73c68ba Cq-Include-Trybots:dart/try:vm-ffi-android-debug-arm-try,vm-ffi-android-debug-arm64-try,app-kernel-linux-debug-x64-try,vm-kernel-linux-debug-ia32-try,vm-kernel-win-debug-x64-try,vm-kernel-win-debug-ia32-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-asan-linux-release-x64-try,vm-kernel-msan-linux-release-x64-try,vm-kernel-precomp-msan-linux-release-x64-try,vm-kernel-linux-release-simarm-try,vm-kernel-linux-release-simarm64-try,vm-kernel-precomp-android-release-arm_x64-try,vm-kernel-precomp-obfuscate-linux-release-x64-try,dart-sdk-linux-try,analyzer-analysis-server-linux-try,analyzer-linux-release-try,front-end-linux-release-x64-try,vm-kernel-precomp-win-release-x64-try,vm-kernel-mac-debug-x64-try,vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-nnbd-linux-debug-x64-try,analyzer-nnbd-linux-release-try,front-end-nnbd-linux-release-x64-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/151525 Commit-Queue: Daco Harkes <dacoharkes@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com>
2020-11-03 10:27:44 +00:00
DART_EXPORT Dart_Handle
Dart_NewExternalTypedDataWithFinalizer(Dart_TypedData_Type type,
void* data,
intptr_t length,
void* peer,
intptr_t external_allocation_size,
Dart_HandleFinalizer callback) {
DARTSCOPE(Thread::Current());
if (data == NULL && length != 0) {
RETURN_NULL_ERROR(data);
}
CHECK_CALLBACK_STATE(T);
switch (type) {
case Dart_TypedData_kByteData:
return NewExternalByteData(T, data, length, peer,
external_allocation_size, callback);
case Dart_TypedData_kInt8:
return NewExternalTypedData(T, kExternalTypedDataInt8ArrayCid, data,
length, peer, external_allocation_size,
callback);
case Dart_TypedData_kUint8:
return NewExternalTypedData(T, kExternalTypedDataUint8ArrayCid, data,
length, peer, external_allocation_size,
callback);
case Dart_TypedData_kUint8Clamped:
return NewExternalTypedData(T, kExternalTypedDataUint8ClampedArrayCid,
data, length, peer, external_allocation_size,
callback);
case Dart_TypedData_kInt16:
return NewExternalTypedData(T, kExternalTypedDataInt16ArrayCid, data,
length, peer, external_allocation_size,
callback);
case Dart_TypedData_kUint16:
return NewExternalTypedData(T, kExternalTypedDataUint16ArrayCid, data,
length, peer, external_allocation_size,
callback);
case Dart_TypedData_kInt32:
return NewExternalTypedData(T, kExternalTypedDataInt32ArrayCid, data,
length, peer, external_allocation_size,
callback);
case Dart_TypedData_kUint32:
return NewExternalTypedData(T, kExternalTypedDataUint32ArrayCid, data,
length, peer, external_allocation_size,
callback);
case Dart_TypedData_kInt64:
return NewExternalTypedData(T, kExternalTypedDataInt64ArrayCid, data,
length, peer, external_allocation_size,
callback);
case Dart_TypedData_kUint64:
return NewExternalTypedData(T, kExternalTypedDataUint64ArrayCid, data,
length, peer, external_allocation_size,
callback);
case Dart_TypedData_kFloat32:
return NewExternalTypedData(T, kExternalTypedDataFloat32ArrayCid, data,
length, peer, external_allocation_size,
callback);
case Dart_TypedData_kFloat64:
return NewExternalTypedData(T, kExternalTypedDataFloat64ArrayCid, data,
length, peer, external_allocation_size,
callback);
case Dart_TypedData_kInt32x4:
return NewExternalTypedData(T, kExternalTypedDataInt32x4ArrayCid, data,
length, peer, external_allocation_size,
callback);
case Dart_TypedData_kFloat32x4:
return NewExternalTypedData(T, kExternalTypedDataFloat32x4ArrayCid, data,
length, peer, external_allocation_size,
callback);
case Dart_TypedData_kFloat64x2:
return NewExternalTypedData(T, kExternalTypedDataFloat64x2ArrayCid, data,
length, peer, external_allocation_size,
callback);
default:
return Api::NewError(
"%s expects argument 'type' to be of"
" 'external TypedData'",
CURRENT_FUNC);
}
UNREACHABLE();
return Api::Null();
}
static ObjectPtr GetByteBufferConstructor(Thread* thread,
const String& class_name,
const String& constructor_name,
intptr_t num_args) {
const Library& lib = Library::Handle(
thread->isolate_group()->object_store()->typed_data_library());
ASSERT(!lib.IsNull());
const Class& cls =
Class::Handle(thread->zone(), lib.LookupClassAllowPrivate(class_name));
ASSERT(!cls.IsNull());
return ResolveConstructor(CURRENT_FUNC, cls, class_name, constructor_name,
num_args);
}
DART_EXPORT Dart_Handle Dart_NewByteBuffer(Dart_Handle typed_data) {
DARTSCOPE(Thread::Current());
intptr_t class_id = Api::ClassId(typed_data);
if (!IsExternalTypedDataClassId(class_id) &&
!IsTypedDataViewClassId(class_id) && !IsTypedDataClassId(class_id)) {
RETURN_TYPE_ERROR(Z, typed_data, 'TypedData');
}
Object& result = Object::Handle(Z);
result = GetByteBufferConstructor(T, Symbols::_ByteBuffer(),
Symbols::_ByteBufferDot_New(), 1);
ASSERT(!result.IsNull());
ASSERT(result.IsFunction());
const Function& factory = Function::Cast(result);
ASSERT(!factory.IsGenerativeConstructor());
// Create the argument list.
const Array& args = Array::Handle(Z, Array::New(2));
// Factories get type arguments.
args.SetAt(0, Object::null_type_arguments());
const Object& obj = Object::Handle(Z, Api::UnwrapHandle(typed_data));
args.SetAt(1, obj);
// Invoke the factory constructor and return the new object.
result = DartEntry::InvokeFunction(factory, args);
ASSERT(result.IsInstance() || result.IsNull() || result.IsError());
return Api::NewHandle(T, result.ptr());
}
// Structure to record acquired typed data for verification purposes.
class AcquiredData {
public:
AcquiredData(void* data, intptr_t size_in_bytes, bool copy)
: size_in_bytes_(size_in_bytes), data_(data), data_copy_(NULL) {
if (copy) {
data_copy_ = malloc(size_in_bytes_);
memmove(data_copy_, data_, size_in_bytes_);
}
}
// The pointer to hand out via the API.
void* GetData() const { return data_copy_ != NULL ? data_copy_ : data_; }
// Writes back and deletes/zaps, if a copy was made.
~AcquiredData() {
if (data_copy_ != NULL) {
memmove(data_, data_copy_, size_in_bytes_);
memset(data_copy_, kZapReleasedByte, size_in_bytes_);
free(data_copy_);
}
}
private:
static const uint8_t kZapReleasedByte = 0xda;
intptr_t size_in_bytes_;
void* data_;
void* data_copy_;
DISALLOW_COPY_AND_ASSIGN(AcquiredData);
};
DART_EXPORT Dart_Handle Dart_TypedDataAcquireData(Dart_Handle object,
Dart_TypedData_Type* type,
void** data,
intptr_t* len) {
DARTSCOPE(Thread::Current());
Isolate* I = T->isolate();
intptr_t class_id = Api::ClassId(object);
if (!IsExternalTypedDataClassId(class_id) &&
!IsTypedDataViewClassId(class_id) && !IsTypedDataClassId(class_id)) {
RETURN_TYPE_ERROR(Z, object, 'TypedData');
}
if (type == NULL) {
RETURN_NULL_ERROR(type);
}
if (data == NULL) {
RETURN_NULL_ERROR(data);
}
if (len == NULL) {
RETURN_NULL_ERROR(len);
}
// Get the type of typed data object.
*type = GetType(class_id);
intptr_t length = 0;
intptr_t size_in_bytes = 0;
void* data_tmp = NULL;
bool external = false;
T->IncrementNoSafepointScopeDepth();
START_NO_CALLBACK_SCOPE(T);
if (IsExternalTypedDataClassId(class_id)) {
const ExternalTypedData& obj =
Api::UnwrapExternalTypedDataHandle(Z, object);
ASSERT(!obj.IsNull());
length = obj.Length();
size_in_bytes = length * ExternalTypedData::ElementSizeInBytes(class_id);
data_tmp = obj.DataAddr(0);
external = true;
} else if (IsTypedDataClassId(class_id)) {
const TypedData& obj = Api::UnwrapTypedDataHandle(Z, object);
ASSERT(!obj.IsNull());
length = obj.Length();
size_in_bytes = length * TypedData::ElementSizeInBytes(class_id);
data_tmp = obj.DataAddr(0);
} else {
ASSERT(IsTypedDataViewClassId(class_id));
const auto& view_obj = Api::UnwrapTypedDataViewHandle(Z, object);
ASSERT(!view_obj.IsNull());
Smi& val = Smi::Handle();
val = view_obj.length();
length = val.Value();
size_in_bytes = length * TypedDataView::ElementSizeInBytes(class_id);
val = view_obj.offset_in_bytes();
intptr_t offset_in_bytes = val.Value();
const auto& obj = Instance::Handle(view_obj.typed_data());
if (TypedData::IsTypedData(obj)) {
const TypedData& data_obj = TypedData::Cast(obj);
data_tmp = data_obj.DataAddr(offset_in_bytes);
} else {
ASSERT(ExternalTypedData::IsExternalTypedData(obj));
const ExternalTypedData& data_obj = ExternalTypedData::Cast(obj);
data_tmp = data_obj.DataAddr(offset_in_bytes);
external = true;
}
}
if (FLAG_verify_acquired_data) {
{
NoSafepointScope no_safepoint(T);
bool sweep_in_progress;
{
PageSpace* old_space = T->heap()->old_space();
MonitorLocker ml(old_space->tasks_lock());
sweep_in_progress = (old_space->phase() == PageSpace::kSweepingLarge) ||
(old_space->phase() == PageSpace::kSweepingRegular);
}
if (!sweep_in_progress) {
if (external) {
ASSERT(!T->heap()->Contains(reinterpret_cast<uword>(data_tmp)));
} else {
ASSERT(T->heap()->Contains(reinterpret_cast<uword>(data_tmp)));
}
}
}
const Object& obj = Object::Handle(Z, Api::UnwrapHandle(object));
WeakTable* table = I->group()->api_state()->acquired_table();
intptr_t current = table->GetValue(obj.ptr());
if (current != 0) {
return Api::NewError("Data was already acquired for this object.");
}
// Do not make a copy if the data is external. Some callers expect external
// data to remain in place, even though the API spec doesn't guarantee it.
// TODO(koda/asiva): Make final decision and document it.
AcquiredData* ad = new AcquiredData(data_tmp, size_in_bytes, !external);
table->SetValue(obj.ptr(), reinterpret_cast<intptr_t>(ad));
data_tmp = ad->GetData();
}
*data = data_tmp;
*len = length;
return Api::Success();
}
DART_EXPORT Dart_Handle Dart_TypedDataReleaseData(Dart_Handle object) {
DARTSCOPE(Thread::Current());
Isolate* I = T->isolate();
intptr_t class_id = Api::ClassId(object);
if (!IsExternalTypedDataClassId(class_id) &&
!IsTypedDataViewClassId(class_id) && !IsTypedDataClassId(class_id)) {
RETURN_TYPE_ERROR(Z, object, 'TypedData');
}
if (FLAG_verify_acquired_data) {
const Object& obj = Object::Handle(Z, Api::UnwrapHandle(object));
WeakTable* table = I->group()->api_state()->acquired_table();
intptr_t current = table->GetValue(obj.ptr());
if (current == 0) {
return Api::NewError("Data was not acquired for this object.");
}
AcquiredData* ad = reinterpret_cast<AcquiredData*>(current);
table->SetValue(obj.ptr(), 0); // Delete entry from table.
delete ad;
}
T->DecrementNoSafepointScopeDepth();
END_NO_CALLBACK_SCOPE(T);
return Api::Success();
}
DART_EXPORT Dart_Handle Dart_GetDataFromByteBuffer(Dart_Handle object) {
Thread* thread = Thread::Current();
Zone* zone = thread->zone();
Isolate* isolate = thread->isolate();
CHECK_ISOLATE(isolate);
TransitionNativeToVM transition(thread);
intptr_t class_id = Api::ClassId(object);
if (class_id != kByteBufferCid) {
RETURN_TYPE_ERROR(zone, object, 'ByteBuffer');
}
const Instance& instance = Api::UnwrapInstanceHandle(zone, object);
ASSERT(!instance.IsNull());
return Api::NewHandle(thread, ByteBuffer::Data(instance));
}
// --- Invoking Constructors, Methods, and Field accessors ---
static ObjectPtr ResolveConstructor(const char* current_func,
const Class& cls,
const String& class_name,
const String& constr_name,
int num_args) {
// The constructor must be present in the interface.
Function& constructor = Function::Handle();
if (cls.EnsureIsFinalized(Thread::Current()) == Error::null()) {
constructor = cls.LookupFunctionAllowPrivate(constr_name);
}
if (constructor.IsNull() ||
(!constructor.IsGenerativeConstructor() && !constructor.IsFactory())) {
const String& lookup_class_name = String::Handle(cls.Name());
if (!class_name.Equals(lookup_class_name)) {
// When the class name used to build the constructor name is
// different than the name of the class in which we are doing
// the lookup, it can be confusing to the user to figure out
// what's going on. Be a little more explicit for these error
// messages.
const String& message = String::Handle(String::NewFormatted(
"%s: could not find factory '%s' in class '%s'.", current_func,
constr_name.ToCString(), lookup_class_name.ToCString()));
return ApiError::New(message);
} else {
const String& message = String::Handle(
String::NewFormatted("%s: could not find constructor '%s'.",
current_func, constr_name.ToCString()));
return ApiError::New(message);
}
}
const int kTypeArgsLen = 0;
const int extra_args = 1;
String& error_message = String::Handle();
if (!constructor.AreValidArgumentCounts(kTypeArgsLen, num_args + extra_args,
0, &error_message)) {
const String& message = String::Handle(String::NewFormatted(
"%s: wrong argument count for "
"constructor '%s': %s.",
current_func, constr_name.ToCString(), error_message.ToCString()));
return ApiError::New(message);
}
ErrorPtr error = constructor.VerifyCallEntryPoint();
if (error != Error::null()) return error;
return constructor.ptr();
}
DART_EXPORT Dart_Handle Dart_New(Dart_Handle type,
Dart_Handle constructor_name,
int number_of_arguments,
Dart_Handle* arguments) {
DARTSCOPE(Thread::Current());
CHECK_CALLBACK_STATE(T);
Object& result = Object::Handle(Z);
if (number_of_arguments < 0) {
return Api::NewError(
"%s expects argument 'number_of_arguments' to be non-negative.",
CURRENT_FUNC);
}
// Get the class to instantiate.
Object& unchecked_type = Object::Handle(Api::UnwrapHandle(type));
if (unchecked_type.IsNull() || !unchecked_type.IsType()) {
RETURN_TYPE_ERROR(Z, type, Type);
}
Type& type_obj = Type::Handle();
type_obj ^= unchecked_type.ptr();
if (!type_obj.IsFinalized()) {
return Api::NewError(
"%s expects argument 'type' to be a fully resolved type.",
CURRENT_FUNC);
}
Class& cls = Class::Handle(Z, type_obj.type_class());
CHECK_ERROR_HANDLE(cls.EnsureIsAllocateFinalized(T));
TypeArguments& type_arguments =
TypeArguments::Handle(Z, type_obj.arguments());
const String& base_constructor_name = String::Handle(Z, cls.Name());
// And get the name of the constructor to invoke.
String& dot_name = String::Handle(Z);
result = Api::UnwrapHandle(constructor_name);
if (result.IsNull()) {
dot_name = Symbols::Dot().ptr();
} else if (result.IsString()) {
dot_name = String::Concat(Symbols::Dot(), String::Cast(result));
} else {
RETURN_TYPE_ERROR(Z, constructor_name, String);
}
// Resolve the constructor.
String& constr_name =
String::Handle(String::Concat(base_constructor_name, dot_name));
result = ResolveConstructor("Dart_New", cls, base_constructor_name,
constr_name, number_of_arguments);
if (result.IsError()) {
return Api::NewHandle(T, result.ptr());
}
ASSERT(result.IsFunction());
Function& constructor = Function::Handle(Z);
constructor ^= result.ptr();
Instance& new_object = Instance::Handle(Z);
if (constructor.IsGenerativeConstructor()) {
CHECK_ERROR_HANDLE(cls.VerifyEntryPoint());
#if defined(DEBUG)
if (!cls.is_allocated() &&
(Dart::vm_snapshot_kind() == Snapshot::kFullAOT)) {
return Api::NewError("Precompilation dropped '%s'", cls.ToCString());
}
#endif
// Create the new object.
new_object = Instance::New(cls);
}
// Create the argument list.
intptr_t arg_index = 0;
int extra_args = 1;
const Array& args =
Array::Handle(Z, Array::New(number_of_arguments + extra_args));
if (constructor.IsGenerativeConstructor()) {
// Constructors get the uninitialized object.
if (!type_arguments.IsNull()) {
// The type arguments will be null if the class has no type parameters, in
// which case the following call would fail because there is no slot
// reserved in the object for the type vector.
new_object.SetTypeArguments(type_arguments);
}
args.SetAt(arg_index++, new_object);
} else {
// Factories get type arguments.
args.SetAt(arg_index++, type_arguments);
}
Object& argument = Object::Handle(Z);
for (int i = 0; i < number_of_arguments; i++) {
argument = Api::UnwrapHandle(arguments[i]);
if (!argument.IsNull() && !argument.IsInstance()) {
if (argument.IsError()) {
return Api::NewHandle(T, argument.ptr());
} else {
return Api::NewError(
"%s expects arguments[%d] to be an Instance handle.", CURRENT_FUNC,
i);
}
}
args.SetAt(arg_index++, argument);
}
const int kTypeArgsLen = 0;
Array& args_descriptor_array = Array::Handle(
Z, ArgumentsDescriptor::NewBoxed(kTypeArgsLen, args.Length()));
ArgumentsDescriptor args_descriptor(args_descriptor_array);
ObjectPtr type_error = constructor.DoArgumentTypesMatch(
args, args_descriptor, type_arguments, Object::empty_type_arguments());
if (type_error != Error::null()) {
return Api::NewHandle(T, type_error);
}
// Invoke the constructor and return the new object.
result = DartEntry::InvokeFunction(constructor, args);
if (result.IsError()) {
return Api::NewHandle(T, result.ptr());
}
if (constructor.IsGenerativeConstructor()) {
ASSERT(result.IsNull());
} else {
ASSERT(result.IsNull() || result.IsInstance());
new_object ^= result.ptr();
}
return Api::NewHandle(T, new_object.ptr());
}
static InstancePtr AllocateObject(Thread* thread, const Class& cls) {
Revert "Reland "[ VM ] Removed Dart_Allocate, Dart_AllocateWithNativeFields, and Dart_InvokeConstructor from embedding API"" This reverts commit 082aece5f400c9405bcfd2cf6ec512d930433f30. Reason for revert: tonic fix not yet landed in google3. Original change's description: > Reland "[ VM ] Removed Dart_Allocate, Dart_AllocateWithNativeFields, and Dart_InvokeConstructor from embedding API" > > This reverts commit 34447c8dbb613f63013ff49d8effd1cb807e06b2. > > Reason for revert: Last Dart_AllocateWithNativeFields usage removed in Tonic > > Original change's description: > > Revert "[ VM ] Removed Dart_Allocate, Dart_AllocateWithNativeFields, and Dart_InvokeConstructor from embedding API" > > > > This reverts commit 3d1b8b26c2282b27559a42c564035f946492e7cd. > > > > Reason for revert: Broke Flutter HHH. Dart_AllocateWithNativeFields is still used in Tonic. > > > > Original change's description: > > > [ VM ] Removed Dart_Allocate, Dart_AllocateWithNativeFields, and Dart_InvokeConstructor from embedding API > > > > > > These methods are no longer necessary and all objects should be created > > > using Dart_New instead. > > > > > > Change-Id: If64d3e3579fc03dd1a2eb6bfec73c35e90c66d8f > > > Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/135523 > > > Reviewed-by: Ryan Macnak <rmacnak@google.com> > > > > TBR=bkonyi@google.com,rmacnak@google.com,asiva@google.com > > > > Change-Id: I3dca62a1db60a90bbcc78c34ae150df628cd85c8 > > No-Presubmit: true > > No-Tree-Checks: true > > No-Try: true > > Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/135642 > > Reviewed-by: Clement Skau <cskau@google.com> > > Commit-Queue: Clement Skau <cskau@google.com> > > TBR=bkonyi@google.com,rmacnak@google.com,asiva@google.com,cskau@google.com > > # Not skipping CQ checks because original CL landed > 1 day ago. > > Change-Id: I2ac83e1bfccccd9b626acfa4a6ac517b4f3968fb > Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/136020 > Auto-Submit: Ben Konyi <bkonyi@google.com> > Reviewed-by: Ben Konyi <bkonyi@google.com> > Commit-Queue: Ben Konyi <bkonyi@google.com> TBR=bkonyi@google.com,rmacnak@google.com,asiva@google.com,cskau@google.com Change-Id: I74b6fafc86a3adcb52ca9f924fceda7831be8fc0 No-Presubmit: true No-Tree-Checks: true No-Try: true Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/136222 Reviewed-by: David Morgan <davidmorgan@google.com> Commit-Queue: David Morgan <davidmorgan@google.com>
2020-02-19 09:28:29 +00:00
if (!cls.is_fields_marked_nullable()) {
// Mark all fields as nullable.
Zone* zone = thread->zone();
Class& iterate_cls = Class::Handle(zone, cls.ptr());
Revert "Reland "[ VM ] Removed Dart_Allocate, Dart_AllocateWithNativeFields, and Dart_InvokeConstructor from embedding API"" This reverts commit 082aece5f400c9405bcfd2cf6ec512d930433f30. Reason for revert: tonic fix not yet landed in google3. Original change's description: > Reland "[ VM ] Removed Dart_Allocate, Dart_AllocateWithNativeFields, and Dart_InvokeConstructor from embedding API" > > This reverts commit 34447c8dbb613f63013ff49d8effd1cb807e06b2. > > Reason for revert: Last Dart_AllocateWithNativeFields usage removed in Tonic > > Original change's description: > > Revert "[ VM ] Removed Dart_Allocate, Dart_AllocateWithNativeFields, and Dart_InvokeConstructor from embedding API" > > > > This reverts commit 3d1b8b26c2282b27559a42c564035f946492e7cd. > > > > Reason for revert: Broke Flutter HHH. Dart_AllocateWithNativeFields is still used in Tonic. > > > > Original change's description: > > > [ VM ] Removed Dart_Allocate, Dart_AllocateWithNativeFields, and Dart_InvokeConstructor from embedding API > > > > > > These methods are no longer necessary and all objects should be created > > > using Dart_New instead. > > > > > > Change-Id: If64d3e3579fc03dd1a2eb6bfec73c35e90c66d8f > > > Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/135523 > > > Reviewed-by: Ryan Macnak <rmacnak@google.com> > > > > TBR=bkonyi@google.com,rmacnak@google.com,asiva@google.com > > > > Change-Id: I3dca62a1db60a90bbcc78c34ae150df628cd85c8 > > No-Presubmit: true > > No-Tree-Checks: true > > No-Try: true > > Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/135642 > > Reviewed-by: Clement Skau <cskau@google.com> > > Commit-Queue: Clement Skau <cskau@google.com> > > TBR=bkonyi@google.com,rmacnak@google.com,asiva@google.com,cskau@google.com > > # Not skipping CQ checks because original CL landed > 1 day ago. > > Change-Id: I2ac83e1bfccccd9b626acfa4a6ac517b4f3968fb > Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/136020 > Auto-Submit: Ben Konyi <bkonyi@google.com> > Reviewed-by: Ben Konyi <bkonyi@google.com> > Commit-Queue: Ben Konyi <bkonyi@google.com> TBR=bkonyi@google.com,rmacnak@google.com,asiva@google.com,cskau@google.com Change-Id: I74b6fafc86a3adcb52ca9f924fceda7831be8fc0 No-Presubmit: true No-Tree-Checks: true No-Try: true Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/136222 Reviewed-by: David Morgan <davidmorgan@google.com> Commit-Queue: David Morgan <davidmorgan@google.com>
2020-02-19 09:28:29 +00:00
Field& field = Field::Handle(zone);
Array& fields = Array::Handle(zone);
SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
if (!cls.is_fields_marked_nullable()) {
while (!iterate_cls.IsNull()) {
ASSERT(iterate_cls.is_finalized());
iterate_cls.set_is_fields_marked_nullable();
fields = iterate_cls.fields();
iterate_cls = iterate_cls.SuperClass();
for (int field_num = 0; field_num < fields.Length(); field_num++) {
field ^= fields.At(field_num);
if (field.is_static()) {
continue;
}
field.RecordStore(Object::null_object());
Revert "Reland "[ VM ] Removed Dart_Allocate, Dart_AllocateWithNativeFields, and Dart_InvokeConstructor from embedding API"" This reverts commit 082aece5f400c9405bcfd2cf6ec512d930433f30. Reason for revert: tonic fix not yet landed in google3. Original change's description: > Reland "[ VM ] Removed Dart_Allocate, Dart_AllocateWithNativeFields, and Dart_InvokeConstructor from embedding API" > > This reverts commit 34447c8dbb613f63013ff49d8effd1cb807e06b2. > > Reason for revert: Last Dart_AllocateWithNativeFields usage removed in Tonic > > Original change's description: > > Revert "[ VM ] Removed Dart_Allocate, Dart_AllocateWithNativeFields, and Dart_InvokeConstructor from embedding API" > > > > This reverts commit 3d1b8b26c2282b27559a42c564035f946492e7cd. > > > > Reason for revert: Broke Flutter HHH. Dart_AllocateWithNativeFields is still used in Tonic. > > > > Original change's description: > > > [ VM ] Removed Dart_Allocate, Dart_AllocateWithNativeFields, and Dart_InvokeConstructor from embedding API > > > > > > These methods are no longer necessary and all objects should be created > > > using Dart_New instead. > > > > > > Change-Id: If64d3e3579fc03dd1a2eb6bfec73c35e90c66d8f > > > Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/135523 > > > Reviewed-by: Ryan Macnak <rmacnak@google.com> > > > > TBR=bkonyi@google.com,rmacnak@google.com,asiva@google.com > > > > Change-Id: I3dca62a1db60a90bbcc78c34ae150df628cd85c8 > > No-Presubmit: true > > No-Tree-Checks: true > > No-Try: true > > Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/135642 > > Reviewed-by: Clement Skau <cskau@google.com> > > Commit-Queue: Clement Skau <cskau@google.com> > > TBR=bkonyi@google.com,rmacnak@google.com,asiva@google.com,cskau@google.com > > # Not skipping CQ checks because original CL landed > 1 day ago. > > Change-Id: I2ac83e1bfccccd9b626acfa4a6ac517b4f3968fb > Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/136020 > Auto-Submit: Ben Konyi <bkonyi@google.com> > Reviewed-by: Ben Konyi <bkonyi@google.com> > Commit-Queue: Ben Konyi <bkonyi@google.com> TBR=bkonyi@google.com,rmacnak@google.com,asiva@google.com,cskau@google.com Change-Id: I74b6fafc86a3adcb52ca9f924fceda7831be8fc0 No-Presubmit: true No-Tree-Checks: true No-Try: true Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/136222 Reviewed-by: David Morgan <davidmorgan@google.com> Commit-Queue: David Morgan <davidmorgan@google.com>
2020-02-19 09:28:29 +00:00
}
}
}
}
// Allocate an object for the given class.
return Instance::New(cls);
}
DART_EXPORT Dart_Handle Dart_Allocate(Dart_Handle type) {
DARTSCOPE(Thread::Current());
CHECK_CALLBACK_STATE(T);
const Type& type_obj = Api::UnwrapTypeHandle(Z, type);
// Get the class to instantiate.
if (type_obj.IsNull()) {
RETURN_TYPE_ERROR(Z, type, Type);
}
if (!type_obj.IsFinalized()) {
return Api::NewError(
"%s expects argument 'type' to be a fully resolved type.",
CURRENT_FUNC);
}
Revert "Reland "[ VM ] Removed Dart_Allocate, Dart_AllocateWithNativeFields, and Dart_InvokeConstructor from embedding API"" This reverts commit 082aece5f400c9405bcfd2cf6ec512d930433f30. Reason for revert: tonic fix not yet landed in google3. Original change's description: > Reland "[ VM ] Removed Dart_Allocate, Dart_AllocateWithNativeFields, and Dart_InvokeConstructor from embedding API" > > This reverts commit 34447c8dbb613f63013ff49d8effd1cb807e06b2. > > Reason for revert: Last Dart_AllocateWithNativeFields usage removed in Tonic > > Original change's description: > > Revert "[ VM ] Removed Dart_Allocate, Dart_AllocateWithNativeFields, and Dart_InvokeConstructor from embedding API" > > > > This reverts commit 3d1b8b26c2282b27559a42c564035f946492e7cd. > > > > Reason for revert: Broke Flutter HHH. Dart_AllocateWithNativeFields is still used in Tonic. > > > > Original change's description: > > > [ VM ] Removed Dart_Allocate, Dart_AllocateWithNativeFields, and Dart_InvokeConstructor from embedding API > > > > > > These methods are no longer necessary and all objects should be created > > > using Dart_New instead. > > > > > > Change-Id: If64d3e3579fc03dd1a2eb6bfec73c35e90c66d8f > > > Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/135523 > > > Reviewed-by: Ryan Macnak <rmacnak@google.com> > > > > TBR=bkonyi@google.com,rmacnak@google.com,asiva@google.com > > > > Change-Id: I3dca62a1db60a90bbcc78c34ae150df628cd85c8 > > No-Presubmit: true > > No-Tree-Checks: true > > No-Try: true > > Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/135642 > > Reviewed-by: Clement Skau <cskau@google.com> > > Commit-Queue: Clement Skau <cskau@google.com> > > TBR=bkonyi@google.com,rmacnak@google.com,asiva@google.com,cskau@google.com > > # Not skipping CQ checks because original CL landed > 1 day ago. > > Change-Id: I2ac83e1bfccccd9b626acfa4a6ac517b4f3968fb > Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/136020 > Auto-Submit: Ben Konyi <bkonyi@google.com> > Reviewed-by: Ben Konyi <bkonyi@google.com> > Commit-Queue: Ben Konyi <bkonyi@google.com> TBR=bkonyi@google.com,rmacnak@google.com,asiva@google.com,cskau@google.com Change-Id: I74b6fafc86a3adcb52ca9f924fceda7831be8fc0 No-Presubmit: true No-Tree-Checks: true No-Try: true Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/136222 Reviewed-by: David Morgan <davidmorgan@google.com> Commit-Queue: David Morgan <davidmorgan@google.com>
2020-02-19 09:28:29 +00:00
const Class& cls = Class::Handle(Z, type_obj.type_class());
const TypeArguments& type_arguments =
TypeArguments::Handle(Z, type_obj.arguments());
Revert "Reland "[ VM ] Removed Dart_Allocate, Dart_AllocateWithNativeFields, and Dart_InvokeConstructor from embedding API"" This reverts commit 082aece5f400c9405bcfd2cf6ec512d930433f30. Reason for revert: tonic fix not yet landed in google3. Original change's description: > Reland "[ VM ] Removed Dart_Allocate, Dart_AllocateWithNativeFields, and Dart_InvokeConstructor from embedding API" > > This reverts commit 34447c8dbb613f63013ff49d8effd1cb807e06b2. > > Reason for revert: Last Dart_AllocateWithNativeFields usage removed in Tonic > > Original change's description: > > Revert "[ VM ] Removed Dart_Allocate, Dart_AllocateWithNativeFields, and Dart_InvokeConstructor from embedding API" > > > > This reverts commit 3d1b8b26c2282b27559a42c564035f946492e7cd. > > > > Reason for revert: Broke Flutter HHH. Dart_AllocateWithNativeFields is still used in Tonic. > > > > Original change's description: > > > [ VM ] Removed Dart_Allocate, Dart_AllocateWithNativeFields, and Dart_InvokeConstructor from embedding API > > > > > > These methods are no longer necessary and all objects should be created > > > using Dart_New instead. > > > > > > Change-Id: If64d3e3579fc03dd1a2eb6bfec73c35e90c66d8f > > > Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/135523 > > > Reviewed-by: Ryan Macnak <rmacnak@google.com> > > > > TBR=bkonyi@google.com,rmacnak@google.com,asiva@google.com > > > > Change-Id: I3dca62a1db60a90bbcc78c34ae150df628cd85c8 > > No-Presubmit: true > > No-Tree-Checks: true > > No-Try: true > > Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/135642 > > Reviewed-by: Clement Skau <cskau@google.com> > > Commit-Queue: Clement Skau <cskau@google.com> > > TBR=bkonyi@google.com,rmacnak@google.com,asiva@google.com,cskau@google.com > > # Not skipping CQ checks because original CL landed > 1 day ago. > > Change-Id: I2ac83e1bfccccd9b626acfa4a6ac517b4f3968fb > Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/136020 > Auto-Submit: Ben Konyi <bkonyi@google.com> > Reviewed-by: Ben Konyi <bkonyi@google.com> > Commit-Queue: Ben Konyi <bkonyi@google.com> TBR=bkonyi@google.com,rmacnak@google.com,asiva@google.com,cskau@google.com Change-Id: I74b6fafc86a3adcb52ca9f924fceda7831be8fc0 No-Presubmit: true No-Tree-Checks: true No-Try: true Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/136222 Reviewed-by: David Morgan <davidmorgan@google.com> Commit-Queue: David Morgan <davidmorgan@google.com>
2020-02-19 09:28:29 +00:00
CHECK_ERROR_HANDLE(cls.VerifyEntryPoint());
#if defined(DEBUG)
if (!cls.is_allocated() && (Dart::vm_snapshot_kind() == Snapshot::kFullAOT)) {
return Api::NewError("Precompilation dropped '%s'", cls.ToCString());
}
#endif
CHECK_ERROR_HANDLE(cls.EnsureIsAllocateFinalized(T));
const Instance& new_obj = Instance::Handle(Z, AllocateObject(T, cls));
if (!type_arguments.IsNull()) {
new_obj.SetTypeArguments(type_arguments);
}
return Api::NewHandle(T, new_obj.ptr());
Revert "Reland "[ VM ] Removed Dart_Allocate, Dart_AllocateWithNativeFields, and Dart_InvokeConstructor from embedding API"" This reverts commit 082aece5f400c9405bcfd2cf6ec512d930433f30. Reason for revert: tonic fix not yet landed in google3. Original change's description: > Reland "[ VM ] Removed Dart_Allocate, Dart_AllocateWithNativeFields, and Dart_InvokeConstructor from embedding API" > > This reverts commit 34447c8dbb613f63013ff49d8effd1cb807e06b2. > > Reason for revert: Last Dart_AllocateWithNativeFields usage removed in Tonic > > Original change's description: > > Revert "[ VM ] Removed Dart_Allocate, Dart_AllocateWithNativeFields, and Dart_InvokeConstructor from embedding API" > > > > This reverts commit 3d1b8b26c2282b27559a42c564035f946492e7cd. > > > > Reason for revert: Broke Flutter HHH. Dart_AllocateWithNativeFields is still used in Tonic. > > > > Original change's description: > > > [ VM ] Removed Dart_Allocate, Dart_AllocateWithNativeFields, and Dart_InvokeConstructor from embedding API > > > > > > These methods are no longer necessary and all objects should be created > > > using Dart_New instead. > > > > > > Change-Id: If64d3e3579fc03dd1a2eb6bfec73c35e90c66d8f > > > Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/135523 > > > Reviewed-by: Ryan Macnak <rmacnak@google.com> > > > > TBR=bkonyi@google.com,rmacnak@google.com,asiva@google.com > > > > Change-Id: I3dca62a1db60a90bbcc78c34ae150df628cd85c8 > > No-Presubmit: true > > No-Tree-Checks: true > > No-Try: true > > Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/135642 > > Reviewed-by: Clement Skau <cskau@google.com> > > Commit-Queue: Clement Skau <cskau@google.com> > > TBR=bkonyi@google.com,rmacnak@google.com,asiva@google.com,cskau@google.com > > # Not skipping CQ checks because original CL landed > 1 day ago. > > Change-Id: I2ac83e1bfccccd9b626acfa4a6ac517b4f3968fb > Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/136020 > Auto-Submit: Ben Konyi <bkonyi@google.com> > Reviewed-by: Ben Konyi <bkonyi@google.com> > Commit-Queue: Ben Konyi <bkonyi@google.com> TBR=bkonyi@google.com,rmacnak@google.com,asiva@google.com,cskau@google.com Change-Id: I74b6fafc86a3adcb52ca9f924fceda7831be8fc0 No-Presubmit: true No-Tree-Checks: true No-Try: true Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/136222 Reviewed-by: David Morgan <davidmorgan@google.com> Commit-Queue: David Morgan <davidmorgan@google.com>
2020-02-19 09:28:29 +00:00
}
DART_EXPORT Dart_Handle
Dart_AllocateWithNativeFields(Dart_Handle type,
intptr_t num_native_fields,
const intptr_t* native_fields) {
DARTSCOPE(Thread::Current());
CHECK_CALLBACK_STATE(T);
const Type& type_obj = Api::UnwrapTypeHandle(Z, type);
// Get the class to instantiate.
if (type_obj.IsNull()) {
RETURN_TYPE_ERROR(Z, type, Type);
}
if (native_fields == NULL) {
RETURN_NULL_ERROR(native_fields);
}
const Class& cls = Class::Handle(Z, type_obj.type_class());
CHECK_ERROR_HANDLE(cls.VerifyEntryPoint());
#if defined(DEBUG)
if (!cls.is_allocated() && (Dart::vm_snapshot_kind() == Snapshot::kFullAOT)) {
return Api::NewError("Precompilation dropped '%s'", cls.ToCString());
}
#endif
CHECK_ERROR_HANDLE(cls.EnsureIsAllocateFinalized(T));
Revert "Reland "[ VM ] Removed Dart_Allocate, Dart_AllocateWithNativeFields, and Dart_InvokeConstructor from embedding API"" This reverts commit 082aece5f400c9405bcfd2cf6ec512d930433f30. Reason for revert: tonic fix not yet landed in google3. Original change's description: > Reland "[ VM ] Removed Dart_Allocate, Dart_AllocateWithNativeFields, and Dart_InvokeConstructor from embedding API" > > This reverts commit 34447c8dbb613f63013ff49d8effd1cb807e06b2. > > Reason for revert: Last Dart_AllocateWithNativeFields usage removed in Tonic > > Original change's description: > > Revert "[ VM ] Removed Dart_Allocate, Dart_AllocateWithNativeFields, and Dart_InvokeConstructor from embedding API" > > > > This reverts commit 3d1b8b26c2282b27559a42c564035f946492e7cd. > > > > Reason for revert: Broke Flutter HHH. Dart_AllocateWithNativeFields is still used in Tonic. > > > > Original change's description: > > > [ VM ] Removed Dart_Allocate, Dart_AllocateWithNativeFields, and Dart_InvokeConstructor from embedding API > > > > > > These methods are no longer necessary and all objects should be created > > > using Dart_New instead. > > > > > > Change-Id: If64d3e3579fc03dd1a2eb6bfec73c35e90c66d8f > > > Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/135523 > > > Reviewed-by: Ryan Macnak <rmacnak@google.com> > > > > TBR=bkonyi@google.com,rmacnak@google.com,asiva@google.com > > > > Change-Id: I3dca62a1db60a90bbcc78c34ae150df628cd85c8 > > No-Presubmit: true > > No-Tree-Checks: true > > No-Try: true > > Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/135642 > > Reviewed-by: Clement Skau <cskau@google.com> > > Commit-Queue: Clement Skau <cskau@google.com> > > TBR=bkonyi@google.com,rmacnak@google.com,asiva@google.com,cskau@google.com > > # Not skipping CQ checks because original CL landed > 1 day ago. > > Change-Id: I2ac83e1bfccccd9b626acfa4a6ac517b4f3968fb > Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/136020 > Auto-Submit: Ben Konyi <bkonyi@google.com> > Reviewed-by: Ben Konyi <bkonyi@google.com> > Commit-Queue: Ben Konyi <bkonyi@google.com> TBR=bkonyi@google.com,rmacnak@google.com,asiva@google.com,cskau@google.com Change-Id: I74b6fafc86a3adcb52ca9f924fceda7831be8fc0 No-Presubmit: true No-Tree-Checks: true No-Try: true Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/136222 Reviewed-by: David Morgan <davidmorgan@google.com> Commit-Queue: David Morgan <davidmorgan@google.com>
2020-02-19 09:28:29 +00:00
if (num_native_fields != cls.num_native_fields()) {
return Api::NewError(
"%s: invalid number of native fields %" Pd " passed in, expected %d",
CURRENT_FUNC, num_native_fields, cls.num_native_fields());
}
const Instance& instance = Instance::Handle(Z, AllocateObject(T, cls));
instance.SetNativeFields(num_native_fields, native_fields);
return Api::NewHandle(T, instance.ptr());
Revert "Reland "[ VM ] Removed Dart_Allocate, Dart_AllocateWithNativeFields, and Dart_InvokeConstructor from embedding API"" This reverts commit 082aece5f400c9405bcfd2cf6ec512d930433f30. Reason for revert: tonic fix not yet landed in google3. Original change's description: > Reland "[ VM ] Removed Dart_Allocate, Dart_AllocateWithNativeFields, and Dart_InvokeConstructor from embedding API" > > This reverts commit 34447c8dbb613f63013ff49d8effd1cb807e06b2. > > Reason for revert: Last Dart_AllocateWithNativeFields usage removed in Tonic > > Original change's description: > > Revert "[ VM ] Removed Dart_Allocate, Dart_AllocateWithNativeFields, and Dart_InvokeConstructor from embedding API" > > > > This reverts commit 3d1b8b26c2282b27559a42c564035f946492e7cd. > > > > Reason for revert: Broke Flutter HHH. Dart_AllocateWithNativeFields is still used in Tonic. > > > > Original change's description: > > > [ VM ] Removed Dart_Allocate, Dart_AllocateWithNativeFields, and Dart_InvokeConstructor from embedding API > > > > > > These methods are no longer necessary and all objects should be created > > > using Dart_New instead. > > > > > > Change-Id: If64d3e3579fc03dd1a2eb6bfec73c35e90c66d8f > > > Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/135523 > > > Reviewed-by: Ryan Macnak <rmacnak@google.com> > > > > TBR=bkonyi@google.com,rmacnak@google.com,asiva@google.com > > > > Change-Id: I3dca62a1db60a90bbcc78c34ae150df628cd85c8 > > No-Presubmit: true > > No-Tree-Checks: true > > No-Try: true > > Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/135642 > > Reviewed-by: Clement Skau <cskau@google.com> > > Commit-Queue: Clement Skau <cskau@google.com> > > TBR=bkonyi@google.com,rmacnak@google.com,asiva@google.com,cskau@google.com > > # Not skipping CQ checks because original CL landed > 1 day ago. > > Change-Id: I2ac83e1bfccccd9b626acfa4a6ac517b4f3968fb > Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/136020 > Auto-Submit: Ben Konyi <bkonyi@google.com> > Reviewed-by: Ben Konyi <bkonyi@google.com> > Commit-Queue: Ben Konyi <bkonyi@google.com> TBR=bkonyi@google.com,rmacnak@google.com,asiva@google.com,cskau@google.com Change-Id: I74b6fafc86a3adcb52ca9f924fceda7831be8fc0 No-Presubmit: true No-Tree-Checks: true No-Try: true Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/136222 Reviewed-by: David Morgan <davidmorgan@google.com> Commit-Queue: David Morgan <davidmorgan@google.com>
2020-02-19 09:28:29 +00:00
}
static Dart_Handle SetupArguments(Thread* thread,
int num_args,
Dart_Handle* arguments,
int extra_args,
Array* args) {
Zone* zone = thread->zone();
// Check for malformed arguments in the arguments list.
*args = Array::New(num_args + extra_args);
Object& arg = Object::Handle(zone);
for (int i = 0; i < num_args; i++) {
arg = Api::UnwrapHandle(arguments[i]);
if (!arg.IsNull() && !arg.IsInstance()) {
*args = Array::null();
if (arg.IsError()) {
return Api::NewHandle(thread, arg.ptr());
} else {
return Api::NewError(
"%s expects arguments[%d] to be an Instance handle.", "Dart_Invoke",
i);
}
}
args->SetAt((i + extra_args), arg);
}
return Api::Success();
}
Revert "Reland "[ VM ] Removed Dart_Allocate, Dart_AllocateWithNativeFields, and Dart_InvokeConstructor from embedding API"" This reverts commit 082aece5f400c9405bcfd2cf6ec512d930433f30. Reason for revert: tonic fix not yet landed in google3. Original change's description: > Reland "[ VM ] Removed Dart_Allocate, Dart_AllocateWithNativeFields, and Dart_InvokeConstructor from embedding API" > > This reverts commit 34447c8dbb613f63013ff49d8effd1cb807e06b2. > > Reason for revert: Last Dart_AllocateWithNativeFields usage removed in Tonic > > Original change's description: > > Revert "[ VM ] Removed Dart_Allocate, Dart_AllocateWithNativeFields, and Dart_InvokeConstructor from embedding API" > > > > This reverts commit 3d1b8b26c2282b27559a42c564035f946492e7cd. > > > > Reason for revert: Broke Flutter HHH. Dart_AllocateWithNativeFields is still used in Tonic. > > > > Original change's description: > > > [ VM ] Removed Dart_Allocate, Dart_AllocateWithNativeFields, and Dart_InvokeConstructor from embedding API > > > > > > These methods are no longer necessary and all objects should be created > > > using Dart_New instead. > > > > > > Change-Id: If64d3e3579fc03dd1a2eb6bfec73c35e90c66d8f > > > Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/135523 > > > Reviewed-by: Ryan Macnak <rmacnak@google.com> > > > > TBR=bkonyi@google.com,rmacnak@google.com,asiva@google.com > > > > Change-Id: I3dca62a1db60a90bbcc78c34ae150df628cd85c8 > > No-Presubmit: true > > No-Tree-Checks: true > > No-Try: true > > Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/135642 > > Reviewed-by: Clement Skau <cskau@google.com> > > Commit-Queue: Clement Skau <cskau@google.com> > > TBR=bkonyi@google.com,rmacnak@google.com,asiva@google.com,cskau@google.com > > # Not skipping CQ checks because original CL landed > 1 day ago. > > Change-Id: I2ac83e1bfccccd9b626acfa4a6ac517b4f3968fb > Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/136020 > Auto-Submit: Ben Konyi <bkonyi@google.com> > Reviewed-by: Ben Konyi <bkonyi@google.com> > Commit-Queue: Ben Konyi <bkonyi@google.com> TBR=bkonyi@google.com,rmacnak@google.com,asiva@google.com,cskau@google.com Change-Id: I74b6fafc86a3adcb52ca9f924fceda7831be8fc0 No-Presubmit: true No-Tree-Checks: true No-Try: true Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/136222 Reviewed-by: David Morgan <davidmorgan@google.com> Commit-Queue: David Morgan <davidmorgan@google.com>
2020-02-19 09:28:29 +00:00
DART_EXPORT Dart_Handle Dart_InvokeConstructor(Dart_Handle object,
Dart_Handle name,
int number_of_arguments,
Dart_Handle* arguments) {
DARTSCOPE(Thread::Current());
API_TIMELINE_DURATION(T);
CHECK_CALLBACK_STATE(T);
if (number_of_arguments < 0) {
return Api::NewError(
"%s expects argument 'number_of_arguments' to be non-negative.",
CURRENT_FUNC);
}
const Instance& instance = Api::UnwrapInstanceHandle(Z, object);
if (instance.IsNull()) {
RETURN_TYPE_ERROR(Z, object, Instance);
}
// Since we have allocated an object it would mean that the type
// is finalized.
// TODO(asiva): How do we ensure that a constructor is not called more than
// once for the same object.
// Construct name of the constructor to invoke.
const String& constructor_name = Api::UnwrapStringHandle(Z, name);
AbstractType& type_obj =
Revert "Reland "[ VM ] Removed Dart_Allocate, Dart_AllocateWithNativeFields, and Dart_InvokeConstructor from embedding API"" This reverts commit 082aece5f400c9405bcfd2cf6ec512d930433f30. Reason for revert: tonic fix not yet landed in google3. Original change's description: > Reland "[ VM ] Removed Dart_Allocate, Dart_AllocateWithNativeFields, and Dart_InvokeConstructor from embedding API" > > This reverts commit 34447c8dbb613f63013ff49d8effd1cb807e06b2. > > Reason for revert: Last Dart_AllocateWithNativeFields usage removed in Tonic > > Original change's description: > > Revert "[ VM ] Removed Dart_Allocate, Dart_AllocateWithNativeFields, and Dart_InvokeConstructor from embedding API" > > > > This reverts commit 3d1b8b26c2282b27559a42c564035f946492e7cd. > > > > Reason for revert: Broke Flutter HHH. Dart_AllocateWithNativeFields is still used in Tonic. > > > > Original change's description: > > > [ VM ] Removed Dart_Allocate, Dart_AllocateWithNativeFields, and Dart_InvokeConstructor from embedding API > > > > > > These methods are no longer necessary and all objects should be created > > > using Dart_New instead. > > > > > > Change-Id: If64d3e3579fc03dd1a2eb6bfec73c35e90c66d8f > > > Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/135523 > > > Reviewed-by: Ryan Macnak <rmacnak@google.com> > > > > TBR=bkonyi@google.com,rmacnak@google.com,asiva@google.com > > > > Change-Id: I3dca62a1db60a90bbcc78c34ae150df628cd85c8 > > No-Presubmit: true > > No-Tree-Checks: true > > No-Try: true > > Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/135642 > > Reviewed-by: Clement Skau <cskau@google.com> > > Commit-Queue: Clement Skau <cskau@google.com> > > TBR=bkonyi@google.com,rmacnak@google.com,asiva@google.com,cskau@google.com > > # Not skipping CQ checks because original CL landed > 1 day ago. > > Change-Id: I2ac83e1bfccccd9b626acfa4a6ac517b4f3968fb > Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/136020 > Auto-Submit: Ben Konyi <bkonyi@google.com> > Reviewed-by: Ben Konyi <bkonyi@google.com> > Commit-Queue: Ben Konyi <bkonyi@google.com> TBR=bkonyi@google.com,rmacnak@google.com,asiva@google.com,cskau@google.com Change-Id: I74b6fafc86a3adcb52ca9f924fceda7831be8fc0 No-Presubmit: true No-Tree-Checks: true No-Try: true Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/136222 Reviewed-by: David Morgan <davidmorgan@google.com> Commit-Queue: David Morgan <davidmorgan@google.com>
2020-02-19 09:28:29 +00:00
AbstractType::Handle(Z, instance.GetType(Heap::kNew));
const Class& cls = Class::Handle(Z, type_obj.type_class());
const String& class_name = String::Handle(Z, cls.Name());
const Array& strings = Array::Handle(Z, Array::New(3));
strings.SetAt(0, class_name);
strings.SetAt(1, Symbols::Dot());
if (constructor_name.IsNull()) {
strings.SetAt(2, Symbols::Empty());
} else {
strings.SetAt(2, constructor_name);
}
const String& dot_name = String::Handle(Z, String::ConcatAll(strings));
const TypeArguments& type_arguments =
TypeArguments::Handle(Z, type_obj.arguments());
const Function& constructor =
Function::Handle(Z, cls.LookupFunctionAllowPrivate(dot_name));
const int kTypeArgsLen = 0;
const int extra_args = 1;
if (!constructor.IsNull() && constructor.IsGenerativeConstructor() &&
constructor.AreValidArgumentCounts(
kTypeArgsLen, number_of_arguments + extra_args, 0, NULL)) {
CHECK_ERROR_HANDLE(constructor.VerifyCallEntryPoint());
// Create the argument list.
Dart_Handle result;
Array& args = Array::Handle(Z);
result =
SetupArguments(T, number_of_arguments, arguments, extra_args, &args);
if (!Api::IsError(result)) {
args.SetAt(0, instance);
const int kTypeArgsLen = 0;
const Array& args_descriptor_array = Array::Handle(
Z, ArgumentsDescriptor::NewBoxed(kTypeArgsLen, args.Length()));
ArgumentsDescriptor args_descriptor(args_descriptor_array);
ObjectPtr type_error = constructor.DoArgumentTypesMatch(
args, args_descriptor, type_arguments);
if (type_error != Error::null()) {
return Api::NewHandle(T, type_error);
}
Revert "Reland "[ VM ] Removed Dart_Allocate, Dart_AllocateWithNativeFields, and Dart_InvokeConstructor from embedding API"" This reverts commit 082aece5f400c9405bcfd2cf6ec512d930433f30. Reason for revert: tonic fix not yet landed in google3. Original change's description: > Reland "[ VM ] Removed Dart_Allocate, Dart_AllocateWithNativeFields, and Dart_InvokeConstructor from embedding API" > > This reverts commit 34447c8dbb613f63013ff49d8effd1cb807e06b2. > > Reason for revert: Last Dart_AllocateWithNativeFields usage removed in Tonic > > Original change's description: > > Revert "[ VM ] Removed Dart_Allocate, Dart_AllocateWithNativeFields, and Dart_InvokeConstructor from embedding API" > > > > This reverts commit 3d1b8b26c2282b27559a42c564035f946492e7cd. > > > > Reason for revert: Broke Flutter HHH. Dart_AllocateWithNativeFields is still used in Tonic. > > > > Original change's description: > > > [ VM ] Removed Dart_Allocate, Dart_AllocateWithNativeFields, and Dart_InvokeConstructor from embedding API > > > > > > These methods are no longer necessary and all objects should be created > > > using Dart_New instead. > > > > > > Change-Id: If64d3e3579fc03dd1a2eb6bfec73c35e90c66d8f > > > Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/135523 > > > Reviewed-by: Ryan Macnak <rmacnak@google.com> > > > > TBR=bkonyi@google.com,rmacnak@google.com,asiva@google.com > > > > Change-Id: I3dca62a1db60a90bbcc78c34ae150df628cd85c8 > > No-Presubmit: true > > No-Tree-Checks: true > > No-Try: true > > Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/135642 > > Reviewed-by: Clement Skau <cskau@google.com> > > Commit-Queue: Clement Skau <cskau@google.com> > > TBR=bkonyi@google.com,rmacnak@google.com,asiva@google.com,cskau@google.com > > # Not skipping CQ checks because original CL landed > 1 day ago. > > Change-Id: I2ac83e1bfccccd9b626acfa4a6ac517b4f3968fb > Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/136020 > Auto-Submit: Ben Konyi <bkonyi@google.com> > Reviewed-by: Ben Konyi <bkonyi@google.com> > Commit-Queue: Ben Konyi <bkonyi@google.com> TBR=bkonyi@google.com,rmacnak@google.com,asiva@google.com,cskau@google.com Change-Id: I74b6fafc86a3adcb52ca9f924fceda7831be8fc0 No-Presubmit: true No-Tree-Checks: true No-Try: true Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/136222 Reviewed-by: David Morgan <davidmorgan@google.com> Commit-Queue: David Morgan <davidmorgan@google.com>
2020-02-19 09:28:29 +00:00
const Object& retval =
Object::Handle(Z, DartEntry::InvokeFunction(constructor, args));
if (retval.IsError()) {
result = Api::NewHandle(T, retval.ptr());
Revert "Reland "[ VM ] Removed Dart_Allocate, Dart_AllocateWithNativeFields, and Dart_InvokeConstructor from embedding API"" This reverts commit 082aece5f400c9405bcfd2cf6ec512d930433f30. Reason for revert: tonic fix not yet landed in google3. Original change's description: > Reland "[ VM ] Removed Dart_Allocate, Dart_AllocateWithNativeFields, and Dart_InvokeConstructor from embedding API" > > This reverts commit 34447c8dbb613f63013ff49d8effd1cb807e06b2. > > Reason for revert: Last Dart_AllocateWithNativeFields usage removed in Tonic > > Original change's description: > > Revert "[ VM ] Removed Dart_Allocate, Dart_AllocateWithNativeFields, and Dart_InvokeConstructor from embedding API" > > > > This reverts commit 3d1b8b26c2282b27559a42c564035f946492e7cd. > > > > Reason for revert: Broke Flutter HHH. Dart_AllocateWithNativeFields is still used in Tonic. > > > > Original change's description: > > > [ VM ] Removed Dart_Allocate, Dart_AllocateWithNativeFields, and Dart_InvokeConstructor from embedding API > > > > > > These methods are no longer necessary and all objects should be created > > > using Dart_New instead. > > > > > > Change-Id: If64d3e3579fc03dd1a2eb6bfec73c35e90c66d8f > > > Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/135523 > > > Reviewed-by: Ryan Macnak <rmacnak@google.com> > > > > TBR=bkonyi@google.com,rmacnak@google.com,asiva@google.com > > > > Change-Id: I3dca62a1db60a90bbcc78c34ae150df628cd85c8 > > No-Presubmit: true > > No-Tree-Checks: true > > No-Try: true > > Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/135642 > > Reviewed-by: Clement Skau <cskau@google.com> > > Commit-Queue: Clement Skau <cskau@google.com> > > TBR=bkonyi@google.com,rmacnak@google.com,asiva@google.com,cskau@google.com > > # Not skipping CQ checks because original CL landed > 1 day ago. > > Change-Id: I2ac83e1bfccccd9b626acfa4a6ac517b4f3968fb > Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/136020 > Auto-Submit: Ben Konyi <bkonyi@google.com> > Reviewed-by: Ben Konyi <bkonyi@google.com> > Commit-Queue: Ben Konyi <bkonyi@google.com> TBR=bkonyi@google.com,rmacnak@google.com,asiva@google.com,cskau@google.com Change-Id: I74b6fafc86a3adcb52ca9f924fceda7831be8fc0 No-Presubmit: true No-Tree-Checks: true No-Try: true Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/136222 Reviewed-by: David Morgan <davidmorgan@google.com> Commit-Queue: David Morgan <davidmorgan@google.com>
2020-02-19 09:28:29 +00:00
} else {
result = Api::NewHandle(T, instance.ptr());
Revert "Reland "[ VM ] Removed Dart_Allocate, Dart_AllocateWithNativeFields, and Dart_InvokeConstructor from embedding API"" This reverts commit 082aece5f400c9405bcfd2cf6ec512d930433f30. Reason for revert: tonic fix not yet landed in google3. Original change's description: > Reland "[ VM ] Removed Dart_Allocate, Dart_AllocateWithNativeFields, and Dart_InvokeConstructor from embedding API" > > This reverts commit 34447c8dbb613f63013ff49d8effd1cb807e06b2. > > Reason for revert: Last Dart_AllocateWithNativeFields usage removed in Tonic > > Original change's description: > > Revert "[ VM ] Removed Dart_Allocate, Dart_AllocateWithNativeFields, and Dart_InvokeConstructor from embedding API" > > > > This reverts commit 3d1b8b26c2282b27559a42c564035f946492e7cd. > > > > Reason for revert: Broke Flutter HHH. Dart_AllocateWithNativeFields is still used in Tonic. > > > > Original change's description: > > > [ VM ] Removed Dart_Allocate, Dart_AllocateWithNativeFields, and Dart_InvokeConstructor from embedding API > > > > > > These methods are no longer necessary and all objects should be created > > > using Dart_New instead. > > > > > > Change-Id: If64d3e3579fc03dd1a2eb6bfec73c35e90c66d8f > > > Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/135523 > > > Reviewed-by: Ryan Macnak <rmacnak@google.com> > > > > TBR=bkonyi@google.com,rmacnak@google.com,asiva@google.com > > > > Change-Id: I3dca62a1db60a90bbcc78c34ae150df628cd85c8 > > No-Presubmit: true > > No-Tree-Checks: true > > No-Try: true > > Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/135642 > > Reviewed-by: Clement Skau <cskau@google.com> > > Commit-Queue: Clement Skau <cskau@google.com> > > TBR=bkonyi@google.com,rmacnak@google.com,asiva@google.com,cskau@google.com > > # Not skipping CQ checks because original CL landed > 1 day ago. > > Change-Id: I2ac83e1bfccccd9b626acfa4a6ac517b4f3968fb > Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/136020 > Auto-Submit: Ben Konyi <bkonyi@google.com> > Reviewed-by: Ben Konyi <bkonyi@google.com> > Commit-Queue: Ben Konyi <bkonyi@google.com> TBR=bkonyi@google.com,rmacnak@google.com,asiva@google.com,cskau@google.com Change-Id: I74b6fafc86a3adcb52ca9f924fceda7831be8fc0 No-Presubmit: true No-Tree-Checks: true No-Try: true Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/136222 Reviewed-by: David Morgan <davidmorgan@google.com> Commit-Queue: David Morgan <davidmorgan@google.com>
2020-02-19 09:28:29 +00:00
}
}
return result;
}
return Api::NewError("%s expects argument 'name' to be a valid constructor.",
CURRENT_FUNC);
}
DART_EXPORT Dart_Handle Dart_Invoke(Dart_Handle target,
Dart_Handle name,
int number_of_arguments,
Dart_Handle* arguments) {
DARTSCOPE(Thread::Current());
API_TIMELINE_DURATION(T);
CHECK_CALLBACK_STATE(T);
String& function_name =
String::Handle(Z, Api::UnwrapStringHandle(Z, name).ptr());
if (function_name.IsNull()) {
RETURN_TYPE_ERROR(Z, name, String);
}
if (number_of_arguments < 0) {
return Api::NewError(
"%s expects argument 'number_of_arguments' to be non-negative.",
CURRENT_FUNC);
}
const Object& obj = Object::Handle(Z, Api::UnwrapHandle(target));
if (obj.IsError()) {
return target;
}
Dart_Handle result;
Array& args = Array::Handle(Z);
// This API does not provide a way to pass named parameters.
const Array& arg_names = Object::empty_array();
const bool respect_reflectable = false;
const bool check_is_entrypoint = FLAG_verify_entry_points;
if (obj.IsType()) {
if (!Type::Cast(obj).IsFinalized()) {
return Api::NewError(
"%s expects argument 'target' to be a fully resolved type.",
CURRENT_FUNC);
}
const Class& cls = Class::Handle(Z, Type::Cast(obj).type_class());
if (Library::IsPrivate(function_name)) {
const Library& lib = Library::Handle(Z, cls.library());
function_name = lib.PrivateName(function_name);
}
// Setup args and check for malformed arguments in the arguments list.
result = SetupArguments(T, number_of_arguments, arguments, 0, &args);
if (Api::IsError(result)) {
return result;
}
return Api::NewHandle(
T, cls.Invoke(function_name, args, arg_names, respect_reflectable,
check_is_entrypoint));
} else if (obj.IsNull() || obj.IsInstance()) {
// Since we have allocated an object it would mean that the type of the
// receiver is already resolved and finalized, hence it is not necessary
// to check here.
Instance& instance = Instance::Handle(Z);
instance ^= obj.ptr();
// Setup args and check for malformed arguments in the arguments list.
result = SetupArguments(T, number_of_arguments, arguments, 1, &args);
if (Api::IsError(result)) {
return result;
}
args.SetAt(0, instance);
return Api::NewHandle(
T, instance.Invoke(function_name, args, arg_names, respect_reflectable,
check_is_entrypoint));
} else if (obj.IsLibrary()) {
// Check whether class finalization is needed.
const Library& lib = Library::Cast(obj);
// Check that the library is loaded.
if (!lib.Loaded()) {
return Api::NewError("%s expects library argument 'target' to be loaded.",
CURRENT_FUNC);
}
if (Library::IsPrivate(function_name)) {
function_name = lib.PrivateName(function_name);
}
// Setup args and check for malformed arguments in the arguments list.
result = SetupArguments(T, number_of_arguments, arguments, 0, &args);
if (Api::IsError(result)) {
return result;
}
return Api::NewHandle(
T, lib.Invoke(function_name, args, arg_names, respect_reflectable,
check_is_entrypoint));
} else {
return Api::NewError(
"%s expects argument 'target' to be an object, type, or library.",
CURRENT_FUNC);
}
}
DART_EXPORT Dart_Handle Dart_InvokeClosure(Dart_Handle closure,
int number_of_arguments,
Dart_Handle* arguments) {
DARTSCOPE(Thread::Current());
API_TIMELINE_DURATION(T);
CHECK_CALLBACK_STATE(T);
const Instance& closure_obj = Api::UnwrapInstanceHandle(Z, closure);
if (closure_obj.IsNull() || !closure_obj.IsCallable(NULL)) {
RETURN_TYPE_ERROR(Z, closure, Instance);
}
if (number_of_arguments < 0) {
return Api::NewError(
"%s expects argument 'number_of_arguments' to be non-negative.",
CURRENT_FUNC);
}
// Set up arguments to include the closure as the first argument.
const Array& args = Array::Handle(Z, Array::New(number_of_arguments + 1));
Object& obj = Object::Handle(Z);
args.SetAt(0, closure_obj);
for (int i = 0; i < number_of_arguments; i++) {
obj = Api::UnwrapHandle(arguments[i]);
if (!obj.IsNull() && !obj.IsInstance()) {
RETURN_TYPE_ERROR(Z, arguments[i], Instance);
}
args.SetAt(i + 1, obj);
}
// Now try to invoke the closure.
return Api::NewHandle(T, DartEntry::InvokeClosure(T, args));
}
DART_EXPORT Dart_Handle Dart_GetField(Dart_Handle container, Dart_Handle name) {
DARTSCOPE(Thread::Current());
API_TIMELINE_DURATION(T);
CHECK_CALLBACK_STATE(T);
String& field_name =
String::Handle(Z, Api::UnwrapStringHandle(Z, name).ptr());
if (field_name.IsNull()) {
RETURN_TYPE_ERROR(Z, name, String);
}
const Object& obj = Object::Handle(Z, Api::UnwrapHandle(container));
const bool throw_nsm_if_absent = true;
const bool respect_reflectable = false;
const bool check_is_entrypoint = FLAG_verify_entry_points;
if (obj.IsType()) {
if (!Type::Cast(obj).IsFinalized()) {
return Api::NewError(
"%s expects argument 'container' to be a fully resolved type.",
CURRENT_FUNC);
}
Class& cls = Class::Handle(Z, Type::Cast(obj).type_class());
if (Library::IsPrivate(field_name)) {
const Library& lib = Library::Handle(Z, cls.library());
field_name = lib.PrivateName(field_name);
}
return Api::NewHandle(
T, cls.InvokeGetter(field_name, throw_nsm_if_absent,
respect_reflectable, check_is_entrypoint));
} else if (obj.IsNull() || obj.IsInstance()) {
Instance& instance = Instance::Handle(Z);
instance ^= obj.ptr();
if (Library::IsPrivate(field_name)) {
const Class& cls = Class::Handle(Z, instance.clazz());
const Library& lib = Library::Handle(Z, cls.library());
field_name = lib.PrivateName(field_name);
}
return Api::NewHandle(T,
instance.InvokeGetter(field_name, respect_reflectable,
check_is_entrypoint));
} else if (obj.IsLibrary()) {
const Library& lib = Library::Cast(obj);
// Check that the library is loaded.
if (!lib.Loaded()) {
return Api::NewError(
"%s expects library argument 'container' to be loaded.",
CURRENT_FUNC);
}
if (Library::IsPrivate(field_name)) {
field_name = lib.PrivateName(field_name);
}
return Api::NewHandle(
T, lib.InvokeGetter(field_name, throw_nsm_if_absent,
respect_reflectable, check_is_entrypoint));
} else if (obj.IsError()) {
return container;
} else {
return Api::NewError(
"%s expects argument 'container' to be an object, type, or library.",
CURRENT_FUNC);
}
}
DART_EXPORT Dart_Handle Dart_SetField(Dart_Handle container,
Dart_Handle name,
Dart_Handle value) {
DARTSCOPE(Thread::Current());
API_TIMELINE_DURATION(T);
CHECK_CALLBACK_STATE(T);
String& field_name =
String::Handle(Z, Api::UnwrapStringHandle(Z, name).ptr());
if (field_name.IsNull()) {
RETURN_TYPE_ERROR(Z, name, String);
}
// Since null is allowed for value, we don't use UnwrapInstanceHandle.
const Object& value_obj = Object::Handle(Z, Api::UnwrapHandle(value));
if (!value_obj.IsNull() && !value_obj.IsInstance()) {
RETURN_TYPE_ERROR(Z, value, Instance);
}
Instance& value_instance = Instance::Handle(Z);
value_instance ^= value_obj.ptr();
const Object& obj = Object::Handle(Z, Api::UnwrapHandle(container));
const bool respect_reflectable = false;
const bool check_is_entrypoint = FLAG_verify_entry_points;
if (obj.IsType()) {
if (!Type::Cast(obj).IsFinalized()) {
return Api::NewError(
"%s expects argument 'container' to be a fully resolved type.",
CURRENT_FUNC);
}
// To access a static field we may need to use the Field or the
// setter Function.
Class& cls = Class::Handle(Z, Type::Cast(obj).type_class());
if (Library::IsPrivate(field_name)) {
const Library& lib = Library::Handle(Z, cls.library());
field_name = lib.PrivateName(field_name);
}
return Api::NewHandle(
T, cls.InvokeSetter(field_name, value_instance, respect_reflectable,
check_is_entrypoint));
} else if (obj.IsNull() || obj.IsInstance()) {
Instance& instance = Instance::Handle(Z);
instance ^= obj.ptr();
if (Library::IsPrivate(field_name)) {
const Class& cls = Class::Handle(Z, instance.clazz());
const Library& lib = Library::Handle(Z, cls.library());
field_name = lib.PrivateName(field_name);
}
return Api::NewHandle(
T, instance.InvokeSetter(field_name, value_instance,
respect_reflectable, check_is_entrypoint));
} else if (obj.IsLibrary()) {
// To access a top-level we may need to use the Field or the
// setter Function. The setter function may either be in the
// library or in the field's owner class, depending.
const Library& lib = Library::Cast(obj);
// Check that the library is loaded.
if (!lib.Loaded()) {
return Api::NewError(
"%s expects library argument 'container' to be loaded.",
CURRENT_FUNC);
}
if (Library::IsPrivate(field_name)) {
field_name = lib.PrivateName(field_name);
}
return Api::NewHandle(
T, lib.InvokeSetter(field_name, value_instance, respect_reflectable,
check_is_entrypoint));
} else if (obj.IsError()) {
return container;
}
return Api::NewError(
"%s expects argument 'container' to be an object, type, or library.",
CURRENT_FUNC);
}
// --- Exceptions ----
DART_EXPORT Dart_Handle Dart_ThrowException(Dart_Handle exception) {
Thread* thread = Thread::Current();
Zone* zone = thread->zone();
Isolate* isolate = thread->isolate();
CHECK_ISOLATE(isolate);
CHECK_CALLBACK_STATE(thread);
if (::Dart_IsError(exception)) {
::Dart_PropagateError(exception);
}
TransitionNativeToVM transition(thread);
const Instance& excp = Api::UnwrapInstanceHandle(zone, exception);
if (excp.IsNull()) {
RETURN_TYPE_ERROR(zone, exception, Instance);
}
if (thread->top_exit_frame_info() == 0) {
// There are no dart frames on the stack so it would be illegal to
// throw an exception here.
return Api::NewError("No Dart frames on stack, cannot throw exception");
}
// Unwind all the API scopes till the exit frame before throwing an
// exception.
const Instance* saved_exception;
{
NoSafepointScope no_safepoint;
InstancePtr raw_exception =
Api::UnwrapInstanceHandle(zone, exception).ptr();
thread->UnwindScopes(thread->top_exit_frame_info());
saved_exception = &Instance::Handle(raw_exception);
}
Exceptions::Throw(thread, *saved_exception);
return Api::NewError("Exception was not thrown, internal error");
}
DART_EXPORT Dart_Handle Dart_ReThrowException(Dart_Handle exception,
Dart_Handle stacktrace) {
Thread* thread = Thread::Current();
Zone* zone = thread->zone();
Isolate* isolate = thread->isolate();
CHECK_ISOLATE(isolate);
CHECK_CALLBACK_STATE(thread);
TransitionNativeToVM transition(thread);
{
const Instance& excp = Api::UnwrapInstanceHandle(zone, exception);
if (excp.IsNull()) {
RETURN_TYPE_ERROR(zone, exception, Instance);
}
const Instance& stk = Api::UnwrapInstanceHandle(zone, stacktrace);
if (stk.IsNull()) {
RETURN_TYPE_ERROR(zone, stacktrace, Instance);
}
}
if (thread->top_exit_frame_info() == 0) {
// There are no dart frames on the stack so it would be illegal to
// throw an exception here.
return Api::NewError("No Dart frames on stack, cannot throw exception");
}
// Unwind all the API scopes till the exit frame before throwing an
// exception.
const Instance* saved_exception;
const StackTrace* saved_stacktrace;
{
NoSafepointScope no_safepoint;
InstancePtr raw_exception =
Api::UnwrapInstanceHandle(zone, exception).ptr();
StackTracePtr raw_stacktrace =
Api::UnwrapStackTraceHandle(zone, stacktrace).ptr();
thread->UnwindScopes(thread->top_exit_frame_info());
saved_exception = &Instance::Handle(raw_exception);
saved_stacktrace = &StackTrace::Handle(raw_stacktrace);
}
Exceptions::ReThrow(thread, *saved_exception, *saved_stacktrace);
return Api::NewError("Exception was not re thrown, internal error");
}
// --- Native fields and functions ---
DART_EXPORT Dart_Handle Dart_GetNativeInstanceFieldCount(Dart_Handle obj,
int* count) {
Thread* thread = Thread::Current();
CHECK_ISOLATE(thread->isolate());
TransitionNativeToVM transition(thread);
{
ReusableObjectHandleScope reused_obj_handle(thread);
const Instance& instance =
Api::UnwrapInstanceHandle(reused_obj_handle, obj);
if (!instance.IsNull()) {
*count = instance.NumNativeFields();
return Api::Success();
}
}
RETURN_TYPE_ERROR(thread->zone(), obj, Instance);
}
DART_EXPORT Dart_Handle Dart_GetNativeInstanceField(Dart_Handle obj,
int index,
intptr_t* value) {
Thread* thread = Thread::Current();
CHECK_ISOLATE(thread->isolate());
TransitionNativeToVM transition(thread);
bool is_null = false;
{
ReusableObjectHandleScope reused_obj_handle(thread);
const Instance& instance =
Api::UnwrapInstanceHandle(reused_obj_handle, obj);
if (!instance.IsNull()) {
if (instance.IsValidNativeIndex(index)) {
*value = instance.GetNativeField(index);
return Api::Success();
}
} else {
is_null = true;
}
}
if (is_null) {
RETURN_TYPE_ERROR(thread->zone(), obj, Instance);
}
return Api::NewError(
"%s: invalid index %d passed in to access native instance field",
CURRENT_FUNC, index);
}
DART_EXPORT Dart_Handle Dart_SetNativeInstanceField(Dart_Handle obj,
int index,
intptr_t value) {
DARTSCOPE(Thread::Current());
const Instance& instance = Api::UnwrapInstanceHandle(Z, obj);
if (instance.IsNull()) {
RETURN_TYPE_ERROR(Z, obj, Instance);
}
if (!instance.IsValidNativeIndex(index)) {
return Api::NewError(
"%s: invalid index %d passed in to set native instance field",
CURRENT_FUNC, index);
}
instance.SetNativeField(index, value);
return Api::Success();
}
Second attempt to reland "[vm/concurrency] Introduce concept of Isolate Groups" This reverts commit 3d14b75f972ca287cd892ff907cf04b22839af59. An Isolate Group (IG) is a collection of isolates which were spawned from the same source. This allows the VM to: * have a guarantee that all isolates within one IG can safely exchange structured objects (currently we rely on embedder for this guarantee) * hot-reload all isolates together (currently we only reload one isolate, leaving same-source isolates in inconsistent state) * make a shared heap for all isolates from the same IG, which paves the way for faster communication and sharing of immutable objects. All isolates within one IG will share the same IsolateGroupSource. **Embedder changes** This change makes breaking embedder API changes to support this new concept of Isolate Groups: The existing isolate lifecycle callbacks given to Dart_Initialize will become Isolate Group lifecycle callbacks. A new callback `initialize_isolate` callback will be added which can initialize a new isolate within an existing IG. Existing embedders can be updated by performing the following renames Dart_CreateIsolate -> Dart_CreateIsolateGroup Dart_IsolateCreateCallback -> Dart_IsolateGroupCreateCallback Dart_IsolateCleanupCallback -> Dart_IsolateGroupShutdownCallback Dart_CreateIsolateFromKernel -> Dart_CreateIsolateGroupFromKernel Dart_CurrentIsolateData -> Dart_CurrentIsolateGroupData Dart_IsolateData -> Dart_IsolateGroupData Dart_GetNativeIsolateData -> Dart_GetNativeIsolateGroupData Dart_InitializeParams.create -> Dart_InitializeParams.create_group Dart_InitializeParams.cleanup -> Dart_InitializeParams.shutdown_group Dart_InitializeParams.shutdown -> Dart_InitializeParams.shutdown_isolate By default `Isolate.spawn` will cause the creation of a new IG. Though an embedder can opt-into supporting multiple isolates within one IG by providing a callback to the newly added `Dart_InitializeParams.initialize_isolate`. The responsibility of this new callback is to initialize an existing isolate (which was setup by re-using source code from the spawning isolate - i.e. the one which used `Isolate.spawn`) by setting native resolvers, initializing global state, etc. Issue https://github.com/dart-lang/sdk/issues/36648 Issue https://github.com/dart-lang/sdk/issues/36097 Original review: https://dart-review.googlesource.com/c/sdk/+/105241 Difference to original review: * Give each isolate it's own [Loader] (for now) * Sort classes during initialization for spawned isolates if app-jit is used (to match main isolate) * Fix IsolateData memory leak if isolate startup fails Difference to first reland(Patchset 2): * Fix typo where memory was freed twice. Change-Id: Ib1c83fe83b629cd50ae6af90ee99fdd44da882d4 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/108367 Commit-Queue: Alexander Aprelev <aam@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com>
2019-07-08 23:49:05 +00:00
DART_EXPORT void* Dart_GetNativeIsolateGroupData(Dart_NativeArguments args) {
NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
Isolate* isolate = arguments->thread()->isolate();
ASSERT(isolate == Isolate::Current());
return isolate->init_callback_data();
}
Add a new API function to extract all the native arguments into an array passed in by the caller. This call can be used in DOM bindings patterns as follows: Old code - Dart_Handle exception = 0; { WebGL* receiver = DartDOMWrapper::receiver< WebGL >(args); unsigned srcRGB = DartUtilities::dartToUnsigned(args, 1, exception); if (exception) goto fail; unsigned dstRGB = DartUtilities::dartToUnsigned(args, 2, exception); if (exception) goto fail; unsigned srcAlpha = DartUtilities::dartToUnsigned(args, 3, exception); if (exception) goto fail; unsigned dstAlpha = DartUtilities::dartToUnsigned(args, 4, exception); if (exception) goto fail; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; } fail: Dart_ThrowException(exception); ASSERT_NOT_REACHED(); Proposed new code - /** * One time initialization code for setting up argument descriptors */ const int kNumArgs = 5; const int kNumNativeFields = 2; static const uint8_t native_arg_descriptor[kNumArgs] = { DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kNativeFields, 0), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 1), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 2), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 3), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 4), }; Dart_NativeArgument_Value native_args[kNumArgs]; intptr_t native_fields[kNumNativeFields]; native_args[0].as_native_fields.num_fields = kNumNativeFields; native_args[0].as_native_fields.values = native_fields; /** * Code executed for each invocation of the binding method */ Dart_Handle result = Dart_GetNativeArguments(args, kNumArgs, native_arg_descriptor, native_args); if (Dart_IsError(result)) { Dart_ThrowException(result); } WebGL* receiver = DartDOMWrapper::receiver< WebGL >(native_args[0].as_native_fields.values); unsigned srcRGB = native_args[1].as_uint32; unsigned dstRGB = native_args[2].as_uint32; unsigned srcAlpha = native_args[3].as_uint32; unsigned dstAlpha = native_args[4].as_uint32; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; R=iposva@google.com, vsm@google.com Review URL: https://codereview.chromium.org//282883002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@36464 260f80e4-7a28-3924-810f-c04153c831b5
2014-05-22 00:08:23 +00:00
DART_EXPORT Dart_Handle Dart_GetNativeArguments(
Dart_NativeArguments args,
int num_arguments,
const Dart_NativeArgument_Descriptor* argument_descriptors,
Dart_NativeArgument_Value* arg_values) {
NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
TransitionNativeToVM transition(arguments->thread());
ASSERT(arguments->thread()->isolate() == Isolate::Current());
Add a new API function to extract all the native arguments into an array passed in by the caller. This call can be used in DOM bindings patterns as follows: Old code - Dart_Handle exception = 0; { WebGL* receiver = DartDOMWrapper::receiver< WebGL >(args); unsigned srcRGB = DartUtilities::dartToUnsigned(args, 1, exception); if (exception) goto fail; unsigned dstRGB = DartUtilities::dartToUnsigned(args, 2, exception); if (exception) goto fail; unsigned srcAlpha = DartUtilities::dartToUnsigned(args, 3, exception); if (exception) goto fail; unsigned dstAlpha = DartUtilities::dartToUnsigned(args, 4, exception); if (exception) goto fail; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; } fail: Dart_ThrowException(exception); ASSERT_NOT_REACHED(); Proposed new code - /** * One time initialization code for setting up argument descriptors */ const int kNumArgs = 5; const int kNumNativeFields = 2; static const uint8_t native_arg_descriptor[kNumArgs] = { DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kNativeFields, 0), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 1), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 2), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 3), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 4), }; Dart_NativeArgument_Value native_args[kNumArgs]; intptr_t native_fields[kNumNativeFields]; native_args[0].as_native_fields.num_fields = kNumNativeFields; native_args[0].as_native_fields.values = native_fields; /** * Code executed for each invocation of the binding method */ Dart_Handle result = Dart_GetNativeArguments(args, kNumArgs, native_arg_descriptor, native_args); if (Dart_IsError(result)) { Dart_ThrowException(result); } WebGL* receiver = DartDOMWrapper::receiver< WebGL >(native_args[0].as_native_fields.values); unsigned srcRGB = native_args[1].as_uint32; unsigned dstRGB = native_args[2].as_uint32; unsigned srcAlpha = native_args[3].as_uint32; unsigned dstAlpha = native_args[4].as_uint32; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; R=iposva@google.com, vsm@google.com Review URL: https://codereview.chromium.org//282883002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@36464 260f80e4-7a28-3924-810f-c04153c831b5
2014-05-22 00:08:23 +00:00
if (arg_values == NULL) {
RETURN_NULL_ERROR(arg_values);
}
for (int i = 0; i < num_arguments; i++) {
Dart_NativeArgument_Descriptor desc = argument_descriptors[i];
Dart_NativeArgument_Type arg_type =
static_cast<Dart_NativeArgument_Type>(desc.type);
Add a new API function to extract all the native arguments into an array passed in by the caller. This call can be used in DOM bindings patterns as follows: Old code - Dart_Handle exception = 0; { WebGL* receiver = DartDOMWrapper::receiver< WebGL >(args); unsigned srcRGB = DartUtilities::dartToUnsigned(args, 1, exception); if (exception) goto fail; unsigned dstRGB = DartUtilities::dartToUnsigned(args, 2, exception); if (exception) goto fail; unsigned srcAlpha = DartUtilities::dartToUnsigned(args, 3, exception); if (exception) goto fail; unsigned dstAlpha = DartUtilities::dartToUnsigned(args, 4, exception); if (exception) goto fail; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; } fail: Dart_ThrowException(exception); ASSERT_NOT_REACHED(); Proposed new code - /** * One time initialization code for setting up argument descriptors */ const int kNumArgs = 5; const int kNumNativeFields = 2; static const uint8_t native_arg_descriptor[kNumArgs] = { DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kNativeFields, 0), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 1), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 2), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 3), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 4), }; Dart_NativeArgument_Value native_args[kNumArgs]; intptr_t native_fields[kNumNativeFields]; native_args[0].as_native_fields.num_fields = kNumNativeFields; native_args[0].as_native_fields.values = native_fields; /** * Code executed for each invocation of the binding method */ Dart_Handle result = Dart_GetNativeArguments(args, kNumArgs, native_arg_descriptor, native_args); if (Dart_IsError(result)) { Dart_ThrowException(result); } WebGL* receiver = DartDOMWrapper::receiver< WebGL >(native_args[0].as_native_fields.values); unsigned srcRGB = native_args[1].as_uint32; unsigned dstRGB = native_args[2].as_uint32; unsigned srcAlpha = native_args[3].as_uint32; unsigned dstAlpha = native_args[4].as_uint32; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; R=iposva@google.com, vsm@google.com Review URL: https://codereview.chromium.org//282883002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@36464 260f80e4-7a28-3924-810f-c04153c831b5
2014-05-22 00:08:23 +00:00
int arg_index = desc.index;
ASSERT(arg_index >= 0 && arg_index < arguments->NativeArgCount());
Dart_NativeArgument_Value* native_value = &(arg_values[i]);
switch (arg_type) {
case Dart_NativeArgument_kBool:
if (!Api::GetNativeBooleanArgument(arguments, arg_index,
Add a new API function to extract all the native arguments into an array passed in by the caller. This call can be used in DOM bindings patterns as follows: Old code - Dart_Handle exception = 0; { WebGL* receiver = DartDOMWrapper::receiver< WebGL >(args); unsigned srcRGB = DartUtilities::dartToUnsigned(args, 1, exception); if (exception) goto fail; unsigned dstRGB = DartUtilities::dartToUnsigned(args, 2, exception); if (exception) goto fail; unsigned srcAlpha = DartUtilities::dartToUnsigned(args, 3, exception); if (exception) goto fail; unsigned dstAlpha = DartUtilities::dartToUnsigned(args, 4, exception); if (exception) goto fail; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; } fail: Dart_ThrowException(exception); ASSERT_NOT_REACHED(); Proposed new code - /** * One time initialization code for setting up argument descriptors */ const int kNumArgs = 5; const int kNumNativeFields = 2; static const uint8_t native_arg_descriptor[kNumArgs] = { DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kNativeFields, 0), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 1), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 2), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 3), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 4), }; Dart_NativeArgument_Value native_args[kNumArgs]; intptr_t native_fields[kNumNativeFields]; native_args[0].as_native_fields.num_fields = kNumNativeFields; native_args[0].as_native_fields.values = native_fields; /** * Code executed for each invocation of the binding method */ Dart_Handle result = Dart_GetNativeArguments(args, kNumArgs, native_arg_descriptor, native_args); if (Dart_IsError(result)) { Dart_ThrowException(result); } WebGL* receiver = DartDOMWrapper::receiver< WebGL >(native_args[0].as_native_fields.values); unsigned srcRGB = native_args[1].as_uint32; unsigned dstRGB = native_args[2].as_uint32; unsigned srcAlpha = native_args[3].as_uint32; unsigned dstAlpha = native_args[4].as_uint32; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; R=iposva@google.com, vsm@google.com Review URL: https://codereview.chromium.org//282883002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@36464 260f80e4-7a28-3924-810f-c04153c831b5
2014-05-22 00:08:23 +00:00
&(native_value->as_bool))) {
return Api::NewArgumentError(
"%s: expects argument at index %d to be of"
" type Boolean.",
CURRENT_FUNC, i);
Add a new API function to extract all the native arguments into an array passed in by the caller. This call can be used in DOM bindings patterns as follows: Old code - Dart_Handle exception = 0; { WebGL* receiver = DartDOMWrapper::receiver< WebGL >(args); unsigned srcRGB = DartUtilities::dartToUnsigned(args, 1, exception); if (exception) goto fail; unsigned dstRGB = DartUtilities::dartToUnsigned(args, 2, exception); if (exception) goto fail; unsigned srcAlpha = DartUtilities::dartToUnsigned(args, 3, exception); if (exception) goto fail; unsigned dstAlpha = DartUtilities::dartToUnsigned(args, 4, exception); if (exception) goto fail; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; } fail: Dart_ThrowException(exception); ASSERT_NOT_REACHED(); Proposed new code - /** * One time initialization code for setting up argument descriptors */ const int kNumArgs = 5; const int kNumNativeFields = 2; static const uint8_t native_arg_descriptor[kNumArgs] = { DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kNativeFields, 0), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 1), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 2), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 3), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 4), }; Dart_NativeArgument_Value native_args[kNumArgs]; intptr_t native_fields[kNumNativeFields]; native_args[0].as_native_fields.num_fields = kNumNativeFields; native_args[0].as_native_fields.values = native_fields; /** * Code executed for each invocation of the binding method */ Dart_Handle result = Dart_GetNativeArguments(args, kNumArgs, native_arg_descriptor, native_args); if (Dart_IsError(result)) { Dart_ThrowException(result); } WebGL* receiver = DartDOMWrapper::receiver< WebGL >(native_args[0].as_native_fields.values); unsigned srcRGB = native_args[1].as_uint32; unsigned dstRGB = native_args[2].as_uint32; unsigned srcAlpha = native_args[3].as_uint32; unsigned dstAlpha = native_args[4].as_uint32; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; R=iposva@google.com, vsm@google.com Review URL: https://codereview.chromium.org//282883002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@36464 260f80e4-7a28-3924-810f-c04153c831b5
2014-05-22 00:08:23 +00:00
}
break;
case Dart_NativeArgument_kInt32: {
int64_t value = 0;
if (!GetNativeIntegerArgument(arguments, arg_index, &value)) {
return Api::NewArgumentError(
"%s: expects argument at index %d to be of"
" type Integer.",
CURRENT_FUNC, i);
Add a new API function to extract all the native arguments into an array passed in by the caller. This call can be used in DOM bindings patterns as follows: Old code - Dart_Handle exception = 0; { WebGL* receiver = DartDOMWrapper::receiver< WebGL >(args); unsigned srcRGB = DartUtilities::dartToUnsigned(args, 1, exception); if (exception) goto fail; unsigned dstRGB = DartUtilities::dartToUnsigned(args, 2, exception); if (exception) goto fail; unsigned srcAlpha = DartUtilities::dartToUnsigned(args, 3, exception); if (exception) goto fail; unsigned dstAlpha = DartUtilities::dartToUnsigned(args, 4, exception); if (exception) goto fail; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; } fail: Dart_ThrowException(exception); ASSERT_NOT_REACHED(); Proposed new code - /** * One time initialization code for setting up argument descriptors */ const int kNumArgs = 5; const int kNumNativeFields = 2; static const uint8_t native_arg_descriptor[kNumArgs] = { DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kNativeFields, 0), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 1), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 2), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 3), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 4), }; Dart_NativeArgument_Value native_args[kNumArgs]; intptr_t native_fields[kNumNativeFields]; native_args[0].as_native_fields.num_fields = kNumNativeFields; native_args[0].as_native_fields.values = native_fields; /** * Code executed for each invocation of the binding method */ Dart_Handle result = Dart_GetNativeArguments(args, kNumArgs, native_arg_descriptor, native_args); if (Dart_IsError(result)) { Dart_ThrowException(result); } WebGL* receiver = DartDOMWrapper::receiver< WebGL >(native_args[0].as_native_fields.values); unsigned srcRGB = native_args[1].as_uint32; unsigned dstRGB = native_args[2].as_uint32; unsigned srcAlpha = native_args[3].as_uint32; unsigned dstAlpha = native_args[4].as_uint32; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; R=iposva@google.com, vsm@google.com Review URL: https://codereview.chromium.org//282883002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@36464 260f80e4-7a28-3924-810f-c04153c831b5
2014-05-22 00:08:23 +00:00
}
if (value < INT32_MIN || value > INT32_MAX) {
return Api::NewArgumentError(
"%s: argument value at index %d is out of range", CURRENT_FUNC,
i);
Add a new API function to extract all the native arguments into an array passed in by the caller. This call can be used in DOM bindings patterns as follows: Old code - Dart_Handle exception = 0; { WebGL* receiver = DartDOMWrapper::receiver< WebGL >(args); unsigned srcRGB = DartUtilities::dartToUnsigned(args, 1, exception); if (exception) goto fail; unsigned dstRGB = DartUtilities::dartToUnsigned(args, 2, exception); if (exception) goto fail; unsigned srcAlpha = DartUtilities::dartToUnsigned(args, 3, exception); if (exception) goto fail; unsigned dstAlpha = DartUtilities::dartToUnsigned(args, 4, exception); if (exception) goto fail; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; } fail: Dart_ThrowException(exception); ASSERT_NOT_REACHED(); Proposed new code - /** * One time initialization code for setting up argument descriptors */ const int kNumArgs = 5; const int kNumNativeFields = 2; static const uint8_t native_arg_descriptor[kNumArgs] = { DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kNativeFields, 0), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 1), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 2), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 3), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 4), }; Dart_NativeArgument_Value native_args[kNumArgs]; intptr_t native_fields[kNumNativeFields]; native_args[0].as_native_fields.num_fields = kNumNativeFields; native_args[0].as_native_fields.values = native_fields; /** * Code executed for each invocation of the binding method */ Dart_Handle result = Dart_GetNativeArguments(args, kNumArgs, native_arg_descriptor, native_args); if (Dart_IsError(result)) { Dart_ThrowException(result); } WebGL* receiver = DartDOMWrapper::receiver< WebGL >(native_args[0].as_native_fields.values); unsigned srcRGB = native_args[1].as_uint32; unsigned dstRGB = native_args[2].as_uint32; unsigned srcAlpha = native_args[3].as_uint32; unsigned dstAlpha = native_args[4].as_uint32; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; R=iposva@google.com, vsm@google.com Review URL: https://codereview.chromium.org//282883002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@36464 260f80e4-7a28-3924-810f-c04153c831b5
2014-05-22 00:08:23 +00:00
}
native_value->as_int32 = static_cast<int32_t>(value);
break;
}
case Dart_NativeArgument_kUint32: {
int64_t value = 0;
if (!GetNativeIntegerArgument(arguments, arg_index, &value)) {
return Api::NewArgumentError(
"%s: expects argument at index %d to be of"
" type Integer.",
CURRENT_FUNC, i);
Add a new API function to extract all the native arguments into an array passed in by the caller. This call can be used in DOM bindings patterns as follows: Old code - Dart_Handle exception = 0; { WebGL* receiver = DartDOMWrapper::receiver< WebGL >(args); unsigned srcRGB = DartUtilities::dartToUnsigned(args, 1, exception); if (exception) goto fail; unsigned dstRGB = DartUtilities::dartToUnsigned(args, 2, exception); if (exception) goto fail; unsigned srcAlpha = DartUtilities::dartToUnsigned(args, 3, exception); if (exception) goto fail; unsigned dstAlpha = DartUtilities::dartToUnsigned(args, 4, exception); if (exception) goto fail; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; } fail: Dart_ThrowException(exception); ASSERT_NOT_REACHED(); Proposed new code - /** * One time initialization code for setting up argument descriptors */ const int kNumArgs = 5; const int kNumNativeFields = 2; static const uint8_t native_arg_descriptor[kNumArgs] = { DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kNativeFields, 0), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 1), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 2), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 3), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 4), }; Dart_NativeArgument_Value native_args[kNumArgs]; intptr_t native_fields[kNumNativeFields]; native_args[0].as_native_fields.num_fields = kNumNativeFields; native_args[0].as_native_fields.values = native_fields; /** * Code executed for each invocation of the binding method */ Dart_Handle result = Dart_GetNativeArguments(args, kNumArgs, native_arg_descriptor, native_args); if (Dart_IsError(result)) { Dart_ThrowException(result); } WebGL* receiver = DartDOMWrapper::receiver< WebGL >(native_args[0].as_native_fields.values); unsigned srcRGB = native_args[1].as_uint32; unsigned dstRGB = native_args[2].as_uint32; unsigned srcAlpha = native_args[3].as_uint32; unsigned dstAlpha = native_args[4].as_uint32; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; R=iposva@google.com, vsm@google.com Review URL: https://codereview.chromium.org//282883002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@36464 260f80e4-7a28-3924-810f-c04153c831b5
2014-05-22 00:08:23 +00:00
}
if (value < 0 || value > UINT32_MAX) {
return Api::NewArgumentError(
"%s: argument value at index %d is out of range", CURRENT_FUNC,
i);
Add a new API function to extract all the native arguments into an array passed in by the caller. This call can be used in DOM bindings patterns as follows: Old code - Dart_Handle exception = 0; { WebGL* receiver = DartDOMWrapper::receiver< WebGL >(args); unsigned srcRGB = DartUtilities::dartToUnsigned(args, 1, exception); if (exception) goto fail; unsigned dstRGB = DartUtilities::dartToUnsigned(args, 2, exception); if (exception) goto fail; unsigned srcAlpha = DartUtilities::dartToUnsigned(args, 3, exception); if (exception) goto fail; unsigned dstAlpha = DartUtilities::dartToUnsigned(args, 4, exception); if (exception) goto fail; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; } fail: Dart_ThrowException(exception); ASSERT_NOT_REACHED(); Proposed new code - /** * One time initialization code for setting up argument descriptors */ const int kNumArgs = 5; const int kNumNativeFields = 2; static const uint8_t native_arg_descriptor[kNumArgs] = { DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kNativeFields, 0), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 1), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 2), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 3), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 4), }; Dart_NativeArgument_Value native_args[kNumArgs]; intptr_t native_fields[kNumNativeFields]; native_args[0].as_native_fields.num_fields = kNumNativeFields; native_args[0].as_native_fields.values = native_fields; /** * Code executed for each invocation of the binding method */ Dart_Handle result = Dart_GetNativeArguments(args, kNumArgs, native_arg_descriptor, native_args); if (Dart_IsError(result)) { Dart_ThrowException(result); } WebGL* receiver = DartDOMWrapper::receiver< WebGL >(native_args[0].as_native_fields.values); unsigned srcRGB = native_args[1].as_uint32; unsigned dstRGB = native_args[2].as_uint32; unsigned srcAlpha = native_args[3].as_uint32; unsigned dstAlpha = native_args[4].as_uint32; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; R=iposva@google.com, vsm@google.com Review URL: https://codereview.chromium.org//282883002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@36464 260f80e4-7a28-3924-810f-c04153c831b5
2014-05-22 00:08:23 +00:00
}
native_value->as_uint32 = static_cast<uint32_t>(value);
break;
}
case Dart_NativeArgument_kInt64: {
int64_t value = 0;
if (!GetNativeIntegerArgument(arguments, arg_index, &value)) {
return Api::NewArgumentError(
"%s: expects argument at index %d to be of"
" type Integer.",
CURRENT_FUNC, i);
Add a new API function to extract all the native arguments into an array passed in by the caller. This call can be used in DOM bindings patterns as follows: Old code - Dart_Handle exception = 0; { WebGL* receiver = DartDOMWrapper::receiver< WebGL >(args); unsigned srcRGB = DartUtilities::dartToUnsigned(args, 1, exception); if (exception) goto fail; unsigned dstRGB = DartUtilities::dartToUnsigned(args, 2, exception); if (exception) goto fail; unsigned srcAlpha = DartUtilities::dartToUnsigned(args, 3, exception); if (exception) goto fail; unsigned dstAlpha = DartUtilities::dartToUnsigned(args, 4, exception); if (exception) goto fail; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; } fail: Dart_ThrowException(exception); ASSERT_NOT_REACHED(); Proposed new code - /** * One time initialization code for setting up argument descriptors */ const int kNumArgs = 5; const int kNumNativeFields = 2; static const uint8_t native_arg_descriptor[kNumArgs] = { DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kNativeFields, 0), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 1), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 2), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 3), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 4), }; Dart_NativeArgument_Value native_args[kNumArgs]; intptr_t native_fields[kNumNativeFields]; native_args[0].as_native_fields.num_fields = kNumNativeFields; native_args[0].as_native_fields.values = native_fields; /** * Code executed for each invocation of the binding method */ Dart_Handle result = Dart_GetNativeArguments(args, kNumArgs, native_arg_descriptor, native_args); if (Dart_IsError(result)) { Dart_ThrowException(result); } WebGL* receiver = DartDOMWrapper::receiver< WebGL >(native_args[0].as_native_fields.values); unsigned srcRGB = native_args[1].as_uint32; unsigned dstRGB = native_args[2].as_uint32; unsigned srcAlpha = native_args[3].as_uint32; unsigned dstAlpha = native_args[4].as_uint32; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; R=iposva@google.com, vsm@google.com Review URL: https://codereview.chromium.org//282883002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@36464 260f80e4-7a28-3924-810f-c04153c831b5
2014-05-22 00:08:23 +00:00
}
native_value->as_int64 = value;
break;
}
case Dart_NativeArgument_kUint64: {
uint64_t value = 0;
if (!GetNativeUnsignedIntegerArgument(arguments, arg_index, &value)) {
return Api::NewArgumentError(
"%s: expects argument at index %d to be of"
" type Integer.",
CURRENT_FUNC, i);
Add a new API function to extract all the native arguments into an array passed in by the caller. This call can be used in DOM bindings patterns as follows: Old code - Dart_Handle exception = 0; { WebGL* receiver = DartDOMWrapper::receiver< WebGL >(args); unsigned srcRGB = DartUtilities::dartToUnsigned(args, 1, exception); if (exception) goto fail; unsigned dstRGB = DartUtilities::dartToUnsigned(args, 2, exception); if (exception) goto fail; unsigned srcAlpha = DartUtilities::dartToUnsigned(args, 3, exception); if (exception) goto fail; unsigned dstAlpha = DartUtilities::dartToUnsigned(args, 4, exception); if (exception) goto fail; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; } fail: Dart_ThrowException(exception); ASSERT_NOT_REACHED(); Proposed new code - /** * One time initialization code for setting up argument descriptors */ const int kNumArgs = 5; const int kNumNativeFields = 2; static const uint8_t native_arg_descriptor[kNumArgs] = { DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kNativeFields, 0), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 1), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 2), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 3), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 4), }; Dart_NativeArgument_Value native_args[kNumArgs]; intptr_t native_fields[kNumNativeFields]; native_args[0].as_native_fields.num_fields = kNumNativeFields; native_args[0].as_native_fields.values = native_fields; /** * Code executed for each invocation of the binding method */ Dart_Handle result = Dart_GetNativeArguments(args, kNumArgs, native_arg_descriptor, native_args); if (Dart_IsError(result)) { Dart_ThrowException(result); } WebGL* receiver = DartDOMWrapper::receiver< WebGL >(native_args[0].as_native_fields.values); unsigned srcRGB = native_args[1].as_uint32; unsigned dstRGB = native_args[2].as_uint32; unsigned srcAlpha = native_args[3].as_uint32; unsigned dstAlpha = native_args[4].as_uint32; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; R=iposva@google.com, vsm@google.com Review URL: https://codereview.chromium.org//282883002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@36464 260f80e4-7a28-3924-810f-c04153c831b5
2014-05-22 00:08:23 +00:00
}
native_value->as_uint64 = value;
break;
}
case Dart_NativeArgument_kDouble:
if (!GetNativeDoubleArgument(arguments, arg_index,
Add a new API function to extract all the native arguments into an array passed in by the caller. This call can be used in DOM bindings patterns as follows: Old code - Dart_Handle exception = 0; { WebGL* receiver = DartDOMWrapper::receiver< WebGL >(args); unsigned srcRGB = DartUtilities::dartToUnsigned(args, 1, exception); if (exception) goto fail; unsigned dstRGB = DartUtilities::dartToUnsigned(args, 2, exception); if (exception) goto fail; unsigned srcAlpha = DartUtilities::dartToUnsigned(args, 3, exception); if (exception) goto fail; unsigned dstAlpha = DartUtilities::dartToUnsigned(args, 4, exception); if (exception) goto fail; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; } fail: Dart_ThrowException(exception); ASSERT_NOT_REACHED(); Proposed new code - /** * One time initialization code for setting up argument descriptors */ const int kNumArgs = 5; const int kNumNativeFields = 2; static const uint8_t native_arg_descriptor[kNumArgs] = { DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kNativeFields, 0), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 1), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 2), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 3), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 4), }; Dart_NativeArgument_Value native_args[kNumArgs]; intptr_t native_fields[kNumNativeFields]; native_args[0].as_native_fields.num_fields = kNumNativeFields; native_args[0].as_native_fields.values = native_fields; /** * Code executed for each invocation of the binding method */ Dart_Handle result = Dart_GetNativeArguments(args, kNumArgs, native_arg_descriptor, native_args); if (Dart_IsError(result)) { Dart_ThrowException(result); } WebGL* receiver = DartDOMWrapper::receiver< WebGL >(native_args[0].as_native_fields.values); unsigned srcRGB = native_args[1].as_uint32; unsigned dstRGB = native_args[2].as_uint32; unsigned srcAlpha = native_args[3].as_uint32; unsigned dstAlpha = native_args[4].as_uint32; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; R=iposva@google.com, vsm@google.com Review URL: https://codereview.chromium.org//282883002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@36464 260f80e4-7a28-3924-810f-c04153c831b5
2014-05-22 00:08:23 +00:00
&(native_value->as_double))) {
return Api::NewArgumentError(
"%s: expects argument at index %d to be of"
" type Double.",
CURRENT_FUNC, i);
Add a new API function to extract all the native arguments into an array passed in by the caller. This call can be used in DOM bindings patterns as follows: Old code - Dart_Handle exception = 0; { WebGL* receiver = DartDOMWrapper::receiver< WebGL >(args); unsigned srcRGB = DartUtilities::dartToUnsigned(args, 1, exception); if (exception) goto fail; unsigned dstRGB = DartUtilities::dartToUnsigned(args, 2, exception); if (exception) goto fail; unsigned srcAlpha = DartUtilities::dartToUnsigned(args, 3, exception); if (exception) goto fail; unsigned dstAlpha = DartUtilities::dartToUnsigned(args, 4, exception); if (exception) goto fail; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; } fail: Dart_ThrowException(exception); ASSERT_NOT_REACHED(); Proposed new code - /** * One time initialization code for setting up argument descriptors */ const int kNumArgs = 5; const int kNumNativeFields = 2; static const uint8_t native_arg_descriptor[kNumArgs] = { DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kNativeFields, 0), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 1), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 2), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 3), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 4), }; Dart_NativeArgument_Value native_args[kNumArgs]; intptr_t native_fields[kNumNativeFields]; native_args[0].as_native_fields.num_fields = kNumNativeFields; native_args[0].as_native_fields.values = native_fields; /** * Code executed for each invocation of the binding method */ Dart_Handle result = Dart_GetNativeArguments(args, kNumArgs, native_arg_descriptor, native_args); if (Dart_IsError(result)) { Dart_ThrowException(result); } WebGL* receiver = DartDOMWrapper::receiver< WebGL >(native_args[0].as_native_fields.values); unsigned srcRGB = native_args[1].as_uint32; unsigned dstRGB = native_args[2].as_uint32; unsigned srcAlpha = native_args[3].as_uint32; unsigned dstAlpha = native_args[4].as_uint32; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; R=iposva@google.com, vsm@google.com Review URL: https://codereview.chromium.org//282883002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@36464 260f80e4-7a28-3924-810f-c04153c831b5
2014-05-22 00:08:23 +00:00
}
break;
case Dart_NativeArgument_kString:
if (!GetNativeStringArgument(arguments, arg_index,
Add a new API function to extract all the native arguments into an array passed in by the caller. This call can be used in DOM bindings patterns as follows: Old code - Dart_Handle exception = 0; { WebGL* receiver = DartDOMWrapper::receiver< WebGL >(args); unsigned srcRGB = DartUtilities::dartToUnsigned(args, 1, exception); if (exception) goto fail; unsigned dstRGB = DartUtilities::dartToUnsigned(args, 2, exception); if (exception) goto fail; unsigned srcAlpha = DartUtilities::dartToUnsigned(args, 3, exception); if (exception) goto fail; unsigned dstAlpha = DartUtilities::dartToUnsigned(args, 4, exception); if (exception) goto fail; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; } fail: Dart_ThrowException(exception); ASSERT_NOT_REACHED(); Proposed new code - /** * One time initialization code for setting up argument descriptors */ const int kNumArgs = 5; const int kNumNativeFields = 2; static const uint8_t native_arg_descriptor[kNumArgs] = { DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kNativeFields, 0), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 1), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 2), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 3), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 4), }; Dart_NativeArgument_Value native_args[kNumArgs]; intptr_t native_fields[kNumNativeFields]; native_args[0].as_native_fields.num_fields = kNumNativeFields; native_args[0].as_native_fields.values = native_fields; /** * Code executed for each invocation of the binding method */ Dart_Handle result = Dart_GetNativeArguments(args, kNumArgs, native_arg_descriptor, native_args); if (Dart_IsError(result)) { Dart_ThrowException(result); } WebGL* receiver = DartDOMWrapper::receiver< WebGL >(native_args[0].as_native_fields.values); unsigned srcRGB = native_args[1].as_uint32; unsigned dstRGB = native_args[2].as_uint32; unsigned srcAlpha = native_args[3].as_uint32; unsigned dstAlpha = native_args[4].as_uint32; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; R=iposva@google.com, vsm@google.com Review URL: https://codereview.chromium.org//282883002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@36464 260f80e4-7a28-3924-810f-c04153c831b5
2014-05-22 00:08:23 +00:00
&(native_value->as_string.dart_str),
&(native_value->as_string.peer))) {
return Api::NewArgumentError(
"%s: expects argument at index %d to be of"
" type String.",
CURRENT_FUNC, i);
Add a new API function to extract all the native arguments into an array passed in by the caller. This call can be used in DOM bindings patterns as follows: Old code - Dart_Handle exception = 0; { WebGL* receiver = DartDOMWrapper::receiver< WebGL >(args); unsigned srcRGB = DartUtilities::dartToUnsigned(args, 1, exception); if (exception) goto fail; unsigned dstRGB = DartUtilities::dartToUnsigned(args, 2, exception); if (exception) goto fail; unsigned srcAlpha = DartUtilities::dartToUnsigned(args, 3, exception); if (exception) goto fail; unsigned dstAlpha = DartUtilities::dartToUnsigned(args, 4, exception); if (exception) goto fail; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; } fail: Dart_ThrowException(exception); ASSERT_NOT_REACHED(); Proposed new code - /** * One time initialization code for setting up argument descriptors */ const int kNumArgs = 5; const int kNumNativeFields = 2; static const uint8_t native_arg_descriptor[kNumArgs] = { DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kNativeFields, 0), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 1), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 2), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 3), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 4), }; Dart_NativeArgument_Value native_args[kNumArgs]; intptr_t native_fields[kNumNativeFields]; native_args[0].as_native_fields.num_fields = kNumNativeFields; native_args[0].as_native_fields.values = native_fields; /** * Code executed for each invocation of the binding method */ Dart_Handle result = Dart_GetNativeArguments(args, kNumArgs, native_arg_descriptor, native_args); if (Dart_IsError(result)) { Dart_ThrowException(result); } WebGL* receiver = DartDOMWrapper::receiver< WebGL >(native_args[0].as_native_fields.values); unsigned srcRGB = native_args[1].as_uint32; unsigned dstRGB = native_args[2].as_uint32; unsigned srcAlpha = native_args[3].as_uint32; unsigned dstAlpha = native_args[4].as_uint32; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; R=iposva@google.com, vsm@google.com Review URL: https://codereview.chromium.org//282883002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@36464 260f80e4-7a28-3924-810f-c04153c831b5
2014-05-22 00:08:23 +00:00
}
break;
case Dart_NativeArgument_kNativeFields: {
Dart_Handle result = GetNativeFieldsOfArgument(
arguments, arg_index, native_value->as_native_fields.num_fields,
native_value->as_native_fields.values, CURRENT_FUNC);
Add a new API function to extract all the native arguments into an array passed in by the caller. This call can be used in DOM bindings patterns as follows: Old code - Dart_Handle exception = 0; { WebGL* receiver = DartDOMWrapper::receiver< WebGL >(args); unsigned srcRGB = DartUtilities::dartToUnsigned(args, 1, exception); if (exception) goto fail; unsigned dstRGB = DartUtilities::dartToUnsigned(args, 2, exception); if (exception) goto fail; unsigned srcAlpha = DartUtilities::dartToUnsigned(args, 3, exception); if (exception) goto fail; unsigned dstAlpha = DartUtilities::dartToUnsigned(args, 4, exception); if (exception) goto fail; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; } fail: Dart_ThrowException(exception); ASSERT_NOT_REACHED(); Proposed new code - /** * One time initialization code for setting up argument descriptors */ const int kNumArgs = 5; const int kNumNativeFields = 2; static const uint8_t native_arg_descriptor[kNumArgs] = { DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kNativeFields, 0), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 1), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 2), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 3), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 4), }; Dart_NativeArgument_Value native_args[kNumArgs]; intptr_t native_fields[kNumNativeFields]; native_args[0].as_native_fields.num_fields = kNumNativeFields; native_args[0].as_native_fields.values = native_fields; /** * Code executed for each invocation of the binding method */ Dart_Handle result = Dart_GetNativeArguments(args, kNumArgs, native_arg_descriptor, native_args); if (Dart_IsError(result)) { Dart_ThrowException(result); } WebGL* receiver = DartDOMWrapper::receiver< WebGL >(native_args[0].as_native_fields.values); unsigned srcRGB = native_args[1].as_uint32; unsigned dstRGB = native_args[2].as_uint32; unsigned srcAlpha = native_args[3].as_uint32; unsigned dstAlpha = native_args[4].as_uint32; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; R=iposva@google.com, vsm@google.com Review URL: https://codereview.chromium.org//282883002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@36464 260f80e4-7a28-3924-810f-c04153c831b5
2014-05-22 00:08:23 +00:00
if (result != Api::Success()) {
return result;
}
break;
}
case Dart_NativeArgument_kInstance: {
ASSERT(arguments->thread() == Thread::Current());
ASSERT(arguments->thread()->api_top_scope() != NULL);
native_value->as_instance = Api::NewHandle(
arguments->thread(), arguments->NativeArgAt(arg_index));
Add a new API function to extract all the native arguments into an array passed in by the caller. This call can be used in DOM bindings patterns as follows: Old code - Dart_Handle exception = 0; { WebGL* receiver = DartDOMWrapper::receiver< WebGL >(args); unsigned srcRGB = DartUtilities::dartToUnsigned(args, 1, exception); if (exception) goto fail; unsigned dstRGB = DartUtilities::dartToUnsigned(args, 2, exception); if (exception) goto fail; unsigned srcAlpha = DartUtilities::dartToUnsigned(args, 3, exception); if (exception) goto fail; unsigned dstAlpha = DartUtilities::dartToUnsigned(args, 4, exception); if (exception) goto fail; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; } fail: Dart_ThrowException(exception); ASSERT_NOT_REACHED(); Proposed new code - /** * One time initialization code for setting up argument descriptors */ const int kNumArgs = 5; const int kNumNativeFields = 2; static const uint8_t native_arg_descriptor[kNumArgs] = { DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kNativeFields, 0), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 1), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 2), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 3), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 4), }; Dart_NativeArgument_Value native_args[kNumArgs]; intptr_t native_fields[kNumNativeFields]; native_args[0].as_native_fields.num_fields = kNumNativeFields; native_args[0].as_native_fields.values = native_fields; /** * Code executed for each invocation of the binding method */ Dart_Handle result = Dart_GetNativeArguments(args, kNumArgs, native_arg_descriptor, native_args); if (Dart_IsError(result)) { Dart_ThrowException(result); } WebGL* receiver = DartDOMWrapper::receiver< WebGL >(native_args[0].as_native_fields.values); unsigned srcRGB = native_args[1].as_uint32; unsigned dstRGB = native_args[2].as_uint32; unsigned srcAlpha = native_args[3].as_uint32; unsigned dstAlpha = native_args[4].as_uint32; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; R=iposva@google.com, vsm@google.com Review URL: https://codereview.chromium.org//282883002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@36464 260f80e4-7a28-3924-810f-c04153c831b5
2014-05-22 00:08:23 +00:00
break;
}
default:
return Api::NewArgumentError("%s: invalid argument type %d.",
CURRENT_FUNC, arg_type);
Add a new API function to extract all the native arguments into an array passed in by the caller. This call can be used in DOM bindings patterns as follows: Old code - Dart_Handle exception = 0; { WebGL* receiver = DartDOMWrapper::receiver< WebGL >(args); unsigned srcRGB = DartUtilities::dartToUnsigned(args, 1, exception); if (exception) goto fail; unsigned dstRGB = DartUtilities::dartToUnsigned(args, 2, exception); if (exception) goto fail; unsigned srcAlpha = DartUtilities::dartToUnsigned(args, 3, exception); if (exception) goto fail; unsigned dstAlpha = DartUtilities::dartToUnsigned(args, 4, exception); if (exception) goto fail; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; } fail: Dart_ThrowException(exception); ASSERT_NOT_REACHED(); Proposed new code - /** * One time initialization code for setting up argument descriptors */ const int kNumArgs = 5; const int kNumNativeFields = 2; static const uint8_t native_arg_descriptor[kNumArgs] = { DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kNativeFields, 0), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 1), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 2), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 3), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 4), }; Dart_NativeArgument_Value native_args[kNumArgs]; intptr_t native_fields[kNumNativeFields]; native_args[0].as_native_fields.num_fields = kNumNativeFields; native_args[0].as_native_fields.values = native_fields; /** * Code executed for each invocation of the binding method */ Dart_Handle result = Dart_GetNativeArguments(args, kNumArgs, native_arg_descriptor, native_args); if (Dart_IsError(result)) { Dart_ThrowException(result); } WebGL* receiver = DartDOMWrapper::receiver< WebGL >(native_args[0].as_native_fields.values); unsigned srcRGB = native_args[1].as_uint32; unsigned dstRGB = native_args[2].as_uint32; unsigned srcAlpha = native_args[3].as_uint32; unsigned dstAlpha = native_args[4].as_uint32; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; R=iposva@google.com, vsm@google.com Review URL: https://codereview.chromium.org//282883002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@36464 260f80e4-7a28-3924-810f-c04153c831b5
2014-05-22 00:08:23 +00:00
}
}
return Api::Success();
}
DART_EXPORT Dart_Handle Dart_GetNativeArgument(Dart_NativeArguments args,
int index) {
NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
if ((index < 0) || (index >= arguments->NativeArgCount())) {
return Api::NewError(
"%s: argument 'index' out of range. Expected 0..%d but saw %d.",
CURRENT_FUNC, arguments->NativeArgCount() - 1, index);
}
TransitionNativeToVM transition(arguments->thread());
return Api::NewHandle(arguments->thread(), arguments->NativeArgAt(index));
}
DART_EXPORT int Dart_GetNativeArgumentCount(Dart_NativeArguments args) {
NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
return arguments->NativeArgCount();
}
DART_EXPORT Dart_Handle
Dart_GetNativeFieldsOfArgument(Dart_NativeArguments args,
int arg_index,
int num_fields,
intptr_t* field_values) {
NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
if ((arg_index < 0) || (arg_index >= arguments->NativeArgCount())) {
return Api::NewError(
"%s: argument 'arg_index' out of range. Expected 0..%d but saw %d.",
CURRENT_FUNC, arguments->NativeArgCount() - 1, arg_index);
}
if (field_values == NULL) {
RETURN_NULL_ERROR(field_values);
}
return GetNativeFieldsOfArgument(arguments, arg_index, num_fields,
field_values, CURRENT_FUNC);
}
DART_EXPORT Dart_Handle Dart_GetNativeReceiver(Dart_NativeArguments args,
intptr_t* value) {
NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
TransitionNativeToVM transition(arguments->thread());
ASSERT(arguments->thread()->isolate() == Isolate::Current());
if (value == NULL) {
RETURN_NULL_ERROR(value);
}
if (Api::GetNativeReceiver(arguments, value)) {
return Api::Success();
}
return Api::NewError(
"%s expects receiver argument to be non-null and of"
" type Instance.",
CURRENT_FUNC);
}
DART_EXPORT Dart_Handle Dart_GetNativeStringArgument(Dart_NativeArguments args,
int arg_index,
void** peer) {
NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
TransitionNativeToVM transition(arguments->thread());
Add a new API function to extract all the native arguments into an array passed in by the caller. This call can be used in DOM bindings patterns as follows: Old code - Dart_Handle exception = 0; { WebGL* receiver = DartDOMWrapper::receiver< WebGL >(args); unsigned srcRGB = DartUtilities::dartToUnsigned(args, 1, exception); if (exception) goto fail; unsigned dstRGB = DartUtilities::dartToUnsigned(args, 2, exception); if (exception) goto fail; unsigned srcAlpha = DartUtilities::dartToUnsigned(args, 3, exception); if (exception) goto fail; unsigned dstAlpha = DartUtilities::dartToUnsigned(args, 4, exception); if (exception) goto fail; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; } fail: Dart_ThrowException(exception); ASSERT_NOT_REACHED(); Proposed new code - /** * One time initialization code for setting up argument descriptors */ const int kNumArgs = 5; const int kNumNativeFields = 2; static const uint8_t native_arg_descriptor[kNumArgs] = { DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kNativeFields, 0), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 1), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 2), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 3), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 4), }; Dart_NativeArgument_Value native_args[kNumArgs]; intptr_t native_fields[kNumNativeFields]; native_args[0].as_native_fields.num_fields = kNumNativeFields; native_args[0].as_native_fields.values = native_fields; /** * Code executed for each invocation of the binding method */ Dart_Handle result = Dart_GetNativeArguments(args, kNumArgs, native_arg_descriptor, native_args); if (Dart_IsError(result)) { Dart_ThrowException(result); } WebGL* receiver = DartDOMWrapper::receiver< WebGL >(native_args[0].as_native_fields.values); unsigned srcRGB = native_args[1].as_uint32; unsigned dstRGB = native_args[2].as_uint32; unsigned srcAlpha = native_args[3].as_uint32; unsigned dstAlpha = native_args[4].as_uint32; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; R=iposva@google.com, vsm@google.com Review URL: https://codereview.chromium.org//282883002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@36464 260f80e4-7a28-3924-810f-c04153c831b5
2014-05-22 00:08:23 +00:00
Dart_Handle result = Api::Null();
if (!GetNativeStringArgument(arguments, arg_index, &result, peer)) {
return Api::NewArgumentError(
"%s expects argument at %d to be of"
" type String.",
CURRENT_FUNC, arg_index);
}
Add a new API function to extract all the native arguments into an array passed in by the caller. This call can be used in DOM bindings patterns as follows: Old code - Dart_Handle exception = 0; { WebGL* receiver = DartDOMWrapper::receiver< WebGL >(args); unsigned srcRGB = DartUtilities::dartToUnsigned(args, 1, exception); if (exception) goto fail; unsigned dstRGB = DartUtilities::dartToUnsigned(args, 2, exception); if (exception) goto fail; unsigned srcAlpha = DartUtilities::dartToUnsigned(args, 3, exception); if (exception) goto fail; unsigned dstAlpha = DartUtilities::dartToUnsigned(args, 4, exception); if (exception) goto fail; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; } fail: Dart_ThrowException(exception); ASSERT_NOT_REACHED(); Proposed new code - /** * One time initialization code for setting up argument descriptors */ const int kNumArgs = 5; const int kNumNativeFields = 2; static const uint8_t native_arg_descriptor[kNumArgs] = { DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kNativeFields, 0), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 1), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 2), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 3), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 4), }; Dart_NativeArgument_Value native_args[kNumArgs]; intptr_t native_fields[kNumNativeFields]; native_args[0].as_native_fields.num_fields = kNumNativeFields; native_args[0].as_native_fields.values = native_fields; /** * Code executed for each invocation of the binding method */ Dart_Handle result = Dart_GetNativeArguments(args, kNumArgs, native_arg_descriptor, native_args); if (Dart_IsError(result)) { Dart_ThrowException(result); } WebGL* receiver = DartDOMWrapper::receiver< WebGL >(native_args[0].as_native_fields.values); unsigned srcRGB = native_args[1].as_uint32; unsigned dstRGB = native_args[2].as_uint32; unsigned srcAlpha = native_args[3].as_uint32; unsigned dstAlpha = native_args[4].as_uint32; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; R=iposva@google.com, vsm@google.com Review URL: https://codereview.chromium.org//282883002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@36464 260f80e4-7a28-3924-810f-c04153c831b5
2014-05-22 00:08:23 +00:00
return result;
}
DART_EXPORT Dart_Handle Dart_GetNativeIntegerArgument(Dart_NativeArguments args,
int index,
int64_t* value) {
NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
if ((index < 0) || (index >= arguments->NativeArgCount())) {
return Api::NewError(
"%s: argument 'index' out of range. Expected 0..%d but saw %d.",
CURRENT_FUNC, arguments->NativeArgCount() - 1, index);
}
Add a new API function to extract all the native arguments into an array passed in by the caller. This call can be used in DOM bindings patterns as follows: Old code - Dart_Handle exception = 0; { WebGL* receiver = DartDOMWrapper::receiver< WebGL >(args); unsigned srcRGB = DartUtilities::dartToUnsigned(args, 1, exception); if (exception) goto fail; unsigned dstRGB = DartUtilities::dartToUnsigned(args, 2, exception); if (exception) goto fail; unsigned srcAlpha = DartUtilities::dartToUnsigned(args, 3, exception); if (exception) goto fail; unsigned dstAlpha = DartUtilities::dartToUnsigned(args, 4, exception); if (exception) goto fail; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; } fail: Dart_ThrowException(exception); ASSERT_NOT_REACHED(); Proposed new code - /** * One time initialization code for setting up argument descriptors */ const int kNumArgs = 5; const int kNumNativeFields = 2; static const uint8_t native_arg_descriptor[kNumArgs] = { DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kNativeFields, 0), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 1), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 2), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 3), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 4), }; Dart_NativeArgument_Value native_args[kNumArgs]; intptr_t native_fields[kNumNativeFields]; native_args[0].as_native_fields.num_fields = kNumNativeFields; native_args[0].as_native_fields.values = native_fields; /** * Code executed for each invocation of the binding method */ Dart_Handle result = Dart_GetNativeArguments(args, kNumArgs, native_arg_descriptor, native_args); if (Dart_IsError(result)) { Dart_ThrowException(result); } WebGL* receiver = DartDOMWrapper::receiver< WebGL >(native_args[0].as_native_fields.values); unsigned srcRGB = native_args[1].as_uint32; unsigned dstRGB = native_args[2].as_uint32; unsigned srcAlpha = native_args[3].as_uint32; unsigned dstAlpha = native_args[4].as_uint32; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; R=iposva@google.com, vsm@google.com Review URL: https://codereview.chromium.org//282883002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@36464 260f80e4-7a28-3924-810f-c04153c831b5
2014-05-22 00:08:23 +00:00
if (!GetNativeIntegerArgument(arguments, index, value)) {
return Api::NewArgumentError(
"%s: expects argument at %d to be of"
" type Integer.",
CURRENT_FUNC, index);
}
Add a new API function to extract all the native arguments into an array passed in by the caller. This call can be used in DOM bindings patterns as follows: Old code - Dart_Handle exception = 0; { WebGL* receiver = DartDOMWrapper::receiver< WebGL >(args); unsigned srcRGB = DartUtilities::dartToUnsigned(args, 1, exception); if (exception) goto fail; unsigned dstRGB = DartUtilities::dartToUnsigned(args, 2, exception); if (exception) goto fail; unsigned srcAlpha = DartUtilities::dartToUnsigned(args, 3, exception); if (exception) goto fail; unsigned dstAlpha = DartUtilities::dartToUnsigned(args, 4, exception); if (exception) goto fail; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; } fail: Dart_ThrowException(exception); ASSERT_NOT_REACHED(); Proposed new code - /** * One time initialization code for setting up argument descriptors */ const int kNumArgs = 5; const int kNumNativeFields = 2; static const uint8_t native_arg_descriptor[kNumArgs] = { DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kNativeFields, 0), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 1), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 2), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 3), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 4), }; Dart_NativeArgument_Value native_args[kNumArgs]; intptr_t native_fields[kNumNativeFields]; native_args[0].as_native_fields.num_fields = kNumNativeFields; native_args[0].as_native_fields.values = native_fields; /** * Code executed for each invocation of the binding method */ Dart_Handle result = Dart_GetNativeArguments(args, kNumArgs, native_arg_descriptor, native_args); if (Dart_IsError(result)) { Dart_ThrowException(result); } WebGL* receiver = DartDOMWrapper::receiver< WebGL >(native_args[0].as_native_fields.values); unsigned srcRGB = native_args[1].as_uint32; unsigned dstRGB = native_args[2].as_uint32; unsigned srcAlpha = native_args[3].as_uint32; unsigned dstAlpha = native_args[4].as_uint32; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; R=iposva@google.com, vsm@google.com Review URL: https://codereview.chromium.org//282883002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@36464 260f80e4-7a28-3924-810f-c04153c831b5
2014-05-22 00:08:23 +00:00
return Api::Success();
}
DART_EXPORT Dart_Handle Dart_GetNativeBooleanArgument(Dart_NativeArguments args,
int index,
bool* value) {
NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
if ((index < 0) || (index >= arguments->NativeArgCount())) {
return Api::NewError(
"%s: argument 'index' out of range. Expected 0..%d but saw %d.",
CURRENT_FUNC, arguments->NativeArgCount() - 1, index);
}
Add a new API function to extract all the native arguments into an array passed in by the caller. This call can be used in DOM bindings patterns as follows: Old code - Dart_Handle exception = 0; { WebGL* receiver = DartDOMWrapper::receiver< WebGL >(args); unsigned srcRGB = DartUtilities::dartToUnsigned(args, 1, exception); if (exception) goto fail; unsigned dstRGB = DartUtilities::dartToUnsigned(args, 2, exception); if (exception) goto fail; unsigned srcAlpha = DartUtilities::dartToUnsigned(args, 3, exception); if (exception) goto fail; unsigned dstAlpha = DartUtilities::dartToUnsigned(args, 4, exception); if (exception) goto fail; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; } fail: Dart_ThrowException(exception); ASSERT_NOT_REACHED(); Proposed new code - /** * One time initialization code for setting up argument descriptors */ const int kNumArgs = 5; const int kNumNativeFields = 2; static const uint8_t native_arg_descriptor[kNumArgs] = { DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kNativeFields, 0), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 1), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 2), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 3), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 4), }; Dart_NativeArgument_Value native_args[kNumArgs]; intptr_t native_fields[kNumNativeFields]; native_args[0].as_native_fields.num_fields = kNumNativeFields; native_args[0].as_native_fields.values = native_fields; /** * Code executed for each invocation of the binding method */ Dart_Handle result = Dart_GetNativeArguments(args, kNumArgs, native_arg_descriptor, native_args); if (Dart_IsError(result)) { Dart_ThrowException(result); } WebGL* receiver = DartDOMWrapper::receiver< WebGL >(native_args[0].as_native_fields.values); unsigned srcRGB = native_args[1].as_uint32; unsigned dstRGB = native_args[2].as_uint32; unsigned srcAlpha = native_args[3].as_uint32; unsigned dstAlpha = native_args[4].as_uint32; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; R=iposva@google.com, vsm@google.com Review URL: https://codereview.chromium.org//282883002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@36464 260f80e4-7a28-3924-810f-c04153c831b5
2014-05-22 00:08:23 +00:00
if (!Api::GetNativeBooleanArgument(arguments, index, value)) {
return Api::NewArgumentError(
"%s: expects argument at %d to be of type Boolean.", CURRENT_FUNC,
index);
}
Add a new API function to extract all the native arguments into an array passed in by the caller. This call can be used in DOM bindings patterns as follows: Old code - Dart_Handle exception = 0; { WebGL* receiver = DartDOMWrapper::receiver< WebGL >(args); unsigned srcRGB = DartUtilities::dartToUnsigned(args, 1, exception); if (exception) goto fail; unsigned dstRGB = DartUtilities::dartToUnsigned(args, 2, exception); if (exception) goto fail; unsigned srcAlpha = DartUtilities::dartToUnsigned(args, 3, exception); if (exception) goto fail; unsigned dstAlpha = DartUtilities::dartToUnsigned(args, 4, exception); if (exception) goto fail; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; } fail: Dart_ThrowException(exception); ASSERT_NOT_REACHED(); Proposed new code - /** * One time initialization code for setting up argument descriptors */ const int kNumArgs = 5; const int kNumNativeFields = 2; static const uint8_t native_arg_descriptor[kNumArgs] = { DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kNativeFields, 0), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 1), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 2), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 3), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 4), }; Dart_NativeArgument_Value native_args[kNumArgs]; intptr_t native_fields[kNumNativeFields]; native_args[0].as_native_fields.num_fields = kNumNativeFields; native_args[0].as_native_fields.values = native_fields; /** * Code executed for each invocation of the binding method */ Dart_Handle result = Dart_GetNativeArguments(args, kNumArgs, native_arg_descriptor, native_args); if (Dart_IsError(result)) { Dart_ThrowException(result); } WebGL* receiver = DartDOMWrapper::receiver< WebGL >(native_args[0].as_native_fields.values); unsigned srcRGB = native_args[1].as_uint32; unsigned dstRGB = native_args[2].as_uint32; unsigned srcAlpha = native_args[3].as_uint32; unsigned dstAlpha = native_args[4].as_uint32; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; R=iposva@google.com, vsm@google.com Review URL: https://codereview.chromium.org//282883002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@36464 260f80e4-7a28-3924-810f-c04153c831b5
2014-05-22 00:08:23 +00:00
return Api::Success();
}
DART_EXPORT Dart_Handle Dart_GetNativeDoubleArgument(Dart_NativeArguments args,
int index,
double* value) {
NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
if ((index < 0) || (index >= arguments->NativeArgCount())) {
return Api::NewError(
"%s: argument 'index' out of range. Expected 0..%d but saw %d.",
CURRENT_FUNC, arguments->NativeArgCount() - 1, index);
}
Add a new API function to extract all the native arguments into an array passed in by the caller. This call can be used in DOM bindings patterns as follows: Old code - Dart_Handle exception = 0; { WebGL* receiver = DartDOMWrapper::receiver< WebGL >(args); unsigned srcRGB = DartUtilities::dartToUnsigned(args, 1, exception); if (exception) goto fail; unsigned dstRGB = DartUtilities::dartToUnsigned(args, 2, exception); if (exception) goto fail; unsigned srcAlpha = DartUtilities::dartToUnsigned(args, 3, exception); if (exception) goto fail; unsigned dstAlpha = DartUtilities::dartToUnsigned(args, 4, exception); if (exception) goto fail; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; } fail: Dart_ThrowException(exception); ASSERT_NOT_REACHED(); Proposed new code - /** * One time initialization code for setting up argument descriptors */ const int kNumArgs = 5; const int kNumNativeFields = 2; static const uint8_t native_arg_descriptor[kNumArgs] = { DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kNativeFields, 0), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 1), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 2), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 3), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 4), }; Dart_NativeArgument_Value native_args[kNumArgs]; intptr_t native_fields[kNumNativeFields]; native_args[0].as_native_fields.num_fields = kNumNativeFields; native_args[0].as_native_fields.values = native_fields; /** * Code executed for each invocation of the binding method */ Dart_Handle result = Dart_GetNativeArguments(args, kNumArgs, native_arg_descriptor, native_args); if (Dart_IsError(result)) { Dart_ThrowException(result); } WebGL* receiver = DartDOMWrapper::receiver< WebGL >(native_args[0].as_native_fields.values); unsigned srcRGB = native_args[1].as_uint32; unsigned dstRGB = native_args[2].as_uint32; unsigned srcAlpha = native_args[3].as_uint32; unsigned dstAlpha = native_args[4].as_uint32; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; R=iposva@google.com, vsm@google.com Review URL: https://codereview.chromium.org//282883002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@36464 260f80e4-7a28-3924-810f-c04153c831b5
2014-05-22 00:08:23 +00:00
if (!GetNativeDoubleArgument(arguments, index, value)) {
return Api::NewArgumentError(
"%s: expects argument at %d to be of"
" type Double.",
CURRENT_FUNC, index);
}
Add a new API function to extract all the native arguments into an array passed in by the caller. This call can be used in DOM bindings patterns as follows: Old code - Dart_Handle exception = 0; { WebGL* receiver = DartDOMWrapper::receiver< WebGL >(args); unsigned srcRGB = DartUtilities::dartToUnsigned(args, 1, exception); if (exception) goto fail; unsigned dstRGB = DartUtilities::dartToUnsigned(args, 2, exception); if (exception) goto fail; unsigned srcAlpha = DartUtilities::dartToUnsigned(args, 3, exception); if (exception) goto fail; unsigned dstAlpha = DartUtilities::dartToUnsigned(args, 4, exception); if (exception) goto fail; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; } fail: Dart_ThrowException(exception); ASSERT_NOT_REACHED(); Proposed new code - /** * One time initialization code for setting up argument descriptors */ const int kNumArgs = 5; const int kNumNativeFields = 2; static const uint8_t native_arg_descriptor[kNumArgs] = { DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kNativeFields, 0), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 1), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 2), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 3), DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kUint32, 4), }; Dart_NativeArgument_Value native_args[kNumArgs]; intptr_t native_fields[kNumNativeFields]; native_args[0].as_native_fields.num_fields = kNumNativeFields; native_args[0].as_native_fields.values = native_fields; /** * Code executed for each invocation of the binding method */ Dart_Handle result = Dart_GetNativeArguments(args, kNumArgs, native_arg_descriptor, native_args); if (Dart_IsError(result)) { Dart_ThrowException(result); } WebGL* receiver = DartDOMWrapper::receiver< WebGL >(native_args[0].as_native_fields.values); unsigned srcRGB = native_args[1].as_uint32; unsigned dstRGB = native_args[2].as_uint32; unsigned srcAlpha = native_args[3].as_uint32; unsigned dstAlpha = native_args[4].as_uint32; receiver->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); return; R=iposva@google.com, vsm@google.com Review URL: https://codereview.chromium.org//282883002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@36464 260f80e4-7a28-3924-810f-c04153c831b5
2014-05-22 00:08:23 +00:00
return Api::Success();
}
DART_EXPORT void Dart_SetReturnValue(Dart_NativeArguments args,
Dart_Handle retval) {
NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
ASSERT(arguments->thread()->isolate() == Isolate::Current());
ASSERT_CALLBACK_STATE(arguments->thread());
TransitionNativeToVM transition(arguments->thread());
if ((retval != Api::Null()) && !Api::IsInstance(retval) &&
!Api::IsError(retval)) {
// Print the current stack trace to make the problematic caller
// easier to find.
const StackTrace& stacktrace = GetCurrentStackTrace(0);
OS::PrintErr("=== Current Trace:\n%s===\n", stacktrace.ToCString());
const Object& ret_obj = Object::Handle(Api::UnwrapHandle(retval));
FATAL1(
"Return value check failed: saw '%s' expected a dart Instance or "
"an Error.",
ret_obj.ToCString());
}
ASSERT(retval != 0);
Api::SetReturnValue(arguments, retval);
}
DART_EXPORT void Dart_SetWeakHandleReturnValue(Dart_NativeArguments args,
Dart_WeakPersistentHandle rval) {
NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
TransitionNativeToVM transition(arguments->thread());
#if defined(DEBUG)
Isolate* isolate = arguments->thread()->isolate();
ASSERT(isolate == Isolate::Current());
ASSERT(isolate->group()->api_state() != NULL &&
(isolate->group()->api_state()->IsValidWeakPersistentHandle(rval)));
#endif
Api::SetWeakHandleReturnValue(arguments, rval);
}
// --- Environment ---
StringPtr Api::GetEnvironmentValue(Thread* thread, const String& name) {
String& result = String::Handle(CallEnvironmentCallback(thread, name));
if (result.IsNull()) {
// Every 'dart:X' library introduces an environment variable
// 'dart.library.X' that is set to 'true'.
// We just need to make sure to hide private libraries (starting with
// "_", and the mirrors library, if it is not supported.
if (!FLAG_enable_mirrors && name.Equals(Symbols::DartLibraryMirrors())) {
return Symbols::False().ptr();
}
if (!Api::IsFfiEnabled() && name.Equals(Symbols::DartLibraryFfi())) {
return Symbols::False().ptr();
}
if (name.Equals(Symbols::DartVMProduct())) {
#ifdef PRODUCT
return Symbols::True().ptr();
#else
return Symbols::False().ptr();
#endif
}
if (name.Equals(Symbols::DartDeveloperTimeline())) {
#ifdef SUPPORT_TIMELINE
return Symbols::True().ptr();
#else
return Symbols::False().ptr();
#endif
}
const String& prefix = Symbols::DartLibrary();
if (name.StartsWith(prefix)) {
const String& library_name =
String::Handle(String::SubString(name, prefix.Length()));
// Private libraries (starting with "_") are not exposed to the user.
if (!library_name.IsNull() && library_name.CharAt(0) != '_') {
const String& dart_library_name =
String::Handle(String::Concat(Symbols::DartScheme(), library_name));
const Library& library =
Library::Handle(Library::LookupLibrary(thread, dart_library_name));
if (!library.IsNull()) {
return Symbols::True().ptr();
}
}
}
// Check for default VM provided values. If it was not overridden on the
// command line.
if (Symbols::DartIsVM().Equals(name)) {
return Symbols::True().ptr();
}
}
return result.ptr();
}
StringPtr Api::CallEnvironmentCallback(Thread* thread, const String& name) {
Isolate* isolate = thread->isolate();
Dart_EnvironmentCallback callback = isolate->environment_callback();
if (callback != NULL) {
Scope api_scope(thread);
Dart_Handle api_name = Api::NewHandle(thread, name.ptr());
Dart_Handle api_response;
{
TransitionVMToNative transition(thread);
api_response = callback(api_name);
}
const Object& response =
Object::Handle(thread->zone(), Api::UnwrapHandle(api_response));
if (response.IsString()) {
return String::Cast(response).ptr();
} else if (response.IsError()) {
Exceptions::ThrowArgumentError(
String::Handle(String::New(Error::Cast(response).ToErrorCString())));
} else if (!response.IsNull()) {
// At this point everything except null are invalid environment values.
Exceptions::ThrowArgumentError(
String::Handle(String::New("Illegal environment value")));
}
}
return String::null();
}
DART_EXPORT Dart_Handle
Dart_SetEnvironmentCallback(Dart_EnvironmentCallback callback) {
Isolate* isolate = Isolate::Current();
CHECK_ISOLATE(isolate);
isolate->set_environment_callback(callback);
return Api::Success();
}
// --- Scripts and Libraries ---
DART_EXPORT void Dart_SetBooleanReturnValue(Dart_NativeArguments args,
bool retval) {
NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
TransitionNativeToVM transition(arguments->thread());
ASSERT(arguments->thread()->isolate() == Isolate::Current());
ASSERT_CALLBACK_STATE(arguments->thread());
arguments->SetReturn(Bool::Get(retval));
}
DART_EXPORT void Dart_SetIntegerReturnValue(Dart_NativeArguments args,
int64_t retval) {
NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
TransitionNativeToVM transition(arguments->thread());
ASSERT(arguments->thread()->isolate() == Isolate::Current());
ASSERT_CALLBACK_STATE(arguments->thread());
if (Smi::IsValid(retval)) {
Api::SetSmiReturnValue(arguments, static_cast<intptr_t>(retval));
} else {
// Slow path for Mints.
Api::SetIntegerReturnValue(arguments, retval);
}
}
DART_EXPORT void Dart_SetDoubleReturnValue(Dart_NativeArguments args,
double retval) {
NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
ASSERT(arguments->thread()->isolate() == Isolate::Current());
ASSERT_CALLBACK_STATE(arguments->thread());
TransitionNativeToVM transition(arguments->thread());
Api::SetDoubleReturnValue(arguments, retval);
}
// --- Scripts and Libraries ---
DART_EXPORT Dart_Handle
Dart_SetLibraryTagHandler(Dart_LibraryTagHandler handler) {
Isolate* isolate = Isolate::Current();
CHECK_ISOLATE(isolate);
isolate->group()->set_library_tag_handler(handler);
return Api::Success();
}
DART_EXPORT Dart_Handle Dart_DefaultCanonicalizeUrl(Dart_Handle base_url,
Dart_Handle url) {
DARTSCOPE(Thread::Current());
API_TIMELINE_DURATION(T);
CHECK_CALLBACK_STATE(T);
const String& base_uri = Api::UnwrapStringHandle(Z, base_url);
if (base_uri.IsNull()) {
RETURN_TYPE_ERROR(Z, base_url, String);
}
const String& uri = Api::UnwrapStringHandle(Z, url);
if (uri.IsNull()) {
RETURN_TYPE_ERROR(Z, url, String);
}
const char* resolved_uri;
if (!ResolveUri(uri.ToCString(), base_uri.ToCString(), &resolved_uri)) {
return Api::NewError("%s: Unable to canonicalize uri '%s'.", CURRENT_FUNC,
uri.ToCString());
}
return Api::NewHandle(T, String::New(resolved_uri));
}
[vm] Initial implementation of deferred loading. (Assignment of libraries to loading units is already done in the kernel generation step.) After compiling and before serializing, we walk the program and for each Code we assign its Instructions, CodeSourceMap and CompressedStackMap to the loading unit of that Code's defining library. Deduplication may cause Instructions, CodeSourceMaps and CompressedStackMaps to belong to more than one loading unit; in this case the objects are assigned to the root loading unit. Later they can be more precisely assigned to the dominating loading unit. All objects except some Instructions, CodeSourceMaps and CompressedStackMaps belong to the root loading unit's snapshot. This snapshot is written like an unsplit snapshot, except that when serializing Code, we will write a reference to a stub or null when the Code's Instructions, CodeSourceMap or CompressedStackMap belongs to a non-root loading unit. The snapshots of non-root loading units contain these deferred objects and references to the corresponding Code objects to patch. The types of objects we defer (Instructions, CodeSourceMaps and CompressedStackMaps) usually represent 70+% of the snapshot size. Bare instructions mode must be disabled when splitting because we cannot have PC-relative calls between loading units. Later we can re-enable this for calls within loading units. Broken: Compactor probably crashes we can now have an unbounded number of image pages and the compactor assumes a fixed number. Embedder's guide: At compile-time, gen_snapshot should be passed --loading_unit_manifest with a path, which will enable splitting and output a mapping from loading unit ids to snapshot output paths. At runtime, sometime during isolate startup, an embedder should call Dart_SetDeferredLoadHandler, probably near an existing call to Dart_SetLibraryTagHandler. The callback is given a loading unit id, and should eventually call Dart_DeferredLoadComplete[Error]. Bug: https://github.com/dart-lang/sdk/issues/41974 Change-Id: Ib597eb87c8cd634416d5ee1f00629c5550aebb00 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/152427 Commit-Queue: Ryan Macnak <rmacnak@google.com> Reviewed-by: Alexander Markov <alexmarkov@google.com>
2020-07-17 19:29:47 +00:00
DART_EXPORT Dart_Handle
Dart_SetDeferredLoadHandler(Dart_DeferredLoadHandler handler) {
Isolate* isolate = Isolate::Current();
CHECK_ISOLATE(isolate);
isolate->group()->set_deferred_load_handler(handler);
return Api::Success();
}
DART_EXPORT Dart_Handle Dart_LoadScriptFromKernel(const uint8_t* buffer,
intptr_t buffer_size) {
#if defined(DART_PRECOMPILED_RUNTIME)
return Api::NewError("%s: Cannot compile on an AOT runtime.", CURRENT_FUNC);
#else
DARTSCOPE(Thread::Current());
API_TIMELINE_DURATION(T);
StackZone zone(T);
IsolateGroup* IG = T->isolate_group();
Library& library = Library::Handle(Z, IG->object_store()->root_library());
if (!library.IsNull()) {
const String& library_url = String::Handle(Z, library.url());
return Api::NewError("%s: A script has already been loaded from '%s'.",
CURRENT_FUNC, library_url.ToCString());
}
CHECK_CALLBACK_STATE(T);
Second attempt to reland "[vm/concurrency] Introduce concept of Isolate Groups" This reverts commit 3d14b75f972ca287cd892ff907cf04b22839af59. An Isolate Group (IG) is a collection of isolates which were spawned from the same source. This allows the VM to: * have a guarantee that all isolates within one IG can safely exchange structured objects (currently we rely on embedder for this guarantee) * hot-reload all isolates together (currently we only reload one isolate, leaving same-source isolates in inconsistent state) * make a shared heap for all isolates from the same IG, which paves the way for faster communication and sharing of immutable objects. All isolates within one IG will share the same IsolateGroupSource. **Embedder changes** This change makes breaking embedder API changes to support this new concept of Isolate Groups: The existing isolate lifecycle callbacks given to Dart_Initialize will become Isolate Group lifecycle callbacks. A new callback `initialize_isolate` callback will be added which can initialize a new isolate within an existing IG. Existing embedders can be updated by performing the following renames Dart_CreateIsolate -> Dart_CreateIsolateGroup Dart_IsolateCreateCallback -> Dart_IsolateGroupCreateCallback Dart_IsolateCleanupCallback -> Dart_IsolateGroupShutdownCallback Dart_CreateIsolateFromKernel -> Dart_CreateIsolateGroupFromKernel Dart_CurrentIsolateData -> Dart_CurrentIsolateGroupData Dart_IsolateData -> Dart_IsolateGroupData Dart_GetNativeIsolateData -> Dart_GetNativeIsolateGroupData Dart_InitializeParams.create -> Dart_InitializeParams.create_group Dart_InitializeParams.cleanup -> Dart_InitializeParams.shutdown_group Dart_InitializeParams.shutdown -> Dart_InitializeParams.shutdown_isolate By default `Isolate.spawn` will cause the creation of a new IG. Though an embedder can opt-into supporting multiple isolates within one IG by providing a callback to the newly added `Dart_InitializeParams.initialize_isolate`. The responsibility of this new callback is to initialize an existing isolate (which was setup by re-using source code from the spawning isolate - i.e. the one which used `Isolate.spawn`) by setting native resolvers, initializing global state, etc. Issue https://github.com/dart-lang/sdk/issues/36648 Issue https://github.com/dart-lang/sdk/issues/36097 Original review: https://dart-review.googlesource.com/c/sdk/+/105241 Difference to original review: * Give each isolate it's own [Loader] (for now) * Sort classes during initialization for spawned isolates if app-jit is used (to match main isolate) * Fix IsolateData memory leak if isolate startup fails Difference to first reland(Patchset 2): * Fix typo where memory was freed twice. Change-Id: Ib1c83fe83b629cd50ae6af90ee99fdd44da882d4 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/108367 Commit-Queue: Alexander Aprelev <aam@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com>
2019-07-08 23:49:05 +00:00
// NOTE: We do not attach a finalizer for this object, because the embedder
// will free it once the isolate group has shutdown.
const auto& td = ExternalTypedData::Handle(ExternalTypedData::New(
kExternalTypedDataUint8ArrayCid, const_cast<uint8_t*>(buffer),
buffer_size, Heap::kOld));
const char* error = nullptr;
std::unique_ptr<kernel::Program> program =
Second attempt to reland "[vm/concurrency] Introduce concept of Isolate Groups" This reverts commit 3d14b75f972ca287cd892ff907cf04b22839af59. An Isolate Group (IG) is a collection of isolates which were spawned from the same source. This allows the VM to: * have a guarantee that all isolates within one IG can safely exchange structured objects (currently we rely on embedder for this guarantee) * hot-reload all isolates together (currently we only reload one isolate, leaving same-source isolates in inconsistent state) * make a shared heap for all isolates from the same IG, which paves the way for faster communication and sharing of immutable objects. All isolates within one IG will share the same IsolateGroupSource. **Embedder changes** This change makes breaking embedder API changes to support this new concept of Isolate Groups: The existing isolate lifecycle callbacks given to Dart_Initialize will become Isolate Group lifecycle callbacks. A new callback `initialize_isolate` callback will be added which can initialize a new isolate within an existing IG. Existing embedders can be updated by performing the following renames Dart_CreateIsolate -> Dart_CreateIsolateGroup Dart_IsolateCreateCallback -> Dart_IsolateGroupCreateCallback Dart_IsolateCleanupCallback -> Dart_IsolateGroupShutdownCallback Dart_CreateIsolateFromKernel -> Dart_CreateIsolateGroupFromKernel Dart_CurrentIsolateData -> Dart_CurrentIsolateGroupData Dart_IsolateData -> Dart_IsolateGroupData Dart_GetNativeIsolateData -> Dart_GetNativeIsolateGroupData Dart_InitializeParams.create -> Dart_InitializeParams.create_group Dart_InitializeParams.cleanup -> Dart_InitializeParams.shutdown_group Dart_InitializeParams.shutdown -> Dart_InitializeParams.shutdown_isolate By default `Isolate.spawn` will cause the creation of a new IG. Though an embedder can opt-into supporting multiple isolates within one IG by providing a callback to the newly added `Dart_InitializeParams.initialize_isolate`. The responsibility of this new callback is to initialize an existing isolate (which was setup by re-using source code from the spawning isolate - i.e. the one which used `Isolate.spawn`) by setting native resolvers, initializing global state, etc. Issue https://github.com/dart-lang/sdk/issues/36648 Issue https://github.com/dart-lang/sdk/issues/36097 Original review: https://dart-review.googlesource.com/c/sdk/+/105241 Difference to original review: * Give each isolate it's own [Loader] (for now) * Sort classes during initialization for spawned isolates if app-jit is used (to match main isolate) * Fix IsolateData memory leak if isolate startup fails Difference to first reland(Patchset 2): * Fix typo where memory was freed twice. Change-Id: Ib1c83fe83b629cd50ae6af90ee99fdd44da882d4 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/108367 Commit-Queue: Alexander Aprelev <aam@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com>
2019-07-08 23:49:05 +00:00
kernel::Program::ReadFromTypedData(td, &error);
if (program == nullptr) {
return Api::NewError("Can't load Kernel binary: %s.", error);
}
const Object& tmp = kernel::KernelLoader::LoadEntireProgram(program.get());
program.reset();
if (tmp.IsError()) {
return Api::NewHandle(T, tmp.ptr());
}
Second attempt to reland "[vm/concurrency] Introduce concept of Isolate Groups" This reverts commit 3d14b75f972ca287cd892ff907cf04b22839af59. An Isolate Group (IG) is a collection of isolates which were spawned from the same source. This allows the VM to: * have a guarantee that all isolates within one IG can safely exchange structured objects (currently we rely on embedder for this guarantee) * hot-reload all isolates together (currently we only reload one isolate, leaving same-source isolates in inconsistent state) * make a shared heap for all isolates from the same IG, which paves the way for faster communication and sharing of immutable objects. All isolates within one IG will share the same IsolateGroupSource. **Embedder changes** This change makes breaking embedder API changes to support this new concept of Isolate Groups: The existing isolate lifecycle callbacks given to Dart_Initialize will become Isolate Group lifecycle callbacks. A new callback `initialize_isolate` callback will be added which can initialize a new isolate within an existing IG. Existing embedders can be updated by performing the following renames Dart_CreateIsolate -> Dart_CreateIsolateGroup Dart_IsolateCreateCallback -> Dart_IsolateGroupCreateCallback Dart_IsolateCleanupCallback -> Dart_IsolateGroupShutdownCallback Dart_CreateIsolateFromKernel -> Dart_CreateIsolateGroupFromKernel Dart_CurrentIsolateData -> Dart_CurrentIsolateGroupData Dart_IsolateData -> Dart_IsolateGroupData Dart_GetNativeIsolateData -> Dart_GetNativeIsolateGroupData Dart_InitializeParams.create -> Dart_InitializeParams.create_group Dart_InitializeParams.cleanup -> Dart_InitializeParams.shutdown_group Dart_InitializeParams.shutdown -> Dart_InitializeParams.shutdown_isolate By default `Isolate.spawn` will cause the creation of a new IG. Though an embedder can opt-into supporting multiple isolates within one IG by providing a callback to the newly added `Dart_InitializeParams.initialize_isolate`. The responsibility of this new callback is to initialize an existing isolate (which was setup by re-using source code from the spawning isolate - i.e. the one which used `Isolate.spawn`) by setting native resolvers, initializing global state, etc. Issue https://github.com/dart-lang/sdk/issues/36648 Issue https://github.com/dart-lang/sdk/issues/36097 Original review: https://dart-review.googlesource.com/c/sdk/+/105241 Difference to original review: * Give each isolate it's own [Loader] (for now) * Sort classes during initialization for spawned isolates if app-jit is used (to match main isolate) * Fix IsolateData memory leak if isolate startup fails Difference to first reland(Patchset 2): * Fix typo where memory was freed twice. Change-Id: Ib1c83fe83b629cd50ae6af90ee99fdd44da882d4 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/108367 Commit-Queue: Alexander Aprelev <aam@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com>
2019-07-08 23:49:05 +00:00
IG->source()->script_kernel_size = buffer_size;
IG->source()->script_kernel_buffer = buffer;
Second attempt to reland "[vm/concurrency] Introduce concept of Isolate Groups" This reverts commit 3d14b75f972ca287cd892ff907cf04b22839af59. An Isolate Group (IG) is a collection of isolates which were spawned from the same source. This allows the VM to: * have a guarantee that all isolates within one IG can safely exchange structured objects (currently we rely on embedder for this guarantee) * hot-reload all isolates together (currently we only reload one isolate, leaving same-source isolates in inconsistent state) * make a shared heap for all isolates from the same IG, which paves the way for faster communication and sharing of immutable objects. All isolates within one IG will share the same IsolateGroupSource. **Embedder changes** This change makes breaking embedder API changes to support this new concept of Isolate Groups: The existing isolate lifecycle callbacks given to Dart_Initialize will become Isolate Group lifecycle callbacks. A new callback `initialize_isolate` callback will be added which can initialize a new isolate within an existing IG. Existing embedders can be updated by performing the following renames Dart_CreateIsolate -> Dart_CreateIsolateGroup Dart_IsolateCreateCallback -> Dart_IsolateGroupCreateCallback Dart_IsolateCleanupCallback -> Dart_IsolateGroupShutdownCallback Dart_CreateIsolateFromKernel -> Dart_CreateIsolateGroupFromKernel Dart_CurrentIsolateData -> Dart_CurrentIsolateGroupData Dart_IsolateData -> Dart_IsolateGroupData Dart_GetNativeIsolateData -> Dart_GetNativeIsolateGroupData Dart_InitializeParams.create -> Dart_InitializeParams.create_group Dart_InitializeParams.cleanup -> Dart_InitializeParams.shutdown_group Dart_InitializeParams.shutdown -> Dart_InitializeParams.shutdown_isolate By default `Isolate.spawn` will cause the creation of a new IG. Though an embedder can opt-into supporting multiple isolates within one IG by providing a callback to the newly added `Dart_InitializeParams.initialize_isolate`. The responsibility of this new callback is to initialize an existing isolate (which was setup by re-using source code from the spawning isolate - i.e. the one which used `Isolate.spawn`) by setting native resolvers, initializing global state, etc. Issue https://github.com/dart-lang/sdk/issues/36648 Issue https://github.com/dart-lang/sdk/issues/36097 Original review: https://dart-review.googlesource.com/c/sdk/+/105241 Difference to original review: * Give each isolate it's own [Loader] (for now) * Sort classes during initialization for spawned isolates if app-jit is used (to match main isolate) * Fix IsolateData memory leak if isolate startup fails Difference to first reland(Patchset 2): * Fix typo where memory was freed twice. Change-Id: Ib1c83fe83b629cd50ae6af90ee99fdd44da882d4 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/108367 Commit-Queue: Alexander Aprelev <aam@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com>
2019-07-08 23:49:05 +00:00
// TODO(32618): Setting root library based on whether it has 'main' or not
// is not correct because main can be in the exported namespace of a library
// or it could be a getter.
if (tmp.IsNull()) {
return Api::NewError(
"Invoked Dart programs must have a 'main' function defined:\n"
"https://dart.dev/guides/language/"
"language-tour#a-basic-dart-program");
}
library ^= tmp.ptr();
IG->object_store()->set_root_library(library);
return Api::NewHandle(T, library.ptr());
#endif // defined(DART_PRECOMPILED_RUNTIME)
}
DART_EXPORT Dart_Handle Dart_RootLibrary() {
Thread* thread = Thread::Current();
Isolate* isolate = thread->isolate();
CHECK_ISOLATE(isolate);
TransitionNativeToVM transition(thread);
return Api::NewHandle(thread,
isolate->group()->object_store()->root_library());
}
DART_EXPORT Dart_Handle Dart_SetRootLibrary(Dart_Handle library) {
DARTSCOPE(Thread::Current());
const Object& obj = Object::Handle(Z, Api::UnwrapHandle(library));
if (obj.IsNull() || obj.IsLibrary()) {
Library& lib = Library::Handle(Z);
lib ^= obj.ptr();
T->isolate_group()->object_store()->set_root_library(lib);
return library;
}
RETURN_TYPE_ERROR(Z, library, Library);
}
DART_EXPORT Dart_Handle Dart_GetClass(Dart_Handle library,
Dart_Handle class_name) {
DARTSCOPE(Thread::Current());
const Library& lib = Api::UnwrapLibraryHandle(Z, library);
if (lib.IsNull()) {
RETURN_TYPE_ERROR(Z, library, Library);
}
const String& cls_name = Api::UnwrapStringHandle(Z, class_name);
if (cls_name.IsNull()) {
RETURN_TYPE_ERROR(Z, class_name, String);
}
const Class& cls = Class::Handle(Z, lib.LookupClassAllowPrivate(cls_name));
if (cls.IsNull()) {
// TODO(turnidge): Return null or error in this case?
const String& lib_name = String::Handle(Z, lib.name());
return Api::NewError("Class '%s' not found in library '%s'.",
cls_name.ToCString(), lib_name.ToCString());
}
cls.EnsureDeclarationLoaded();
CHECK_ERROR_HANDLE(cls.VerifyEntryPoint());
return Api::NewHandle(T, cls.RareType());
}
static Dart_Handle GetTypeCommon(Dart_Handle library,
Dart_Handle class_name,
intptr_t number_of_type_arguments,
Dart_Handle* type_arguments,
Nullability nullability) {
DARTSCOPE(Thread::Current());
// Validate the input arguments.
const Library& lib = Api::UnwrapLibraryHandle(Z, library);
if (lib.IsNull()) {
RETURN_TYPE_ERROR(Z, library, Library);
}
if (!lib.Loaded()) {
return Api::NewError("%s expects library argument 'library' to be loaded.",
CURRENT_FUNC);
}
const String& name_str = Api::UnwrapStringHandle(Z, class_name);
if (name_str.IsNull()) {
RETURN_TYPE_ERROR(Z, class_name, String);
}
const Class& cls = Class::Handle(Z, lib.LookupClassAllowPrivate(name_str));
if (cls.IsNull()) {
const String& lib_name = String::Handle(Z, lib.name());
return Api::NewError("Type '%s' not found in library '%s'.",
name_str.ToCString(), lib_name.ToCString());
}
[vm/bytecode] Bootstrapping VM from bytecode Previously, core snapshot was generated from AST (because --enable-interpreter/--use-bytecode-compiler was not specified when building core snapshot). As the result, CL https://dart.googlesource.com/sdk/+/da8cb470cc94830a98d49532e8d5d1a5b3d80f8b which declared libraries in bytecode also removed bytecode entirely from core snapshot in Dart SDK. This CL enables bytecode by default if --bytecode argument is specified for gn.py. This enables JIT compiler from bytecode (interpreter is still disabled by default but can be enabled using --enable-interpreter). Core snapshot and other snapshots now have bytecode. This change revealed a bunch of bugs which are fixed in this CL: * _Closure fields were treated as unboxing candidates which triggered assertion in LoadFieldTOS in interpreter. * Several places should load class declarations if they are not loaded yet. * Canonicalization of TypeRef objects which are not fully initialized may cause duplicate entries in the hash table of canonical TypeArguments. This triggers assertions when hash table is rehashed. The solution is to avoid canonicalization of non-root recursive types and recursive type arguments. Also, TypeRef::Canonicalize and TypeRef::Hash are reverted to assert and work only if type was set. * Native wrapper classes are eagerly stamped as type-finalized which caused assertion failures when reading their class declarations from bytecode. * When building flow graph for FFI trampolines kernel offset of library (which is now declared in bytecode) was queried. Added special case to Function::KernelDataProgramOffset(). * In interpreter-only mode with simulator (e.g. SIMARM64) if simulator is not called before code is interrupted with stack overflow check, simulator returns get_sp() = 0, which was treated as stack overflow. * test standalone_2/io/platform_resolved_executable_test.dart spawns sub-process but it didn't pass VM options. Change-Id: I81bc4f1a4c6725cfa246a435ebe5d8abe43abc67 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/107199 Commit-Queue: Alexander Markov <alexmarkov@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com> Reviewed-by: Régis Crelier <regis@google.com>
2019-06-26 18:25:26 +00:00
cls.EnsureDeclarationLoaded();
CHECK_ERROR_HANDLE(cls.VerifyEntryPoint());
Type& type = Type::Handle();
if (cls.NumTypeArguments() == 0) {
if (number_of_type_arguments != 0) {
return Api::NewError(
"Invalid number of type arguments specified, "
"got %" Pd " expected 0",
number_of_type_arguments);
}
type ^= Type::NewNonParameterizedType(cls);
type ^= type.ToNullability(nullability, Heap::kOld);
} else {
intptr_t num_expected_type_arguments = cls.NumTypeParameters();
TypeArguments& type_args_obj = TypeArguments::Handle();
if (number_of_type_arguments > 0) {
if (type_arguments == NULL) {
RETURN_NULL_ERROR(type_arguments);
}
if (num_expected_type_arguments != number_of_type_arguments) {
return Api::NewError(
"Invalid number of type arguments specified, "
"got %" Pd " expected %" Pd,
number_of_type_arguments, num_expected_type_arguments);
}
const Array& array = Api::UnwrapArrayHandle(Z, *type_arguments);
if (array.IsNull()) {
RETURN_TYPE_ERROR(Z, *type_arguments, Array);
}
if (array.Length() != num_expected_type_arguments) {
return Api::NewError(
"Invalid type arguments specified, expected an "
"array of len %" Pd " but got an array of len %" Pd,
number_of_type_arguments, array.Length());
}
// Set up the type arguments array.
type_args_obj = TypeArguments::New(num_expected_type_arguments);
AbstractType& type_arg = AbstractType::Handle();
for (intptr_t i = 0; i < number_of_type_arguments; i++) {
type_arg ^= array.At(i);
type_args_obj.SetTypeAt(i, type_arg);
}
}
// Construct the type object, canonicalize it and return.
type ^= Type::New(cls, type_args_obj, nullability);
}
type ^= ClassFinalizer::FinalizeType(type);
return Api::NewHandle(T, type.ptr());
}
DART_EXPORT Dart_Handle Dart_GetType(Dart_Handle library,
Dart_Handle class_name,
intptr_t number_of_type_arguments,
Dart_Handle* type_arguments) {
if (IsolateGroup::Current()->null_safety()) {
return Api::NewError(
"Cannot use legacy types with --sound-null-safety enabled. "
"Use Dart_GetNullableType or Dart_GetNonNullableType instead.");
}
return GetTypeCommon(library, class_name, number_of_type_arguments,
type_arguments, Nullability::kLegacy);
}
DART_EXPORT Dart_Handle Dart_GetNullableType(Dart_Handle library,
Dart_Handle class_name,
intptr_t number_of_type_arguments,
Dart_Handle* type_arguments) {
return GetTypeCommon(library, class_name, number_of_type_arguments,
type_arguments, Nullability::kNullable);
}
DART_EXPORT Dart_Handle
Dart_GetNonNullableType(Dart_Handle library,
Dart_Handle class_name,
intptr_t number_of_type_arguments,
Dart_Handle* type_arguments) {
return GetTypeCommon(library, class_name, number_of_type_arguments,
type_arguments, Nullability::kNonNullable);
}
static Dart_Handle TypeToHelper(Dart_Handle type, Nullability nullability) {
DARTSCOPE(Thread::Current());
const Type& ty = Api::UnwrapTypeHandle(Z, type);
if (ty.IsNull()) {
RETURN_TYPE_ERROR(Z, type, Type);
}
if (ty.nullability() == nullability) {
return type;
}
return Api::NewHandle(T, ty.ToNullability(nullability, Heap::kOld));
}
DART_EXPORT Dart_Handle Dart_TypeToNullableType(Dart_Handle type) {
return TypeToHelper(type, Nullability::kNullable);
}
DART_EXPORT Dart_Handle Dart_TypeToNonNullableType(Dart_Handle type) {
return TypeToHelper(type, Nullability::kNonNullable);
}
static Dart_Handle IsOfTypeNullabilityHelper(Dart_Handle type,
Nullability nullability,
bool* result) {
DARTSCOPE(Thread::Current());
const Type& ty = Api::UnwrapTypeHandle(Z, type);
if (ty.IsNull()) {
*result = false;
RETURN_TYPE_ERROR(Z, type, Type);
}
*result = (ty.nullability() == nullability);
return Api::Success();
}
DART_EXPORT Dart_Handle Dart_IsNullableType(Dart_Handle type, bool* result) {
return IsOfTypeNullabilityHelper(type, Nullability::kNullable, result);
}
DART_EXPORT Dart_Handle Dart_IsNonNullableType(Dart_Handle type, bool* result) {
return IsOfTypeNullabilityHelper(type, Nullability::kNonNullable, result);
}
DART_EXPORT Dart_Handle Dart_IsLegacyType(Dart_Handle type, bool* result) {
return IsOfTypeNullabilityHelper(type, Nullability::kLegacy, result);
}
DART_EXPORT Dart_Handle Dart_LibraryUrl(Dart_Handle library) {
DARTSCOPE(Thread::Current());
const Library& lib = Api::UnwrapLibraryHandle(Z, library);
if (lib.IsNull()) {
RETURN_TYPE_ERROR(Z, library, Library);
}
const String& url = String::Handle(Z, lib.url());
ASSERT(!url.IsNull());
return Api::NewHandle(T, url.ptr());
}
DART_EXPORT Dart_Handle Dart_LibraryResolvedUrl(Dart_Handle library) {
DARTSCOPE(Thread::Current());
const Library& lib = Api::UnwrapLibraryHandle(Z, library);
if (lib.IsNull()) {
RETURN_TYPE_ERROR(Z, library, Library);
}
const Class& toplevel = Class::Handle(lib.toplevel_class());
ASSERT(!toplevel.IsNull());
const Script& script = Script::Handle(toplevel.script());
ASSERT(!script.IsNull());
const String& url = String::Handle(script.resolved_url());
ASSERT(!url.IsNull());
return Api::NewHandle(T, url.ptr());
}
DART_EXPORT Dart_Handle Dart_GetLoadedLibraries() {
DARTSCOPE(Thread::Current());
auto IG = T->isolate_group();
const GrowableObjectArray& libs =
GrowableObjectArray::Handle(Z, IG->object_store()->libraries());
int num_libs = libs.Length();
// Create new list and populate with the loaded libraries.
Library& lib = Library::Handle();
const Array& library_list = Array::Handle(Z, Array::New(num_libs));
for (int i = 0; i < num_libs; i++) {
lib ^= libs.At(i);
ASSERT(!lib.IsNull());
library_list.SetAt(i, lib);
}
return Api::NewHandle(T, library_list.ptr());
}
DART_EXPORT Dart_Handle Dart_LookupLibrary(Dart_Handle url) {
DARTSCOPE(Thread::Current());
const String& url_str = Api::UnwrapStringHandle(Z, url);
if (url_str.IsNull()) {
RETURN_TYPE_ERROR(Z, url, String);
}
const Library& library =
Library::Handle(Z, Library::LookupLibrary(T, url_str));
if (library.IsNull()) {
return Api::NewError("%s: library '%s' not found.", CURRENT_FUNC,
url_str.ToCString());
} else {
return Api::NewHandle(T, library.ptr());
}
}
DART_EXPORT Dart_Handle Dart_LibraryHandleError(Dart_Handle library_in,
Dart_Handle error_in) {
DARTSCOPE(Thread::Current());
const Library& lib = Api::UnwrapLibraryHandle(Z, library_in);
if (lib.IsNull()) {
RETURN_TYPE_ERROR(Z, library_in, Library);
}
const Instance& err = Api::UnwrapInstanceHandle(Z, error_in);
if (err.IsNull()) {
RETURN_TYPE_ERROR(Z, error_in, Instance);
}
CHECK_CALLBACK_STATE(T);
return error_in;
}
DART_EXPORT Dart_Handle Dart_LoadLibraryFromKernel(const uint8_t* buffer,
intptr_t buffer_size) {
#if defined(DART_PRECOMPILED_RUNTIME)
return Api::NewError("%s: Cannot compile on an AOT runtime.", CURRENT_FUNC);
#else
DARTSCOPE(Thread::Current());
API_TIMELINE_DURATION(T);
StackZone zone(T);
CHECK_CALLBACK_STATE(T);
Second attempt to reland "[vm/concurrency] Introduce concept of Isolate Groups" This reverts commit 3d14b75f972ca287cd892ff907cf04b22839af59. An Isolate Group (IG) is a collection of isolates which were spawned from the same source. This allows the VM to: * have a guarantee that all isolates within one IG can safely exchange structured objects (currently we rely on embedder for this guarantee) * hot-reload all isolates together (currently we only reload one isolate, leaving same-source isolates in inconsistent state) * make a shared heap for all isolates from the same IG, which paves the way for faster communication and sharing of immutable objects. All isolates within one IG will share the same IsolateGroupSource. **Embedder changes** This change makes breaking embedder API changes to support this new concept of Isolate Groups: The existing isolate lifecycle callbacks given to Dart_Initialize will become Isolate Group lifecycle callbacks. A new callback `initialize_isolate` callback will be added which can initialize a new isolate within an existing IG. Existing embedders can be updated by performing the following renames Dart_CreateIsolate -> Dart_CreateIsolateGroup Dart_IsolateCreateCallback -> Dart_IsolateGroupCreateCallback Dart_IsolateCleanupCallback -> Dart_IsolateGroupShutdownCallback Dart_CreateIsolateFromKernel -> Dart_CreateIsolateGroupFromKernel Dart_CurrentIsolateData -> Dart_CurrentIsolateGroupData Dart_IsolateData -> Dart_IsolateGroupData Dart_GetNativeIsolateData -> Dart_GetNativeIsolateGroupData Dart_InitializeParams.create -> Dart_InitializeParams.create_group Dart_InitializeParams.cleanup -> Dart_InitializeParams.shutdown_group Dart_InitializeParams.shutdown -> Dart_InitializeParams.shutdown_isolate By default `Isolate.spawn` will cause the creation of a new IG. Though an embedder can opt-into supporting multiple isolates within one IG by providing a callback to the newly added `Dart_InitializeParams.initialize_isolate`. The responsibility of this new callback is to initialize an existing isolate (which was setup by re-using source code from the spawning isolate - i.e. the one which used `Isolate.spawn`) by setting native resolvers, initializing global state, etc. Issue https://github.com/dart-lang/sdk/issues/36648 Issue https://github.com/dart-lang/sdk/issues/36097 Original review: https://dart-review.googlesource.com/c/sdk/+/105241 Difference to original review: * Give each isolate it's own [Loader] (for now) * Sort classes during initialization for spawned isolates if app-jit is used (to match main isolate) * Fix IsolateData memory leak if isolate startup fails Difference to first reland(Patchset 2): * Fix typo where memory was freed twice. Change-Id: Ib1c83fe83b629cd50ae6af90ee99fdd44da882d4 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/108367 Commit-Queue: Alexander Aprelev <aam@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com>
2019-07-08 23:49:05 +00:00
// NOTE: We do not attach a finalizer for this object, because the embedder
// will/should free it once the isolate group has shutdown.
// See also http://dartbug.com/37030.
const auto& td = ExternalTypedData::Handle(ExternalTypedData::New(
kExternalTypedDataUint8ArrayCid, const_cast<uint8_t*>(buffer),
buffer_size, Heap::kOld));
const char* error = nullptr;
std::unique_ptr<kernel::Program> program =
Second attempt to reland "[vm/concurrency] Introduce concept of Isolate Groups" This reverts commit 3d14b75f972ca287cd892ff907cf04b22839af59. An Isolate Group (IG) is a collection of isolates which were spawned from the same source. This allows the VM to: * have a guarantee that all isolates within one IG can safely exchange structured objects (currently we rely on embedder for this guarantee) * hot-reload all isolates together (currently we only reload one isolate, leaving same-source isolates in inconsistent state) * make a shared heap for all isolates from the same IG, which paves the way for faster communication and sharing of immutable objects. All isolates within one IG will share the same IsolateGroupSource. **Embedder changes** This change makes breaking embedder API changes to support this new concept of Isolate Groups: The existing isolate lifecycle callbacks given to Dart_Initialize will become Isolate Group lifecycle callbacks. A new callback `initialize_isolate` callback will be added which can initialize a new isolate within an existing IG. Existing embedders can be updated by performing the following renames Dart_CreateIsolate -> Dart_CreateIsolateGroup Dart_IsolateCreateCallback -> Dart_IsolateGroupCreateCallback Dart_IsolateCleanupCallback -> Dart_IsolateGroupShutdownCallback Dart_CreateIsolateFromKernel -> Dart_CreateIsolateGroupFromKernel Dart_CurrentIsolateData -> Dart_CurrentIsolateGroupData Dart_IsolateData -> Dart_IsolateGroupData Dart_GetNativeIsolateData -> Dart_GetNativeIsolateGroupData Dart_InitializeParams.create -> Dart_InitializeParams.create_group Dart_InitializeParams.cleanup -> Dart_InitializeParams.shutdown_group Dart_InitializeParams.shutdown -> Dart_InitializeParams.shutdown_isolate By default `Isolate.spawn` will cause the creation of a new IG. Though an embedder can opt-into supporting multiple isolates within one IG by providing a callback to the newly added `Dart_InitializeParams.initialize_isolate`. The responsibility of this new callback is to initialize an existing isolate (which was setup by re-using source code from the spawning isolate - i.e. the one which used `Isolate.spawn`) by setting native resolvers, initializing global state, etc. Issue https://github.com/dart-lang/sdk/issues/36648 Issue https://github.com/dart-lang/sdk/issues/36097 Original review: https://dart-review.googlesource.com/c/sdk/+/105241 Difference to original review: * Give each isolate it's own [Loader] (for now) * Sort classes during initialization for spawned isolates if app-jit is used (to match main isolate) * Fix IsolateData memory leak if isolate startup fails Difference to first reland(Patchset 2): * Fix typo where memory was freed twice. Change-Id: Ib1c83fe83b629cd50ae6af90ee99fdd44da882d4 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/108367 Commit-Queue: Alexander Aprelev <aam@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com>
2019-07-08 23:49:05 +00:00
kernel::Program::ReadFromTypedData(td, &error);
if (program == nullptr) {
return Api::NewError("Can't load Kernel binary: %s.", error);
}
const Object& result =
kernel::KernelLoader::LoadEntireProgram(program.get(), false);
program.reset();
IsolateGroupSource* source = Isolate::Current()->source();
source->add_loaded_blob(Z, td);
return Api::NewHandle(T, result.ptr());
#endif // defined(DART_PRECOMPILED_RUNTIME)
}
// Finalizes classes and invokes Dart core library function that completes
// futures of loadLibrary calls (deferred library loading).
DART_EXPORT Dart_Handle Dart_FinalizeLoading(bool complete_futures) {
DARTSCOPE(Thread::Current());
API_TIMELINE_DURATION(T);
Isolate* I = T->isolate();
CHECK_CALLBACK_STATE(T);
// Finalize all classes if needed.
Dart_Handle state = Api::CheckAndFinalizePendingClasses(T);
if (Api::IsError(state)) {
return state;
}
#if !defined(PRODUCT)
// Now that the newly loaded classes are finalized, notify the debugger
// that new code has been loaded. If there are latent breakpoints in
// the new code, the debugger convert them to unresolved source breakpoints.
// The code that completes the futures (invoked below) may call into the
// newly loaded code and trigger one of these breakpoints.
I->debugger()->NotifyDoneLoading();
#endif
// After having loaded all the code, we can let the GC set reaonsable limits
// for the heap growth.
// If this is an auxiliary isolate inside a larger isolate group, we will not
// re-initialize the growth policy.
if (I->group()->ContainsOnlyOneIsolate()) {
I->group()->heap()->old_space()->EvaluateAfterLoading();
}
#if !defined(DART_PRECOMPILED_RUNTIME)
if (FLAG_enable_mirrors) {
// Notify mirrors that MirrorSystem.libraries needs to be recomputed.
const Library& libmirrors = Library::Handle(Z, Library::MirrorsLibrary());
const Field& dirty_bit = Field::Handle(
Z, libmirrors.LookupLocalField(String::Handle(String::New("_dirty"))));
ASSERT(!dirty_bit.IsNull() && dirty_bit.is_static());
dirty_bit.SetStaticValue(Bool::True());
}
#endif
return Api::Success();
}
[vm] Initial implementation of deferred loading. (Assignment of libraries to loading units is already done in the kernel generation step.) After compiling and before serializing, we walk the program and for each Code we assign its Instructions, CodeSourceMap and CompressedStackMap to the loading unit of that Code's defining library. Deduplication may cause Instructions, CodeSourceMaps and CompressedStackMaps to belong to more than one loading unit; in this case the objects are assigned to the root loading unit. Later they can be more precisely assigned to the dominating loading unit. All objects except some Instructions, CodeSourceMaps and CompressedStackMaps belong to the root loading unit's snapshot. This snapshot is written like an unsplit snapshot, except that when serializing Code, we will write a reference to a stub or null when the Code's Instructions, CodeSourceMap or CompressedStackMap belongs to a non-root loading unit. The snapshots of non-root loading units contain these deferred objects and references to the corresponding Code objects to patch. The types of objects we defer (Instructions, CodeSourceMaps and CompressedStackMaps) usually represent 70+% of the snapshot size. Bare instructions mode must be disabled when splitting because we cannot have PC-relative calls between loading units. Later we can re-enable this for calls within loading units. Broken: Compactor probably crashes we can now have an unbounded number of image pages and the compactor assumes a fixed number. Embedder's guide: At compile-time, gen_snapshot should be passed --loading_unit_manifest with a path, which will enable splitting and output a mapping from loading unit ids to snapshot output paths. At runtime, sometime during isolate startup, an embedder should call Dart_SetDeferredLoadHandler, probably near an existing call to Dart_SetLibraryTagHandler. The callback is given a loading unit id, and should eventually call Dart_DeferredLoadComplete[Error]. Bug: https://github.com/dart-lang/sdk/issues/41974 Change-Id: Ib597eb87c8cd634416d5ee1f00629c5550aebb00 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/152427 Commit-Queue: Ryan Macnak <rmacnak@google.com> Reviewed-by: Alexander Markov <alexmarkov@google.com>
2020-07-17 19:29:47 +00:00
static Dart_Handle DeferredLoadComplete(intptr_t loading_unit_id,
bool error,
const uint8_t* snapshot_data,
const uint8_t* snapshot_instructions,
const char* error_message,
bool transient_error) {
DARTSCOPE(Thread::Current());
API_TIMELINE_DURATION(T);
auto IG = T->isolate_group();
[vm] Initial implementation of deferred loading. (Assignment of libraries to loading units is already done in the kernel generation step.) After compiling and before serializing, we walk the program and for each Code we assign its Instructions, CodeSourceMap and CompressedStackMap to the loading unit of that Code's defining library. Deduplication may cause Instructions, CodeSourceMaps and CompressedStackMaps to belong to more than one loading unit; in this case the objects are assigned to the root loading unit. Later they can be more precisely assigned to the dominating loading unit. All objects except some Instructions, CodeSourceMaps and CompressedStackMaps belong to the root loading unit's snapshot. This snapshot is written like an unsplit snapshot, except that when serializing Code, we will write a reference to a stub or null when the Code's Instructions, CodeSourceMap or CompressedStackMap belongs to a non-root loading unit. The snapshots of non-root loading units contain these deferred objects and references to the corresponding Code objects to patch. The types of objects we defer (Instructions, CodeSourceMaps and CompressedStackMaps) usually represent 70+% of the snapshot size. Bare instructions mode must be disabled when splitting because we cannot have PC-relative calls between loading units. Later we can re-enable this for calls within loading units. Broken: Compactor probably crashes we can now have an unbounded number of image pages and the compactor assumes a fixed number. Embedder's guide: At compile-time, gen_snapshot should be passed --loading_unit_manifest with a path, which will enable splitting and output a mapping from loading unit ids to snapshot output paths. At runtime, sometime during isolate startup, an embedder should call Dart_SetDeferredLoadHandler, probably near an existing call to Dart_SetLibraryTagHandler. The callback is given a loading unit id, and should eventually call Dart_DeferredLoadComplete[Error]. Bug: https://github.com/dart-lang/sdk/issues/41974 Change-Id: Ib597eb87c8cd634416d5ee1f00629c5550aebb00 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/152427 Commit-Queue: Ryan Macnak <rmacnak@google.com> Reviewed-by: Alexander Markov <alexmarkov@google.com>
2020-07-17 19:29:47 +00:00
CHECK_CALLBACK_STATE(T);
const Array& loading_units =
Array::Handle(IG->object_store()->loading_units());
[vm] Initial implementation of deferred loading. (Assignment of libraries to loading units is already done in the kernel generation step.) After compiling and before serializing, we walk the program and for each Code we assign its Instructions, CodeSourceMap and CompressedStackMap to the loading unit of that Code's defining library. Deduplication may cause Instructions, CodeSourceMaps and CompressedStackMaps to belong to more than one loading unit; in this case the objects are assigned to the root loading unit. Later they can be more precisely assigned to the dominating loading unit. All objects except some Instructions, CodeSourceMaps and CompressedStackMaps belong to the root loading unit's snapshot. This snapshot is written like an unsplit snapshot, except that when serializing Code, we will write a reference to a stub or null when the Code's Instructions, CodeSourceMap or CompressedStackMap belongs to a non-root loading unit. The snapshots of non-root loading units contain these deferred objects and references to the corresponding Code objects to patch. The types of objects we defer (Instructions, CodeSourceMaps and CompressedStackMaps) usually represent 70+% of the snapshot size. Bare instructions mode must be disabled when splitting because we cannot have PC-relative calls between loading units. Later we can re-enable this for calls within loading units. Broken: Compactor probably crashes we can now have an unbounded number of image pages and the compactor assumes a fixed number. Embedder's guide: At compile-time, gen_snapshot should be passed --loading_unit_manifest with a path, which will enable splitting and output a mapping from loading unit ids to snapshot output paths. At runtime, sometime during isolate startup, an embedder should call Dart_SetDeferredLoadHandler, probably near an existing call to Dart_SetLibraryTagHandler. The callback is given a loading unit id, and should eventually call Dart_DeferredLoadComplete[Error]. Bug: https://github.com/dart-lang/sdk/issues/41974 Change-Id: Ib597eb87c8cd634416d5ee1f00629c5550aebb00 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/152427 Commit-Queue: Ryan Macnak <rmacnak@google.com> Reviewed-by: Alexander Markov <alexmarkov@google.com>
2020-07-17 19:29:47 +00:00
if (loading_units.IsNull() || (loading_unit_id < LoadingUnit::kRootId) ||
(loading_unit_id >= loading_units.Length())) {
return Api::NewError("Invalid loading unit");
}
LoadingUnit& unit = LoadingUnit::Handle();
unit ^= loading_units.At(loading_unit_id);
if (unit.loaded()) {
return Api::NewError("Unit already loaded");
}
if (error) {
CHECK_NULL(error_message);
return Api::NewHandle(
T, unit.CompleteLoad(String::Handle(String::New(error_message)),
transient_error));
[vm] Initial implementation of deferred loading. (Assignment of libraries to loading units is already done in the kernel generation step.) After compiling and before serializing, we walk the program and for each Code we assign its Instructions, CodeSourceMap and CompressedStackMap to the loading unit of that Code's defining library. Deduplication may cause Instructions, CodeSourceMaps and CompressedStackMaps to belong to more than one loading unit; in this case the objects are assigned to the root loading unit. Later they can be more precisely assigned to the dominating loading unit. All objects except some Instructions, CodeSourceMaps and CompressedStackMaps belong to the root loading unit's snapshot. This snapshot is written like an unsplit snapshot, except that when serializing Code, we will write a reference to a stub or null when the Code's Instructions, CodeSourceMap or CompressedStackMap belongs to a non-root loading unit. The snapshots of non-root loading units contain these deferred objects and references to the corresponding Code objects to patch. The types of objects we defer (Instructions, CodeSourceMaps and CompressedStackMaps) usually represent 70+% of the snapshot size. Bare instructions mode must be disabled when splitting because we cannot have PC-relative calls between loading units. Later we can re-enable this for calls within loading units. Broken: Compactor probably crashes we can now have an unbounded number of image pages and the compactor assumes a fixed number. Embedder's guide: At compile-time, gen_snapshot should be passed --loading_unit_manifest with a path, which will enable splitting and output a mapping from loading unit ids to snapshot output paths. At runtime, sometime during isolate startup, an embedder should call Dart_SetDeferredLoadHandler, probably near an existing call to Dart_SetLibraryTagHandler. The callback is given a loading unit id, and should eventually call Dart_DeferredLoadComplete[Error]. Bug: https://github.com/dart-lang/sdk/issues/41974 Change-Id: Ib597eb87c8cd634416d5ee1f00629c5550aebb00 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/152427 Commit-Queue: Ryan Macnak <rmacnak@google.com> Reviewed-by: Alexander Markov <alexmarkov@google.com>
2020-07-17 19:29:47 +00:00
} else {
#if defined(SUPPORT_TIMELINE)
TimelineBeginEndScope tbes(T, Timeline::GetIsolateStream(),
"ReadUnitSnapshot");
#endif // defined(SUPPORT_TIMELINE)
const Snapshot* snapshot = Snapshot::SetupFromBuffer(snapshot_data);
if (snapshot == NULL) {
return Api::NewError("Invalid snapshot");
}
if (!IsSnapshotCompatible(Dart::vm_snapshot_kind(), snapshot->kind())) {
const String& message = String::Handle(String::NewFormatted(
"Incompatible snapshot kinds: vm '%s', isolate '%s'",
Snapshot::KindToCString(Dart::vm_snapshot_kind()),
Snapshot::KindToCString(snapshot->kind())));
return Api::NewHandle(T, ApiError::New(message));
}
FullSnapshotReader reader(snapshot, snapshot_instructions, T);
const Error& error = Error::Handle(reader.ReadUnitSnapshot(unit));
if (!error.IsNull()) {
return Api::NewHandle(T, error.ptr());
[vm] Initial implementation of deferred loading. (Assignment of libraries to loading units is already done in the kernel generation step.) After compiling and before serializing, we walk the program and for each Code we assign its Instructions, CodeSourceMap and CompressedStackMap to the loading unit of that Code's defining library. Deduplication may cause Instructions, CodeSourceMaps and CompressedStackMaps to belong to more than one loading unit; in this case the objects are assigned to the root loading unit. Later they can be more precisely assigned to the dominating loading unit. All objects except some Instructions, CodeSourceMaps and CompressedStackMaps belong to the root loading unit's snapshot. This snapshot is written like an unsplit snapshot, except that when serializing Code, we will write a reference to a stub or null when the Code's Instructions, CodeSourceMap or CompressedStackMap belongs to a non-root loading unit. The snapshots of non-root loading units contain these deferred objects and references to the corresponding Code objects to patch. The types of objects we defer (Instructions, CodeSourceMaps and CompressedStackMaps) usually represent 70+% of the snapshot size. Bare instructions mode must be disabled when splitting because we cannot have PC-relative calls between loading units. Later we can re-enable this for calls within loading units. Broken: Compactor probably crashes we can now have an unbounded number of image pages and the compactor assumes a fixed number. Embedder's guide: At compile-time, gen_snapshot should be passed --loading_unit_manifest with a path, which will enable splitting and output a mapping from loading unit ids to snapshot output paths. At runtime, sometime during isolate startup, an embedder should call Dart_SetDeferredLoadHandler, probably near an existing call to Dart_SetLibraryTagHandler. The callback is given a loading unit id, and should eventually call Dart_DeferredLoadComplete[Error]. Bug: https://github.com/dart-lang/sdk/issues/41974 Change-Id: Ib597eb87c8cd634416d5ee1f00629c5550aebb00 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/152427 Commit-Queue: Ryan Macnak <rmacnak@google.com> Reviewed-by: Alexander Markov <alexmarkov@google.com>
2020-07-17 19:29:47 +00:00
}
return Api::NewHandle(T, unit.CompleteLoad(String::Handle(), false));
[vm] Initial implementation of deferred loading. (Assignment of libraries to loading units is already done in the kernel generation step.) After compiling and before serializing, we walk the program and for each Code we assign its Instructions, CodeSourceMap and CompressedStackMap to the loading unit of that Code's defining library. Deduplication may cause Instructions, CodeSourceMaps and CompressedStackMaps to belong to more than one loading unit; in this case the objects are assigned to the root loading unit. Later they can be more precisely assigned to the dominating loading unit. All objects except some Instructions, CodeSourceMaps and CompressedStackMaps belong to the root loading unit's snapshot. This snapshot is written like an unsplit snapshot, except that when serializing Code, we will write a reference to a stub or null when the Code's Instructions, CodeSourceMap or CompressedStackMap belongs to a non-root loading unit. The snapshots of non-root loading units contain these deferred objects and references to the corresponding Code objects to patch. The types of objects we defer (Instructions, CodeSourceMaps and CompressedStackMaps) usually represent 70+% of the snapshot size. Bare instructions mode must be disabled when splitting because we cannot have PC-relative calls between loading units. Later we can re-enable this for calls within loading units. Broken: Compactor probably crashes we can now have an unbounded number of image pages and the compactor assumes a fixed number. Embedder's guide: At compile-time, gen_snapshot should be passed --loading_unit_manifest with a path, which will enable splitting and output a mapping from loading unit ids to snapshot output paths. At runtime, sometime during isolate startup, an embedder should call Dart_SetDeferredLoadHandler, probably near an existing call to Dart_SetLibraryTagHandler. The callback is given a loading unit id, and should eventually call Dart_DeferredLoadComplete[Error]. Bug: https://github.com/dart-lang/sdk/issues/41974 Change-Id: Ib597eb87c8cd634416d5ee1f00629c5550aebb00 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/152427 Commit-Queue: Ryan Macnak <rmacnak@google.com> Reviewed-by: Alexander Markov <alexmarkov@google.com>
2020-07-17 19:29:47 +00:00
}
}
DART_EXPORT Dart_Handle
Dart_DeferredLoadComplete(intptr_t loading_unit_id,
const uint8_t* snapshot_data,
const uint8_t* snapshot_instructions) {
return DeferredLoadComplete(loading_unit_id, false, snapshot_data,
snapshot_instructions, nullptr, false);
}
DART_EXPORT Dart_Handle
Dart_DeferredLoadCompleteError(intptr_t loading_unit_id,
const char* error_message,
bool transient) {
return DeferredLoadComplete(loading_unit_id, true, nullptr, nullptr,
error_message, transient);
}
DART_EXPORT Dart_Handle
Dart_SetNativeResolver(Dart_Handle library,
Dart_NativeEntryResolver resolver,
Dart_NativeEntrySymbol symbol) {
DARTSCOPE(Thread::Current());
const Library& lib = Api::UnwrapLibraryHandle(Z, library);
if (lib.IsNull()) {
RETURN_TYPE_ERROR(Z, library, Library);
}
lib.set_native_entry_resolver(resolver);
lib.set_native_entry_symbol_resolver(symbol);
return Api::Success();
}
DART_EXPORT Dart_Handle
Dart_GetNativeResolver(Dart_Handle library,
Dart_NativeEntryResolver* resolver) {
if (resolver == NULL) {
RETURN_NULL_ERROR(resolver);
}
*resolver = NULL;
DARTSCOPE(Thread::Current());
const Library& lib = Api::UnwrapLibraryHandle(Z, library);
if (lib.IsNull()) {
RETURN_TYPE_ERROR(Z, library, Library);
}
*resolver = lib.native_entry_resolver();
return Api::Success();
}
DART_EXPORT Dart_Handle Dart_GetNativeSymbol(Dart_Handle library,
Dart_NativeEntrySymbol* resolver) {
if (resolver == NULL) {
RETURN_NULL_ERROR(resolver);
}
*resolver = NULL;
DARTSCOPE(Thread::Current());
const Library& lib = Api::UnwrapLibraryHandle(Z, library);
if (lib.IsNull()) {
RETURN_TYPE_ERROR(Z, library, Library);
}
*resolver = lib.native_entry_symbol_resolver();
return Api::Success();
}
DART_EXPORT Dart_Handle
Dart_SetFfiNativeResolver(Dart_Handle library,
Dart_FfiNativeResolver resolver) {
DARTSCOPE(Thread::Current());
const Library& lib = Api::UnwrapLibraryHandle(Z, library);
if (lib.IsNull()) {
RETURN_TYPE_ERROR(Z, library, Library);
}
lib.set_ffi_native_resolver(resolver);
return Api::Success();
}
// --- Peer support ---
DART_EXPORT Dart_Handle Dart_GetPeer(Dart_Handle object, void** peer) {
if (peer == NULL) {
RETURN_NULL_ERROR(peer);
}
Thread* thread = Thread::Current();
CHECK_ISOLATE(thread->isolate());
TransitionNativeToVM transition(thread);
REUSABLE_OBJECT_HANDLESCOPE(thread);
Object& obj = thread->ObjectHandle();
obj = Api::UnwrapHandle(object);
if (obj.IsNull() || obj.IsNumber() || obj.IsBool()) {
const char* msg =
"%s: argument 'object' cannot be a subtype of Null, num, or bool";
return Api::NewError(msg, CURRENT_FUNC);
}
{
NoSafepointScope no_safepoint;
ObjectPtr raw_obj = obj.ptr();
*peer = thread->heap()->GetPeer(raw_obj);
}
return Api::Success();
}
DART_EXPORT Dart_Handle Dart_SetPeer(Dart_Handle object, void* peer) {
Thread* thread = Thread::Current();
CHECK_ISOLATE(thread->isolate());
TransitionNativeToVM transition(thread);
REUSABLE_OBJECT_HANDLESCOPE(thread);
Object& obj = thread->ObjectHandle();
obj = Api::UnwrapHandle(object);
if (obj.IsNull() || obj.IsNumber() || obj.IsBool()) {
const char* msg =
"%s: argument 'object' cannot be a subtype of Null, num, or bool";
return Api::NewError(msg, CURRENT_FUNC);
}
{
NoSafepointScope no_safepoint;
ObjectPtr raw_obj = obj.ptr();
thread->heap()->SetPeer(raw_obj, peer);
}
return Api::Success();
}
// --- Dart Front-End (Kernel) support ---
DART_EXPORT bool Dart_IsKernelIsolate(Dart_Isolate isolate) {
#if defined(DART_PRECOMPILED_RUNTIME)
return false;
#else
Isolate* iso = reinterpret_cast<Isolate*>(isolate);
return KernelIsolate::IsKernelIsolate(iso);
#endif
}
DART_EXPORT bool Dart_KernelIsolateIsRunning() {
#if defined(DART_PRECOMPILED_RUNTIME)
return false;
#else
return KernelIsolate::IsRunning();
#endif
}
DART_EXPORT Dart_Port Dart_KernelPort() {
#if defined(DART_PRECOMPILED_RUNTIME)
return false;
#else
return KernelIsolate::KernelPort();
#endif
}
DART_EXPORT Dart_KernelCompilationResult
Dart_CompileToKernel(const char* script_uri,
const uint8_t* platform_kernel,
intptr_t platform_kernel_size,
bool incremental_compile,
bool snapshot_compile,
const char* package_config,
Dart_KernelCompilationVerbosityLevel verbosity) {
API_TIMELINE_DURATION(Thread::Current());
Dart_KernelCompilationResult result = {};
#if defined(DART_PRECOMPILED_RUNTIME)
result.status = Dart_KernelCompilationStatus_Unknown;
result.error = Utils::StrDup("Dart_CompileToKernel is unsupported.");
#else
result = KernelIsolate::CompileToKernel(
script_uri, platform_kernel, platform_kernel_size, 0, NULL,
incremental_compile, snapshot_compile, package_config, NULL, NULL,
FLAG_sound_null_safety, verbosity);
if (result.status == Dart_KernelCompilationStatus_Ok) {
Dart_KernelCompilationResult accept_result =
KernelIsolate::AcceptCompilation();
if (accept_result.status != Dart_KernelCompilationStatus_Ok) {
FATAL1(
"An error occurred in the CFE while accepting the most recent"
" compilation results: %s",
accept_result.error);
}
}
#endif
return result;
}
DART_EXPORT Dart_KernelCompilationResult
Dart_CompileToKernelWithGivenNullsafety(
const char* script_uri,
const uint8_t* platform_kernel,
intptr_t platform_kernel_size,
bool snapshot_compile,
const char* package_config,
bool null_safety,
Dart_KernelCompilationVerbosityLevel verbosity) {
API_TIMELINE_DURATION(Thread::Current());
Dart_KernelCompilationResult result = {};
#if defined(DART_PRECOMPILED_RUNTIME)
result.status = Dart_KernelCompilationStatus_Unknown;
result.error = Utils::StrDup("Dart_CompileToKernel is unsupported.");
#else
intptr_t null_safety_option =
null_safety ? kNullSafetyOptionStrong : kNullSafetyOptionWeak;
result = KernelIsolate::CompileToKernel(
script_uri, platform_kernel, platform_kernel_size,
/*source_files_count=*/0, /*source_files=*/nullptr,
/*incremental_compile=*/false, snapshot_compile, package_config,
/*multiroot_filepaths=*/nullptr, /*multiroot_scheme=*/nullptr,
null_safety_option, verbosity);
#endif
return result;
}
DART_EXPORT Dart_KernelCompilationResult Dart_KernelListDependencies() {
Dart_KernelCompilationResult result = {};
#if defined(DART_PRECOMPILED_RUNTIME)
result.status = Dart_KernelCompilationStatus_Unknown;
result.error = Utils::StrDup("Dart_KernelListDependencies is unsupported.");
#else
result = KernelIsolate::ListDependencies();
#endif
return result;
}
DART_EXPORT void Dart_SetDartLibrarySourcesKernel(
const uint8_t* platform_kernel,
const intptr_t platform_kernel_size) {
#if !defined(PRODUCT)
Service::SetDartLibraryKernelForSources(platform_kernel,
platform_kernel_size);
#endif
}
DART_EXPORT bool Dart_DetectNullSafety(const char* script_uri,
const char* package_config,
const char* original_working_directory,
const uint8_t* snapshot_data,
const uint8_t* snapshot_instructions,
const uint8_t* kernel_buffer,
intptr_t kernel_buffer_size) {
#if defined(DART_PRECOMPILED_RUNTIME)
ASSERT(FLAG_sound_null_safety != kNullSafetyOptionUnspecified);
return (FLAG_sound_null_safety == kNullSafetyOptionStrong);
#else
bool null_safety;
if (FLAG_sound_null_safety == kNullSafetyOptionUnspecified) {
null_safety = Dart::DetectNullSafety(
script_uri, snapshot_data, snapshot_instructions, kernel_buffer,
kernel_buffer_size, package_config, original_working_directory);
} else {
null_safety = (FLAG_sound_null_safety == kNullSafetyOptionStrong);
}
return null_safety;
#endif // defined(DART_PRECOMPILED_RUNTIME)
}
// --- Service support ---
DART_EXPORT bool Dart_IsServiceIsolate(Dart_Isolate isolate) {
Isolate* iso = reinterpret_cast<Isolate*>(isolate);
return ServiceIsolate::IsServiceIsolate(iso);
}
DART_EXPORT void Dart_RegisterIsolateServiceRequestCallback(
const char* name,
Dart_ServiceRequestCallback callback,
void* user_data) {
#if !defined(PRODUCT)
Service::RegisterIsolateEmbedderCallback(name, callback, user_data);
#endif
}
DART_EXPORT void Dart_RegisterRootServiceRequestCallback(
const char* name,
Dart_ServiceRequestCallback callback,
void* user_data) {
#if !defined(PRODUCT)
Service::RegisterRootEmbedderCallback(name, callback, user_data);
#endif
}
DART_EXPORT void Dart_SetEmbedderInformationCallback(
Dart_EmbedderInformationCallback callback) {
#if !defined(PRODUCT)
Service::SetEmbedderInformationCallback(callback);
#endif
}
DART_EXPORT char* Dart_SetServiceStreamCallbacks(
Dart_ServiceStreamListenCallback listen_callback,
Dart_ServiceStreamCancelCallback cancel_callback) {
#if defined(PRODUCT)
return NULL;
#else
if (listen_callback != NULL) {
if (Service::stream_listen_callback() != NULL) {
return Utils::StrDup(
"Dart_SetServiceStreamCallbacks "
"permits only one listen callback to be registered, please "
"remove the existing callback and then add this callback");
}
} else {
if (Service::stream_listen_callback() == NULL) {
return Utils::StrDup(
"Dart_SetServiceStreamCallbacks "
"expects 'listen_callback' to be present in the callback set.");
}
}
if (cancel_callback != NULL) {
if (Service::stream_cancel_callback() != NULL) {
return Utils::StrDup(
"Dart_SetServiceStreamCallbacks "
"permits only one cancel callback to be registered, please "
"remove the existing callback and then add this callback");
}
} else {
if (Service::stream_cancel_callback() == NULL) {
return Utils::StrDup(
"Dart_SetServiceStreamCallbacks "
"expects 'cancel_callback' to be present in the callback set.");
}
}
Service::SetEmbedderStreamCallbacks(listen_callback, cancel_callback);
return NULL;
#endif
}
DART_EXPORT char* Dart_ServiceSendDataEvent(const char* stream_id,
const char* event_kind,
const uint8_t* bytes,
intptr_t bytes_length) {
#if !defined(PRODUCT)
if (stream_id == NULL) {
return Utils::StrDup(
"Dart_ServiceSendDataEvent expects argument 'stream_id' to be "
"non-null.");
}
if (event_kind == NULL) {
return Utils::StrDup(
"Dart_ServiceSendDataEvent expects argument 'event_kind' to be "
"non-null.");
}
if (bytes == NULL) {
return Utils::StrDup(
"Dart_ServiceSendDataEvent expects argument 'bytes' to be non-null.");
}
if (bytes_length < 0) {
return Utils::StrDup(
"Dart_ServiceSendDataEvent expects argument 'bytes_length' to be >= "
"0.");
}
Service::SendEmbedderEvent(Isolate::Current(), // May be NULL
stream_id, event_kind, bytes, bytes_length);
#endif
return nullptr;
}
DART_EXPORT void Dart_SetGCEventCallback(Dart_GCEventCallback callback) {
Dart::set_gc_event_callback(callback);
}
DART_EXPORT char* Dart_SetFileModifiedCallback(
Dart_FileModifiedCallback file_modified_callback) {
#if !defined(PRODUCT)
#if !defined(DART_PRECOMPILED_RUNTIME)
if (file_modified_callback != NULL) {
[vm/concurrency] Split up IsolateReloadContext into IsolateReloadContext/IsolateGroupReloadContext Similar to the split of ClassTable into ClassTable/SharedClassTable, this CL splits up the IsolateReloadContext into: * IsolateGroupReloadContext: Consists of reload-related information across all isolates. The [Reload()] method is split up in phases that are performed on all isolates before the next phase is started. => This allows each isolate to add reasons for rolling back, if no reasons are found the reload will be accepted atomically. * IsolateReloadContext: Constists of reload-related information for a particular isolate (e.g. mappings of old to new classes) The assumption is that all isolates have the same source (and therefore the same libraries). For certain things, e.g. discovering which libraries changed, it is necessary to examine the object store. We use the first isolate in a group (but could use any of them) to do so, since the isolate group does not have this information atm. This is a preparation CL for supporting hot-reloading multiple isolates within one isolate group. Though the support in this CL stays at having only a single isolate in a group. => This CL turns off FLAG_enable_isolate_groups in JIT mode. Issue https://github.com/dart-lang/sdk/issues/36097 Change-Id: I7f4d536d4f5ab4a2a73fb0c7618ba967c9b77234 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/123254 Commit-Queue: Martin Kustermann <kustermann@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com> Reviewed-by: Alexander Aprelev <aam@google.com>
2019-11-15 14:08:45 +00:00
if (IsolateGroupReloadContext::file_modified_callback() != NULL) {
return Utils::StrDup(
"Dart_SetFileModifiedCallback permits only one callback to be"
" registered, please remove the existing callback and then add"
" this callback");
}
} else {
[vm/concurrency] Split up IsolateReloadContext into IsolateReloadContext/IsolateGroupReloadContext Similar to the split of ClassTable into ClassTable/SharedClassTable, this CL splits up the IsolateReloadContext into: * IsolateGroupReloadContext: Consists of reload-related information across all isolates. The [Reload()] method is split up in phases that are performed on all isolates before the next phase is started. => This allows each isolate to add reasons for rolling back, if no reasons are found the reload will be accepted atomically. * IsolateReloadContext: Constists of reload-related information for a particular isolate (e.g. mappings of old to new classes) The assumption is that all isolates have the same source (and therefore the same libraries). For certain things, e.g. discovering which libraries changed, it is necessary to examine the object store. We use the first isolate in a group (but could use any of them) to do so, since the isolate group does not have this information atm. This is a preparation CL for supporting hot-reloading multiple isolates within one isolate group. Though the support in this CL stays at having only a single isolate in a group. => This CL turns off FLAG_enable_isolate_groups in JIT mode. Issue https://github.com/dart-lang/sdk/issues/36097 Change-Id: I7f4d536d4f5ab4a2a73fb0c7618ba967c9b77234 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/123254 Commit-Queue: Martin Kustermann <kustermann@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com> Reviewed-by: Alexander Aprelev <aam@google.com>
2019-11-15 14:08:45 +00:00
if (IsolateGroupReloadContext::file_modified_callback() == NULL) {
return Utils::StrDup(
"Dart_SetFileModifiedCallback expects 'file_modified_callback' to"
" be set before it is cleared.");
}
}
[vm/concurrency] Split up IsolateReloadContext into IsolateReloadContext/IsolateGroupReloadContext Similar to the split of ClassTable into ClassTable/SharedClassTable, this CL splits up the IsolateReloadContext into: * IsolateGroupReloadContext: Consists of reload-related information across all isolates. The [Reload()] method is split up in phases that are performed on all isolates before the next phase is started. => This allows each isolate to add reasons for rolling back, if no reasons are found the reload will be accepted atomically. * IsolateReloadContext: Constists of reload-related information for a particular isolate (e.g. mappings of old to new classes) The assumption is that all isolates have the same source (and therefore the same libraries). For certain things, e.g. discovering which libraries changed, it is necessary to examine the object store. We use the first isolate in a group (but could use any of them) to do so, since the isolate group does not have this information atm. This is a preparation CL for supporting hot-reloading multiple isolates within one isolate group. Though the support in this CL stays at having only a single isolate in a group. => This CL turns off FLAG_enable_isolate_groups in JIT mode. Issue https://github.com/dart-lang/sdk/issues/36097 Change-Id: I7f4d536d4f5ab4a2a73fb0c7618ba967c9b77234 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/123254 Commit-Queue: Martin Kustermann <kustermann@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com> Reviewed-by: Alexander Aprelev <aam@google.com>
2019-11-15 14:08:45 +00:00
IsolateGroupReloadContext::SetFileModifiedCallback(file_modified_callback);
#endif // !defined(DART_PRECOMPILED_RUNTIME)
#endif // !defined(PRODUCT)
return NULL;
}
DART_EXPORT bool Dart_IsReloading() {
[vm/concurrency] Split up IsolateReloadContext into IsolateReloadContext/IsolateGroupReloadContext Similar to the split of ClassTable into ClassTable/SharedClassTable, this CL splits up the IsolateReloadContext into: * IsolateGroupReloadContext: Consists of reload-related information across all isolates. The [Reload()] method is split up in phases that are performed on all isolates before the next phase is started. => This allows each isolate to add reasons for rolling back, if no reasons are found the reload will be accepted atomically. * IsolateReloadContext: Constists of reload-related information for a particular isolate (e.g. mappings of old to new classes) The assumption is that all isolates have the same source (and therefore the same libraries). For certain things, e.g. discovering which libraries changed, it is necessary to examine the object store. We use the first isolate in a group (but could use any of them) to do so, since the isolate group does not have this information atm. This is a preparation CL for supporting hot-reloading multiple isolates within one isolate group. Though the support in this CL stays at having only a single isolate in a group. => This CL turns off FLAG_enable_isolate_groups in JIT mode. Issue https://github.com/dart-lang/sdk/issues/36097 Change-Id: I7f4d536d4f5ab4a2a73fb0c7618ba967c9b77234 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/123254 Commit-Queue: Martin Kustermann <kustermann@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com> Reviewed-by: Alexander Aprelev <aam@google.com>
2019-11-15 14:08:45 +00:00
#if defined(PRODUCT) || defined(DART_PRECOMPILED_RUNTIME)
return false;
#else
Thread* thread = Thread::Current();
Isolate* isolate = thread->isolate();
CHECK_ISOLATE(isolate);
[vm/concurrency] Split up IsolateReloadContext into IsolateReloadContext/IsolateGroupReloadContext Similar to the split of ClassTable into ClassTable/SharedClassTable, this CL splits up the IsolateReloadContext into: * IsolateGroupReloadContext: Consists of reload-related information across all isolates. The [Reload()] method is split up in phases that are performed on all isolates before the next phase is started. => This allows each isolate to add reasons for rolling back, if no reasons are found the reload will be accepted atomically. * IsolateReloadContext: Constists of reload-related information for a particular isolate (e.g. mappings of old to new classes) The assumption is that all isolates have the same source (and therefore the same libraries). For certain things, e.g. discovering which libraries changed, it is necessary to examine the object store. We use the first isolate in a group (but could use any of them) to do so, since the isolate group does not have this information atm. This is a preparation CL for supporting hot-reloading multiple isolates within one isolate group. Though the support in this CL stays at having only a single isolate in a group. => This CL turns off FLAG_enable_isolate_groups in JIT mode. Issue https://github.com/dart-lang/sdk/issues/36097 Change-Id: I7f4d536d4f5ab4a2a73fb0c7618ba967c9b77234 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/123254 Commit-Queue: Martin Kustermann <kustermann@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com> Reviewed-by: Alexander Aprelev <aam@google.com>
2019-11-15 14:08:45 +00:00
return isolate->group()->IsReloading();
#endif
}
DART_EXPORT bool Dart_SetEnabledTimelineCategory(const char* categories) {
#if defined(SUPPORT_TIMELINE)
bool result = false;
if (categories != nullptr) {
char* carray = Utils::SCreate("[%s]", categories);
result = Service::EnableTimelineStreams(carray);
free(carray);
}
return result;
#else
return false;
#endif
}
DART_EXPORT int64_t Dart_TimelineGetMicros() {
return OS::GetCurrentMonotonicMicros();
}
DART_EXPORT int64_t Dart_TimelineGetTicks() {
return OS::GetCurrentMonotonicTicks();
}
DART_EXPORT int64_t Dart_TimelineGetTicksFrequency() {
return OS::GetCurrentMonotonicFrequency();
}
DART_EXPORT void Dart_TimelineEvent(const char* label,
int64_t timestamp0,
int64_t timestamp1_or_async_id,
Dart_Timeline_Event_Type type,
intptr_t argument_count,
const char** argument_names,
const char** argument_values) {
#if defined(SUPPORT_TIMELINE)
if (type < Dart_Timeline_Event_Begin) {
return;
}
if (type > Dart_Timeline_Event_Flow_End) {
return;
}
if (!Dart::SetActiveApiCall()) {
return;
}
TimelineStream* stream = Timeline::GetEmbedderStream();
ASSERT(stream != NULL);
TimelineEvent* event = stream->StartEvent();
if (event != NULL) {
switch (type) {
case Dart_Timeline_Event_Begin:
event->Begin(label, timestamp1_or_async_id, timestamp0);
break;
case Dart_Timeline_Event_End:
event->End(label, timestamp1_or_async_id, timestamp0);
break;
case Dart_Timeline_Event_Instant:
event->Instant(label, timestamp0);
break;
case Dart_Timeline_Event_Duration:
event->Duration(label, timestamp0, timestamp1_or_async_id);
break;
case Dart_Timeline_Event_Async_Begin:
event->AsyncBegin(label, timestamp1_or_async_id, timestamp0);
break;
case Dart_Timeline_Event_Async_End:
event->AsyncEnd(label, timestamp1_or_async_id, timestamp0);
break;
case Dart_Timeline_Event_Async_Instant:
event->AsyncInstant(label, timestamp1_or_async_id, timestamp0);
break;
case Dart_Timeline_Event_Counter:
event->Counter(label, timestamp0);
break;
case Dart_Timeline_Event_Flow_Begin:
event->FlowBegin(label, timestamp1_or_async_id, timestamp0);
break;
case Dart_Timeline_Event_Flow_Step:
event->FlowStep(label, timestamp1_or_async_id, timestamp0);
break;
case Dart_Timeline_Event_Flow_End:
event->FlowEnd(label, timestamp1_or_async_id, timestamp0);
break;
default:
FATAL("Unknown Dart_Timeline_Event_Type");
}
event->SetNumArguments(argument_count);
for (intptr_t i = 0; i < argument_count; i++) {
event->CopyArgument(i, argument_names[i], argument_values[i]);
}
event->Complete();
}
Dart::ResetActiveApiCall();
#endif
}
DART_EXPORT void Dart_SetThreadName(const char* name) {
OSThread* thread = OSThread::Current();
if (thread == NULL) {
// VM is shutting down.
return;
}
thread->SetName(name);
}
DART_EXPORT Dart_Handle Dart_SortClasses() {
#if defined(DART_PRECOMPILED_RUNTIME)
return Api::NewError("%s: Cannot compile on an AOT runtime.", CURRENT_FUNC);
#else
DARTSCOPE(Thread::Current());
// Prevent background compiler from running while code is being cleared and
// adding new code.
NoBackgroundCompilerScope no_bg_compiler(T);
// We don't have mechanisms to change class-ids that are embedded in code and
// ICData.
ClassFinalizer::ClearAllCode();
// Make sure that ICData etc. that have been cleared are also removed from
// the heap so that they are not found by the heap verifier.
IsolateGroup::Current()->heap()->CollectAllGarbage();
ClassFinalizer::SortClasses();
return Api::Success();
#endif // defined(DART_PRECOMPILED_RUNTIME)
}
DART_EXPORT Dart_Handle Dart_Precompile() {
#if defined(TARGET_ARCH_IA32)
return Api::NewError("AOT compilation is not supported on IA32.");
#elif !defined(DART_PRECOMPILER)
return Api::NewError(
"This VM was built without support for AOT compilation.");
#else
DARTSCOPE(Thread::Current());
API_TIMELINE_BEGIN_END(T);
if (!FLAG_precompiled_mode) {
return Api::NewError("Flag --precompilation was not specified.");
}
Dart_Handle result = Api::CheckAndFinalizePendingClasses(T);
if (Api::IsError(result)) {
return result;
}
CHECK_CALLBACK_STATE(T);
CompilerState state(Thread::Current(), /*is_aot=*/true,
/*is_optimizing=*/true);
CHECK_ERROR_HANDLE(Precompiler::CompileAll());
return Api::Success();
#endif
}
// Used for StreamingWriteStream/BlobImageWriter sizes for ELF and blobs.
#if !defined(TARGET_ARCH_IA32) && defined(DART_PRECOMPILER)
[vm] Consolidate the *WriteStream hierarchy. All *WriteStream classes are now part of the same hierarchy: class BaseWriteStream : ValueObject; Base class for all *WriteStreams. Provides all the methods from the old WriteStream except for buffer() and SetPosition() (relegated to NonStreamingWriteStreams). Has one pure virtual method Realloc that must be overridden by concrete subclasses. class NonStreamingWriteStream : BaseWriteStream; Base class for all *WriteStreams where the entire stream is available at all times (i.e., no flushing to an external sink). Extends the public BaseWriteStream API with buffer() (for accessing the stream contents) and SetPosition() (for changing the current stream pointer to the given absolute position in the stream). class MallocWriteStream : NonStreamingWriteStream; Uses realloc to reallocate the internal buffer. Almost the same as the old WriteStream, except that it only takes an initial size. Adds one public method Steal() for taking ownership of the current buffer contents (after which the buffer is reset to an empty state). Instead of passing a pointer to a buffer, the internal buffer must be accessed via either Steal() or buffer(), which allows access to the current stream contents without changing ownership or resetting the stream. The internal buffer is freed on stream destruction. class ZoneWriteStream: NonStreamingWriteStream; Takes a zone and reallocates the internal buffer in that zone. No additional public methods beyond those available from NonStreamingWriteStream. class StreamingWriteStream : BaseWriteStream; Uses realloc to reallocate the internal buffer. Generally same as before, where the contents of the stream are periodically flushed using Dart_StreamingWriteCallback. Since it extends BaseWriteStream, there are now more methods available for writing data to the stream than just Print/VPrint/WriteBytes. Since portions of the stream may be flushed and thus no longer in the internal buffer, does not provide access to the contents of the stream or a way to reposition the current stream pointer. Flushes any unflushed data and frees the internal buffer on stream destruction. Also refactor things so that write streams are passed to appropriate recipients, instead of the recipients taking arguments they only used to create a WriteStream internally. Thus, recipients now can just specify the appropriate base class for the public API used: * BaseWriteStream for just writing to the stream, or * NonStreamingWriteStream if re-positioning or the stream contents are needed. Change-Id: I419096ecd9331483d168b079fca55b69ef397f15 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/164080 Commit-Queue: Tess Strickland <sstrickl@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com>
2020-09-23 21:05:59 +00:00
static const intptr_t kAssemblyInitialSize = 512 * KB;
static const intptr_t kInitialSize = 2 * MB;
static const intptr_t kInitialDebugSize = 1 * MB;
[vm] Initial implementation of deferred loading. (Assignment of libraries to loading units is already done in the kernel generation step.) After compiling and before serializing, we walk the program and for each Code we assign its Instructions, CodeSourceMap and CompressedStackMap to the loading unit of that Code's defining library. Deduplication may cause Instructions, CodeSourceMaps and CompressedStackMaps to belong to more than one loading unit; in this case the objects are assigned to the root loading unit. Later they can be more precisely assigned to the dominating loading unit. All objects except some Instructions, CodeSourceMaps and CompressedStackMaps belong to the root loading unit's snapshot. This snapshot is written like an unsplit snapshot, except that when serializing Code, we will write a reference to a stub or null when the Code's Instructions, CodeSourceMap or CompressedStackMap belongs to a non-root loading unit. The snapshots of non-root loading units contain these deferred objects and references to the corresponding Code objects to patch. The types of objects we defer (Instructions, CodeSourceMaps and CompressedStackMaps) usually represent 70+% of the snapshot size. Bare instructions mode must be disabled when splitting because we cannot have PC-relative calls between loading units. Later we can re-enable this for calls within loading units. Broken: Compactor probably crashes we can now have an unbounded number of image pages and the compactor assumes a fixed number. Embedder's guide: At compile-time, gen_snapshot should be passed --loading_unit_manifest with a path, which will enable splitting and output a mapping from loading unit ids to snapshot output paths. At runtime, sometime during isolate startup, an embedder should call Dart_SetDeferredLoadHandler, probably near an existing call to Dart_SetLibraryTagHandler. The callback is given a loading unit id, and should eventually call Dart_DeferredLoadComplete[Error]. Bug: https://github.com/dart-lang/sdk/issues/41974 Change-Id: Ib597eb87c8cd634416d5ee1f00629c5550aebb00 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/152427 Commit-Queue: Ryan Macnak <rmacnak@google.com> Reviewed-by: Alexander Markov <alexmarkov@google.com>
2020-07-17 19:29:47 +00:00
static void CreateAppAOTSnapshot(
Dart_StreamingWriteCallback callback,
void* callback_data,
bool strip,
bool as_elf,
void* debug_callback_data,
GrowableArray<LoadingUnitSerializationData*>* units,
LoadingUnitSerializationData* unit,
uint32_t program_hash) {
Thread* T = Thread::Current();
NOT_IN_PRODUCT(TimelineBeginEndScope tbes2(T, Timeline::GetIsolateStream(),
"WriteAppAOTSnapshot"));
[vm] Consolidate the *WriteStream hierarchy. All *WriteStream classes are now part of the same hierarchy: class BaseWriteStream : ValueObject; Base class for all *WriteStreams. Provides all the methods from the old WriteStream except for buffer() and SetPosition() (relegated to NonStreamingWriteStreams). Has one pure virtual method Realloc that must be overridden by concrete subclasses. class NonStreamingWriteStream : BaseWriteStream; Base class for all *WriteStreams where the entire stream is available at all times (i.e., no flushing to an external sink). Extends the public BaseWriteStream API with buffer() (for accessing the stream contents) and SetPosition() (for changing the current stream pointer to the given absolute position in the stream). class MallocWriteStream : NonStreamingWriteStream; Uses realloc to reallocate the internal buffer. Almost the same as the old WriteStream, except that it only takes an initial size. Adds one public method Steal() for taking ownership of the current buffer contents (after which the buffer is reset to an empty state). Instead of passing a pointer to a buffer, the internal buffer must be accessed via either Steal() or buffer(), which allows access to the current stream contents without changing ownership or resetting the stream. The internal buffer is freed on stream destruction. class ZoneWriteStream: NonStreamingWriteStream; Takes a zone and reallocates the internal buffer in that zone. No additional public methods beyond those available from NonStreamingWriteStream. class StreamingWriteStream : BaseWriteStream; Uses realloc to reallocate the internal buffer. Generally same as before, where the contents of the stream are periodically flushed using Dart_StreamingWriteCallback. Since it extends BaseWriteStream, there are now more methods available for writing data to the stream than just Print/VPrint/WriteBytes. Since portions of the stream may be flushed and thus no longer in the internal buffer, does not provide access to the contents of the stream or a way to reposition the current stream pointer. Flushes any unflushed data and frees the internal buffer on stream destruction. Also refactor things so that write streams are passed to appropriate recipients, instead of the recipients taking arguments they only used to create a WriteStream internally. Thus, recipients now can just specify the appropriate base class for the public API used: * BaseWriteStream for just writing to the stream, or * NonStreamingWriteStream if re-positioning or the stream contents are needed. Change-Id: I419096ecd9331483d168b079fca55b69ef397f15 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/164080 Commit-Queue: Tess Strickland <sstrickl@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com>
2020-09-23 21:05:59 +00:00
ZoneWriteStream vm_snapshot_data(T->zone(), FullSnapshotWriter::kInitialSize);
ZoneWriteStream vm_snapshot_instructions(T->zone(), kInitialSize);
ZoneWriteStream isolate_snapshot_data(T->zone(),
FullSnapshotWriter::kInitialSize);
ZoneWriteStream isolate_snapshot_instructions(T->zone(), kInitialSize);
[vm] Initial implementation of deferred loading. (Assignment of libraries to loading units is already done in the kernel generation step.) After compiling and before serializing, we walk the program and for each Code we assign its Instructions, CodeSourceMap and CompressedStackMap to the loading unit of that Code's defining library. Deduplication may cause Instructions, CodeSourceMaps and CompressedStackMaps to belong to more than one loading unit; in this case the objects are assigned to the root loading unit. Later they can be more precisely assigned to the dominating loading unit. All objects except some Instructions, CodeSourceMaps and CompressedStackMaps belong to the root loading unit's snapshot. This snapshot is written like an unsplit snapshot, except that when serializing Code, we will write a reference to a stub or null when the Code's Instructions, CodeSourceMap or CompressedStackMap belongs to a non-root loading unit. The snapshots of non-root loading units contain these deferred objects and references to the corresponding Code objects to patch. The types of objects we defer (Instructions, CodeSourceMaps and CompressedStackMaps) usually represent 70+% of the snapshot size. Bare instructions mode must be disabled when splitting because we cannot have PC-relative calls between loading units. Later we can re-enable this for calls within loading units. Broken: Compactor probably crashes we can now have an unbounded number of image pages and the compactor assumes a fixed number. Embedder's guide: At compile-time, gen_snapshot should be passed --loading_unit_manifest with a path, which will enable splitting and output a mapping from loading unit ids to snapshot output paths. At runtime, sometime during isolate startup, an embedder should call Dart_SetDeferredLoadHandler, probably near an existing call to Dart_SetLibraryTagHandler. The callback is given a loading unit id, and should eventually call Dart_DeferredLoadComplete[Error]. Bug: https://github.com/dart-lang/sdk/issues/41974 Change-Id: Ib597eb87c8cd634416d5ee1f00629c5550aebb00 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/152427 Commit-Queue: Ryan Macnak <rmacnak@google.com> Reviewed-by: Alexander Markov <alexmarkov@google.com>
2020-07-17 19:29:47 +00:00
const bool generate_debug = debug_callback_data != nullptr;
if (as_elf) {
StreamingWriteStream elf_stream(kInitialSize, callback, callback_data);
StreamingWriteStream debug_stream(generate_debug ? kInitialDebugSize : 0,
callback, debug_callback_data);
auto const dwarf = strip ? nullptr : new (Z) Dwarf(Z);
auto const elf = new (Z) Elf(Z, &elf_stream, Elf::Type::Snapshot, dwarf);
// Re-use the same DWARF object if the snapshot is unstripped.
auto const debug_elf =
generate_debug ? new (Z) Elf(Z, &debug_stream, Elf::Type::DebugInfo,
strip ? new (Z) Dwarf(Z) : dwarf)
: nullptr;
BlobImageWriter image_writer(T, &vm_snapshot_instructions,
&isolate_snapshot_instructions, debug_elf,
elf);
[vm] Consolidate the *WriteStream hierarchy. All *WriteStream classes are now part of the same hierarchy: class BaseWriteStream : ValueObject; Base class for all *WriteStreams. Provides all the methods from the old WriteStream except for buffer() and SetPosition() (relegated to NonStreamingWriteStreams). Has one pure virtual method Realloc that must be overridden by concrete subclasses. class NonStreamingWriteStream : BaseWriteStream; Base class for all *WriteStreams where the entire stream is available at all times (i.e., no flushing to an external sink). Extends the public BaseWriteStream API with buffer() (for accessing the stream contents) and SetPosition() (for changing the current stream pointer to the given absolute position in the stream). class MallocWriteStream : NonStreamingWriteStream; Uses realloc to reallocate the internal buffer. Almost the same as the old WriteStream, except that it only takes an initial size. Adds one public method Steal() for taking ownership of the current buffer contents (after which the buffer is reset to an empty state). Instead of passing a pointer to a buffer, the internal buffer must be accessed via either Steal() or buffer(), which allows access to the current stream contents without changing ownership or resetting the stream. The internal buffer is freed on stream destruction. class ZoneWriteStream: NonStreamingWriteStream; Takes a zone and reallocates the internal buffer in that zone. No additional public methods beyond those available from NonStreamingWriteStream. class StreamingWriteStream : BaseWriteStream; Uses realloc to reallocate the internal buffer. Generally same as before, where the contents of the stream are periodically flushed using Dart_StreamingWriteCallback. Since it extends BaseWriteStream, there are now more methods available for writing data to the stream than just Print/VPrint/WriteBytes. Since portions of the stream may be flushed and thus no longer in the internal buffer, does not provide access to the contents of the stream or a way to reposition the current stream pointer. Flushes any unflushed data and frees the internal buffer on stream destruction. Also refactor things so that write streams are passed to appropriate recipients, instead of the recipients taking arguments they only used to create a WriteStream internally. Thus, recipients now can just specify the appropriate base class for the public API used: * BaseWriteStream for just writing to the stream, or * NonStreamingWriteStream if re-positioning or the stream contents are needed. Change-Id: I419096ecd9331483d168b079fca55b69ef397f15 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/164080 Commit-Queue: Tess Strickland <sstrickl@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com>
2020-09-23 21:05:59 +00:00
FullSnapshotWriter writer(Snapshot::kFullAOT, &vm_snapshot_data,
&isolate_snapshot_data, &image_writer,
&image_writer);
[vm] Initial implementation of deferred loading. (Assignment of libraries to loading units is already done in the kernel generation step.) After compiling and before serializing, we walk the program and for each Code we assign its Instructions, CodeSourceMap and CompressedStackMap to the loading unit of that Code's defining library. Deduplication may cause Instructions, CodeSourceMaps and CompressedStackMaps to belong to more than one loading unit; in this case the objects are assigned to the root loading unit. Later they can be more precisely assigned to the dominating loading unit. All objects except some Instructions, CodeSourceMaps and CompressedStackMaps belong to the root loading unit's snapshot. This snapshot is written like an unsplit snapshot, except that when serializing Code, we will write a reference to a stub or null when the Code's Instructions, CodeSourceMap or CompressedStackMap belongs to a non-root loading unit. The snapshots of non-root loading units contain these deferred objects and references to the corresponding Code objects to patch. The types of objects we defer (Instructions, CodeSourceMaps and CompressedStackMaps) usually represent 70+% of the snapshot size. Bare instructions mode must be disabled when splitting because we cannot have PC-relative calls between loading units. Later we can re-enable this for calls within loading units. Broken: Compactor probably crashes we can now have an unbounded number of image pages and the compactor assumes a fixed number. Embedder's guide: At compile-time, gen_snapshot should be passed --loading_unit_manifest with a path, which will enable splitting and output a mapping from loading unit ids to snapshot output paths. At runtime, sometime during isolate startup, an embedder should call Dart_SetDeferredLoadHandler, probably near an existing call to Dart_SetLibraryTagHandler. The callback is given a loading unit id, and should eventually call Dart_DeferredLoadComplete[Error]. Bug: https://github.com/dart-lang/sdk/issues/41974 Change-Id: Ib597eb87c8cd634416d5ee1f00629c5550aebb00 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/152427 Commit-Queue: Ryan Macnak <rmacnak@google.com> Reviewed-by: Alexander Markov <alexmarkov@google.com>
2020-07-17 19:29:47 +00:00
if (unit == nullptr || unit->id() == LoadingUnit::kRootId) {
writer.WriteFullSnapshot(units);
} else {
writer.WriteUnitSnapshot(units, unit, program_hash);
}
elf->Finalize();
if (debug_elf != nullptr) {
debug_elf->Finalize();
}
} else {
[vm] Consolidate the *WriteStream hierarchy. All *WriteStream classes are now part of the same hierarchy: class BaseWriteStream : ValueObject; Base class for all *WriteStreams. Provides all the methods from the old WriteStream except for buffer() and SetPosition() (relegated to NonStreamingWriteStreams). Has one pure virtual method Realloc that must be overridden by concrete subclasses. class NonStreamingWriteStream : BaseWriteStream; Base class for all *WriteStreams where the entire stream is available at all times (i.e., no flushing to an external sink). Extends the public BaseWriteStream API with buffer() (for accessing the stream contents) and SetPosition() (for changing the current stream pointer to the given absolute position in the stream). class MallocWriteStream : NonStreamingWriteStream; Uses realloc to reallocate the internal buffer. Almost the same as the old WriteStream, except that it only takes an initial size. Adds one public method Steal() for taking ownership of the current buffer contents (after which the buffer is reset to an empty state). Instead of passing a pointer to a buffer, the internal buffer must be accessed via either Steal() or buffer(), which allows access to the current stream contents without changing ownership or resetting the stream. The internal buffer is freed on stream destruction. class ZoneWriteStream: NonStreamingWriteStream; Takes a zone and reallocates the internal buffer in that zone. No additional public methods beyond those available from NonStreamingWriteStream. class StreamingWriteStream : BaseWriteStream; Uses realloc to reallocate the internal buffer. Generally same as before, where the contents of the stream are periodically flushed using Dart_StreamingWriteCallback. Since it extends BaseWriteStream, there are now more methods available for writing data to the stream than just Print/VPrint/WriteBytes. Since portions of the stream may be flushed and thus no longer in the internal buffer, does not provide access to the contents of the stream or a way to reposition the current stream pointer. Flushes any unflushed data and frees the internal buffer on stream destruction. Also refactor things so that write streams are passed to appropriate recipients, instead of the recipients taking arguments they only used to create a WriteStream internally. Thus, recipients now can just specify the appropriate base class for the public API used: * BaseWriteStream for just writing to the stream, or * NonStreamingWriteStream if re-positioning or the stream contents are needed. Change-Id: I419096ecd9331483d168b079fca55b69ef397f15 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/164080 Commit-Queue: Tess Strickland <sstrickl@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com>
2020-09-23 21:05:59 +00:00
StreamingWriteStream assembly_stream(kAssemblyInitialSize, callback,
callback_data);
[vm] Initial implementation of deferred loading. (Assignment of libraries to loading units is already done in the kernel generation step.) After compiling and before serializing, we walk the program and for each Code we assign its Instructions, CodeSourceMap and CompressedStackMap to the loading unit of that Code's defining library. Deduplication may cause Instructions, CodeSourceMaps and CompressedStackMaps to belong to more than one loading unit; in this case the objects are assigned to the root loading unit. Later they can be more precisely assigned to the dominating loading unit. All objects except some Instructions, CodeSourceMaps and CompressedStackMaps belong to the root loading unit's snapshot. This snapshot is written like an unsplit snapshot, except that when serializing Code, we will write a reference to a stub or null when the Code's Instructions, CodeSourceMap or CompressedStackMap belongs to a non-root loading unit. The snapshots of non-root loading units contain these deferred objects and references to the corresponding Code objects to patch. The types of objects we defer (Instructions, CodeSourceMaps and CompressedStackMaps) usually represent 70+% of the snapshot size. Bare instructions mode must be disabled when splitting because we cannot have PC-relative calls between loading units. Later we can re-enable this for calls within loading units. Broken: Compactor probably crashes we can now have an unbounded number of image pages and the compactor assumes a fixed number. Embedder's guide: At compile-time, gen_snapshot should be passed --loading_unit_manifest with a path, which will enable splitting and output a mapping from loading unit ids to snapshot output paths. At runtime, sometime during isolate startup, an embedder should call Dart_SetDeferredLoadHandler, probably near an existing call to Dart_SetLibraryTagHandler. The callback is given a loading unit id, and should eventually call Dart_DeferredLoadComplete[Error]. Bug: https://github.com/dart-lang/sdk/issues/41974 Change-Id: Ib597eb87c8cd634416d5ee1f00629c5550aebb00 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/152427 Commit-Queue: Ryan Macnak <rmacnak@google.com> Reviewed-by: Alexander Markov <alexmarkov@google.com>
2020-07-17 19:29:47 +00:00
StreamingWriteStream debug_stream(generate_debug ? kInitialDebugSize : 0,
callback, debug_callback_data);
auto const elf = generate_debug
? new (Z) Elf(Z, &debug_stream, Elf::Type::DebugInfo,
new (Z) Dwarf(Z))
: nullptr;
[vm] Consolidate the *WriteStream hierarchy. All *WriteStream classes are now part of the same hierarchy: class BaseWriteStream : ValueObject; Base class for all *WriteStreams. Provides all the methods from the old WriteStream except for buffer() and SetPosition() (relegated to NonStreamingWriteStreams). Has one pure virtual method Realloc that must be overridden by concrete subclasses. class NonStreamingWriteStream : BaseWriteStream; Base class for all *WriteStreams where the entire stream is available at all times (i.e., no flushing to an external sink). Extends the public BaseWriteStream API with buffer() (for accessing the stream contents) and SetPosition() (for changing the current stream pointer to the given absolute position in the stream). class MallocWriteStream : NonStreamingWriteStream; Uses realloc to reallocate the internal buffer. Almost the same as the old WriteStream, except that it only takes an initial size. Adds one public method Steal() for taking ownership of the current buffer contents (after which the buffer is reset to an empty state). Instead of passing a pointer to a buffer, the internal buffer must be accessed via either Steal() or buffer(), which allows access to the current stream contents without changing ownership or resetting the stream. The internal buffer is freed on stream destruction. class ZoneWriteStream: NonStreamingWriteStream; Takes a zone and reallocates the internal buffer in that zone. No additional public methods beyond those available from NonStreamingWriteStream. class StreamingWriteStream : BaseWriteStream; Uses realloc to reallocate the internal buffer. Generally same as before, where the contents of the stream are periodically flushed using Dart_StreamingWriteCallback. Since it extends BaseWriteStream, there are now more methods available for writing data to the stream than just Print/VPrint/WriteBytes. Since portions of the stream may be flushed and thus no longer in the internal buffer, does not provide access to the contents of the stream or a way to reposition the current stream pointer. Flushes any unflushed data and frees the internal buffer on stream destruction. Also refactor things so that write streams are passed to appropriate recipients, instead of the recipients taking arguments they only used to create a WriteStream internally. Thus, recipients now can just specify the appropriate base class for the public API used: * BaseWriteStream for just writing to the stream, or * NonStreamingWriteStream if re-positioning or the stream contents are needed. Change-Id: I419096ecd9331483d168b079fca55b69ef397f15 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/164080 Commit-Queue: Tess Strickland <sstrickl@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com>
2020-09-23 21:05:59 +00:00
AssemblyImageWriter image_writer(T, &assembly_stream, strip, elf);
FullSnapshotWriter writer(Snapshot::kFullAOT, &vm_snapshot_data,
&isolate_snapshot_data, &image_writer,
&image_writer);
[vm] Initial implementation of deferred loading. (Assignment of libraries to loading units is already done in the kernel generation step.) After compiling and before serializing, we walk the program and for each Code we assign its Instructions, CodeSourceMap and CompressedStackMap to the loading unit of that Code's defining library. Deduplication may cause Instructions, CodeSourceMaps and CompressedStackMaps to belong to more than one loading unit; in this case the objects are assigned to the root loading unit. Later they can be more precisely assigned to the dominating loading unit. All objects except some Instructions, CodeSourceMaps and CompressedStackMaps belong to the root loading unit's snapshot. This snapshot is written like an unsplit snapshot, except that when serializing Code, we will write a reference to a stub or null when the Code's Instructions, CodeSourceMap or CompressedStackMap belongs to a non-root loading unit. The snapshots of non-root loading units contain these deferred objects and references to the corresponding Code objects to patch. The types of objects we defer (Instructions, CodeSourceMaps and CompressedStackMaps) usually represent 70+% of the snapshot size. Bare instructions mode must be disabled when splitting because we cannot have PC-relative calls between loading units. Later we can re-enable this for calls within loading units. Broken: Compactor probably crashes we can now have an unbounded number of image pages and the compactor assumes a fixed number. Embedder's guide: At compile-time, gen_snapshot should be passed --loading_unit_manifest with a path, which will enable splitting and output a mapping from loading unit ids to snapshot output paths. At runtime, sometime during isolate startup, an embedder should call Dart_SetDeferredLoadHandler, probably near an existing call to Dart_SetLibraryTagHandler. The callback is given a loading unit id, and should eventually call Dart_DeferredLoadComplete[Error]. Bug: https://github.com/dart-lang/sdk/issues/41974 Change-Id: Ib597eb87c8cd634416d5ee1f00629c5550aebb00 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/152427 Commit-Queue: Ryan Macnak <rmacnak@google.com> Reviewed-by: Alexander Markov <alexmarkov@google.com>
2020-07-17 19:29:47 +00:00
if (unit == nullptr || unit->id() == LoadingUnit::kRootId) {
writer.WriteFullSnapshot(units);
} else {
writer.WriteUnitSnapshot(units, unit, program_hash);
}
image_writer.Finalize();
}
}
static void Split(Dart_CreateLoadingUnitCallback next_callback,
void* next_callback_data,
bool strip,
bool as_elf,
Dart_StreamingWriteCallback write_callback,
Dart_StreamingCloseCallback close_callback) {
Thread* T = Thread::Current();
ProgramVisitor::AssignUnits(T);
const Array& loading_units =
Array::Handle(T->isolate_group()->object_store()->loading_units());
[vm] Initial implementation of deferred loading. (Assignment of libraries to loading units is already done in the kernel generation step.) After compiling and before serializing, we walk the program and for each Code we assign its Instructions, CodeSourceMap and CompressedStackMap to the loading unit of that Code's defining library. Deduplication may cause Instructions, CodeSourceMaps and CompressedStackMaps to belong to more than one loading unit; in this case the objects are assigned to the root loading unit. Later they can be more precisely assigned to the dominating loading unit. All objects except some Instructions, CodeSourceMaps and CompressedStackMaps belong to the root loading unit's snapshot. This snapshot is written like an unsplit snapshot, except that when serializing Code, we will write a reference to a stub or null when the Code's Instructions, CodeSourceMap or CompressedStackMap belongs to a non-root loading unit. The snapshots of non-root loading units contain these deferred objects and references to the corresponding Code objects to patch. The types of objects we defer (Instructions, CodeSourceMaps and CompressedStackMaps) usually represent 70+% of the snapshot size. Bare instructions mode must be disabled when splitting because we cannot have PC-relative calls between loading units. Later we can re-enable this for calls within loading units. Broken: Compactor probably crashes we can now have an unbounded number of image pages and the compactor assumes a fixed number. Embedder's guide: At compile-time, gen_snapshot should be passed --loading_unit_manifest with a path, which will enable splitting and output a mapping from loading unit ids to snapshot output paths. At runtime, sometime during isolate startup, an embedder should call Dart_SetDeferredLoadHandler, probably near an existing call to Dart_SetLibraryTagHandler. The callback is given a loading unit id, and should eventually call Dart_DeferredLoadComplete[Error]. Bug: https://github.com/dart-lang/sdk/issues/41974 Change-Id: Ib597eb87c8cd634416d5ee1f00629c5550aebb00 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/152427 Commit-Queue: Ryan Macnak <rmacnak@google.com> Reviewed-by: Alexander Markov <alexmarkov@google.com>
2020-07-17 19:29:47 +00:00
const uint32_t program_hash = ProgramVisitor::Hash(T);
loading_units.SetAt(0, Smi::Handle(Z, Smi::New(program_hash)));
GrowableArray<LoadingUnitSerializationData*> data;
data.SetLength(loading_units.Length());
data[0] = nullptr;
LoadingUnit& loading_unit = LoadingUnit::Handle();
LoadingUnit& parent = LoadingUnit::Handle();
for (intptr_t id = 1; id < loading_units.Length(); id++) {
loading_unit ^= loading_units.At(id);
parent = loading_unit.parent();
LoadingUnitSerializationData* parent_data =
parent.IsNull() ? nullptr : data[parent.id()];
data[id] = new LoadingUnitSerializationData(id, parent_data);
}
for (intptr_t id = 1; id < loading_units.Length(); id++) {
void* write_callback_data = nullptr;
void* write_debug_callback_data = nullptr;
{
TransitionVMToNative transition(T);
next_callback(next_callback_data, id, &write_callback_data,
&write_debug_callback_data);
}
[vm] Initial implementation of deferred loading. (Assignment of libraries to loading units is already done in the kernel generation step.) After compiling and before serializing, we walk the program and for each Code we assign its Instructions, CodeSourceMap and CompressedStackMap to the loading unit of that Code's defining library. Deduplication may cause Instructions, CodeSourceMaps and CompressedStackMaps to belong to more than one loading unit; in this case the objects are assigned to the root loading unit. Later they can be more precisely assigned to the dominating loading unit. All objects except some Instructions, CodeSourceMaps and CompressedStackMaps belong to the root loading unit's snapshot. This snapshot is written like an unsplit snapshot, except that when serializing Code, we will write a reference to a stub or null when the Code's Instructions, CodeSourceMap or CompressedStackMap belongs to a non-root loading unit. The snapshots of non-root loading units contain these deferred objects and references to the corresponding Code objects to patch. The types of objects we defer (Instructions, CodeSourceMaps and CompressedStackMaps) usually represent 70+% of the snapshot size. Bare instructions mode must be disabled when splitting because we cannot have PC-relative calls between loading units. Later we can re-enable this for calls within loading units. Broken: Compactor probably crashes we can now have an unbounded number of image pages and the compactor assumes a fixed number. Embedder's guide: At compile-time, gen_snapshot should be passed --loading_unit_manifest with a path, which will enable splitting and output a mapping from loading unit ids to snapshot output paths. At runtime, sometime during isolate startup, an embedder should call Dart_SetDeferredLoadHandler, probably near an existing call to Dart_SetLibraryTagHandler. The callback is given a loading unit id, and should eventually call Dart_DeferredLoadComplete[Error]. Bug: https://github.com/dart-lang/sdk/issues/41974 Change-Id: Ib597eb87c8cd634416d5ee1f00629c5550aebb00 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/152427 Commit-Queue: Ryan Macnak <rmacnak@google.com> Reviewed-by: Alexander Markov <alexmarkov@google.com>
2020-07-17 19:29:47 +00:00
CreateAppAOTSnapshot(write_callback, write_callback_data, strip, as_elf,
write_debug_callback_data, &data, data[id],
program_hash);
{
TransitionVMToNative transition(T);
close_callback(write_callback_data);
if (write_debug_callback_data != nullptr) {
close_callback(write_debug_callback_data);
}
[vm] Initial implementation of deferred loading. (Assignment of libraries to loading units is already done in the kernel generation step.) After compiling and before serializing, we walk the program and for each Code we assign its Instructions, CodeSourceMap and CompressedStackMap to the loading unit of that Code's defining library. Deduplication may cause Instructions, CodeSourceMaps and CompressedStackMaps to belong to more than one loading unit; in this case the objects are assigned to the root loading unit. Later they can be more precisely assigned to the dominating loading unit. All objects except some Instructions, CodeSourceMaps and CompressedStackMaps belong to the root loading unit's snapshot. This snapshot is written like an unsplit snapshot, except that when serializing Code, we will write a reference to a stub or null when the Code's Instructions, CodeSourceMap or CompressedStackMap belongs to a non-root loading unit. The snapshots of non-root loading units contain these deferred objects and references to the corresponding Code objects to patch. The types of objects we defer (Instructions, CodeSourceMaps and CompressedStackMaps) usually represent 70+% of the snapshot size. Bare instructions mode must be disabled when splitting because we cannot have PC-relative calls between loading units. Later we can re-enable this for calls within loading units. Broken: Compactor probably crashes we can now have an unbounded number of image pages and the compactor assumes a fixed number. Embedder's guide: At compile-time, gen_snapshot should be passed --loading_unit_manifest with a path, which will enable splitting and output a mapping from loading unit ids to snapshot output paths. At runtime, sometime during isolate startup, an embedder should call Dart_SetDeferredLoadHandler, probably near an existing call to Dart_SetLibraryTagHandler. The callback is given a loading unit id, and should eventually call Dart_DeferredLoadComplete[Error]. Bug: https://github.com/dart-lang/sdk/issues/41974 Change-Id: Ib597eb87c8cd634416d5ee1f00629c5550aebb00 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/152427 Commit-Queue: Ryan Macnak <rmacnak@google.com> Reviewed-by: Alexander Markov <alexmarkov@google.com>
2020-07-17 19:29:47 +00:00
}
}
}
#endif
DART_EXPORT Dart_Handle
Dart_CreateAppAOTSnapshotAsAssembly(Dart_StreamingWriteCallback callback,
void* callback_data,
bool strip,
void* debug_callback_data) {
#if defined(TARGET_ARCH_IA32)
return Api::NewError("AOT compilation is not supported on IA32.");
#elif defined(DART_TARGET_OS_WINDOWS)
return Api::NewError("Assembly generation is not implemented for Windows.");
#elif !defined(DART_PRECOMPILER)
return Api::NewError(
"This VM was built without support for AOT compilation.");
#else
DARTSCOPE(Thread::Current());
API_TIMELINE_DURATION(T);
CHECK_NULL(callback);
[vm] Initial implementation of deferred loading. (Assignment of libraries to loading units is already done in the kernel generation step.) After compiling and before serializing, we walk the program and for each Code we assign its Instructions, CodeSourceMap and CompressedStackMap to the loading unit of that Code's defining library. Deduplication may cause Instructions, CodeSourceMaps and CompressedStackMaps to belong to more than one loading unit; in this case the objects are assigned to the root loading unit. Later they can be more precisely assigned to the dominating loading unit. All objects except some Instructions, CodeSourceMaps and CompressedStackMaps belong to the root loading unit's snapshot. This snapshot is written like an unsplit snapshot, except that when serializing Code, we will write a reference to a stub or null when the Code's Instructions, CodeSourceMap or CompressedStackMap belongs to a non-root loading unit. The snapshots of non-root loading units contain these deferred objects and references to the corresponding Code objects to patch. The types of objects we defer (Instructions, CodeSourceMaps and CompressedStackMaps) usually represent 70+% of the snapshot size. Bare instructions mode must be disabled when splitting because we cannot have PC-relative calls between loading units. Later we can re-enable this for calls within loading units. Broken: Compactor probably crashes we can now have an unbounded number of image pages and the compactor assumes a fixed number. Embedder's guide: At compile-time, gen_snapshot should be passed --loading_unit_manifest with a path, which will enable splitting and output a mapping from loading unit ids to snapshot output paths. At runtime, sometime during isolate startup, an embedder should call Dart_SetDeferredLoadHandler, probably near an existing call to Dart_SetLibraryTagHandler. The callback is given a loading unit id, and should eventually call Dart_DeferredLoadComplete[Error]. Bug: https://github.com/dart-lang/sdk/issues/41974 Change-Id: Ib597eb87c8cd634416d5ee1f00629c5550aebb00 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/152427 Commit-Queue: Ryan Macnak <rmacnak@google.com> Reviewed-by: Alexander Markov <alexmarkov@google.com>
2020-07-17 19:29:47 +00:00
// Mark as not split.
T->isolate_group()->object_store()->set_loading_units(Object::null_array());
[vm] Initial implementation of deferred loading. (Assignment of libraries to loading units is already done in the kernel generation step.) After compiling and before serializing, we walk the program and for each Code we assign its Instructions, CodeSourceMap and CompressedStackMap to the loading unit of that Code's defining library. Deduplication may cause Instructions, CodeSourceMaps and CompressedStackMaps to belong to more than one loading unit; in this case the objects are assigned to the root loading unit. Later they can be more precisely assigned to the dominating loading unit. All objects except some Instructions, CodeSourceMaps and CompressedStackMaps belong to the root loading unit's snapshot. This snapshot is written like an unsplit snapshot, except that when serializing Code, we will write a reference to a stub or null when the Code's Instructions, CodeSourceMap or CompressedStackMap belongs to a non-root loading unit. The snapshots of non-root loading units contain these deferred objects and references to the corresponding Code objects to patch. The types of objects we defer (Instructions, CodeSourceMaps and CompressedStackMaps) usually represent 70+% of the snapshot size. Bare instructions mode must be disabled when splitting because we cannot have PC-relative calls between loading units. Later we can re-enable this for calls within loading units. Broken: Compactor probably crashes we can now have an unbounded number of image pages and the compactor assumes a fixed number. Embedder's guide: At compile-time, gen_snapshot should be passed --loading_unit_manifest with a path, which will enable splitting and output a mapping from loading unit ids to snapshot output paths. At runtime, sometime during isolate startup, an embedder should call Dart_SetDeferredLoadHandler, probably near an existing call to Dart_SetLibraryTagHandler. The callback is given a loading unit id, and should eventually call Dart_DeferredLoadComplete[Error]. Bug: https://github.com/dart-lang/sdk/issues/41974 Change-Id: Ib597eb87c8cd634416d5ee1f00629c5550aebb00 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/152427 Commit-Queue: Ryan Macnak <rmacnak@google.com> Reviewed-by: Alexander Markov <alexmarkov@google.com>
2020-07-17 19:29:47 +00:00
CreateAppAOTSnapshot(callback, callback_data, strip, /*as_elf*/ false,
debug_callback_data, nullptr, nullptr, 0);
[vm] Initial implementation of deferred loading. (Assignment of libraries to loading units is already done in the kernel generation step.) After compiling and before serializing, we walk the program and for each Code we assign its Instructions, CodeSourceMap and CompressedStackMap to the loading unit of that Code's defining library. Deduplication may cause Instructions, CodeSourceMaps and CompressedStackMaps to belong to more than one loading unit; in this case the objects are assigned to the root loading unit. Later they can be more precisely assigned to the dominating loading unit. All objects except some Instructions, CodeSourceMaps and CompressedStackMaps belong to the root loading unit's snapshot. This snapshot is written like an unsplit snapshot, except that when serializing Code, we will write a reference to a stub or null when the Code's Instructions, CodeSourceMap or CompressedStackMap belongs to a non-root loading unit. The snapshots of non-root loading units contain these deferred objects and references to the corresponding Code objects to patch. The types of objects we defer (Instructions, CodeSourceMaps and CompressedStackMaps) usually represent 70+% of the snapshot size. Bare instructions mode must be disabled when splitting because we cannot have PC-relative calls between loading units. Later we can re-enable this for calls within loading units. Broken: Compactor probably crashes we can now have an unbounded number of image pages and the compactor assumes a fixed number. Embedder's guide: At compile-time, gen_snapshot should be passed --loading_unit_manifest with a path, which will enable splitting and output a mapping from loading unit ids to snapshot output paths. At runtime, sometime during isolate startup, an embedder should call Dart_SetDeferredLoadHandler, probably near an existing call to Dart_SetLibraryTagHandler. The callback is given a loading unit id, and should eventually call Dart_DeferredLoadComplete[Error]. Bug: https://github.com/dart-lang/sdk/issues/41974 Change-Id: Ib597eb87c8cd634416d5ee1f00629c5550aebb00 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/152427 Commit-Queue: Ryan Macnak <rmacnak@google.com> Reviewed-by: Alexander Markov <alexmarkov@google.com>
2020-07-17 19:29:47 +00:00
return Api::Success();
#endif
}
[vm] Initial implementation of deferred loading. (Assignment of libraries to loading units is already done in the kernel generation step.) After compiling and before serializing, we walk the program and for each Code we assign its Instructions, CodeSourceMap and CompressedStackMap to the loading unit of that Code's defining library. Deduplication may cause Instructions, CodeSourceMaps and CompressedStackMaps to belong to more than one loading unit; in this case the objects are assigned to the root loading unit. Later they can be more precisely assigned to the dominating loading unit. All objects except some Instructions, CodeSourceMaps and CompressedStackMaps belong to the root loading unit's snapshot. This snapshot is written like an unsplit snapshot, except that when serializing Code, we will write a reference to a stub or null when the Code's Instructions, CodeSourceMap or CompressedStackMap belongs to a non-root loading unit. The snapshots of non-root loading units contain these deferred objects and references to the corresponding Code objects to patch. The types of objects we defer (Instructions, CodeSourceMaps and CompressedStackMaps) usually represent 70+% of the snapshot size. Bare instructions mode must be disabled when splitting because we cannot have PC-relative calls between loading units. Later we can re-enable this for calls within loading units. Broken: Compactor probably crashes we can now have an unbounded number of image pages and the compactor assumes a fixed number. Embedder's guide: At compile-time, gen_snapshot should be passed --loading_unit_manifest with a path, which will enable splitting and output a mapping from loading unit ids to snapshot output paths. At runtime, sometime during isolate startup, an embedder should call Dart_SetDeferredLoadHandler, probably near an existing call to Dart_SetLibraryTagHandler. The callback is given a loading unit id, and should eventually call Dart_DeferredLoadComplete[Error]. Bug: https://github.com/dart-lang/sdk/issues/41974 Change-Id: Ib597eb87c8cd634416d5ee1f00629c5550aebb00 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/152427 Commit-Queue: Ryan Macnak <rmacnak@google.com> Reviewed-by: Alexander Markov <alexmarkov@google.com>
2020-07-17 19:29:47 +00:00
DART_EXPORT Dart_Handle Dart_CreateAppAOTSnapshotAsAssemblies(
Dart_CreateLoadingUnitCallback next_callback,
void* next_callback_data,
bool strip,
Dart_StreamingWriteCallback write_callback,
Dart_StreamingCloseCallback close_callback) {
#if defined(TARGET_ARCH_IA32)
return Api::NewError("AOT compilation is not supported on IA32.");
#elif defined(DART_TARGET_OS_WINDOWS)
[vm] Initial implementation of deferred loading. (Assignment of libraries to loading units is already done in the kernel generation step.) After compiling and before serializing, we walk the program and for each Code we assign its Instructions, CodeSourceMap and CompressedStackMap to the loading unit of that Code's defining library. Deduplication may cause Instructions, CodeSourceMaps and CompressedStackMaps to belong to more than one loading unit; in this case the objects are assigned to the root loading unit. Later they can be more precisely assigned to the dominating loading unit. All objects except some Instructions, CodeSourceMaps and CompressedStackMaps belong to the root loading unit's snapshot. This snapshot is written like an unsplit snapshot, except that when serializing Code, we will write a reference to a stub or null when the Code's Instructions, CodeSourceMap or CompressedStackMap belongs to a non-root loading unit. The snapshots of non-root loading units contain these deferred objects and references to the corresponding Code objects to patch. The types of objects we defer (Instructions, CodeSourceMaps and CompressedStackMaps) usually represent 70+% of the snapshot size. Bare instructions mode must be disabled when splitting because we cannot have PC-relative calls between loading units. Later we can re-enable this for calls within loading units. Broken: Compactor probably crashes we can now have an unbounded number of image pages and the compactor assumes a fixed number. Embedder's guide: At compile-time, gen_snapshot should be passed --loading_unit_manifest with a path, which will enable splitting and output a mapping from loading unit ids to snapshot output paths. At runtime, sometime during isolate startup, an embedder should call Dart_SetDeferredLoadHandler, probably near an existing call to Dart_SetLibraryTagHandler. The callback is given a loading unit id, and should eventually call Dart_DeferredLoadComplete[Error]. Bug: https://github.com/dart-lang/sdk/issues/41974 Change-Id: Ib597eb87c8cd634416d5ee1f00629c5550aebb00 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/152427 Commit-Queue: Ryan Macnak <rmacnak@google.com> Reviewed-by: Alexander Markov <alexmarkov@google.com>
2020-07-17 19:29:47 +00:00
return Api::NewError("Assembly generation is not implemented for Windows.");
#elif !defined(DART_PRECOMPILER)
return Api::NewError(
"This VM was built without support for AOT compilation.");
#else
DARTSCOPE(Thread::Current());
API_TIMELINE_DURATION(T);
CHECK_NULL(next_callback);
CHECK_NULL(write_callback);
CHECK_NULL(close_callback);
Split(next_callback, next_callback_data, strip, /*as_elf*/ false,
write_callback, close_callback);
return Api::Success();
#endif
}
DART_EXPORT Dart_Handle
Dart_CreateVMAOTSnapshotAsAssembly(Dart_StreamingWriteCallback callback,
void* callback_data) {
#if defined(TARGET_ARCH_IA32)
return Api::NewError("AOT compilation is not supported on IA32.");
#elif defined(DART_TARGET_OS_WINDOWS)
return Api::NewError("Assembly generation is not implemented for Windows.");
#elif !defined(DART_PRECOMPILER)
return Api::NewError(
"This VM was built without support for AOT compilation.");
#else
DARTSCOPE(Thread::Current());
API_TIMELINE_DURATION(T);
CHECK_NULL(callback);
TIMELINE_DURATION(T, Isolate, "WriteVMAOTSnapshot");
[vm] Consolidate the *WriteStream hierarchy. All *WriteStream classes are now part of the same hierarchy: class BaseWriteStream : ValueObject; Base class for all *WriteStreams. Provides all the methods from the old WriteStream except for buffer() and SetPosition() (relegated to NonStreamingWriteStreams). Has one pure virtual method Realloc that must be overridden by concrete subclasses. class NonStreamingWriteStream : BaseWriteStream; Base class for all *WriteStreams where the entire stream is available at all times (i.e., no flushing to an external sink). Extends the public BaseWriteStream API with buffer() (for accessing the stream contents) and SetPosition() (for changing the current stream pointer to the given absolute position in the stream). class MallocWriteStream : NonStreamingWriteStream; Uses realloc to reallocate the internal buffer. Almost the same as the old WriteStream, except that it only takes an initial size. Adds one public method Steal() for taking ownership of the current buffer contents (after which the buffer is reset to an empty state). Instead of passing a pointer to a buffer, the internal buffer must be accessed via either Steal() or buffer(), which allows access to the current stream contents without changing ownership or resetting the stream. The internal buffer is freed on stream destruction. class ZoneWriteStream: NonStreamingWriteStream; Takes a zone and reallocates the internal buffer in that zone. No additional public methods beyond those available from NonStreamingWriteStream. class StreamingWriteStream : BaseWriteStream; Uses realloc to reallocate the internal buffer. Generally same as before, where the contents of the stream are periodically flushed using Dart_StreamingWriteCallback. Since it extends BaseWriteStream, there are now more methods available for writing data to the stream than just Print/VPrint/WriteBytes. Since portions of the stream may be flushed and thus no longer in the internal buffer, does not provide access to the contents of the stream or a way to reposition the current stream pointer. Flushes any unflushed data and frees the internal buffer on stream destruction. Also refactor things so that write streams are passed to appropriate recipients, instead of the recipients taking arguments they only used to create a WriteStream internally. Thus, recipients now can just specify the appropriate base class for the public API used: * BaseWriteStream for just writing to the stream, or * NonStreamingWriteStream if re-positioning or the stream contents are needed. Change-Id: I419096ecd9331483d168b079fca55b69ef397f15 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/164080 Commit-Queue: Tess Strickland <sstrickl@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com>
2020-09-23 21:05:59 +00:00
StreamingWriteStream assembly_stream(kAssemblyInitialSize, callback,
callback_data);
AssemblyImageWriter image_writer(T, &assembly_stream);
ZoneWriteStream vm_snapshot_data(T->zone(), FullSnapshotWriter::kInitialSize);
FullSnapshotWriter writer(Snapshot::kFullAOT, &vm_snapshot_data, nullptr,
&image_writer, nullptr);
writer.WriteFullSnapshot();
return Api::Success();
#endif
}
DART_EXPORT Dart_Handle
Dart_CreateAppAOTSnapshotAsElf(Dart_StreamingWriteCallback callback,
void* callback_data,
[vm/compiler] Reland "Add --save-debugging-info flag to gen_snapshot." Removes an unnecessary change to the names of type testing stubs that allowed name collisions to happen. Old commit message: The flag can be used when creating AOT snapshots. The resulting file can be used with package:vm/dwarf/convert.dart to convert DWARF-based stack traces to stack traces with function, file, and line number information. Currently the saved file will be an ELF file with DWARF debugging information, but this is subject to change in the future. To avoid being affected by any changes in format, read the DWARF information from the file using Dwarf.fromFile() in package:vm/dwarf/dwarf.dart. Also adds --dwarf-stack-traces to the VM global flag list, so its value at compilation will be read out of snapshots by the precompiled runtime. Fixes https://github.com/dart-lang/sdk/issues/39512, which was due to a missing compiler::target:: prefix for Instructions::HeaderSize() in BlobImageWriter::WriteText(). Exposes the information suggested in https://github.com/dart-lang/sdk/issues/39490 so that package:vm/dwarf can appropriately convert absolute PC addresses to the correct virtual address for a given DWARF line number program. Bug: https://github.com/dart-lang/sdk/issues/35851 Change-Id: I6723449dceb0b89c054a1f1e70e7acd7749baf14 Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-mac-release-simarm64-try,vm-kernel-precomp-win-release-x64-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/128730 Reviewed-by: Martin Kustermann <kustermann@google.com>
2019-12-18 14:14:41 +00:00
bool strip,
void* debug_callback_data) {
#if defined(TARGET_ARCH_IA32)
return Api::NewError("AOT compilation is not supported on IA32.");
#elif !defined(DART_PRECOMPILER)
return Api::NewError(
"This VM was built without support for AOT compilation.");
#else
DARTSCOPE(Thread::Current());
API_TIMELINE_DURATION(T);
[vm] Initial implementation of deferred loading. (Assignment of libraries to loading units is already done in the kernel generation step.) After compiling and before serializing, we walk the program and for each Code we assign its Instructions, CodeSourceMap and CompressedStackMap to the loading unit of that Code's defining library. Deduplication may cause Instructions, CodeSourceMaps and CompressedStackMaps to belong to more than one loading unit; in this case the objects are assigned to the root loading unit. Later they can be more precisely assigned to the dominating loading unit. All objects except some Instructions, CodeSourceMaps and CompressedStackMaps belong to the root loading unit's snapshot. This snapshot is written like an unsplit snapshot, except that when serializing Code, we will write a reference to a stub or null when the Code's Instructions, CodeSourceMap or CompressedStackMap belongs to a non-root loading unit. The snapshots of non-root loading units contain these deferred objects and references to the corresponding Code objects to patch. The types of objects we defer (Instructions, CodeSourceMaps and CompressedStackMaps) usually represent 70+% of the snapshot size. Bare instructions mode must be disabled when splitting because we cannot have PC-relative calls between loading units. Later we can re-enable this for calls within loading units. Broken: Compactor probably crashes we can now have an unbounded number of image pages and the compactor assumes a fixed number. Embedder's guide: At compile-time, gen_snapshot should be passed --loading_unit_manifest with a path, which will enable splitting and output a mapping from loading unit ids to snapshot output paths. At runtime, sometime during isolate startup, an embedder should call Dart_SetDeferredLoadHandler, probably near an existing call to Dart_SetLibraryTagHandler. The callback is given a loading unit id, and should eventually call Dart_DeferredLoadComplete[Error]. Bug: https://github.com/dart-lang/sdk/issues/41974 Change-Id: Ib597eb87c8cd634416d5ee1f00629c5550aebb00 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/152427 Commit-Queue: Ryan Macnak <rmacnak@google.com> Reviewed-by: Alexander Markov <alexmarkov@google.com>
2020-07-17 19:29:47 +00:00
CHECK_NULL(callback);
[vm] Initial implementation of deferred loading. (Assignment of libraries to loading units is already done in the kernel generation step.) After compiling and before serializing, we walk the program and for each Code we assign its Instructions, CodeSourceMap and CompressedStackMap to the loading unit of that Code's defining library. Deduplication may cause Instructions, CodeSourceMaps and CompressedStackMaps to belong to more than one loading unit; in this case the objects are assigned to the root loading unit. Later they can be more precisely assigned to the dominating loading unit. All objects except some Instructions, CodeSourceMaps and CompressedStackMaps belong to the root loading unit's snapshot. This snapshot is written like an unsplit snapshot, except that when serializing Code, we will write a reference to a stub or null when the Code's Instructions, CodeSourceMap or CompressedStackMap belongs to a non-root loading unit. The snapshots of non-root loading units contain these deferred objects and references to the corresponding Code objects to patch. The types of objects we defer (Instructions, CodeSourceMaps and CompressedStackMaps) usually represent 70+% of the snapshot size. Bare instructions mode must be disabled when splitting because we cannot have PC-relative calls between loading units. Later we can re-enable this for calls within loading units. Broken: Compactor probably crashes we can now have an unbounded number of image pages and the compactor assumes a fixed number. Embedder's guide: At compile-time, gen_snapshot should be passed --loading_unit_manifest with a path, which will enable splitting and output a mapping from loading unit ids to snapshot output paths. At runtime, sometime during isolate startup, an embedder should call Dart_SetDeferredLoadHandler, probably near an existing call to Dart_SetLibraryTagHandler. The callback is given a loading unit id, and should eventually call Dart_DeferredLoadComplete[Error]. Bug: https://github.com/dart-lang/sdk/issues/41974 Change-Id: Ib597eb87c8cd634416d5ee1f00629c5550aebb00 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/152427 Commit-Queue: Ryan Macnak <rmacnak@google.com> Reviewed-by: Alexander Markov <alexmarkov@google.com>
2020-07-17 19:29:47 +00:00
// Mark as not split.
T->isolate_group()->object_store()->set_loading_units(Object::null_array());
[vm/compiler] Add --save-debugging-info flag to gen_snapshot. The flag can be used when creating AOT snapshots. The resulting file can be used with package:vm/dwarf/convert.dart to convert DWARF-based stack traces to stack traces with function, file, and line number information. Currently the saved file will be an ELF file with DWARF debugging information, but this is subject to change in the future. To avoid being affected by any changes in format, read the DWARF information from the file using Dwarf.fromFile() in package:vm/dwarf/dwarf.dart. Also adds --dwarf-stack-traces to the VM global flag list, so its value at compilation will be read out of snapshots by the precompiled runtime. Fixes https://github.com/dart-lang/sdk/issues/39512, which was due to a missing compiler::target:: prefix for Instructions::HeaderSize() in BlobImageWriter::WriteText(). Exposes the information suggested in https://github.com/dart-lang/sdk/issues/39490 so that package:vm/dwarf can appropriately convert absolute PC addresses to the correct virtual address for a given DWARF line number program. Bug: https://github.com/dart-lang/sdk/issues/35851 Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-mac-release-simarm_x64-try,vm-kernel-precomp-win-release-x64-try Change-Id: I80d900fd9e5f1e2399ad3f2fd25c85131a7ea43c Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/121857 Commit-Queue: Teagan Strickland <sstrickl@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com>
2019-12-12 14:18:59 +00:00
[vm] Initial implementation of deferred loading. (Assignment of libraries to loading units is already done in the kernel generation step.) After compiling and before serializing, we walk the program and for each Code we assign its Instructions, CodeSourceMap and CompressedStackMap to the loading unit of that Code's defining library. Deduplication may cause Instructions, CodeSourceMaps and CompressedStackMaps to belong to more than one loading unit; in this case the objects are assigned to the root loading unit. Later they can be more precisely assigned to the dominating loading unit. All objects except some Instructions, CodeSourceMaps and CompressedStackMaps belong to the root loading unit's snapshot. This snapshot is written like an unsplit snapshot, except that when serializing Code, we will write a reference to a stub or null when the Code's Instructions, CodeSourceMap or CompressedStackMap belongs to a non-root loading unit. The snapshots of non-root loading units contain these deferred objects and references to the corresponding Code objects to patch. The types of objects we defer (Instructions, CodeSourceMaps and CompressedStackMaps) usually represent 70+% of the snapshot size. Bare instructions mode must be disabled when splitting because we cannot have PC-relative calls between loading units. Later we can re-enable this for calls within loading units. Broken: Compactor probably crashes we can now have an unbounded number of image pages and the compactor assumes a fixed number. Embedder's guide: At compile-time, gen_snapshot should be passed --loading_unit_manifest with a path, which will enable splitting and output a mapping from loading unit ids to snapshot output paths. At runtime, sometime during isolate startup, an embedder should call Dart_SetDeferredLoadHandler, probably near an existing call to Dart_SetLibraryTagHandler. The callback is given a loading unit id, and should eventually call Dart_DeferredLoadComplete[Error]. Bug: https://github.com/dart-lang/sdk/issues/41974 Change-Id: Ib597eb87c8cd634416d5ee1f00629c5550aebb00 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/152427 Commit-Queue: Ryan Macnak <rmacnak@google.com> Reviewed-by: Alexander Markov <alexmarkov@google.com>
2020-07-17 19:29:47 +00:00
CreateAppAOTSnapshot(callback, callback_data, strip, /*as_elf*/ true,
debug_callback_data, nullptr, nullptr, 0);
[vm] Initial implementation of deferred loading. (Assignment of libraries to loading units is already done in the kernel generation step.) After compiling and before serializing, we walk the program and for each Code we assign its Instructions, CodeSourceMap and CompressedStackMap to the loading unit of that Code's defining library. Deduplication may cause Instructions, CodeSourceMaps and CompressedStackMaps to belong to more than one loading unit; in this case the objects are assigned to the root loading unit. Later they can be more precisely assigned to the dominating loading unit. All objects except some Instructions, CodeSourceMaps and CompressedStackMaps belong to the root loading unit's snapshot. This snapshot is written like an unsplit snapshot, except that when serializing Code, we will write a reference to a stub or null when the Code's Instructions, CodeSourceMap or CompressedStackMap belongs to a non-root loading unit. The snapshots of non-root loading units contain these deferred objects and references to the corresponding Code objects to patch. The types of objects we defer (Instructions, CodeSourceMaps and CompressedStackMaps) usually represent 70+% of the snapshot size. Bare instructions mode must be disabled when splitting because we cannot have PC-relative calls between loading units. Later we can re-enable this for calls within loading units. Broken: Compactor probably crashes we can now have an unbounded number of image pages and the compactor assumes a fixed number. Embedder's guide: At compile-time, gen_snapshot should be passed --loading_unit_manifest with a path, which will enable splitting and output a mapping from loading unit ids to snapshot output paths. At runtime, sometime during isolate startup, an embedder should call Dart_SetDeferredLoadHandler, probably near an existing call to Dart_SetLibraryTagHandler. The callback is given a loading unit id, and should eventually call Dart_DeferredLoadComplete[Error]. Bug: https://github.com/dart-lang/sdk/issues/41974 Change-Id: Ib597eb87c8cd634416d5ee1f00629c5550aebb00 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/152427 Commit-Queue: Ryan Macnak <rmacnak@google.com> Reviewed-by: Alexander Markov <alexmarkov@google.com>
2020-07-17 19:29:47 +00:00
return Api::Success();
#endif
}
[vm/compiler] Add --save-debugging-info flag to gen_snapshot. The flag can be used when creating AOT snapshots. The resulting file can be used with package:vm/dwarf/convert.dart to convert DWARF-based stack traces to stack traces with function, file, and line number information. Currently the saved file will be an ELF file with DWARF debugging information, but this is subject to change in the future. To avoid being affected by any changes in format, read the DWARF information from the file using Dwarf.fromFile() in package:vm/dwarf/dwarf.dart. Also adds --dwarf-stack-traces to the VM global flag list, so its value at compilation will be read out of snapshots by the precompiled runtime. Fixes https://github.com/dart-lang/sdk/issues/39512, which was due to a missing compiler::target:: prefix for Instructions::HeaderSize() in BlobImageWriter::WriteText(). Exposes the information suggested in https://github.com/dart-lang/sdk/issues/39490 so that package:vm/dwarf can appropriately convert absolute PC addresses to the correct virtual address for a given DWARF line number program. Bug: https://github.com/dart-lang/sdk/issues/35851 Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-mac-release-simarm_x64-try,vm-kernel-precomp-win-release-x64-try Change-Id: I80d900fd9e5f1e2399ad3f2fd25c85131a7ea43c Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/121857 Commit-Queue: Teagan Strickland <sstrickl@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com>
2019-12-12 14:18:59 +00:00
[vm] Initial implementation of deferred loading. (Assignment of libraries to loading units is already done in the kernel generation step.) After compiling and before serializing, we walk the program and for each Code we assign its Instructions, CodeSourceMap and CompressedStackMap to the loading unit of that Code's defining library. Deduplication may cause Instructions, CodeSourceMaps and CompressedStackMaps to belong to more than one loading unit; in this case the objects are assigned to the root loading unit. Later they can be more precisely assigned to the dominating loading unit. All objects except some Instructions, CodeSourceMaps and CompressedStackMaps belong to the root loading unit's snapshot. This snapshot is written like an unsplit snapshot, except that when serializing Code, we will write a reference to a stub or null when the Code's Instructions, CodeSourceMap or CompressedStackMap belongs to a non-root loading unit. The snapshots of non-root loading units contain these deferred objects and references to the corresponding Code objects to patch. The types of objects we defer (Instructions, CodeSourceMaps and CompressedStackMaps) usually represent 70+% of the snapshot size. Bare instructions mode must be disabled when splitting because we cannot have PC-relative calls between loading units. Later we can re-enable this for calls within loading units. Broken: Compactor probably crashes we can now have an unbounded number of image pages and the compactor assumes a fixed number. Embedder's guide: At compile-time, gen_snapshot should be passed --loading_unit_manifest with a path, which will enable splitting and output a mapping from loading unit ids to snapshot output paths. At runtime, sometime during isolate startup, an embedder should call Dart_SetDeferredLoadHandler, probably near an existing call to Dart_SetLibraryTagHandler. The callback is given a loading unit id, and should eventually call Dart_DeferredLoadComplete[Error]. Bug: https://github.com/dart-lang/sdk/issues/41974 Change-Id: Ib597eb87c8cd634416d5ee1f00629c5550aebb00 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/152427 Commit-Queue: Ryan Macnak <rmacnak@google.com> Reviewed-by: Alexander Markov <alexmarkov@google.com>
2020-07-17 19:29:47 +00:00
DART_EXPORT Dart_Handle
Dart_CreateAppAOTSnapshotAsElfs(Dart_CreateLoadingUnitCallback next_callback,
void* next_callback_data,
bool strip,
Dart_StreamingWriteCallback write_callback,
Dart_StreamingCloseCallback close_callback) {
#if defined(TARGET_ARCH_IA32)
return Api::NewError("AOT compilation is not supported on IA32.");
#elif !defined(DART_PRECOMPILER)
return Api::NewError(
"This VM was built without support for AOT compilation.");
#else
DARTSCOPE(Thread::Current());
API_TIMELINE_DURATION(T);
CHECK_NULL(next_callback);
CHECK_NULL(write_callback);
CHECK_NULL(close_callback);
[vm/compiler] Clean up ELF creation code. Instead of making the ELF object handle stripping and keep track of two possible output stream, just revert ELF objects to only output to a single stream. Now, layers that use ELF, like the ImageWriters, handle the stripping by deciding whether or not to add certain sections or static symbols to the generated ELF, and we create separate DWARF objects for each unstripped ELF object. We also avoid duplication of writing segment and section table entries by just creating special Sections that correspond to reserved entries, the program table header entries for itself, etc, and then move the section and segment entry writing into Section itself. We also lift a lot of the same calculations used in subclass construction to the Section level, and replace the old fields with four different kind of object members: * Fields that are known at construction time and thus now const (e.g., section_type) * Fields that are not known at construction time that have reasonable defaults for most instances and so need not be changed from their default value (e.g., section_link) * Fields that are not known at construction time which must be set once (and only once) before use. These are now accessed via getters/setters that check whether or not the field has been set (e.g., section_name) * Fields that are calculated from the contents of the particular subclass, which are now just methods (e.g., FileSize()) We also change the snapshot profile writer test to test the size of internally stripped ELF output on all platforms without running it through an external stripping utility (previously untested), and test assembled or externally stripped output on more platforms where we support those. Instead of depending on pkg/vm/tool/precompiler2 for assembling (which always uses gcc), I've added assembleSnapshot and stripSnapshot to use_flag_test_helper.dart, which mimics the way the test_runner determines the executable and flags to use. Change-Id: I4ade45c5caffb443abb3f5c567343504c8085f89 Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-release-simarm-try,vm-kernel-precomp-linux-release-simarm64-try,vm-kernel-precomp-linux-release-simarm_x64-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-mac-release-simarm64-try,vm-kernel-precomp-win-release-x64-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/129083 Commit-Queue: Teagan Strickland <sstrickl@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com>
2020-01-10 11:51:57 +00:00
[vm] Initial implementation of deferred loading. (Assignment of libraries to loading units is already done in the kernel generation step.) After compiling and before serializing, we walk the program and for each Code we assign its Instructions, CodeSourceMap and CompressedStackMap to the loading unit of that Code's defining library. Deduplication may cause Instructions, CodeSourceMaps and CompressedStackMaps to belong to more than one loading unit; in this case the objects are assigned to the root loading unit. Later they can be more precisely assigned to the dominating loading unit. All objects except some Instructions, CodeSourceMaps and CompressedStackMaps belong to the root loading unit's snapshot. This snapshot is written like an unsplit snapshot, except that when serializing Code, we will write a reference to a stub or null when the Code's Instructions, CodeSourceMap or CompressedStackMap belongs to a non-root loading unit. The snapshots of non-root loading units contain these deferred objects and references to the corresponding Code objects to patch. The types of objects we defer (Instructions, CodeSourceMaps and CompressedStackMaps) usually represent 70+% of the snapshot size. Bare instructions mode must be disabled when splitting because we cannot have PC-relative calls between loading units. Later we can re-enable this for calls within loading units. Broken: Compactor probably crashes we can now have an unbounded number of image pages and the compactor assumes a fixed number. Embedder's guide: At compile-time, gen_snapshot should be passed --loading_unit_manifest with a path, which will enable splitting and output a mapping from loading unit ids to snapshot output paths. At runtime, sometime during isolate startup, an embedder should call Dart_SetDeferredLoadHandler, probably near an existing call to Dart_SetLibraryTagHandler. The callback is given a loading unit id, and should eventually call Dart_DeferredLoadComplete[Error]. Bug: https://github.com/dart-lang/sdk/issues/41974 Change-Id: Ib597eb87c8cd634416d5ee1f00629c5550aebb00 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/152427 Commit-Queue: Ryan Macnak <rmacnak@google.com> Reviewed-by: Alexander Markov <alexmarkov@google.com>
2020-07-17 19:29:47 +00:00
Split(next_callback, next_callback_data, strip, /*as_elf*/ true,
write_callback, close_callback);
return Api::Success();
#endif
}
DART_EXPORT Dart_Handle Dart_LoadingUnitLibraryUris(intptr_t loading_unit_id) {
#if defined(TARGET_ARCH_IA32)
return Api::NewError("AOT compilation is not supported on IA32.");
#elif !defined(DART_PRECOMPILER)
return Api::NewError(
"This VM was built without support for AOT compilation.");
#else
DARTSCOPE(Thread::Current());
API_TIMELINE_DURATION(T);
const Array& loading_units =
Array::Handle(Z, T->isolate_group()->object_store()->loading_unit_uris());
if (loading_unit_id >= 0 && loading_unit_id < loading_units.Length()) {
return Api::NewHandle(T, loading_units.At(loading_unit_id));
}
return Api::NewError("Invalid loading_unit_id");
#endif
}
#if (!defined(TARGET_ARCH_IA32) && !defined(DART_PRECOMPILED_RUNTIME))
// Any flag that affects how we compile code might cause a problem when the
// snapshot writer generates code with one value of the flag and the snapshot
// reader expects code to behave according to another value of the flag.
// Normally, we add these flags to Dart::FeaturesString and refuse to run the
// snapshot it they don't match, but since --interpret-irregexp affects only
// 2 functions we choose to remove the code instead. See issue #34422.
static void DropRegExpMatchCode(Zone* zone) {
const String& execute_match_name =
String::Handle(zone, String::New("_ExecuteMatch"));
const String& execute_match_sticky_name =
String::Handle(zone, String::New("_ExecuteMatchSticky"));
const Library& core_lib = Library::Handle(zone, Library::CoreLibrary());
const Class& reg_exp_class =
Class::Handle(zone, core_lib.LookupClassAllowPrivate(Symbols::_RegExp()));
ASSERT(!reg_exp_class.IsNull());
auto thread = Thread::Current();
Function& func = Function::Handle(
zone, reg_exp_class.LookupFunctionAllowPrivate(execute_match_name));
ASSERT(!func.IsNull());
Code& code = Code::Handle(zone);
SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
if (func.HasCode()) {
code = func.CurrentCode();
ASSERT(!code.IsNull());
code.DisableDartCode();
}
func.ClearCode();
func.ClearICDataArray();
ASSERT(!func.HasCode());
func = reg_exp_class.LookupFunctionAllowPrivate(execute_match_sticky_name);
ASSERT(!func.IsNull());
if (func.HasCode()) {
code = func.CurrentCode();
ASSERT(!code.IsNull());
code.DisableDartCode();
}
func.ClearCode();
func.ClearICDataArray();
ASSERT(!func.HasCode());
}
#endif // (!defined(TARGET_ARCH_IA32) && !defined(DART_PRECOMPILED_RUNTIME))
DART_EXPORT Dart_Handle Dart_CreateCoreJITSnapshotAsBlobs(
uint8_t** vm_snapshot_data_buffer,
intptr_t* vm_snapshot_data_size,
uint8_t** vm_snapshot_instructions_buffer,
intptr_t* vm_snapshot_instructions_size,
uint8_t** isolate_snapshot_data_buffer,
intptr_t* isolate_snapshot_data_size,
uint8_t** isolate_snapshot_instructions_buffer,
intptr_t* isolate_snapshot_instructions_size) {
#if defined(TARGET_ARCH_IA32)
return Api::NewError("Snapshots with code are not supported on IA32.");
#elif defined(DART_PRECOMPILED_RUNTIME)
return Api::NewError("JIT app snapshots cannot be taken from an AOT runtime");
#else
DARTSCOPE(Thread::Current());
API_TIMELINE_DURATION(T);
CHECK_NULL(vm_snapshot_data_buffer);
CHECK_NULL(vm_snapshot_data_size);
CHECK_NULL(vm_snapshot_instructions_buffer);
CHECK_NULL(vm_snapshot_instructions_size);
CHECK_NULL(isolate_snapshot_data_buffer);
CHECK_NULL(isolate_snapshot_data_size);
CHECK_NULL(isolate_snapshot_instructions_buffer);
CHECK_NULL(isolate_snapshot_instructions_size);
// Finalize all classes if needed.
Dart_Handle state = Api::CheckAndFinalizePendingClasses(T);
if (Api::IsError(state)) {
return state;
}
NoBackgroundCompilerScope no_bg_compiler(T);
DropRegExpMatchCode(Z);
ProgramVisitor::Dedup(T);
TIMELINE_DURATION(T, Isolate, "WriteCoreJITSnapshot");
[vm] Consolidate the *WriteStream hierarchy. All *WriteStream classes are now part of the same hierarchy: class BaseWriteStream : ValueObject; Base class for all *WriteStreams. Provides all the methods from the old WriteStream except for buffer() and SetPosition() (relegated to NonStreamingWriteStreams). Has one pure virtual method Realloc that must be overridden by concrete subclasses. class NonStreamingWriteStream : BaseWriteStream; Base class for all *WriteStreams where the entire stream is available at all times (i.e., no flushing to an external sink). Extends the public BaseWriteStream API with buffer() (for accessing the stream contents) and SetPosition() (for changing the current stream pointer to the given absolute position in the stream). class MallocWriteStream : NonStreamingWriteStream; Uses realloc to reallocate the internal buffer. Almost the same as the old WriteStream, except that it only takes an initial size. Adds one public method Steal() for taking ownership of the current buffer contents (after which the buffer is reset to an empty state). Instead of passing a pointer to a buffer, the internal buffer must be accessed via either Steal() or buffer(), which allows access to the current stream contents without changing ownership or resetting the stream. The internal buffer is freed on stream destruction. class ZoneWriteStream: NonStreamingWriteStream; Takes a zone and reallocates the internal buffer in that zone. No additional public methods beyond those available from NonStreamingWriteStream. class StreamingWriteStream : BaseWriteStream; Uses realloc to reallocate the internal buffer. Generally same as before, where the contents of the stream are periodically flushed using Dart_StreamingWriteCallback. Since it extends BaseWriteStream, there are now more methods available for writing data to the stream than just Print/VPrint/WriteBytes. Since portions of the stream may be flushed and thus no longer in the internal buffer, does not provide access to the contents of the stream or a way to reposition the current stream pointer. Flushes any unflushed data and frees the internal buffer on stream destruction. Also refactor things so that write streams are passed to appropriate recipients, instead of the recipients taking arguments they only used to create a WriteStream internally. Thus, recipients now can just specify the appropriate base class for the public API used: * BaseWriteStream for just writing to the stream, or * NonStreamingWriteStream if re-positioning or the stream contents are needed. Change-Id: I419096ecd9331483d168b079fca55b69ef397f15 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/164080 Commit-Queue: Tess Strickland <sstrickl@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com>
2020-09-23 21:05:59 +00:00
ZoneWriteStream vm_snapshot_data(Api::TopScope(T)->zone(),
FullSnapshotWriter::kInitialSize);
ZoneWriteStream vm_snapshot_instructions(Api::TopScope(T)->zone(),
FullSnapshotWriter::kInitialSize);
ZoneWriteStream isolate_snapshot_data(Api::TopScope(T)->zone(),
FullSnapshotWriter::kInitialSize);
ZoneWriteStream isolate_snapshot_instructions(
Api::TopScope(T)->zone(), FullSnapshotWriter::kInitialSize);
BlobImageWriter image_writer(T, &vm_snapshot_instructions,
&isolate_snapshot_instructions);
[vm] Consolidate the *WriteStream hierarchy. All *WriteStream classes are now part of the same hierarchy: class BaseWriteStream : ValueObject; Base class for all *WriteStreams. Provides all the methods from the old WriteStream except for buffer() and SetPosition() (relegated to NonStreamingWriteStreams). Has one pure virtual method Realloc that must be overridden by concrete subclasses. class NonStreamingWriteStream : BaseWriteStream; Base class for all *WriteStreams where the entire stream is available at all times (i.e., no flushing to an external sink). Extends the public BaseWriteStream API with buffer() (for accessing the stream contents) and SetPosition() (for changing the current stream pointer to the given absolute position in the stream). class MallocWriteStream : NonStreamingWriteStream; Uses realloc to reallocate the internal buffer. Almost the same as the old WriteStream, except that it only takes an initial size. Adds one public method Steal() for taking ownership of the current buffer contents (after which the buffer is reset to an empty state). Instead of passing a pointer to a buffer, the internal buffer must be accessed via either Steal() or buffer(), which allows access to the current stream contents without changing ownership or resetting the stream. The internal buffer is freed on stream destruction. class ZoneWriteStream: NonStreamingWriteStream; Takes a zone and reallocates the internal buffer in that zone. No additional public methods beyond those available from NonStreamingWriteStream. class StreamingWriteStream : BaseWriteStream; Uses realloc to reallocate the internal buffer. Generally same as before, where the contents of the stream are periodically flushed using Dart_StreamingWriteCallback. Since it extends BaseWriteStream, there are now more methods available for writing data to the stream than just Print/VPrint/WriteBytes. Since portions of the stream may be flushed and thus no longer in the internal buffer, does not provide access to the contents of the stream or a way to reposition the current stream pointer. Flushes any unflushed data and frees the internal buffer on stream destruction. Also refactor things so that write streams are passed to appropriate recipients, instead of the recipients taking arguments they only used to create a WriteStream internally. Thus, recipients now can just specify the appropriate base class for the public API used: * BaseWriteStream for just writing to the stream, or * NonStreamingWriteStream if re-positioning or the stream contents are needed. Change-Id: I419096ecd9331483d168b079fca55b69ef397f15 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/164080 Commit-Queue: Tess Strickland <sstrickl@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com>
2020-09-23 21:05:59 +00:00
FullSnapshotWriter writer(Snapshot::kFullJIT, &vm_snapshot_data,
&isolate_snapshot_data, &image_writer,
&image_writer);
writer.WriteFullSnapshot();
[vm] Consolidate the *WriteStream hierarchy. All *WriteStream classes are now part of the same hierarchy: class BaseWriteStream : ValueObject; Base class for all *WriteStreams. Provides all the methods from the old WriteStream except for buffer() and SetPosition() (relegated to NonStreamingWriteStreams). Has one pure virtual method Realloc that must be overridden by concrete subclasses. class NonStreamingWriteStream : BaseWriteStream; Base class for all *WriteStreams where the entire stream is available at all times (i.e., no flushing to an external sink). Extends the public BaseWriteStream API with buffer() (for accessing the stream contents) and SetPosition() (for changing the current stream pointer to the given absolute position in the stream). class MallocWriteStream : NonStreamingWriteStream; Uses realloc to reallocate the internal buffer. Almost the same as the old WriteStream, except that it only takes an initial size. Adds one public method Steal() for taking ownership of the current buffer contents (after which the buffer is reset to an empty state). Instead of passing a pointer to a buffer, the internal buffer must be accessed via either Steal() or buffer(), which allows access to the current stream contents without changing ownership or resetting the stream. The internal buffer is freed on stream destruction. class ZoneWriteStream: NonStreamingWriteStream; Takes a zone and reallocates the internal buffer in that zone. No additional public methods beyond those available from NonStreamingWriteStream. class StreamingWriteStream : BaseWriteStream; Uses realloc to reallocate the internal buffer. Generally same as before, where the contents of the stream are periodically flushed using Dart_StreamingWriteCallback. Since it extends BaseWriteStream, there are now more methods available for writing data to the stream than just Print/VPrint/WriteBytes. Since portions of the stream may be flushed and thus no longer in the internal buffer, does not provide access to the contents of the stream or a way to reposition the current stream pointer. Flushes any unflushed data and frees the internal buffer on stream destruction. Also refactor things so that write streams are passed to appropriate recipients, instead of the recipients taking arguments they only used to create a WriteStream internally. Thus, recipients now can just specify the appropriate base class for the public API used: * BaseWriteStream for just writing to the stream, or * NonStreamingWriteStream if re-positioning or the stream contents are needed. Change-Id: I419096ecd9331483d168b079fca55b69ef397f15 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/164080 Commit-Queue: Tess Strickland <sstrickl@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com>
2020-09-23 21:05:59 +00:00
*vm_snapshot_data_buffer = vm_snapshot_data.buffer();
*vm_snapshot_data_size = vm_snapshot_data.bytes_written();
*vm_snapshot_instructions_buffer = vm_snapshot_instructions.buffer();
*vm_snapshot_instructions_size = vm_snapshot_instructions.bytes_written();
*isolate_snapshot_data_buffer = isolate_snapshot_data.buffer();
*isolate_snapshot_data_size = isolate_snapshot_data.bytes_written();
*isolate_snapshot_instructions_buffer =
isolate_snapshot_instructions.buffer();
*isolate_snapshot_instructions_size =
[vm] Consolidate the *WriteStream hierarchy. All *WriteStream classes are now part of the same hierarchy: class BaseWriteStream : ValueObject; Base class for all *WriteStreams. Provides all the methods from the old WriteStream except for buffer() and SetPosition() (relegated to NonStreamingWriteStreams). Has one pure virtual method Realloc that must be overridden by concrete subclasses. class NonStreamingWriteStream : BaseWriteStream; Base class for all *WriteStreams where the entire stream is available at all times (i.e., no flushing to an external sink). Extends the public BaseWriteStream API with buffer() (for accessing the stream contents) and SetPosition() (for changing the current stream pointer to the given absolute position in the stream). class MallocWriteStream : NonStreamingWriteStream; Uses realloc to reallocate the internal buffer. Almost the same as the old WriteStream, except that it only takes an initial size. Adds one public method Steal() for taking ownership of the current buffer contents (after which the buffer is reset to an empty state). Instead of passing a pointer to a buffer, the internal buffer must be accessed via either Steal() or buffer(), which allows access to the current stream contents without changing ownership or resetting the stream. The internal buffer is freed on stream destruction. class ZoneWriteStream: NonStreamingWriteStream; Takes a zone and reallocates the internal buffer in that zone. No additional public methods beyond those available from NonStreamingWriteStream. class StreamingWriteStream : BaseWriteStream; Uses realloc to reallocate the internal buffer. Generally same as before, where the contents of the stream are periodically flushed using Dart_StreamingWriteCallback. Since it extends BaseWriteStream, there are now more methods available for writing data to the stream than just Print/VPrint/WriteBytes. Since portions of the stream may be flushed and thus no longer in the internal buffer, does not provide access to the contents of the stream or a way to reposition the current stream pointer. Flushes any unflushed data and frees the internal buffer on stream destruction. Also refactor things so that write streams are passed to appropriate recipients, instead of the recipients taking arguments they only used to create a WriteStream internally. Thus, recipients now can just specify the appropriate base class for the public API used: * BaseWriteStream for just writing to the stream, or * NonStreamingWriteStream if re-positioning or the stream contents are needed. Change-Id: I419096ecd9331483d168b079fca55b69ef397f15 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/164080 Commit-Queue: Tess Strickland <sstrickl@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com>
2020-09-23 21:05:59 +00:00
isolate_snapshot_instructions.bytes_written();
return Api::Success();
#endif
}
#if !defined(TARGET_ARCH_IA32) && !defined(DART_PRECOMPILED_RUNTIME)
static void KillNonMainIsolatesSlow(Thread* thread, Isolate* main_isolate) {
auto group = main_isolate->group();
while (true) {
bool non_main_isolates_alive = false;
{
[vm/concurrency] Distinguish "gc safepoint operations" from "deopt safepoint operations" This extends the existing safepoint operation mechanism by allowing to perform two different operations: * "gc safepoint operations": All mutators are stopped at places where it's safe to GC. It therefore requires stackmaps to be available for all optimized mutator frames. * "deopt safepoint operations": All mutators are stopped at places where it's safe to GC, but also safe to lazy-deopt mutator frames. It therefore requires deopt-id/deopt-info to be available for all optimized mutator frames. Mutators can be asked to block for any of those two safepoint operations. If a mutator is at a place where its safe to GC it will respond to "gc safepoint operations" requests, if a mutator is additionally at a place where it's also safe to lazy-deopt it will respond to "deopt safepoint operation" requests. Depending on how the runtime was entered (which is tracked via the [Thread::runtime_call_deopt_ability_] value) - the mutator might participate in both or only in gc safepoint operations. During the start of a "deopt safepoint operation", the safepoint handler will request all threads to stop at a "deopt safepoint". Some threads might first want to initiate their own "gc safepoint operation" (e.g. due to allocation failure) before they reach a "deopt safepoint". We do allow this by letting the safepoint handler own a "deopt safepoint operation" but still participate in other thread's "gc safepoint operation" requests until all mutators are checked into places where it's safe to lazy-deopt at which point the "deopt safepoint operation" also owns a "gc safepoint operation". In order to facilitate this, the Thread's safepoint_state will be extended to consist of the following bits: * AtSafepoint * SafepointRequested * AtDeoptSafepoint * DeoptSafepointRequested * BlockedForSafepoint Issue https://github.com/dart-lang/sdk/issues/45213 TEST=vm/cc/SafepointOperation_* Change-Id: Icdc2827718f6780818f99b829a5e806d6bb5b130 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/196927 Commit-Queue: Martin Kustermann <kustermann@google.com> Reviewed-by: Vyacheslav Egorov <vegorov@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com>
2021-05-10 09:13:09 +00:00
DeoptSafepointOperationScope safepoint(thread);
group->ForEachIsolate(
[&](Isolate* isolate) {
if (isolate != main_isolate) {
Isolate::KillIfExists(isolate, Isolate::kKillMsg);
non_main_isolates_alive = true;
}
},
/*at_safepoint=*/true);
if (!non_main_isolates_alive) {
break;
}
}
OS::SleepMicros(10 * 1000);
}
}
#endif // !defined(TARGET_ARCH_IA32) && !defined(DART_PRECOMPILED_RUNTIME)
DART_EXPORT Dart_Handle
Dart_CreateAppJITSnapshotAsBlobs(uint8_t** isolate_snapshot_data_buffer,
intptr_t* isolate_snapshot_data_size,
uint8_t** isolate_snapshot_instructions_buffer,
intptr_t* isolate_snapshot_instructions_size) {
#if defined(TARGET_ARCH_IA32)
return Api::NewError("Snapshots with code are not supported on IA32.");
#elif defined(DART_PRECOMPILED_RUNTIME)
return Api::NewError("JIT app snapshots cannot be taken from an AOT runtime");
#else
JIT precompilated snapshots. (Precompiled snapshots with unoptimized code.) + ./out/ReleaseX64/dart --package-root=./out/ReleaseX64/packages ./pkg/compiler/lib/src/dart2js.dart /usr/local/google/home/rmacnak/hello.dart Dart file (/usr/local/google/home/rmacnak/hello.dart) compiled to JavaScript: out.js real 0m3.299s user 0m3.197s sys 0m0.831s + ./out/ProductX64/dart_bootstrap --full-snapshot-after-run=/usr/local/google/home/rmacnak/dart3/sdk/app --package-root=./out/ReleaseX64/packages ./pkg/compiler/lib/src/dart2js.dart /usr/local/google/home/rmacnak/hello.dart Dart file (/usr/local/google/home/rmacnak/hello.dart) compiled to JavaScript: out.js + ./out/ProductX64/dart --run-full-snapshot=/usr/local/google/home/rmacnak/dart3/sdk/app --package-root=./out/ReleaseX64/packages ./pkg/compiler/lib/src/dart2js.dart /usr/local/google/home/rmacnak/hello.dart vm-service: Isolate creation error: (null) Dart file (/usr/local/google/home/rmacnak/hello.dart) compiled to JavaScript: out.js real 0m1.979s user 0m1.806s sys 0m0.581s + ./out/ReleaseX64/dart_bootstrap --use_blobs --gen-precompiled-jit-snapshot=/usr/local/google/home/rmacnak/dart3/sdk --package-root=./out/ReleaseX64/packages ./pkg/compiler/lib/src/dart2js.dart /usr/local/google/home/rmacnak/hello.dart Dart file (/usr/local/google/home/rmacnak/hello.dart) compiled to JavaScript: out.js VMIsolate(CodeSize): 2699304 Isolate(CodeSize): 5930097 Instructions(CodeSize): 9440176 Total(CodeSize): 18069577 + ./out/ReleaseX64/dart --use_blobs --run-precompiled-jit-snapshot=/usr/local/google/home/rmacnak/dart3/sdk --package-root=./out/ReleaseX64/packages ./pkg/compiler/lib/src/dart2js.dart /usr/local/google/home/rmacnak/hello.dart Dart file (/usr/local/google/home/rmacnak/hello.dart) compiled to JavaScript: out.js real 0m0.994s user 0m1.259s sys 0m0.229s R=asiva@google.com, fschneider@google.com Review URL: https://codereview.chromium.org/1938653002 .
2016-05-05 01:47:36 +00:00
DARTSCOPE(Thread::Current());
API_TIMELINE_DURATION(T);
auto I = T->isolate();
auto IG = T->isolate_group();
CHECK_NULL(isolate_snapshot_data_buffer);
CHECK_NULL(isolate_snapshot_data_size);
CHECK_NULL(isolate_snapshot_instructions_buffer);
CHECK_NULL(isolate_snapshot_instructions_size);
JIT precompilated snapshots. (Precompiled snapshots with unoptimized code.) + ./out/ReleaseX64/dart --package-root=./out/ReleaseX64/packages ./pkg/compiler/lib/src/dart2js.dart /usr/local/google/home/rmacnak/hello.dart Dart file (/usr/local/google/home/rmacnak/hello.dart) compiled to JavaScript: out.js real 0m3.299s user 0m3.197s sys 0m0.831s + ./out/ProductX64/dart_bootstrap --full-snapshot-after-run=/usr/local/google/home/rmacnak/dart3/sdk/app --package-root=./out/ReleaseX64/packages ./pkg/compiler/lib/src/dart2js.dart /usr/local/google/home/rmacnak/hello.dart Dart file (/usr/local/google/home/rmacnak/hello.dart) compiled to JavaScript: out.js + ./out/ProductX64/dart --run-full-snapshot=/usr/local/google/home/rmacnak/dart3/sdk/app --package-root=./out/ReleaseX64/packages ./pkg/compiler/lib/src/dart2js.dart /usr/local/google/home/rmacnak/hello.dart vm-service: Isolate creation error: (null) Dart file (/usr/local/google/home/rmacnak/hello.dart) compiled to JavaScript: out.js real 0m1.979s user 0m1.806s sys 0m0.581s + ./out/ReleaseX64/dart_bootstrap --use_blobs --gen-precompiled-jit-snapshot=/usr/local/google/home/rmacnak/dart3/sdk --package-root=./out/ReleaseX64/packages ./pkg/compiler/lib/src/dart2js.dart /usr/local/google/home/rmacnak/hello.dart Dart file (/usr/local/google/home/rmacnak/hello.dart) compiled to JavaScript: out.js VMIsolate(CodeSize): 2699304 Isolate(CodeSize): 5930097 Instructions(CodeSize): 9440176 Total(CodeSize): 18069577 + ./out/ReleaseX64/dart --use_blobs --run-precompiled-jit-snapshot=/usr/local/google/home/rmacnak/dart3/sdk --package-root=./out/ReleaseX64/packages ./pkg/compiler/lib/src/dart2js.dart /usr/local/google/home/rmacnak/hello.dart Dart file (/usr/local/google/home/rmacnak/hello.dart) compiled to JavaScript: out.js real 0m0.994s user 0m1.259s sys 0m0.229s R=asiva@google.com, fschneider@google.com Review URL: https://codereview.chromium.org/1938653002 .
2016-05-05 01:47:36 +00:00
// Finalize all classes if needed.
Dart_Handle state = Api::CheckAndFinalizePendingClasses(T);
if (Api::IsError(state)) {
JIT precompilated snapshots. (Precompiled snapshots with unoptimized code.) + ./out/ReleaseX64/dart --package-root=./out/ReleaseX64/packages ./pkg/compiler/lib/src/dart2js.dart /usr/local/google/home/rmacnak/hello.dart Dart file (/usr/local/google/home/rmacnak/hello.dart) compiled to JavaScript: out.js real 0m3.299s user 0m3.197s sys 0m0.831s + ./out/ProductX64/dart_bootstrap --full-snapshot-after-run=/usr/local/google/home/rmacnak/dart3/sdk/app --package-root=./out/ReleaseX64/packages ./pkg/compiler/lib/src/dart2js.dart /usr/local/google/home/rmacnak/hello.dart Dart file (/usr/local/google/home/rmacnak/hello.dart) compiled to JavaScript: out.js + ./out/ProductX64/dart --run-full-snapshot=/usr/local/google/home/rmacnak/dart3/sdk/app --package-root=./out/ReleaseX64/packages ./pkg/compiler/lib/src/dart2js.dart /usr/local/google/home/rmacnak/hello.dart vm-service: Isolate creation error: (null) Dart file (/usr/local/google/home/rmacnak/hello.dart) compiled to JavaScript: out.js real 0m1.979s user 0m1.806s sys 0m0.581s + ./out/ReleaseX64/dart_bootstrap --use_blobs --gen-precompiled-jit-snapshot=/usr/local/google/home/rmacnak/dart3/sdk --package-root=./out/ReleaseX64/packages ./pkg/compiler/lib/src/dart2js.dart /usr/local/google/home/rmacnak/hello.dart Dart file (/usr/local/google/home/rmacnak/hello.dart) compiled to JavaScript: out.js VMIsolate(CodeSize): 2699304 Isolate(CodeSize): 5930097 Instructions(CodeSize): 9440176 Total(CodeSize): 18069577 + ./out/ReleaseX64/dart --use_blobs --run-precompiled-jit-snapshot=/usr/local/google/home/rmacnak/dart3/sdk --package-root=./out/ReleaseX64/packages ./pkg/compiler/lib/src/dart2js.dart /usr/local/google/home/rmacnak/hello.dart Dart file (/usr/local/google/home/rmacnak/hello.dart) compiled to JavaScript: out.js real 0m0.994s user 0m1.259s sys 0m0.229s R=asiva@google.com, fschneider@google.com Review URL: https://codereview.chromium.org/1938653002 .
2016-05-05 01:47:36 +00:00
return state;
}
// Kill off any auxiliary isolates before starting with deduping.
KillNonMainIsolatesSlow(T, I);
NoBackgroundCompilerScope no_bg_compiler(T);
DropRegExpMatchCode(Z);
JIT precompilated snapshots. (Precompiled snapshots with unoptimized code.) + ./out/ReleaseX64/dart --package-root=./out/ReleaseX64/packages ./pkg/compiler/lib/src/dart2js.dart /usr/local/google/home/rmacnak/hello.dart Dart file (/usr/local/google/home/rmacnak/hello.dart) compiled to JavaScript: out.js real 0m3.299s user 0m3.197s sys 0m0.831s + ./out/ProductX64/dart_bootstrap --full-snapshot-after-run=/usr/local/google/home/rmacnak/dart3/sdk/app --package-root=./out/ReleaseX64/packages ./pkg/compiler/lib/src/dart2js.dart /usr/local/google/home/rmacnak/hello.dart Dart file (/usr/local/google/home/rmacnak/hello.dart) compiled to JavaScript: out.js + ./out/ProductX64/dart --run-full-snapshot=/usr/local/google/home/rmacnak/dart3/sdk/app --package-root=./out/ReleaseX64/packages ./pkg/compiler/lib/src/dart2js.dart /usr/local/google/home/rmacnak/hello.dart vm-service: Isolate creation error: (null) Dart file (/usr/local/google/home/rmacnak/hello.dart) compiled to JavaScript: out.js real 0m1.979s user 0m1.806s sys 0m0.581s + ./out/ReleaseX64/dart_bootstrap --use_blobs --gen-precompiled-jit-snapshot=/usr/local/google/home/rmacnak/dart3/sdk --package-root=./out/ReleaseX64/packages ./pkg/compiler/lib/src/dart2js.dart /usr/local/google/home/rmacnak/hello.dart Dart file (/usr/local/google/home/rmacnak/hello.dart) compiled to JavaScript: out.js VMIsolate(CodeSize): 2699304 Isolate(CodeSize): 5930097 Instructions(CodeSize): 9440176 Total(CodeSize): 18069577 + ./out/ReleaseX64/dart --use_blobs --run-precompiled-jit-snapshot=/usr/local/google/home/rmacnak/dart3/sdk --package-root=./out/ReleaseX64/packages ./pkg/compiler/lib/src/dart2js.dart /usr/local/google/home/rmacnak/hello.dart Dart file (/usr/local/google/home/rmacnak/hello.dart) compiled to JavaScript: out.js real 0m0.994s user 0m1.259s sys 0m0.229s R=asiva@google.com, fschneider@google.com Review URL: https://codereview.chromium.org/1938653002 .
2016-05-05 01:47:36 +00:00
ProgramVisitor::Dedup(T);
if (FLAG_dump_tables) {
Symbols::DumpTable(IG);
DumpTypeTable(I);
DumpTypeParameterTable(I);
DumpTypeArgumentsTable(I);
}
TIMELINE_DURATION(T, Isolate, "WriteAppJITSnapshot");
[vm] Consolidate the *WriteStream hierarchy. All *WriteStream classes are now part of the same hierarchy: class BaseWriteStream : ValueObject; Base class for all *WriteStreams. Provides all the methods from the old WriteStream except for buffer() and SetPosition() (relegated to NonStreamingWriteStreams). Has one pure virtual method Realloc that must be overridden by concrete subclasses. class NonStreamingWriteStream : BaseWriteStream; Base class for all *WriteStreams where the entire stream is available at all times (i.e., no flushing to an external sink). Extends the public BaseWriteStream API with buffer() (for accessing the stream contents) and SetPosition() (for changing the current stream pointer to the given absolute position in the stream). class MallocWriteStream : NonStreamingWriteStream; Uses realloc to reallocate the internal buffer. Almost the same as the old WriteStream, except that it only takes an initial size. Adds one public method Steal() for taking ownership of the current buffer contents (after which the buffer is reset to an empty state). Instead of passing a pointer to a buffer, the internal buffer must be accessed via either Steal() or buffer(), which allows access to the current stream contents without changing ownership or resetting the stream. The internal buffer is freed on stream destruction. class ZoneWriteStream: NonStreamingWriteStream; Takes a zone and reallocates the internal buffer in that zone. No additional public methods beyond those available from NonStreamingWriteStream. class StreamingWriteStream : BaseWriteStream; Uses realloc to reallocate the internal buffer. Generally same as before, where the contents of the stream are periodically flushed using Dart_StreamingWriteCallback. Since it extends BaseWriteStream, there are now more methods available for writing data to the stream than just Print/VPrint/WriteBytes. Since portions of the stream may be flushed and thus no longer in the internal buffer, does not provide access to the contents of the stream or a way to reposition the current stream pointer. Flushes any unflushed data and frees the internal buffer on stream destruction. Also refactor things so that write streams are passed to appropriate recipients, instead of the recipients taking arguments they only used to create a WriteStream internally. Thus, recipients now can just specify the appropriate base class for the public API used: * BaseWriteStream for just writing to the stream, or * NonStreamingWriteStream if re-positioning or the stream contents are needed. Change-Id: I419096ecd9331483d168b079fca55b69ef397f15 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/164080 Commit-Queue: Tess Strickland <sstrickl@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com>
2020-09-23 21:05:59 +00:00
ZoneWriteStream isolate_snapshot_data(Api::TopScope(T)->zone(),
FullSnapshotWriter::kInitialSize);
ZoneWriteStream isolate_snapshot_instructions(
Api::TopScope(T)->zone(), FullSnapshotWriter::kInitialSize);
BlobImageWriter image_writer(T, /*vm_instructions=*/nullptr,
&isolate_snapshot_instructions);
[vm] Consolidate the *WriteStream hierarchy. All *WriteStream classes are now part of the same hierarchy: class BaseWriteStream : ValueObject; Base class for all *WriteStreams. Provides all the methods from the old WriteStream except for buffer() and SetPosition() (relegated to NonStreamingWriteStreams). Has one pure virtual method Realloc that must be overridden by concrete subclasses. class NonStreamingWriteStream : BaseWriteStream; Base class for all *WriteStreams where the entire stream is available at all times (i.e., no flushing to an external sink). Extends the public BaseWriteStream API with buffer() (for accessing the stream contents) and SetPosition() (for changing the current stream pointer to the given absolute position in the stream). class MallocWriteStream : NonStreamingWriteStream; Uses realloc to reallocate the internal buffer. Almost the same as the old WriteStream, except that it only takes an initial size. Adds one public method Steal() for taking ownership of the current buffer contents (after which the buffer is reset to an empty state). Instead of passing a pointer to a buffer, the internal buffer must be accessed via either Steal() or buffer(), which allows access to the current stream contents without changing ownership or resetting the stream. The internal buffer is freed on stream destruction. class ZoneWriteStream: NonStreamingWriteStream; Takes a zone and reallocates the internal buffer in that zone. No additional public methods beyond those available from NonStreamingWriteStream. class StreamingWriteStream : BaseWriteStream; Uses realloc to reallocate the internal buffer. Generally same as before, where the contents of the stream are periodically flushed using Dart_StreamingWriteCallback. Since it extends BaseWriteStream, there are now more methods available for writing data to the stream than just Print/VPrint/WriteBytes. Since portions of the stream may be flushed and thus no longer in the internal buffer, does not provide access to the contents of the stream or a way to reposition the current stream pointer. Flushes any unflushed data and frees the internal buffer on stream destruction. Also refactor things so that write streams are passed to appropriate recipients, instead of the recipients taking arguments they only used to create a WriteStream internally. Thus, recipients now can just specify the appropriate base class for the public API used: * BaseWriteStream for just writing to the stream, or * NonStreamingWriteStream if re-positioning or the stream contents are needed. Change-Id: I419096ecd9331483d168b079fca55b69ef397f15 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/164080 Commit-Queue: Tess Strickland <sstrickl@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com>
2020-09-23 21:05:59 +00:00
FullSnapshotWriter writer(Snapshot::kFullJIT, nullptr, &isolate_snapshot_data,
nullptr, &image_writer);
JIT precompilated snapshots. (Precompiled snapshots with unoptimized code.) + ./out/ReleaseX64/dart --package-root=./out/ReleaseX64/packages ./pkg/compiler/lib/src/dart2js.dart /usr/local/google/home/rmacnak/hello.dart Dart file (/usr/local/google/home/rmacnak/hello.dart) compiled to JavaScript: out.js real 0m3.299s user 0m3.197s sys 0m0.831s + ./out/ProductX64/dart_bootstrap --full-snapshot-after-run=/usr/local/google/home/rmacnak/dart3/sdk/app --package-root=./out/ReleaseX64/packages ./pkg/compiler/lib/src/dart2js.dart /usr/local/google/home/rmacnak/hello.dart Dart file (/usr/local/google/home/rmacnak/hello.dart) compiled to JavaScript: out.js + ./out/ProductX64/dart --run-full-snapshot=/usr/local/google/home/rmacnak/dart3/sdk/app --package-root=./out/ReleaseX64/packages ./pkg/compiler/lib/src/dart2js.dart /usr/local/google/home/rmacnak/hello.dart vm-service: Isolate creation error: (null) Dart file (/usr/local/google/home/rmacnak/hello.dart) compiled to JavaScript: out.js real 0m1.979s user 0m1.806s sys 0m0.581s + ./out/ReleaseX64/dart_bootstrap --use_blobs --gen-precompiled-jit-snapshot=/usr/local/google/home/rmacnak/dart3/sdk --package-root=./out/ReleaseX64/packages ./pkg/compiler/lib/src/dart2js.dart /usr/local/google/home/rmacnak/hello.dart Dart file (/usr/local/google/home/rmacnak/hello.dart) compiled to JavaScript: out.js VMIsolate(CodeSize): 2699304 Isolate(CodeSize): 5930097 Instructions(CodeSize): 9440176 Total(CodeSize): 18069577 + ./out/ReleaseX64/dart --use_blobs --run-precompiled-jit-snapshot=/usr/local/google/home/rmacnak/dart3/sdk --package-root=./out/ReleaseX64/packages ./pkg/compiler/lib/src/dart2js.dart /usr/local/google/home/rmacnak/hello.dart Dart file (/usr/local/google/home/rmacnak/hello.dart) compiled to JavaScript: out.js real 0m0.994s user 0m1.259s sys 0m0.229s R=asiva@google.com, fschneider@google.com Review URL: https://codereview.chromium.org/1938653002 .
2016-05-05 01:47:36 +00:00
writer.WriteFullSnapshot();
[vm] Consolidate the *WriteStream hierarchy. All *WriteStream classes are now part of the same hierarchy: class BaseWriteStream : ValueObject; Base class for all *WriteStreams. Provides all the methods from the old WriteStream except for buffer() and SetPosition() (relegated to NonStreamingWriteStreams). Has one pure virtual method Realloc that must be overridden by concrete subclasses. class NonStreamingWriteStream : BaseWriteStream; Base class for all *WriteStreams where the entire stream is available at all times (i.e., no flushing to an external sink). Extends the public BaseWriteStream API with buffer() (for accessing the stream contents) and SetPosition() (for changing the current stream pointer to the given absolute position in the stream). class MallocWriteStream : NonStreamingWriteStream; Uses realloc to reallocate the internal buffer. Almost the same as the old WriteStream, except that it only takes an initial size. Adds one public method Steal() for taking ownership of the current buffer contents (after which the buffer is reset to an empty state). Instead of passing a pointer to a buffer, the internal buffer must be accessed via either Steal() or buffer(), which allows access to the current stream contents without changing ownership or resetting the stream. The internal buffer is freed on stream destruction. class ZoneWriteStream: NonStreamingWriteStream; Takes a zone and reallocates the internal buffer in that zone. No additional public methods beyond those available from NonStreamingWriteStream. class StreamingWriteStream : BaseWriteStream; Uses realloc to reallocate the internal buffer. Generally same as before, where the contents of the stream are periodically flushed using Dart_StreamingWriteCallback. Since it extends BaseWriteStream, there are now more methods available for writing data to the stream than just Print/VPrint/WriteBytes. Since portions of the stream may be flushed and thus no longer in the internal buffer, does not provide access to the contents of the stream or a way to reposition the current stream pointer. Flushes any unflushed data and frees the internal buffer on stream destruction. Also refactor things so that write streams are passed to appropriate recipients, instead of the recipients taking arguments they only used to create a WriteStream internally. Thus, recipients now can just specify the appropriate base class for the public API used: * BaseWriteStream for just writing to the stream, or * NonStreamingWriteStream if re-positioning or the stream contents are needed. Change-Id: I419096ecd9331483d168b079fca55b69ef397f15 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/164080 Commit-Queue: Tess Strickland <sstrickl@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com>
2020-09-23 21:05:59 +00:00
*isolate_snapshot_data_buffer = isolate_snapshot_data.buffer();
*isolate_snapshot_data_size = isolate_snapshot_data.bytes_written();
*isolate_snapshot_instructions_buffer =
isolate_snapshot_instructions.buffer();
*isolate_snapshot_instructions_size =
[vm] Consolidate the *WriteStream hierarchy. All *WriteStream classes are now part of the same hierarchy: class BaseWriteStream : ValueObject; Base class for all *WriteStreams. Provides all the methods from the old WriteStream except for buffer() and SetPosition() (relegated to NonStreamingWriteStreams). Has one pure virtual method Realloc that must be overridden by concrete subclasses. class NonStreamingWriteStream : BaseWriteStream; Base class for all *WriteStreams where the entire stream is available at all times (i.e., no flushing to an external sink). Extends the public BaseWriteStream API with buffer() (for accessing the stream contents) and SetPosition() (for changing the current stream pointer to the given absolute position in the stream). class MallocWriteStream : NonStreamingWriteStream; Uses realloc to reallocate the internal buffer. Almost the same as the old WriteStream, except that it only takes an initial size. Adds one public method Steal() for taking ownership of the current buffer contents (after which the buffer is reset to an empty state). Instead of passing a pointer to a buffer, the internal buffer must be accessed via either Steal() or buffer(), which allows access to the current stream contents without changing ownership or resetting the stream. The internal buffer is freed on stream destruction. class ZoneWriteStream: NonStreamingWriteStream; Takes a zone and reallocates the internal buffer in that zone. No additional public methods beyond those available from NonStreamingWriteStream. class StreamingWriteStream : BaseWriteStream; Uses realloc to reallocate the internal buffer. Generally same as before, where the contents of the stream are periodically flushed using Dart_StreamingWriteCallback. Since it extends BaseWriteStream, there are now more methods available for writing data to the stream than just Print/VPrint/WriteBytes. Since portions of the stream may be flushed and thus no longer in the internal buffer, does not provide access to the contents of the stream or a way to reposition the current stream pointer. Flushes any unflushed data and frees the internal buffer on stream destruction. Also refactor things so that write streams are passed to appropriate recipients, instead of the recipients taking arguments they only used to create a WriteStream internally. Thus, recipients now can just specify the appropriate base class for the public API used: * BaseWriteStream for just writing to the stream, or * NonStreamingWriteStream if re-positioning or the stream contents are needed. Change-Id: I419096ecd9331483d168b079fca55b69ef397f15 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/164080 Commit-Queue: Tess Strickland <sstrickl@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com>
2020-09-23 21:05:59 +00:00
isolate_snapshot_instructions.bytes_written();
JIT precompilated snapshots. (Precompiled snapshots with unoptimized code.) + ./out/ReleaseX64/dart --package-root=./out/ReleaseX64/packages ./pkg/compiler/lib/src/dart2js.dart /usr/local/google/home/rmacnak/hello.dart Dart file (/usr/local/google/home/rmacnak/hello.dart) compiled to JavaScript: out.js real 0m3.299s user 0m3.197s sys 0m0.831s + ./out/ProductX64/dart_bootstrap --full-snapshot-after-run=/usr/local/google/home/rmacnak/dart3/sdk/app --package-root=./out/ReleaseX64/packages ./pkg/compiler/lib/src/dart2js.dart /usr/local/google/home/rmacnak/hello.dart Dart file (/usr/local/google/home/rmacnak/hello.dart) compiled to JavaScript: out.js + ./out/ProductX64/dart --run-full-snapshot=/usr/local/google/home/rmacnak/dart3/sdk/app --package-root=./out/ReleaseX64/packages ./pkg/compiler/lib/src/dart2js.dart /usr/local/google/home/rmacnak/hello.dart vm-service: Isolate creation error: (null) Dart file (/usr/local/google/home/rmacnak/hello.dart) compiled to JavaScript: out.js real 0m1.979s user 0m1.806s sys 0m0.581s + ./out/ReleaseX64/dart_bootstrap --use_blobs --gen-precompiled-jit-snapshot=/usr/local/google/home/rmacnak/dart3/sdk --package-root=./out/ReleaseX64/packages ./pkg/compiler/lib/src/dart2js.dart /usr/local/google/home/rmacnak/hello.dart Dart file (/usr/local/google/home/rmacnak/hello.dart) compiled to JavaScript: out.js VMIsolate(CodeSize): 2699304 Isolate(CodeSize): 5930097 Instructions(CodeSize): 9440176 Total(CodeSize): 18069577 + ./out/ReleaseX64/dart --use_blobs --run-precompiled-jit-snapshot=/usr/local/google/home/rmacnak/dart3/sdk --package-root=./out/ReleaseX64/packages ./pkg/compiler/lib/src/dart2js.dart /usr/local/google/home/rmacnak/hello.dart Dart file (/usr/local/google/home/rmacnak/hello.dart) compiled to JavaScript: out.js real 0m0.994s user 0m1.259s sys 0m0.229s R=asiva@google.com, fschneider@google.com Review URL: https://codereview.chromium.org/1938653002 .
2016-05-05 01:47:36 +00:00
return Api::Success();
#endif
JIT precompilated snapshots. (Precompiled snapshots with unoptimized code.) + ./out/ReleaseX64/dart --package-root=./out/ReleaseX64/packages ./pkg/compiler/lib/src/dart2js.dart /usr/local/google/home/rmacnak/hello.dart Dart file (/usr/local/google/home/rmacnak/hello.dart) compiled to JavaScript: out.js real 0m3.299s user 0m3.197s sys 0m0.831s + ./out/ProductX64/dart_bootstrap --full-snapshot-after-run=/usr/local/google/home/rmacnak/dart3/sdk/app --package-root=./out/ReleaseX64/packages ./pkg/compiler/lib/src/dart2js.dart /usr/local/google/home/rmacnak/hello.dart Dart file (/usr/local/google/home/rmacnak/hello.dart) compiled to JavaScript: out.js + ./out/ProductX64/dart --run-full-snapshot=/usr/local/google/home/rmacnak/dart3/sdk/app --package-root=./out/ReleaseX64/packages ./pkg/compiler/lib/src/dart2js.dart /usr/local/google/home/rmacnak/hello.dart vm-service: Isolate creation error: (null) Dart file (/usr/local/google/home/rmacnak/hello.dart) compiled to JavaScript: out.js real 0m1.979s user 0m1.806s sys 0m0.581s + ./out/ReleaseX64/dart_bootstrap --use_blobs --gen-precompiled-jit-snapshot=/usr/local/google/home/rmacnak/dart3/sdk --package-root=./out/ReleaseX64/packages ./pkg/compiler/lib/src/dart2js.dart /usr/local/google/home/rmacnak/hello.dart Dart file (/usr/local/google/home/rmacnak/hello.dart) compiled to JavaScript: out.js VMIsolate(CodeSize): 2699304 Isolate(CodeSize): 5930097 Instructions(CodeSize): 9440176 Total(CodeSize): 18069577 + ./out/ReleaseX64/dart --use_blobs --run-precompiled-jit-snapshot=/usr/local/google/home/rmacnak/dart3/sdk --package-root=./out/ReleaseX64/packages ./pkg/compiler/lib/src/dart2js.dart /usr/local/google/home/rmacnak/hello.dart Dart file (/usr/local/google/home/rmacnak/hello.dart) compiled to JavaScript: out.js real 0m0.994s user 0m1.259s sys 0m0.229s R=asiva@google.com, fschneider@google.com Review URL: https://codereview.chromium.org/1938653002 .
2016-05-05 01:47:36 +00:00
}
DART_EXPORT Dart_Handle Dart_GetObfuscationMap(uint8_t** buffer,
intptr_t* buffer_length) {
#if defined(DART_PRECOMPILED_RUNTIME)
return Api::NewError("No obfuscation map to save on an AOT runtime.");
#elif !defined(DART_PRECOMPILER)
return Api::NewError("Obfuscation is only supported for AOT compiler.");
#else
Thread* thread = Thread::Current();
DARTSCOPE(thread);
auto isolate_group = thread->isolate_group();
if (buffer == NULL) {
RETURN_NULL_ERROR(buffer);
}
if (buffer_length == NULL) {
RETURN_NULL_ERROR(buffer_length);
}
// Note: can't use JSONStream in PRODUCT builds.
const intptr_t kInitialBufferSize = 1 * MB;
TextBuffer text_buffer(kInitialBufferSize);
text_buffer.AddChar('[');
if (isolate_group->obfuscation_map() != nullptr) {
for (intptr_t i = 0; isolate_group->obfuscation_map()[i] != nullptr; i++) {
if (i > 0) {
text_buffer.AddChar(',');
}
text_buffer.AddChar('"');
text_buffer.AddEscapedString(isolate_group->obfuscation_map()[i]);
text_buffer.AddChar('"');
}
}
text_buffer.AddChar(']');
*buffer_length = text_buffer.length();
*reinterpret_cast<char**>(buffer) = text_buffer.Steal();
return Api::Success();
#endif
}
DART_EXPORT bool Dart_IsPrecompiledRuntime() {
#if defined(DART_PRECOMPILED_RUNTIME)
return true;
#else
return false;
#endif
}
DART_EXPORT void Dart_DumpNativeStackTrace(void* context) {
#if !defined(PRODUCT) || defined(DART_PRECOMPILER)
Profiler::DumpStackTrace(context);
#endif
}
DART_EXPORT void Dart_PrepareToAbort() {
OS::PrepareToAbort();
}
DART_EXPORT Dart_Handle Dart_GetCurrentUserTag() {
Thread* thread = Thread::Current();
CHECK_ISOLATE(thread->isolate());
DARTSCOPE(thread);
Isolate* isolate = thread->isolate();
return Api::NewHandle(thread, isolate->current_tag());
}
DART_EXPORT Dart_Handle Dart_GetDefaultUserTag() {
Thread* thread = Thread::Current();
CHECK_ISOLATE(thread->isolate());
DARTSCOPE(thread);
Isolate* isolate = thread->isolate();
return Api::NewHandle(thread, isolate->default_tag());
}
DART_EXPORT Dart_Handle Dart_NewUserTag(const char* label) {
Thread* thread = Thread::Current();
CHECK_ISOLATE(thread->isolate());
DARTSCOPE(thread);
if (label == nullptr) {
return Api::NewError(
"Dart_NewUserTag expects argument 'label' to be non-null");
}
const String& value = String::Handle(String::New(label));
return Api::NewHandle(thread, UserTag::New(value));
}
DART_EXPORT Dart_Handle Dart_SetCurrentUserTag(Dart_Handle user_tag) {
Thread* thread = Thread::Current();
CHECK_ISOLATE(thread->isolate());
DARTSCOPE(thread);
const UserTag& tag = Api::UnwrapUserTagHandle(Z, user_tag);
if (tag.IsNull()) {
RETURN_TYPE_ERROR(Z, user_tag, UserTag);
}
return Api::NewHandle(thread, tag.MakeActive());
}
DART_EXPORT char* Dart_GetUserTagLabel(Dart_Handle user_tag) {
DARTSCOPE(Thread::Current());
const UserTag& tag = Api::UnwrapUserTagHandle(Z, user_tag);
if (tag.IsNull()) {
return nullptr;
}
const String& label = String::Handle(Z, tag.label());
return Utils::StrDup(label.ToCString());
}
} // namespace dart