dart-sdk/runtime/vm/dart_api_impl.cc

6541 lines
230 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"
#include "lib/stacktrace.h"
#include "platform/assert.h"
#include "vm/class_finalizer.h"
#include "vm/clustered_snapshot.h"
#include "vm/compilation_trace.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"
#if !defined(DART_PRECOMPILED_RUNTIME)
#include "vm/kernel_loader.h"
#endif
#include "vm/compiler/aot/precompiler.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/native_entry.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/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/unicode.h"
#include "vm/uri.h"
#include "vm/version.h"
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);
DECLARE_FLAG(bool, verify_handles);
#if defined(DART_NO_SNAPSHOT)
DEFINE_FLAG(bool,
check_function_fingerprints,
true,
"Check function fingerprints");
#endif // defined(DART_NO_SNAPSHOT).
DEFINE_FLAG(bool,
verify_acquired_data,
false,
"Verify correct API acquire/release of typed data.");
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;
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(RawObject* obj) {
if (obj->IsFunction()) {
funcHandle_ ^= obj;
classHandle_ ^= funcHandle_.Owner();
// Signature functions get created, but not canonicalized, when function
// types get instantiated during run time type tests.
if (funcHandle_.IsSignatureFunction()) {
return;
}
// Verify that the result type of a function is canonical or a
// TypeParameter.
typeHandle_ ^= funcHandle_.result_type();
ASSERT(typeHandle_.IsMalformed() || !typeHandle_.IsResolved() ||
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_.IsMalformed() || !typeHandle_.IsResolved() ||
typeHandle_.IsTypeParameter() || typeHandle_.IsCanonical());
}
}
}
private:
Class& classHandle_;
Function& funcHandle_;
AbstractType& typeHandle_;
};
#endif // #if defined(DEBUG).
static RawInstance* GetListInstance(Zone* zone, const Object& obj) {
if (obj.IsInstance()) {
const Library& core_lib = Library::Handle(zone, Library::CoreLibrary());
const Class& list_class =
Class::Handle(zone, core_lib.LookupClass(Symbols::List()));
ASSERT(!list_class.IsNull());
const Instance& instance = Instance::Cast(obj);
const Class& obj_class = Class::Handle(zone, obj.clazz());
Error& malformed_type_error = Error::Handle(zone);
if (obj_class.IsSubtypeOf(Object::null_type_arguments(), list_class,
Object::null_type_arguments(),
&malformed_type_error, NULL, Heap::kNew)) {
ASSERT(malformed_type_error.IsNull()); // Type is a raw List.
return instance.raw();
}
}
return Instance::null();
}
static RawInstance* GetMapInstance(Zone* zone, const Object& obj) {
if (obj.IsInstance()) {
const Library& core_lib = Library::Handle(zone, Library::CoreLibrary());
const Class& map_class =
Class::Handle(core_lib.LookupClass(Symbols::Map()));
ASSERT(!map_class.IsNull());
const Instance& instance = Instance::Cast(obj);
const Class& obj_class = Class::Handle(zone, obj.clazz());
Error& malformed_type_error = Error::Handle(zone);
if (obj_class.IsSubtypeOf(Object::null_type_arguments(), map_class,
Object::null_type_arguments(),
&malformed_type_error, NULL, Heap::kNew)) {
ASSERT(malformed_type_error.IsNull()); // Type is a raw Map.
return instance.raw();
}
}
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
Isolate* I = Thread::Current()->isolate();
const Class& error_class =
Class::Handle(zone, I->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 (RawObject::IsStringClassId(obj.GetClassId())) {
ASSERT(thread->api_top_scope() != NULL);
*str = Api::NewHandle(thread, obj.raw());
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
}
Heap::Space SpaceForExternal(Thread* thread, intptr_t size) {
Heap* heap = thread->heap();
// If 'size' would be a significant fraction of new space, then use old.
static const int kExtNewRatio = 16;
if (size > (heap->CapacityInWords(Heap::kNew) * kWordSize) / kExtNewRatio) {
return Heap::kOld;
} else {
return Heap::kNew;
}
}
static RawObject* Send0Arg(const Instance& receiver, const String& selector) {
const intptr_t kTypeArgsLen = 0;
const intptr_t kNumArgs = 1;
ArgumentsDescriptor args_desc(
Array::Handle(ArgumentsDescriptor::New(kTypeArgsLen, kNumArgs)));
const Function& function =
Function::Handle(Resolver::ResolveDynamic(receiver, selector, args_desc));
if (function.IsNull()) {
return ApiError::New(String::Handle(String::New("")));
}
const Array& args = Array::Handle(Array::New(kNumArgs));
args.SetAt(0, receiver);
return DartEntry::InvokeFunction(function, args);
}
static RawObject* Send1Arg(const Instance& receiver,
const String& selector,
const Instance& argument) {
const intptr_t kTypeArgsLen = 0;
const intptr_t kNumArgs = 2;
ArgumentsDescriptor args_desc(
Array::Handle(ArgumentsDescriptor::New(kTypeArgsLen, kNumArgs)));
const Function& function =
Function::Handle(Resolver::ResolveDynamic(receiver, selector, args_desc));
if (function.IsNull()) {
return ApiError::New(String::Handle(String::New("")));
}
const Array& args = Array::Handle(Array::New(kNumArgs));
args.SetAt(0, receiver);
args.SetAt(1, argument);
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, RawObject* raw) {
LocalHandles* local_handles = Api::TopScope(thread)->local_handles();
ASSERT(local_handles != NULL);
LocalHandle* ref = local_handles->AllocateHandle();
ref->set_raw(raw);
return ref->apiHandle();
}
Dart_Handle Api::NewHandle(Thread* thread, RawObject* raw) {
if (raw == Object::null()) {
return Null();
}
if (raw == Bool::True().raw()) {
return True();
}
if (raw == Bool::False().raw()) {
return False();
}
ASSERT(thread->execution_state() == Thread::kThreadInVM);
return InitNewHandle(thread, raw);
}
RawObject* Api::UnwrapHandle(Dart_Handle object) {
#if defined(DEBUG)
Thread* thread = Thread::Current();
ASSERT(thread->IsMutatorThread());
ASSERT(thread->isolate() != NULL);
ASSERT(!FLAG_verify_handles || thread->IsValidLocalHandle(object) ||
thread->isolate()->api_state()->IsActivePersistentHandle(
reinterpret_cast<Dart_PersistentHandle>(object)) ||
Dart::IsReadOnlyApiHandle(object));
ASSERT(FinalizablePersistentHandle::raw_offset() == 0 &&
PersistentHandle::raw_offset() == 0 && LocalHandle::raw_offset() == 0);
#endif
return (reinterpret_cast<LocalHandle*>(object))->raw();
}
#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_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);
intptr_t len = Utils::VSNPrint(NULL, 0, format, args);
va_end(args);
char* buffer = Z->Alloc<char>(len + 1);
va_list args2;
va_start(args2, format);
Utils::VSNPrint(buffer, (len + 1), format, args2);
va_end(args2);
const String& message = String::Handle(Z, String::New(buffer));
return Api::NewHandle(T, ApiError::New(message));
}
void Api::SetupAcquiredError(Isolate* isolate) {
ASSERT(isolate != NULL);
ApiState* state = isolate->api_state();
ASSERT(state != NULL);
state->SetupAcquiredError();
}
Dart_Handle Api::AcquiredError(Isolate* isolate) {
ASSERT(isolate != NULL);
ApiState* state = isolate->api_state();
ASSERT(state != NULL);
PersistentHandle* acquired_error_handle = state->AcquiredError();
return reinterpret_cast<Dart_Handle>(acquired_error_handle);
}
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->api_state()->IsActivePersistentHandle(
reinterpret_cast<Dart_PersistentHandle>(handle)) ||
isolate->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(RawObject* raw) {
ASSERT(raw->IsVMHeapObject());
LocalHandle* ref = Dart::AllocateReadOnlyApiHandle();
ref->set_raw(raw);
return ref->apiHandle();
}
void Api::InitHandles() {
Isolate* isolate = Isolate::Current();
ASSERT(isolate != NULL);
ASSERT(isolate == Dart::vm_isolate());
ApiState* state = isolate->api_state();
ASSERT(state != NULL);
ASSERT(true_handle_ == NULL);
true_handle_ = InitNewReadOnlyApiHandle(Bool::True().raw());
ASSERT(false_handle_ == NULL);
false_handle_ = InitNewReadOnlyApiHandle(Bool::False().raw());
ASSERT(null_handle_ == NULL);
null_handle_ = InitNewReadOnlyApiHandle(Object::null());
ASSERT(empty_string_handle_ == NULL);
empty_string_handle_ = InitNewReadOnlyApiHandle(Symbols::Empty().raw());
}
void Api::Cleanup() {
true_handle_ = NULL;
false_handle_ = NULL;
null_handle_ = NULL;
empty_string_handle_ = NULL;
}
bool Api::StringGetPeerHelper(NativeArguments* arguments,
int arg_index,
void** peer) {
NoSafepointScope no_safepoint_scope;
RawObject* raw_obj = arguments->NativeArgAt(arg_index);
if (!raw_obj->IsHeapObject()) {
return false;
}
intptr_t cid = raw_obj->GetClassId();
if (cid == kExternalOneByteStringCid) {
RawExternalOneByteString* raw_string =
reinterpret_cast<RawExternalOneByteString*>(raw_obj);
*peer = raw_string->ptr()->peer_;
return true;
}
if (cid == kOneByteStringCid || cid == kTwoByteStringCid) {
Isolate* isolate = arguments->thread()->isolate();
*peer = isolate->heap()->GetPeer(raw_obj);
return (*peer != 0);
}
if (cid == kExternalTwoByteStringCid) {
RawExternalTwoByteString* raw_string =
reinterpret_cast<RawExternalTwoByteString*>(raw_obj);
*peer = raw_string->ptr()->peer_;
return true;
}
return false;
}
bool Api::GetNativeReceiver(NativeArguments* arguments, intptr_t* value) {
NoSafepointScope no_safepoint_scope;
RawObject* 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));
RawTypedData* native_fields = *reinterpret_cast<RawTypedData**>(
RawObject::ToAddr(raw_obj) + sizeof(RawObject));
if (native_fields == TypedData::null()) {
*value = 0;
} else {
*value = *bit_cast<intptr_t*, uint8_t*>(native_fields->ptr()->data());
}
return true;
}
}
return false;
}
bool Api::GetNativeBooleanArgument(NativeArguments* arguments,
int arg_index,
bool* value) {
NoSafepointScope no_safepoint_scope;
RawObject* 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().raw());
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;
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
RawObject* raw_obj = arguments->NativeArgAt(arg_index);
if (raw_obj->IsHeapObject()) {
intptr_t cid = raw_obj->GetClassId();
if (cid == kMintCid) {
*value = reinterpret_cast<RawMint*>(raw_obj)->ptr()->value_;
return true;
}
return false;
}
*value = Smi::Value(reinterpret_cast<RawSmi*>(raw_obj));
return true;
}
bool Api::GetNativeDoubleArgument(NativeArguments* arguments,
int arg_index,
double* value) {
NoSafepointScope no_safepoint_scope;
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
RawObject* raw_obj = arguments->NativeArgAt(arg_index);
if (raw_obj->IsHeapObject()) {
intptr_t cid = raw_obj->GetClassId();
if (cid == kDoubleCid) {
*value = reinterpret_cast<RawDouble*>(raw_obj)->ptr()->value_;
return true;
}
if (cid == kMintCid) {
*value = static_cast<double>(
reinterpret_cast<RawMint*>(raw_obj)->ptr()->value_);
return true;
}
return false;
}
*value = static_cast<double>(Smi::Value(reinterpret_cast<RawSmi*>(raw_obj)));
return true;
}
bool Api::GetNativeFieldsOfArgument(NativeArguments* arguments,
int arg_index,
int num_fields,
intptr_t* field_values) {
NoSafepointScope no_safepoint_scope;
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
RawObject* raw_obj = arguments->NativeArgAt(arg_index);
if (raw_obj->IsHeapObject()) {
intptr_t cid = raw_obj->GetClassId();
if (cid >= kNumPredefinedCids) {
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
RawTypedData* native_fields = *reinterpret_cast<RawTypedData**>(
RawObject::ToAddr(raw_obj) + sizeof(RawObject));
if (native_fields == TypedData::null()) {
memset(field_values, 0, (num_fields * sizeof(field_values[0])));
} else if (num_fields == Smi::Value(native_fields->ptr()->length_)) {
intptr_t* native_values =
bit_cast<intptr_t*, uint8_t*>(native_fields->ptr()->data());
memmove(field_values, native_values,
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
(num_fields * sizeof(field_values[0])));
}
return true;
}
}
return false;
}
void Api::SetWeakHandleReturnValue(NativeArguments* args,
Dart_WeakPersistentHandle retval) {
args->SetReturnUnsafe(FinalizablePersistentHandle::Cast(retval)->raw());
}
PersistentHandle* PersistentHandle::Cast(Dart_PersistentHandle handle) {
ASSERT(Isolate::Current()->api_state()->IsValidPersistentHandle(handle));
return reinterpret_cast<PersistentHandle*>(handle);
}
FinalizablePersistentHandle* FinalizablePersistentHandle::Cast(
Dart_WeakPersistentHandle handle) {
#if defined(DEBUG)
ApiState* state = Isolate::Current()->api_state();
ASSERT(state->IsValidWeakPersistentHandle(handle));
#endif
return reinterpret_cast<FinalizablePersistentHandle*>(handle);
}
void FinalizablePersistentHandle::Finalize(
Isolate* isolate,
FinalizablePersistentHandle* handle) {
if (!handle->raw()->IsHeapObject()) {
return; // Free handle.
}
Dart_WeakPersistentHandleFinalizer callback = handle->callback();
ASSERT(callback != NULL);
void* peer = handle->peer();
Dart_WeakPersistentHandle object = handle->apiHandle();
(*callback)(isolate->init_callback_data(), object, peer);
ApiState* state = isolate->api_state();
ASSERT(state != NULL);
state->weak_persistent_handles().FreeHandle(handle);
}
// --- Handles ---
DART_EXPORT bool Dart_IsError(Dart_Handle handle) {
return Api::IsError(handle);
}
DART_EXPORT bool Dart_IsApiError(Dart_Handle object) {
return Api::ClassId(object) == kApiErrorCid;
}
DART_EXPORT bool Dart_IsUnhandledExceptionError(Dart_Handle object) {
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);
}
return Api::ClassId(object) == kLanguageErrorCid;
}
DART_EXPORT bool Dart_IsFatalError(Dart_Handle object) {
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).raw();
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 Dart_Handle Dart_PropagateError(Dart_Handle handle) {
Thread* thread = Thread::Current();
TransitionNativeToVM transition(thread);
const Object& obj = Object::Handle(thread->zone(), Api::UnwrapHandle(handle));
if (!obj.IsError()) {
return Api::NewError(
"%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.
return Api::NewError("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;
RawError* raw_error = Api::UnwrapErrorHandle(thread->zone(), handle).raw();
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();
return Api::NewError("Cannot reach here. Internal error.");
}
DART_EXPORT void _Dart_ReportErrorHandle(const char* file,
int line,
const char* handle,
const char* message) {
fprintf(stderr, "%s:%d: error handle: '%s':\n '%s'\n", file, line, handle,
message);
OS::Abort();
}
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.raw());
} 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->api_state();
ASSERT(state != NULL);
TransitionNativeToVM transition(thread);
NoSafepointScope no_safepoint_scope;
PersistentHandle* ref = PersistentHandle::Cast(object);
return Api::NewHandle(thread, ref->raw());
}
DART_EXPORT Dart_Handle
Dart_HandleFromWeakPersistent(Dart_WeakPersistentHandle object) {
Thread* thread = Thread::Current();
Isolate* isolate = thread->isolate();
CHECK_ISOLATE(isolate);
ApiState* state = isolate->api_state();
ASSERT(state != NULL);
TransitionNativeToVM transition(thread);
NoSafepointScope no_safepoint_scope;
FinalizablePersistentHandle* weak_ref =
FinalizablePersistentHandle::Cast(object);
return Api::NewHandle(thread, weak_ref->raw());
}
DART_EXPORT Dart_PersistentHandle Dart_NewPersistentHandle(Dart_Handle object) {
DARTSCOPE(Thread::Current());
Isolate* I = T->isolate();
ApiState* state = I->api_state();
ASSERT(state != NULL);
const Object& old_ref = Object::Handle(Z, Api::UnwrapHandle(object));
PersistentHandle* new_ref = state->persistent_handles().AllocateHandle();
new_ref->set_raw(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->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_raw(obj2_ref);
}
static Dart_WeakPersistentHandle AllocateFinalizableHandle(
Thread* thread,
const Object& ref,
void* peer,
intptr_t external_allocation_size,
Dart_WeakPersistentHandleFinalizer callback) {
if (!ref.raw()->IsHeapObject()) {
return NULL;
}
FinalizablePersistentHandle* finalizable_ref =
FinalizablePersistentHandle::New(thread->isolate(), ref, peer, callback,
external_allocation_size);
return finalizable_ref->apiHandle();
}
static Dart_WeakPersistentHandle AllocateFinalizableHandle(
Thread* thread,
Dart_Handle object,
void* peer,
intptr_t external_allocation_size,
Dart_WeakPersistentHandleFinalizer callback) {
REUSABLE_OBJECT_HANDLESCOPE(thread);
Object& ref = thread->ObjectHandle();
ref = Api::UnwrapHandle(object);
return AllocateFinalizableHandle(thread, ref, peer, external_allocation_size,
callback);
}
DART_EXPORT Dart_WeakPersistentHandle
Dart_NewWeakPersistentHandle(Dart_Handle object,
void* peer,
intptr_t external_allocation_size,
Dart_WeakPersistentHandleFinalizer callback) {
Thread* thread = Thread::Current();
CHECK_ISOLATE(thread->isolate());
if (callback == NULL) {
return NULL;
}
TransitionNativeToVM transition(thread);
return AllocateFinalizableHandle(thread, object, peer,
external_allocation_size, callback);
}
DART_EXPORT void Dart_DeletePersistentHandle(Dart_PersistentHandle object) {
Isolate* isolate = Isolate::Current();
CHECK_ISOLATE(isolate);
NoSafepointScope no_safepoint_scope;
ApiState* state = isolate->api_state();
ASSERT(state != NULL);
PersistentHandle* ref = PersistentHandle::Cast(object);
ASSERT(!state->IsProtectedHandle(ref));
if (!state->IsProtectedHandle(ref)) {
state->persistent_handles().FreeHandle(ref);
}
}
DART_EXPORT void Dart_DeleteWeakPersistentHandle(
Dart_Isolate current_isolate,
Dart_WeakPersistentHandle object) {
Isolate* isolate = reinterpret_cast<Isolate*>(current_isolate);
CHECK_ISOLATE(isolate);
NoSafepointScope no_safepoint_scope;
ASSERT(isolate == Isolate::Current());
ApiState* state = isolate->api_state();
ASSERT(state != NULL);
FinalizablePersistentHandle* weak_ref =
FinalizablePersistentHandle::Cast(object);
weak_ref->EnsureFreeExternal(isolate);
state->weak_persistent_handles().FreeHandle(weak_ref);
}
// --- Initialization and Globals ---
DART_EXPORT const char* Dart_VersionString() {
return Version::String();
}
DART_EXPORT char* Dart_Initialize(Dart_InitializeParams* params) {
if (params == NULL) {
return strdup(
"Dart_Initialize: "
"Dart_InitializeParams is null.");
}
if (params->version != DART_INITIALIZE_PARAMS_CURRENT_VERSION) {
return strdup(
"Dart_Initialize: "
"Invalid Dart_InitializeParams version.");
}
return Dart::Init(params->vm_snapshot_data, params->vm_snapshot_instructions,
params->create, params->shutdown, params->cleanup,
params->thread_exit, params->file_open, params->file_read,
params->file_write, params->file_close,
params->entropy_source, params->get_service_assets,
params->start_kernel_isolate);
}
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
#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 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
#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);
#endif // !defined(PRODUCT)
// --- Isolates ---
static char* BuildIsolateName(const char* script_uri, const char* main) {
if (script_uri == NULL) {
// Just use the main as the name.
if (main == NULL) {
return strdup("isolate");
} else {
return strdup(main);
}
}
if (ServiceIsolate::NameEquals(script_uri) ||
(strcmp(script_uri, DART_KERNEL_ISOLATE_NAME) == 0)) {
return strdup(script_uri);
}
// Skip past any slashes and backslashes in the script uri.
const char* last_slash = strrchr(script_uri, '/');
if (last_slash != NULL) {
script_uri = last_slash + 1;
}
const char* last_backslash = strrchr(script_uri, '\\');
if (last_backslash != NULL) {
script_uri = last_backslash + 1;
}
if (main == NULL) {
main = "main";
}
char* chars = NULL;
intptr_t len = Utils::SNPrint(NULL, 0, "%s:%s()", script_uri, main) + 1;
chars = reinterpret_cast<char*>(malloc(len));
Utils::SNPrint(chars, len, "%s:%s()", script_uri, main);
return chars;
}
static Dart_Isolate CreateIsolate(const char* script_uri,
const char* main,
const uint8_t* snapshot_data,
const uint8_t* snapshot_instructions,
const uint8_t* shared_data,
const uint8_t* shared_instructions,
const uint8_t* kernel_buffer,
intptr_t kernel_buffer_size,
Dart_IsolateFlags* flags,
void* callback_data,
char** error) {
CHECK_NO_ISOLATE(Isolate::Current());
char* isolate_name = BuildIsolateName(script_uri, main);
// Setup default flags in case none were passed.
Dart_IsolateFlags api_flags;
if (flags == NULL) {
Isolate::FlagsInitialize(&api_flags);
flags = &api_flags;
}
Isolate* I = Dart::CreateIsolate(isolate_name, *flags);
free(isolate_name);
if (I == NULL) {
if (error != NULL) {
*error = strdup("Isolate creation failed");
}
return reinterpret_cast<Dart_Isolate>(NULL);
}
{
Thread* T = Thread::Current();
StackZone zone(T);
HANDLESCOPE(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(snapshot_data, snapshot_instructions,
shared_data, shared_instructions, kernel_buffer,
kernel_buffer_size, callback_data));
if (error_obj.IsNull()) {
#if defined(DART_NO_SNAPSHOT) && !defined(PRODUCT)
if (FLAG_check_function_fingerprints && kernel_buffer == NULL) {
Library::CheckFunctionFingerprints();
}
#endif // defined(DART_NO_SNAPSHOT) && !defined(PRODUCT).
// We exit the API scope entered above.
T->ExitApiScope();
// 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);
}
if (error != NULL) {
*error = strdup(error_obj.ToErrorCString());
}
// We exit the API scope entered above.
T->ExitApiScope();
}
Dart::ShutdownIsolate();
return reinterpret_cast<Dart_Isolate>(NULL);
}
DART_EXPORT void Dart_IsolateFlagsInitialize(Dart_IsolateFlags* flags) {
Isolate::FlagsInitialize(flags);
}
DART_EXPORT Dart_Isolate
Dart_CreateIsolate(const char* script_uri,
const char* main,
const uint8_t* snapshot_data,
const uint8_t* snapshot_instructions,
const uint8_t* shared_data,
const uint8_t* shared_instructions,
Dart_IsolateFlags* flags,
void* callback_data,
char** error) {
API_TIMELINE_DURATION(Thread::Current());
return CreateIsolate(script_uri, main, snapshot_data, snapshot_instructions,
shared_data, shared_instructions, NULL, 0, flags,
callback_data, error);
}
DART_EXPORT Dart_Isolate
Dart_CreateIsolateFromKernel(const char* script_uri,
const char* main,
const uint8_t* kernel_buffer,
intptr_t kernel_buffer_size,
Dart_IsolateFlags* flags,
void* callback_data,
char** error) {
API_TIMELINE_DURATION(Thread::Current());
return CreateIsolate(script_uri, main, NULL, NULL, NULL, NULL, kernel_buffer,
kernel_buffer_size, flags, callback_data, error);
}
DART_EXPORT void Dart_ShutdownIsolate() {
Thread* T = Thread::Current();
Isolate* 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
// Dart_EnterIsolate/Dart_CreateIsolate.
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);
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);
}
// TODO(16615): Validate isolate parameter.
Isolate* iso = reinterpret_cast<Isolate*>(isolate);
return iso->init_callback_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 void Dart_EnterIsolate(Dart_Isolate isolate) {
CHECK_NO_ISOLATE(Isolate::Current());
// TODO(16615): Validate isolate parameter.
Isolate* iso = reinterpret_cast<Isolate*>(isolate);
if (!Thread::EnterIsolate(iso)) {
FATAL(
"Unable to Enter Isolate : "
"Multiple mutators entering an isolate / "
"Dart VM is shutting down");
}
// 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_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 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
}
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;
if ((isolate->sticky_error() != Error::null()) && !::Dart_IsNull(error)) {
FATAL1("%s expects there to be no sticky error.", CURRENT_FUNC);
}
if (!::Dart_IsUnhandledExceptionError(error) && !::Dart_IsNull(error)) {
FATAL1("%s expects the error to be an unhandled exception error or null.",
CURRENT_FUNC);
}
isolate->SetStickyError(Api::UnwrapErrorHandle(Z, error).raw());
}
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()) {
TransitionNativeToVM transition(T);
Dart_Handle error = Api::NewHandle(T, I->sticky_error());
return error;
}
return Dart_Null();
}
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()->NotifyIdle(deadline);
}
DART_EXPORT void Dart_NotifyLowMemory() {
API_TIMELINE_BEGIN_END(Thread::Current());
Isolate::NotifyLowMemory();
}
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
// Dart_EnterIsolate/Dart_CreateIsolate.
ASSERT(T->execution_state() == Thread::kThreadInNative);
T->ExitSafepoint();
T->set_execution_state(Thread::kThreadInVM);
Thread::ExitIsolate();
}
static uint8_t* ApiReallocate(uint8_t* ptr,
intptr_t old_size,
intptr_t new_size) {
return Api::TopScope(Thread::Current())
->zone()
->Realloc<uint8_t>(ptr, old_size, new_size);
}
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) {
DARTSCOPE(Thread::Current());
API_TIMELINE_DURATION(T);
Isolate* I = T->isolate();
if (!FLAG_load_deferred_eagerly) {
return Api::NewError(
"Creating full snapshots requires --load_deferred_eagerly");
}
if (vm_snapshot_data_buffer != NULL && vm_snapshot_data_size == NULL) {
RETURN_NULL_ERROR(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 (::Dart_IsError(state)) {
return state;
}
BackgroundCompiler::Stop(I);
#if defined(DEBUG)
I->heap()->CollectAllGarbage();
{
HeapIterationScope iteration(T);
CheckFunctionTypesVisitor check_canonical(T);
iteration.IterateObjects(&check_canonical);
}
#endif // #if defined(DEBUG)
Symbols::Compact(I);
FullSnapshotWriter writer(Snapshot::kFull, vm_snapshot_data_buffer,
isolate_snapshot_data_buffer, ApiReallocate,
NULL /* vm_image_writer */,
NULL /* isolate_image_writer */);
writer.WriteFullSnapshot();
if (vm_snapshot_data_buffer != NULL) {
*vm_snapshot_data_size = writer.VmIsolateSnapshotSize();
}
*isolate_snapshot_data_size = writer.IsolateSnapshotSize();
return Api::Success();
}
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.
Isolate* iso = reinterpret_cast<Isolate*>(isolate);
const char* error;
if (iso->object_store()->root_library() == Library::null()) {
// The embedder should have called Dart_LoadScript by now.
error = "Missing root library";
} else {
error = iso->MakeRunnable();
}
if (error != NULL) {
return strdup(error);
}
return NULL;
}
// --- 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);
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;
{
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;
I->message_handler()->Run(Dart::thread_pool(), NULL, RunLoopDone,
reinterpret_cast<uword>(&data));
while (!data.done) {
ml.Wait();
}
}
::Dart_EnterIsolate(Api::CastIsolate(I));
if (I->sticky_error() != Object::null()) {
Thread* T = Thread::Current();
TransitionNativeToVM transition(T);
Dart_Handle error = Api::NewHandle(T, I->sticky_error());
I->clear_sticky_error();
return error;
}
if (FLAG_print_class_table) {
HANDLESCOPE(Thread::Current());
I->class_table()->Print();
}
return Api::Success();
}
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_BASIC(T);
TransitionNativeToVM transition(T);
if (I->message_handler()->HandleNextMessage() != MessageHandler::kOK) {
Dart_Handle error = Api::NewHandle(T, T->sticky_error());
T->clear_sticky_error();
return error;
}
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_BASIC(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.raw());
}
// 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;
RawError* raw_error = Error::Cast(result).raw();
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;
RawError* raw_error = T->get_and_clear_sticky_error();
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;
}
// Smis and null can be sent without serialization.
RawObject* raw_obj = Api::UnwrapHandle(handle);
if (ApiObjectConverter::CanConvert(raw_obj)) {
return PortMap::PostMessage(
new Message(port_id, raw_obj, Message::kNormalPriority));
}
const Object& object = Object::Handle(Z, raw_obj);
MessageWriter writer(false);
return PortMap::PostMessage(
writer.WriteMessage(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 Dart_Handle Dart_EmptyString() {
ASSERT(Isolate::Current() != NULL);
return Api::EmptyString();
}
DART_EXPORT bool Dart_IsNull(Dart_Handle object) {
return Api::UnwrapHandle(object) == Object::null();
}
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.raw());
} else {
return Api::NewError("Expected boolean result from ==");
}
}
// TODO(iposva): This call actually implements IsInstanceOfClass.
// Do we also need a real Dart_IsInstanceOf, which should take an instance
// rather than an object?
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);
}
CHECK_CALLBACK_STATE(T);
Error& malformed_type_error = Error::Handle(Z);
*value = instance.IsInstanceOf(type_obj, Object::null_type_arguments(),
Object::null_type_arguments(),
&malformed_type_error);
ASSERT(malformed_type_error.IsNull()); // Type was created from a class.
return Api::Success();
}
DART_EXPORT bool Dart_IsInstance(Dart_Handle object) {
Thread* thread = Thread::Current();
CHECK_ISOLATE(thread->isolate());
REUSABLE_OBJECT_HANDLESCOPE(thread);
Object& ref = thread->ObjectHandle();
ref = Api::UnwrapHandle(object);
return ref.IsInstance();
}
DART_EXPORT bool Dart_IsNumber(Dart_Handle object) {
return RawObject::IsNumberClassId(Api::ClassId(object));
}
DART_EXPORT bool Dart_IsInteger(Dart_Handle object) {
return RawObject::IsIntegerClassId(Api::ClassId(object));
}
DART_EXPORT bool Dart_IsDouble(Dart_Handle object) {
return Api::ClassId(object) == kDoubleCid;
}
DART_EXPORT bool Dart_IsBoolean(Dart_Handle object) {
return Api::ClassId(object) == kBoolCid;
}
DART_EXPORT bool Dart_IsString(Dart_Handle object) {
return RawObject::IsStringClassId(Api::ClassId(object));
}
DART_EXPORT bool Dart_IsStringLatin1(Dart_Handle object) {
return RawObject::IsOneByteStringClassId(Api::ClassId(object));
}
DART_EXPORT bool Dart_IsExternalString(Dart_Handle object) {
return RawObject::IsExternalStringClassId(Api::ClassId(object));
}
DART_EXPORT bool Dart_IsList(Dart_Handle object) {
if (RawObject::IsBuiltinListClassId(Api::ClassId(object))) {
return true;
}
DARTSCOPE(Thread::Current());
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) {
return Api::ClassId(object) == kLibraryCid;
}
DART_EXPORT bool Dart_IsType(Dart_Handle handle) {
return Api::ClassId(handle) == kTypeCid;
}
DART_EXPORT bool Dart_IsFunction(Dart_Handle handle) {
return Api::ClassId(handle) == kFunctionCid;
}
DART_EXPORT bool Dart_IsVariable(Dart_Handle handle) {
return Api::ClassId(handle) == kFieldCid;
}
DART_EXPORT bool Dart_IsTypeVariable(Dart_Handle handle) {
return Api::ClassId(handle) == kTypeParameterCid;
}
DART_EXPORT bool Dart_IsClosure(Dart_Handle object) {
return Api::ClassId(object) == kClosureCid;
}
DART_EXPORT bool Dart_IsTypedData(Dart_Handle handle) {
intptr_t cid = Api::ClassId(handle);
return RawObject::IsTypedDataClassId(cid) ||
RawObject::IsExternalTypedDataClassId(cid) ||
RawObject::IsTypedDataViewClassId(cid);
}
DART_EXPORT bool Dart_IsByteBuffer(Dart_Handle handle) {
return Api::ClassId(handle) == kByteBufferCid;
}
DART_EXPORT bool Dart_IsFuture(Dart_Handle handle) {
DARTSCOPE(Thread::Current());
API_TIMELINE_DURATION(T);
Isolate* I = T->isolate();
const Object& obj = Object::Handle(Z, Api::UnwrapHandle(handle));
if (obj.IsInstance()) {
const Class& future_class =
Class::Handle(I->object_store()->future_class());
ASSERT(!future_class.IsNull());
const Class& obj_class = Class::Handle(Z, obj.clazz());
Error& malformed_type_error = Error::Handle(Z);
bool is_future = obj_class.IsSubtypeOf(
Object::null_type_arguments(), future_class,
Object::null_type_arguments(), &malformed_type_error, NULL, Heap::kNew);
ASSERT(malformed_type_error.IsNull()); // Type is a raw Future.
return is_future;
}
return false;
}
// --- Instances ----
DART_EXPORT Dart_Handle Dart_InstanceGetType(Dart_Handle instance) {
DARTSCOPE(Thread::Current());
API_TIMELINE_DURATION(T);
Isolate* I = T->isolate();
const Object& obj = Object::Handle(Z, Api::UnwrapHandle(instance));
if (obj.IsNull()) {
return Api::NewHandle(T, I->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());
}
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()) {
RawFunction* 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());
}
#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());
RawFunction* 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.raw());
}
// --- 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);
intptr_t class_id = Api::ClassId(integer);
if (class_id == kSmiCid || class_id == kMintCid) {
*fits = true;
return Api::Success();
}
// Slow path for type error.
DARTSCOPE(thread);
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));
RawInteger* 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 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() != RawFunction::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();
CHECK_ISOLATE(thread->isolate());
ReusableObjectHandleScope reused_obj_handle(thread);
const String& str_obj = Api::UnwrapStringHandle(reused_obj_handle, str);
if (str_obj.IsNull()) {
RETURN_TYPE_ERROR(thread->zone(), str, String);
}
*len = str_obj.Length();
return Api::Success();
}
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,
Dart_WeakPersistentHandleFinalizer 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,
callback, SpaceForExternal(T, length)));
}
DART_EXPORT Dart_Handle
Dart_NewExternalUTF16String(const uint16_t* utf16_array,
intptr_t length,
void* peer,
intptr_t external_allocation_size,
Dart_WeakPersistentHandleFinalizer 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,
callback, SpaceForExternal(T, 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());
ReusableObjectHandleScope reused_obj_handle(thread);
const String& str_obj = Api::UnwrapStringHandle(reused_obj_handle, str);
if (str_obj.IsNull()) {
RETURN_TYPE_ERROR(thread->zone(), str, String);
}
if (size == NULL) {
RETURN_NULL_ERROR(size);
}
*size = (str_obj.Length() * str_obj.CharSize());
return Api::Success();
}
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());
ReusableObjectHandleScope reused_obj_handle(thread);
const String& str = Api::UnwrapStringHandle(reused_obj_handle, object);
if (str.IsNull()) {
RETURN_TYPE_ERROR(thread->zone(), object, String);
}
if (str.IsExternal()) {
*peer = str.GetPeer();
ASSERT(*peer != NULL);
} else {
NoSafepointScope no_safepoint_scope;
*peer = thread->isolate()->heap()->GetPeer(str.raw());
}
*char_size = str.CharSize();
*str_len = str.Length();
return Api::Success();
}
// --- Lists ---
DART_EXPORT Dart_Handle Dart_NewList(intptr_t length) {
return Dart_NewListOf(Dart_CoreType_Dynamic, length);
}
static RawTypeArguments* 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_int();
case Dart_CoreType_String:
return store->type_argument_string();
}
UNREACHABLE();
return NULL;
}
DART_EXPORT Dart_Handle Dart_NewListOf(Dart_CoreType_Id element_type_id,
intptr_t length) {
DARTSCOPE(Thread::Current());
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()->object_store(),
element_type_id)));
}
return Api::NewHandle(T, arr.raw());
}
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);
}
return Api::NewHandle(T, Array::New(length, type));
}
#define GET_LIST_LENGTH(zone, type, obj, len) \
type& array = type::Handle(zone); \
array ^= obj.raw(); \
*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.IsTypedData()) {
GET_LIST_LENGTH(Z, TypedData, obj, len);
}
if (obj.IsArray()) {
GET_LIST_LENGTH(Z, Array, obj, len);
}
if (obj.IsGrowableObjectArray()) {
GET_LIST_LENGTH(Z, GrowableObjectArray, obj, len);
}
if (obj.IsExternalTypedData()) {
GET_LIST_LENGTH(Z, ExternalTypedData, 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::NewError("Object does not implement the List interface");
}
const String& name = String::Handle(Z, Field::GetterName(Symbols::Length()));
const int kTypeArgsLen = 0;
const int kNumArgs = 1;
ArgumentsDescriptor args_desc(
Array::Handle(Z, ArgumentsDescriptor::New(kTypeArgsLen, kNumArgs)));
const Function& function =
Function::Handle(Z, Resolver::ResolveDynamic(instance, name, args_desc));
if (function.IsNull()) {
return Api::NewError("List object does not have a 'length' field.");
}
const Array& args = Array::Handle(Z, Array::New(kNumArgs));
args.SetAt(0, instance); // Set up the receiver as the first argument.
const Object& retval =
Object::Handle(Z, DartEntry::InvokeFunction(function, args));
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.raw());
} 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,
Send1Arg(instance, Symbols::IndexToken(),
Instance::Handle(Z, Integer::New(index))));
}
return Api::NewError("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 kTypeArgsLen = 0;
const intptr_t kNumArgs = 2;
ArgumentsDescriptor args_desc(
Array::Handle(ArgumentsDescriptor::New(kTypeArgsLen, kNumArgs)));
const Function& function = Function::Handle(
Z, Resolver::ResolveDynamic(instance, Symbols::AssignIndexToken(),
args_desc));
if (!function.IsNull()) {
const Array& args = Array::Handle(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 (::Dart_IsError(value)) return value;
result[i] = value;
}
return Api::Success();
}
}
return Api::NewError("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 intptr_t kTypeArgsLen = 0;
const intptr_t kNumArgs = 3;
ArgumentsDescriptor args_desc(
Array::Handle(ArgumentsDescriptor::New(kTypeArgsLen, kNumArgs)));
const Function& function = Function::Handle(
Z, Resolver::ResolveDynamic(instance, Symbols::AssignIndexToken(),
args_desc));
if (!function.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);
}
const Array& args = Array::Handle(Z, Array::New(kNumArgs));
args.SetAt(0, instance);
args.SetAt(1, index_obj);
args.SetAt(2, value_obj);
return Api::NewHandle(T, DartEntry::InvokeFunction(function, args));
}
}
return Api::NewError("Object does not implement the 'List' interface");
}
}
static RawObject* ResolveConstructor(const char* current_func,
const Class& cls,
const String& class_name,
const String& dotted_name,
int num_args);
static RawObject* 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.raw();
ASSERT(result.IsFunction());
Function& constructor = Function::Handle(zone);
constructor ^= result.raw();
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.raw();
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;
RawInstance* raw_exception = exception.raw();
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");
template <typename T>
static Dart_Handle CopyBytes(const T& array,
intptr_t offset,
uint8_t* native_array,
intptr_t length) {
ASSERT(array.ElementSizeInBytes() == 1);
NoSafepointScope no_safepoint;
memmove(native_array, reinterpret_cast<uint8_t*>(array.DataAddr(offset)),
length);
return Api::Success();
}
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.IsTypedData()) {
const TypedData& array = TypedData::Cast(obj);
if (array.ElementSizeInBytes() == 1) {
if (!Utils::RangeCheck(offset, length, array.Length())) {
return Api::NewError(
"Invalid length passed in to access list elements");
}
return CopyBytes(array, offset, native_array, length);
}
}
if (obj.IsExternalTypedData()) {
const ExternalTypedData& external_array = ExternalTypedData::Cast(obj);
if (external_array.ElementSizeInBytes() == 1) {
if (!Utils::RangeCheck(offset, length, external_array.Length())) {
return Api::NewError(
"Invalid length passed in to access list elements");
}
return CopyBytes(external_array, offset, native_array, length);
}
}
if (RawObject::IsTypedDataViewClassId(obj.GetClassId())) {
const Instance& view = Instance::Cast(obj);
if (TypedDataView::ElementSizeInBytes(view) == 1) {
intptr_t view_length = Smi::Value(TypedDataView::Length(view));
if (!Utils::RangeCheck(offset, length, view_length)) {
return Api::NewError(
"Invalid length passed in to access list elements");
}
const Instance& data = Instance::Handle(TypedDataView::Data(view));
if (data.IsTypedData()) {
const TypedData& array = TypedData::Cast(data);
if (array.ElementSizeInBytes() == 1) {
intptr_t data_offset =
Smi::Value(TypedDataView::OffsetInBytes(view)) + offset;
// Range check already performed on the view object.
ASSERT(Utils::RangeCheck(data_offset, length, array.Length()));
return CopyBytes(array, data_offset, native_array, length);
}
}
}
}
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 kTypeArgsLen = 0;
const int kNumArgs = 2;
ArgumentsDescriptor args_desc(
Array::Handle(ArgumentsDescriptor::New(kTypeArgsLen, kNumArgs)));
const Function& function = Function::Handle(
Z,
Resolver::ResolveDynamic(instance, Symbols::IndexToken(), args_desc));
if (!function.IsNull()) {
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.raw());
}
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::NewError("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.IsTypedData()) {
const TypedData& array = TypedData::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 kTypeArgsLen = 0;
const int kNumArgs = 3;
ArgumentsDescriptor args_desc(
Array::Handle(Z, ArgumentsDescriptor::New(kTypeArgsLen, kNumArgs)));
const Function& function = Function::Handle(
Z, Resolver::ResolveDynamic(instance, Symbols::AssignIndexToken(),
args_desc));
if (!function.IsNull()) {
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.raw());
}
}
return Api::Success();
}
}
return Api::NewError("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, Send1Arg(instance, Symbols::IndexToken(), Instance::Cast(key_obj)));
}
return Api::NewError("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, Send1Arg(instance, String::Handle(Z, String::New("containsKey")),
Instance::Cast(key_obj)));
}
return Api::NewError("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()) {
const Object& iterator = Object::Handle(
Send0Arg(instance, String::Handle(Z, String::New("get:keys"))));
if (!iterator.IsInstance()) {
return Api::NewHandle(T, iterator.raw());
}
return Api::NewHandle(T, Send0Arg(Instance::Cast(iterator),
String::Handle(String::New("toList"))));
}
return Api::NewError("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 kTypedDataFloat32x4ArrayCid:
case kTypedDataFloat32x4ArrayViewCid:
case kExternalTypedDataFloat32x4ArrayCid:
type = Dart_TypedData_kFloat32x4;
break;
default:
type = Dart_TypedData_kInvalid;
break;
}
return type;
}
DART_EXPORT Dart_TypedData_Type Dart_GetTypeOfTypedData(Dart_Handle object) {
API_TIMELINE_DURATION(Thread::Current());
intptr_t class_id = Api::ClassId(object);
if (RawObject::IsTypedDataClassId(class_id) ||
RawObject::IsTypedDataViewClassId(class_id)) {
return GetType(class_id);
}
return Dart_TypedData_kInvalid;
}
DART_EXPORT Dart_TypedData_Type
Dart_GetTypeOfExternalTypedData(Dart_Handle object) {
API_TIMELINE_DURATION(Thread::Current());
intptr_t class_id = Api::ClassId(object);
if (RawObject::IsExternalTypedDataClassId(class_id)) {
return GetType(class_id);
}
if (RawObject::IsTypedDataViewClassId(class_id)) {
// Check if data object of the view is external.
Zone* zone = Thread::Current()->zone();
const Instance& view_obj = Api::UnwrapInstanceHandle(zone, object);
ASSERT(!view_obj.IsNull());
const Instance& data_obj =
Instance::Handle(zone, TypedDataView::Data(view_obj));
if (ExternalTypedData::IsExternalTypedData(data_obj)) {
return GetType(class_id);
}
}
return Dart_TypedData_kInvalid;
}
static RawObject* GetByteDataConstructor(Thread* thread,
const String& constructor_name,
intptr_t num_args) {
const Library& lib =
Library::Handle(thread->isolate()->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.raw());
}
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));
}
static Dart_Handle NewExternalTypedData(
Thread* thread,
intptr_t cid,
void* data,
intptr_t length,
void* peer,
intptr_t external_allocation_size,
Dart_WeakPersistentHandleFinalizer callback) {
CHECK_LENGTH(length, ExternalTypedData::MaxElements(cid));
Zone* zone = thread->zone();
intptr_t bytes = length * ExternalTypedData::ElementSizeInBytes(cid);
const ExternalTypedData& result = ExternalTypedData::Handle(
zone, ExternalTypedData::New(cid, reinterpret_cast<uint8_t*>(data),
length, SpaceForExternal(thread, bytes)));
if (callback != NULL) {
AllocateFinalizableHandle(thread, result, peer, external_allocation_size,
callback);
}
return Api::NewHandle(thread, result.raw());
}
static Dart_Handle NewExternalByteData(
Thread* thread,
void* data,
intptr_t length,
void* peer,
intptr_t external_allocation_size,
Dart_WeakPersistentHandleFinalizer callback) {
Zone* zone = thread->zone();
Dart_Handle ext_data =
NewExternalTypedData(thread, kExternalTypedDataUint8ArrayCid, data,
length, peer, external_allocation_size, callback);
if (::Dart_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.raw());
}
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_kFloat32x4:
return NewTypedData(T, kTypedDataFloat32x4ArrayCid, 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);
}
DART_EXPORT Dart_Handle Dart_NewExternalTypedDataWithFinalizer(
Dart_TypedData_Type type,
void* data,
intptr_t length,
void* peer,
intptr_t external_allocation_size,
Dart_WeakPersistentHandleFinalizer 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_kFloat32x4:
return NewExternalTypedData(T, kExternalTypedDataFloat32x4ArrayCid, 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 RawObject* GetByteBufferConstructor(Thread* thread,
const String& class_name,
const String& constructor_name,
intptr_t num_args) {
const Library& lib =
Library::Handle(thread->isolate()->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 (!RawObject::IsExternalTypedDataClassId(class_id) &&
!RawObject::IsTypedDataViewClassId(class_id) &&
!RawObject::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.raw());
}
// 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 (!RawObject::IsExternalTypedDataClassId(class_id) &&
!RawObject::IsTypedDataViewClassId(class_id) &&
!RawObject::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;
// If it is an external typed data object just return the data field.
if (RawObject::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 (RawObject::IsTypedDataClassId(class_id)) {
// Regular typed data object, set up some GC and API callback guards.
const TypedData& obj = Api::UnwrapTypedDataHandle(Z, object);
ASSERT(!obj.IsNull());
length = obj.Length();
size_in_bytes = length * TypedData::ElementSizeInBytes(class_id);
T->IncrementNoSafepointScopeDepth();
START_NO_CALLBACK_SCOPE(T);
data_tmp = obj.DataAddr(0);
} else {
ASSERT(RawObject::IsTypedDataViewClassId(class_id));
const Instance& view_obj = Api::UnwrapInstanceHandle(Z, object);
ASSERT(!view_obj.IsNull());
Smi& val = Smi::Handle();
val ^= TypedDataView::Length(view_obj);
length = val.Value();
size_in_bytes = length * TypedDataView::ElementSizeInBytes(class_id);
val ^= TypedDataView::OffsetInBytes(view_obj);
intptr_t offset_in_bytes = val.Value();
const Instance& obj = Instance::Handle(TypedDataView::Data(view_obj));
T->IncrementNoSafepointScopeDepth();
START_NO_CALLBACK_SCOPE(T);
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) {
if (external) {
ASSERT(!I->heap()->Contains(reinterpret_cast<uword>(data_tmp)));
} else {
ASSERT(I->heap()->Contains(reinterpret_cast<uword>(data_tmp)));
}
const Object& obj = Object::Handle(Z, Api::UnwrapHandle(object));
WeakTable* table = I->api_state()->acquired_table();
intptr_t current = table->GetValue(obj.raw());
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.raw(), 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 (!RawObject::IsExternalTypedDataClassId(class_id) &&
!RawObject::IsTypedDataViewClassId(class_id) &&
!RawObject::IsTypedDataClassId(class_id)) {
RETURN_TYPE_ERROR(Z, object, 'TypedData');
}
if (!RawObject::IsExternalTypedDataClassId(class_id)) {
T->DecrementNoSafepointScopeDepth();
END_NO_CALLBACK_SCOPE(T);
}
if (FLAG_verify_acquired_data) {
const Object& obj = Object::Handle(Z, Api::UnwrapHandle(object));
WeakTable* table = I->api_state()->acquired_table();
intptr_t current = table->GetValue(obj.raw());
if (current == 0) {
return Api::NewError("Data was not acquired for this object.");
}
AcquiredData* ad = reinterpret_cast<AcquiredData*>(current);
table->SetValue(obj.raw(), 0); // Delete entry from table.
delete ad;
}
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 RawObject* 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.
const Function& constructor =
Function::Handle(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);
}
return constructor.raw();
}
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.raw();
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());
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().raw();
} 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.raw());
}
ASSERT(result.IsFunction());
Function& constructor = Function::Handle(Z);
constructor ^= result.raw();
Instance& new_object = Instance::Handle(Z);
if (constructor.IsRedirectingFactory()) {
ClassFinalizer::ResolveRedirectingFactory(cls, constructor);
Type& redirect_type = Type::Handle(constructor.RedirectionType());
constructor = constructor.RedirectionTarget();
if (constructor.IsNull()) {
ASSERT(redirect_type.IsMalformed());
return Api::NewHandle(T, redirect_type.error());
}
if (!redirect_type.IsInstantiated()) {
// The type arguments of the redirection type are instantiated from the
// type arguments of the type argument.
// We do not support generic constructors.
ASSERT(redirect_type.IsInstantiated(kFunctions));
Error& bound_error = Error::Handle();
redirect_type ^= redirect_type.InstantiateFrom(
type_arguments, Object::null_type_arguments(), kNoneFree,
&bound_error, NULL, NULL, Heap::kNew);
if (!bound_error.IsNull()) {
return Api::NewHandle(T, bound_error.raw());
}
redirect_type ^= redirect_type.Canonicalize();
}
type_obj = redirect_type.raw();
type_arguments = redirect_type.arguments();
cls = type_obj.type_class();
}
if (constructor.IsGenerativeConstructor()) {
#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.raw());
} else {
return Api::NewError(
"%s expects arguments[%d] to be an Instance handle.", CURRENT_FUNC,
i);
}
}
args.SetAt(arg_index++, argument);
}
// Invoke the constructor and return the new object.
result = DartEntry::InvokeFunction(constructor, args);
if (result.IsError()) {
return Api::NewHandle(T, result.raw());
}
if (constructor.IsGenerativeConstructor()) {
ASSERT(result.IsNull());
} else {
ASSERT(result.IsNull() || result.IsInstance());
new_object ^= result.raw();
}
return Api::NewHandle(T, new_object.raw());
}
static RawInstance* AllocateObject(Thread* thread, const Class& cls) {
if (!cls.is_fields_marked_nullable()) {
// Mark all fields as nullable.
Zone* zone = thread->zone();
Class& iterate_cls = Class::Handle(zone, cls.raw());
Field& field = Field::Handle(zone);
Array& fields = Array::Handle(zone);
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());
}
}
}
// 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);
}
const Class& cls = Class::Handle(Z, type_obj.type_class());
#if defined(DEBUG)
if (!cls.is_allocated() && (Dart::vm_snapshot_kind() == Snapshot::kFullAOT)) {
return Api::NewError("Precompilation dropped '%s'", cls.ToCString());
}
#endif
const Error& error = Error::Handle(Z, cls.EnsureIsFinalized(T));
if (!error.IsNull()) {
// An error occurred, return error object.
return Api::NewHandle(T, error.raw());
}
return Api::NewHandle(T, AllocateObject(T, cls));
}
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());
#if defined(DEBUG)
if (!cls.is_allocated() && (Dart::vm_snapshot_kind() == Snapshot::kFullAOT)) {
return Api::NewError("Precompilation dropped '%s'", cls.ToCString());
}
#endif
const Error& error = Error::Handle(Z, cls.EnsureIsFinalized(T));
if (!error.IsNull()) {
// An error occurred, return error object.
return Api::NewHandle(T, error.raw());
}
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.raw());
}
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.raw());
} 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();
}
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);
const AbstractType& type_obj =
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)) {
// Create the argument list.
// 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.
instance.SetTypeArguments(type_arguments);
}
Dart_Handle result;
Array& args = Array::Handle(Z);
result =
SetupArguments(T, number_of_arguments, arguments, extra_args, &args);
if (!::Dart_IsError(result)) {
args.SetAt(0, instance);
const Object& retval =
Object::Handle(Z, DartEntry::InvokeFunction(constructor, args));
if (retval.IsError()) {
result = Api::NewHandle(T, retval.raw());
} else {
result = Api::NewHandle(T, instance.raw());
}
}
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).raw());
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;
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 (::Dart_IsError(result)) {
return result;
}
return Api::NewHandle(
T, cls.Invoke(function_name, args, arg_names, respect_reflectable));
} 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.raw();
// Setup args and check for malformed arguments in the arguments list.
result = SetupArguments(T, number_of_arguments, arguments, 1, &args);
if (::Dart_IsError(result)) {
return result;
}
args.SetAt(0, instance);
return Api::NewHandle(T, instance.Invoke(function_name, args, arg_names,
respect_reflectable));
} 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 (::Dart_IsError(result)) {
return result;
}
return Api::NewHandle(
T, lib.Invoke(function_name, args, arg_names, respect_reflectable));
} 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(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).raw());
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;
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));
} else if (obj.IsNull() || obj.IsInstance()) {
Instance& instance = Instance::Handle(Z);
instance ^= obj.raw();
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));
} 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));
} 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).raw());
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.raw();
const Object& obj = Object::Handle(Z, Api::UnwrapHandle(container));
const bool respect_reflectable = false;
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));
} else if (obj.IsNull() || obj.IsInstance()) {
Instance& instance = Instance::Handle(Z);
instance ^= obj.raw();
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));
} 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));
} 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 (Api::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;
RawInstance* raw_exception =
Api::UnwrapInstanceHandle(zone, exception).raw();
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;
RawInstance* raw_exception =
Api::UnwrapInstanceHandle(zone, exception).raw();
RawStackTrace* raw_stacktrace =
Api::UnwrapStackTraceHandle(zone, stacktrace).raw();
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_CreateNativeWrapperClass(Dart_Handle library,
Dart_Handle name,
int field_count) {
#if defined(DART_PRECOMPILED_RUNTIME)
return Api::NewError("%s: Cannot compile on an AOT runtime.", CURRENT_FUNC);
#else
DARTSCOPE(Thread::Current());
const String& cls_name = Api::UnwrapStringHandle(Z, name);
if (cls_name.IsNull()) {
RETURN_TYPE_ERROR(Z, name, String);
}
const Library& lib = Api::UnwrapLibraryHandle(Z, library);
if (lib.IsNull()) {
RETURN_TYPE_ERROR(Z, library, Library);
}
if (!Utils::IsUint(16, field_count)) {
return Api::NewError(
"Invalid field_count passed to Dart_CreateNativeWrapperClass");
}
CHECK_CALLBACK_STATE(T);
String& cls_symbol = String::Handle(Z, Symbols::New(T, cls_name));
const Class& cls =
Class::Handle(Z, Class::NewNativeWrapper(lib, cls_symbol, field_count));
if (cls.IsNull()) {
return Api::NewError(
"Unable to create native wrapper class : already exists");
}
return Api::NewHandle(T, cls.RareType());
#endif // defined(DART_PRECOMPILED_RUNTIME)
}
DART_EXPORT Dart_Handle Dart_GetNativeInstanceFieldCount(Dart_Handle obj,
int* count) {
Thread* thread = Thread::Current();
CHECK_ISOLATE(thread->isolate());
ReusableObjectHandleScope reused_obj_handle(thread);
const Instance& instance = Api::UnwrapInstanceHandle(reused_obj_handle, obj);
if (instance.IsNull()) {
RETURN_TYPE_ERROR(thread->zone(), obj, Instance);
}
*count = instance.NumNativeFields();
return Api::Success();
}
DART_EXPORT Dart_Handle Dart_GetNativeInstanceField(Dart_Handle obj,
int index,
intptr_t* value) {
Thread* thread = Thread::Current();
CHECK_ISOLATE(thread->isolate());
ReusableObjectHandleScope reused_obj_handle(thread);
const Instance& instance = Api::UnwrapInstanceHandle(reused_obj_handle, obj);
if (instance.IsNull()) {
RETURN_TYPE_ERROR(thread->zone(), obj, Instance);
}
if (!instance.IsValidNativeIndex(index)) {
return Api::NewError(
"%s: invalid index %d passed in to access native instance field",
CURRENT_FUNC, index);
}
*value = instance.GetNativeField(index);
return Api::Success();
}
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();
}
DART_EXPORT void* Dart_GetNativeIsolateData(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::NewError(
"%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::NewError(
"%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 < INT_MIN || value > INT_MAX) {
return Api::NewError("%s: argument value at index %d is out of range",
CURRENT_FUNC, i);
}
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::NewError(
"%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 > UINT_MAX) {
return Api::NewError("%s: argument value at index %d is out of range",
CURRENT_FUNC, i);
}
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::NewError(
"%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::NewError(
"%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::NewError(
"%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::NewError(
"%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::NewError("%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);
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::NewError(
"%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::NewError(
"%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::NewError("%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::NewError(
"%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());
if ((retval != Api::Null()) && !Api::IsInstance(retval) &&
!Api::IsError(retval)) {
// Print the current stack trace to make the problematic caller
// easier to find.
TransitionNativeToVM transition(arguments->thread());
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);
#if defined(DEBUG)
Isolate* isolate = arguments->thread()->isolate();
ASSERT(isolate == Isolate::Current());
ASSERT(isolate->api_state() != NULL &&
(isolate->api_state()->IsValidWeakPersistentHandle(rval)));
#endif
Api::SetWeakHandleReturnValue(arguments, rval);
}
// --- Environment ---
RawString* 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().raw();
}
if (name.Equals(Symbols::DartVMProduct())) {
#ifdef PRODUCT
return Symbols::True().raw();
#else
return Symbols::False().raw();
#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().raw();
}
}
}
// Check for default VM provided values. If it was not overridden on the
// command line.
if (Symbols::DartIsVM().Equals(name)) {
return Symbols::True().raw();
}
if (FLAG_causal_async_stacks) {
if (Symbols::DartDeveloperCausalAsyncStacks().Equals(name)) {
return Symbols::True().raw();
}
}
}
return result.raw();
}
RawString* 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.raw());
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).raw();
} 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);
arguments->SetReturn(Bool::Get(retval));
}
DART_EXPORT void Dart_SetIntegerReturnValue(Dart_NativeArguments args,
int64_t retval) {
NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
ASSERT(arguments->thread()->isolate() == Isolate::Current());
if (Smi::IsValid(retval)) {
Api::SetSmiReturnValue(arguments, static_cast<intptr_t>(retval));
} else {
// Slow path for Mints.
ASSERT_CALLBACK_STATE(arguments->thread());
TransitionNativeToVM transition(arguments->thread());
Api::SetIntegerReturnValue(arguments, retval);
}
}
DART_EXPORT void Dart_SetDoubleReturnValue(Dart_NativeArguments args,
double retval) {
NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
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->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));
}
#if !defined(DART_PRECOMPILED_RUNTIME)
// NOTE: Need to pass 'result' as a parameter here in order to avoid
// warning: variable 'result' might be clobbered by 'longjmp' or 'vfork'
// which shows up because of the use of setjmp.
static void CompileSource(Thread* thread,
const Library& lib,
const Script& script,
Dart_Handle* result) {
bool update_lib_status = (script.kind() == RawScript::kScriptTag ||
script.kind() == RawScript::kLibraryTag);
if (update_lib_status) {
lib.SetLoadInProgress();
}
ASSERT(thread != NULL);
const Error& error =
Error::Handle(thread->zone(), Compiler::Compile(lib, script));
if (error.IsNull()) {
*result = Api::NewHandle(thread, lib.raw());
} else {
*result = Api::NewHandle(thread, error.raw());
// Compilation errors are not Dart instances, so just mark the library
// as having failed to load without providing an error instance.
lib.SetLoadError(Object::null_instance());
}
}
#endif // !defined(DART_PRECOMPILED_RUNTIME)
DART_EXPORT Dart_Handle Dart_LoadScript(Dart_Handle url,
Dart_Handle resolved_url,
Dart_Handle source,
intptr_t line_offset,
intptr_t column_offset) {
#if defined(DART_PRECOMPILED_RUNTIME)
return Api::NewError("%s: Cannot compile on an AOT runtime.", CURRENT_FUNC);
#else
return Api::NewError("%s: Should not be called in Dart 2", CURRENT_FUNC);
#endif // defined(DART_PRECOMPILED_RUNTIME)
}
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);
Isolate* I = T->isolate();
Library& library = Library::Handle(Z, I->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);
CHECK_COMPILATION_ALLOWED(I);
// The kernel loader is about to allocate a bunch of new libraries, classes,
// and functions into old space. Force growth, and use of the bump allocator
// instead of freelists.
BumpAllocateScope bump_allocate_scope(T);
const char* error = nullptr;
kernel::Program* program =
kernel::Program::ReadFromBuffer(buffer, buffer_size, &error);
if (program == nullptr) {
return Api::NewError("Can't load Kernel binary: %s.", error);
}
[kernel] Allow VM to load concatenated dill file The kernel format has been designed so that one can concatenate several dill files into one file and then load it. For instance the dart function BinaryBuilder.readProgram supports this. Currently a dill file contains one or more programs. In the VM each of these programs are called either program or subprogram. Technically a dill "program" isn't necessarily a program at all (e.g. it could be missing a library). This naming snafu should probably be cleaned up at some point, but that's for another CL. When loading a dill file via BinaryBuilder.readProgram what happens is this: - Each program in the dill file ends in 4 bytes that indicates the size of the program. - Reading the input from the end one can then read the size, skip back that amount of bytes, if we have more data (i.e. there's another program), read another size and so on, and continue until we have accounted for all bytes in the input. - We then read each program from the start, and basically overwrite any library, class, procedure etc. we find. The first main reference found is the one used though. (Saying that we overwrite is not completely true, but when the library is a non-external library that's basically what happens). This CL introduces (some) support on the C++ side for the same thing. So far the C++ side could only handle single-program-dills, and trying to load anything else would probably crash the VM. The support added is this: - Assume the SDK (i.e. vm_platform.dill) is not a concatenated file (error out if it is). - For user provided input, loop over each contained program one-by-one, for each individual one behave as normal. - The way LibraryLoad is implemented (i.e. it skips if the library is already loaded) this means that it currently would behave differently than the dart version (i.e. the first one is used, not the last one). For now it is assumed that that's not a problem. - There is a possibly snafu if the same script is included several times. This could probably mostly be remedied by not creating scripts up front, but only as needed. By the "keep only one" (and fixing the above point, probably by simply loading in the opposite order, i.e. last program in the binary first) the (theoretical) problem would probably do away. Note that we will have separate string tables, canonical name tables etc per "sub program" and that there might be some duplication. The implementation was tested as indicated below, but introduces no tests. $ cat test_lib1.dart import "test_lib2.dart" as lib2; String lib1field = "lib #1 field!!"; main() { foo(); lib2.foo(); print("From lib2: ${lib2.lib2field}"); } foo() { print("Hello, Foo, from test_lib1!"); var x = 42; print(x); } $ cat test_lib2.dart String lib2field = "Lib #2 field!!!!"; foo() { print("Hello, Foo, from test_lib2!"); var y = 34; print(y); } $ out/ReleaseX64/dart pkg/front_end/tool/_fasta/compile.dart --packages=.packages --platform=out/ReleaseX64/vm_platform.dill test_lib1.dart $ ls -lha test_lib1.dart.dill [...] 4.2M Oct 26 14:42 test_lib1.dart.dill $ dart pkg/kernel/bin/split.dart test_lib1.dart.dill Wrote test_lib1.dart.dill.part1.dill Wrote test_lib1.dart.dill.part2.dill $ ls -lha test_lib1.dart.dill.part{1,2}.dill [...] 811 Oct 26 14:42 test_lib1.dart.dill.part1.dill [...] 582 Oct 26 14:42 test_lib1.dart.dill.part2.dill $ cat test_lib1.dart.dill.part1.dill test_lib1.dart.dill.part2.dill > test_lib1.dart.dill.concat.dill $ ls -lha test_lib1.dart.dill.concat.dill [...] 1.4K Oct 26 14:44 test_lib1.dart.dill.concat.dill $ out/ReleaseX64/dart --kernel-binaries=out/ReleaseX64 --packages=.packages test_lib1.dart.dill.concat.dill Hello, Foo, from test_lib1! 42 Hello, Foo, from test_lib2! 34 From lib2: Lib #2 field!!!! Change-Id: I233a033aa3042b202dd4708908a5be3089474588 Reviewed-on: https://dart-review.googlesource.com/16820 Commit-Queue: Jens Johansen <jensj@google.com> Reviewed-by: Dmitry Stefantsov <dmitryas@google.com>
2017-10-27 12:01:48 +00:00
const Object& tmp = kernel::KernelLoader::LoadEntireProgram(program);
delete program;
if (tmp.IsError()) {
return Api::NewHandle(T, tmp.raw());
}
// 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("%s: The binary program does not contain 'main'.",
CURRENT_FUNC);
}
library ^= tmp.raw();
I->object_store()->set_root_library(library);
return Api::NewHandle(T, library.raw());
#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->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.raw();
T->isolate()->object_store()->set_root_library(lib);
return library;
}
RETURN_TYPE_ERROR(Z, library, Library);
}
static void CheckIsEntryPoint(const Class& klass) {
#if defined(DART_PRECOMPILED_RUNTIME)
// This is not a completely thorough check that the class is an entry-point,
// but it catches most missing annotations.
RELEASE_ASSERT(klass.has_pragma());
#endif
}
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());
}
CheckIsEntryPoint(cls);
return Api::NewHandle(T, cls.RareType());
}
DART_EXPORT Dart_Handle Dart_GetType(Dart_Handle library,
Dart_Handle class_name,
intptr_t number_of_type_arguments,
Dart_Handle* type_arguments) {
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());
}
CheckIsEntryPoint(cls);
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);
}
return Api::NewHandle(T, Type::NewNonParameterizedType(cls));
}
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& instantiated_type =
Type::Handle(Type::New(cls, type_args_obj, TokenPosition::kNoSource));
instantiated_type ^= ClassFinalizer::FinalizeType(cls, instantiated_type);
return Api::NewHandle(T, instantiated_type.raw());
}
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.raw());
}
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.raw());
}
DART_EXPORT Dart_Handle Dart_GetLoadedLibraries() {
DARTSCOPE(Thread::Current());
Isolate* I = T->isolate();
const GrowableObjectArray& libs =
GrowableObjectArray::Handle(Z, I->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.raw());
}
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.raw());
}
}
DART_EXPORT Dart_Handle Dart_LibraryHandleError(Dart_Handle library_in,
Dart_Handle error_in) {
DARTSCOPE(Thread::Current());
Isolate* I = T->isolate();
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);
const GrowableObjectArray& pending_deferred_loads =
GrowableObjectArray::Handle(Z,
I->object_store()->pending_deferred_loads());
for (intptr_t i = 0; i < pending_deferred_loads.Length(); i++) {
if (pending_deferred_loads.At(i) == lib.raw()) {
lib.SetLoadError(err);
return Api::Null();
}
}
return error_in;
}
DART_EXPORT Dart_Handle Dart_LoadLibrary(Dart_Handle url,
Dart_Handle resolved_url,
Dart_Handle source,
intptr_t line_offset,
intptr_t column_offset) {
#if defined(DART_PRECOMPILED_RUNTIME)
return Api::NewError("%s: Cannot compile on an AOT runtime.", CURRENT_FUNC);
#else
return Api::NewError("%s: Should not be called in Dart 2", CURRENT_FUNC);
#endif // defined(DART_PRECOMPILED_RUNTIME)
}
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);
Isolate* I = T->isolate();
CHECK_CALLBACK_STATE(T);
CHECK_COMPILATION_ALLOWED(I);
// The kernel loader is about to allocate a bunch of new libraries, classes,
// and functions into old space. Force growth, and use of the bump allocator
// instead of freelists.
BumpAllocateScope bump_allocate_scope(T);
const char* error = nullptr;
kernel::Program* program =
kernel::Program::ReadFromBuffer(buffer, buffer_size, &error);
if (program == nullptr) {
return Api::NewError("Can't load Kernel binary: %s.", error);
}
const Object& result =
kernel::KernelLoader::LoadEntireProgram(program, false);
delete program;
return Api::NewHandle(T, result.raw());
#endif // defined(DART_PRECOMPILED_RUNTIME)
}
DART_EXPORT Dart_Handle Dart_LibraryImportLibrary(Dart_Handle library,
Dart_Handle import,
Dart_Handle prefix) {
#if defined(DART_PRECOMPILED_RUNTIME)
return Api::NewError("%s: Cannot compile on an AOT runtime.", CURRENT_FUNC);
#else
DARTSCOPE(Thread::Current());
Isolate* I = T->isolate();
const Library& library_vm = Api::UnwrapLibraryHandle(Z, library);
if (library_vm.IsNull()) {
RETURN_TYPE_ERROR(Z, library, Library);
}
const Library& import_vm = Api::UnwrapLibraryHandle(Z, import);
if (import_vm.IsNull()) {
RETURN_TYPE_ERROR(Z, import, Library);
}
const Object& prefix_object = Object::Handle(Z, Api::UnwrapHandle(prefix));
const String& prefix_vm =
prefix_object.IsNull() ? Symbols::Empty() : String::Cast(prefix_object);
if (prefix_vm.IsNull()) {
RETURN_TYPE_ERROR(Z, prefix, String);
}
CHECK_CALLBACK_STATE(T);
CHECK_COMPILATION_ALLOWED(I);
const String& prefix_symbol = String::Handle(Z, Symbols::New(T, prefix_vm));
const Namespace& import_ns = Namespace::Handle(
Z, Namespace::New(import_vm, Object::null_array(), Object::null_array()));
if (prefix_vm.Length() == 0) {
library_vm.AddImport(import_ns);
} else {
LibraryPrefix& library_prefix = LibraryPrefix::Handle();
library_prefix = library_vm.LookupLocalLibraryPrefix(prefix_symbol);
if (!library_prefix.IsNull()) {
library_prefix.AddImport(import_ns);
} else {
library_prefix =
LibraryPrefix::New(prefix_symbol, import_ns, false, library_vm);
library_vm.AddObject(library_prefix, prefix_symbol);
}
}
return Api::Success();
#endif // defined(DART_PRECOMPILED_RUNTIME)
}
DART_EXPORT Dart_Handle Dart_GetImportsOfScheme(Dart_Handle scheme) {
DARTSCOPE(Thread::Current());
Isolate* I = T->isolate();
const String& scheme_vm = Api::UnwrapStringHandle(Z, scheme);
if (scheme_vm.IsNull()) {
RETURN_TYPE_ERROR(Z, scheme, String);
}
const GrowableObjectArray& libraries =
GrowableObjectArray::Handle(Z, I->object_store()->libraries());
const GrowableObjectArray& result =
GrowableObjectArray::Handle(Z, GrowableObjectArray::New());
Library& importer = Library::Handle(Z);
Array& imports = Array::Handle(Z);
Namespace& ns = Namespace::Handle(Z);
Library& importee = Library::Handle(Z);
String& importee_uri = String::Handle(Z);
for (intptr_t i = 0; i < libraries.Length(); i++) {
importer ^= libraries.At(i);
imports = importer.imports();
for (intptr_t j = 0; j < imports.Length(); j++) {
ns ^= imports.At(j);
if (ns.IsNull()) continue;
importee = ns.library();
importee_uri = importee.url();
if (importee_uri.StartsWith(scheme_vm)) {
result.Add(importer);
result.Add(importee);
}
}
}
return Api::NewHandle(T, Array::MakeFixedLength(result));
}
DART_EXPORT Dart_Handle Dart_LoadSource(Dart_Handle library,
Dart_Handle url,
Dart_Handle resolved_url,
Dart_Handle source,
intptr_t line_offset,
intptr_t column_offset) {
#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);
Isolate* I = T->isolate();
const Library& lib = Api::UnwrapLibraryHandle(Z, library);
if (lib.IsNull()) {
RETURN_TYPE_ERROR(Z, library, Library);
}
const String& url_str = Api::UnwrapStringHandle(Z, url);
if (url_str.IsNull()) {
RETURN_TYPE_ERROR(Z, url, String);
}
if (::Dart_IsNull(resolved_url)) {
resolved_url = url;
}
const String& resolved_url_str = Api::UnwrapStringHandle(Z, resolved_url);
if (resolved_url_str.IsNull()) {
RETURN_TYPE_ERROR(Z, resolved_url, String);
}
const String& source_str = Api::UnwrapStringHandle(Z, source);
if (source_str.IsNull()) {
RETURN_TYPE_ERROR(Z, source, String);
}
if (line_offset < 0) {
return Api::NewError("%s: argument 'line_offset' must be positive number",
CURRENT_FUNC);
}
if (column_offset < 0) {
return Api::NewError("%s: argument 'column_offset' must be positive number",
CURRENT_FUNC);
}
CHECK_CALLBACK_STATE(T);
CHECK_COMPILATION_ALLOWED(I);
NoHeapGrowthControlScope no_growth_control;
const Script& script =
Script::Handle(Z, Script::New(url_str, resolved_url_str, source_str,
RawScript::kSourceTag));
script.SetLocationOffset(line_offset, column_offset);
Dart_Handle result;
CompileSource(T, lib, script, &result);
return result;
#endif // defined(DART_PRECOMPILED_RUNTIME)
}
DART_EXPORT Dart_Handle Dart_LibraryLoadPatch(Dart_Handle library,
Dart_Handle url,
Dart_Handle patch_source) {
#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);
Isolate* I = T->isolate();
const Library& lib = Api::UnwrapLibraryHandle(Z, library);
if (lib.IsNull()) {
RETURN_TYPE_ERROR(Z, library, Library);
}
const String& url_str = Api::UnwrapStringHandle(Z, url);
if (url_str.IsNull()) {
RETURN_TYPE_ERROR(Z, url, String);
}
const String& source_str = Api::UnwrapStringHandle(Z, patch_source);
if (source_str.IsNull()) {
RETURN_TYPE_ERROR(Z, patch_source, String);
}
CHECK_CALLBACK_STATE(T);
CHECK_COMPILATION_ALLOWED(I);
NoHeapGrowthControlScope no_growth_control;
const Script& script = Script::Handle(
Z, Script::New(url_str, url_str, source_str, RawScript::kPatchTag));
Dart_Handle result;
CompileSource(T, lib, script, &result);
return result;
#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);
I->DoneLoading();
// TODO(hausner): move the remaining code below (finalization and
// invoking of _completeDeferredLoads) into Isolate::DoneLoading().
// Finalize all classes if needed.
Dart_Handle state = Api::CheckAndFinalizePendingClasses(T);
if (::Dart_IsError(state)) {
return state;
}
I->DoneFinalizing();
#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
#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
if (complete_futures) {
const Library& corelib = Library::Handle(Z, Library::CoreLibrary());
const String& function_name =
String::Handle(Z, String::New("_completeDeferredLoads"));
const Function& function =
Function::Handle(Z, corelib.LookupFunctionAllowPrivate(function_name));
ASSERT(!function.IsNull());
const Array& args = Array::empty_array();
const Object& res =
Object::Handle(Z, DartEntry::InvokeFunction(function, args));
I->object_store()->clear_pending_deferred_loads();
if (res.IsError() || res.IsUnhandledException()) {
return Api::NewHandle(T, res.raw());
}
}
return Api::Success();
}
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();
}
// --- 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());
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;
RawObject* raw_obj = obj.raw();
*peer = thread->isolate()->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());
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;
RawObject* raw_obj = obj.raw();
thread->isolate()->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,
const char* package_config) {
Dart_KernelCompilationResult result;
#if defined(DART_PRECOMPILED_RUNTIME)
result.status = Dart_KernelCompilationStatus_Unknown;
result.error = strdup("Dart_CompileToKernel is unsupported.");
#else
result = KernelIsolate::CompileToKernel(script_uri, platform_kernel,
platform_kernel_size, 0, NULL,
incremental_compile, package_config);
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_CompileSourcesToKernel(const char* script_uri,
const uint8_t* platform_kernel,
intptr_t platform_kernel_size,
int source_files_count,
Dart_SourceFile sources[],
bool incremental_compile,
const char* package_config,
const char* multiroot_filepaths,
const char* multiroot_scheme) {
Dart_KernelCompilationResult result;
#if defined(DART_PRECOMPILED_RUNTIME)
result.status = Dart_KernelCompilationStatus_Unknown;
result.error = strdup("Dart_CompileSourcesToKernel is unsupported.");
#else
result = KernelIsolate::CompileToKernel(
script_uri, platform_kernel, platform_kernel_size, source_files_count,
sources, incremental_compile, package_config, multiroot_filepaths,
multiroot_scheme);
if (result.status == Dart_KernelCompilationStatus_Ok) {
if (KernelIsolate::AcceptCompilation().status !=
Dart_KernelCompilationStatus_Ok) {
FATAL(
"An error occurred in the CFE while accepting the most recent"
" compilation results.");
}
}
#endif
return result;
}
DART_EXPORT Dart_KernelCompilationResult Dart_KernelListDependencies() {
Dart_KernelCompilationResult result;
#if defined(DART_PRECOMPILED_RUNTIME)
result.status = Dart_KernelCompilationStatus_Unknown;
result.error = strdup("Dart_KernelListDependencies is unsupported.");
#else
result = KernelIsolate::ListDependencies();
#endif
return result;
}
// --- Service support ---
DART_EXPORT bool Dart_IsServiceIsolate(Dart_Isolate isolate) {
Isolate* iso = reinterpret_cast<Isolate*>(isolate);
return ServiceIsolate::IsServiceIsolate(iso);
}
DART_EXPORT Dart_Port Dart_ServiceWaitForLoadPort() {
return ServiceIsolate::WaitForLoadPort();
}
DART_EXPORT int64_t Dart_TimelineGetMicros() {
return OS::GetCurrentMonotonicMicros();
}
#if defined(PRODUCT)
DART_EXPORT void Dart_RegisterIsolateServiceRequestCallback(
const char* name,
Dart_ServiceRequestCallback callback,
void* user_data) {
return;
}
DART_EXPORT void Dart_RegisterRootServiceRequestCallback(
const char* name,
Dart_ServiceRequestCallback callback,
void* user_data) {
return;
}
DART_EXPORT void Dart_SetEmbedderInformationCallback(
Dart_EmbedderInformationCallback callback) {
return;
}
DART_EXPORT char* Dart_SetServiceStreamCallbacks(
Dart_ServiceStreamListenCallback listen_callback,
Dart_ServiceStreamCancelCallback cancel_callback) {
return NULL;
}
DART_EXPORT Dart_Handle Dart_ServiceSendDataEvent(const char* stream_id,
const char* event_kind,
const uint8_t* bytes,
intptr_t bytes_length) {
return Api::Success();
}
DART_EXPORT char* Dart_SetFileModifiedCallback(
Dart_FileModifiedCallback file_mod_callback) {
return NULL;
}
DART_EXPORT bool Dart_IsReloading() {
return false;
}
DART_EXPORT void Dart_GlobalTimelineSetRecordedStreams(int64_t stream_mask) {
return;
}
DART_EXPORT void Dart_SetEmbedderTimelineCallbacks(
Dart_EmbedderTimelineStartRecording start_recording,
Dart_EmbedderTimelineStopRecording stop_recording) {
return;
}
DART_EXPORT bool Dart_GlobalTimelineGetTrace(Dart_StreamConsumer consumer,
void* user_data) {
return false;
}
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) {
return;
}
#else // defined(PRODUCT)
DART_EXPORT void Dart_RegisterIsolateServiceRequestCallback(
const char* name,
Dart_ServiceRequestCallback callback,
void* user_data) {
if (FLAG_support_service) {
Service::RegisterIsolateEmbedderCallback(name, callback, user_data);
}
}
DART_EXPORT void Dart_RegisterRootServiceRequestCallback(
const char* name,
Dart_ServiceRequestCallback callback,
void* user_data) {
if (FLAG_support_service) {
Service::RegisterRootEmbedderCallback(name, callback, user_data);
}
}
DART_EXPORT void Dart_SetEmbedderInformationCallback(
Dart_EmbedderInformationCallback callback) {
if (FLAG_support_service) {
Service::SetEmbedderInformationCallback(callback);
}
}
DART_EXPORT char* Dart_SetServiceStreamCallbacks(
Dart_ServiceStreamListenCallback listen_callback,
Dart_ServiceStreamCancelCallback cancel_callback) {
if (!FLAG_support_service) {
return NULL;
}
if (listen_callback != NULL) {
if (Service::stream_listen_callback() != NULL) {
return 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 strdup(
"Dart_SetServiceStreamCallbacks "
"expects 'listen_callback' to be present in the callback set.");
}
}
if (cancel_callback != NULL) {
if (Service::stream_cancel_callback() != NULL) {
return 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 strdup(
"Dart_SetServiceStreamCallbacks "
"expects 'cancel_callback' to be present in the callback set.");
}
}
Service::SetEmbedderStreamCallbacks(listen_callback, cancel_callback);
return NULL;
}
DART_EXPORT Dart_Handle Dart_ServiceSendDataEvent(const char* stream_id,
const char* event_kind,
const uint8_t* bytes,
intptr_t bytes_length) {
DARTSCOPE(Thread::Current());
Isolate* I = T->isolate();
if (stream_id == NULL) {
RETURN_NULL_ERROR(stream_id);
}
if (event_kind == NULL) {
RETURN_NULL_ERROR(event_kind);
}
if (bytes == NULL) {
RETURN_NULL_ERROR(bytes);
}
if (bytes_length < 0) {
return Api::NewError("%s expects argument 'bytes_length' to be >= 0.",
CURRENT_FUNC);
}
Service::SendEmbedderEvent(I, stream_id, event_kind, bytes, bytes_length);
return Api::Success();
}
DART_EXPORT char* Dart_SetFileModifiedCallback(
Dart_FileModifiedCallback file_modified_callback) {
if (!FLAG_support_service) {
return NULL;
}
#if !defined(DART_PRECOMPILED_RUNTIME)
if (file_modified_callback != NULL) {
if (IsolateReloadContext::file_modified_callback() != NULL) {
return strdup(
"Dart_SetFileModifiedCallback permits only one callback to be"
" registered, please remove the existing callback and then add"
" this callback");
}
} else {
if (IsolateReloadContext::file_modified_callback() == NULL) {
return strdup(
"Dart_SetFileModifiedCallback expects 'file_modified_callback' to"
" be set before it is cleared.");
}
}
IsolateReloadContext::SetFileModifiedCallback(file_modified_callback);
#endif // !defined(DART_PRECOMPILED_RUNTIME)
return NULL;
}
DART_EXPORT bool Dart_IsReloading() {
Thread* thread = Thread::Current();
Isolate* isolate = thread->isolate();
CHECK_ISOLATE(isolate);
return isolate->IsReloading();
}
DART_EXPORT void Dart_GlobalTimelineSetRecordedStreams(int64_t stream_mask) {
if (!FLAG_support_timeline) {
return;
}
const bool api_enabled = (stream_mask & DART_TIMELINE_STREAM_API) != 0;
const bool compiler_enabled =
(stream_mask & DART_TIMELINE_STREAM_COMPILER) != 0;
const bool dart_enabled = (stream_mask & DART_TIMELINE_STREAM_DART) != 0;
const bool debugger_enabled =
(stream_mask & DART_TIMELINE_STREAM_DEBUGGER) != 0;
const bool embedder_enabled =
(stream_mask & DART_TIMELINE_STREAM_EMBEDDER) != 0;
const bool gc_enabled = (stream_mask & DART_TIMELINE_STREAM_GC) != 0;
const bool isolate_enabled =
(stream_mask & DART_TIMELINE_STREAM_ISOLATE) != 0;
const bool vm_enabled = (stream_mask & DART_TIMELINE_STREAM_VM) != 0;
Timeline::SetStreamAPIEnabled(api_enabled);
Timeline::SetStreamCompilerEnabled(compiler_enabled);
Timeline::SetStreamDartEnabled(dart_enabled);
Timeline::SetStreamDebuggerEnabled(debugger_enabled);
Timeline::SetStreamEmbedderEnabled(embedder_enabled);
Timeline::SetStreamGCEnabled(gc_enabled);
Timeline::SetStreamIsolateEnabled(isolate_enabled);
Timeline::SetStreamVMEnabled(vm_enabled);
}
static void StartStreamToConsumer(Dart_StreamConsumer consumer,
void* user_data,
const char* stream_name) {
// Start stream.
consumer(Dart_StreamConsumer_kStart, stream_name, NULL, 0, user_data);
}
static void FinishStreamToConsumer(Dart_StreamConsumer consumer,
void* user_data,
const char* stream_name) {
// Finish stream.
consumer(Dart_StreamConsumer_kFinish, stream_name, NULL, 0, user_data);
}
static void DataStreamToConsumer(Dart_StreamConsumer consumer,
void* user_data,
const char* output,
intptr_t output_length,
const char* stream_name) {
if (output == NULL) {
return;
}
const intptr_t kDataSize = 64 * KB;
intptr_t cursor = 0;
intptr_t remaining = output_length;
while (remaining >= kDataSize) {
consumer(Dart_StreamConsumer_kData, stream_name,
reinterpret_cast<const uint8_t*>(&output[cursor]), kDataSize,
user_data);
cursor += kDataSize;
remaining -= kDataSize;
}
if (remaining > 0) {
ASSERT(remaining < kDataSize);
consumer(Dart_StreamConsumer_kData, stream_name,
reinterpret_cast<const uint8_t*>(&output[cursor]), remaining,
user_data);
cursor += remaining;
remaining -= remaining;
}
ASSERT(cursor == output_length);
ASSERT(remaining == 0);
}
static bool StreamTraceEvents(Dart_StreamConsumer consumer,
void* user_data,
JSONStream* js) {
ASSERT(js != NULL);
// Steal output from JSONStream.
char* output = NULL;
intptr_t output_length = 0;
js->Steal(&output, &output_length);
if (output_length < 3) {
// Empty JSON array.
free(output);
return false;
}
// We want to send the JSON array without the leading '[' or trailing ']'
// characters.
ASSERT(output[0] == '[');
ASSERT(output[output_length - 1] == ']');
// Replace the ']' with the null character.
output[output_length - 1] = '\0';
char* start = &output[1];
// We are skipping the '['.
output_length -= 1;
DataStreamToConsumer(consumer, user_data, start, output_length, "timeline");
// We stole the JSONStream's output buffer, free it.
free(output);
return true;
}
DART_EXPORT void Dart_SetEmbedderTimelineCallbacks(
Dart_EmbedderTimelineStartRecording start_recording,
Dart_EmbedderTimelineStopRecording stop_recording) {
if (!FLAG_support_timeline) {
return;
}
Timeline::set_start_recording_cb(start_recording);
Timeline::set_stop_recording_cb(stop_recording);
}
DART_EXPORT bool Dart_GlobalTimelineGetTrace(Dart_StreamConsumer consumer,
void* user_data) {
if (!FLAG_support_timeline) {
return false;
}
// To support various embedders, it must be possible to call this function
// from a thread for which we have not entered an Isolate and set up a Thread
// TLS object. Therefore, a Zone may not be available, a StackZone cannot be
// created, and no ZoneAllocated objects can be allocated.
if (consumer == NULL) {
return false;
}
TimelineEventRecorder* timeline_recorder = Timeline::recorder();
if (timeline_recorder == NULL) {
// Nothing has been recorded.
return false;
}
Timeline::ReclaimCachedBlocksFromThreads();
bool success = false;
JSONStream js;
TimelineEventFilter filter;
timeline_recorder->PrintTraceEvent(&js, &filter);
StartStreamToConsumer(consumer, user_data, "timeline");
if (StreamTraceEvents(consumer, user_data, &js)) {
success = true;
}
FinishStreamToConsumer(consumer, user_data, "timeline");
return success;
}
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 (!FLAG_support_timeline) {
return;
}
if (type < Dart_Timeline_Event_Begin) {
return;
}
if (type > Dart_Timeline_Event_Flow_End) {
return;
}
TimelineStream* stream = Timeline::GetEmbedderStream();
ASSERT(stream != NULL);
TimelineEvent* event = stream->StartEvent();
if (event == NULL) {
return;
}
label = strdup(label);
switch (type) {
case Dart_Timeline_Event_Begin:
event->Begin(label, timestamp0);
break;
case Dart_Timeline_Event_End:
event->End(label, 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->set_owns_label(true);
event->SetNumArguments(argument_count);
for (intptr_t i = 0; i < argument_count; i++) {
event->CopyArgument(i, argument_names[i], argument_values[i]);
}
event->Complete();
}
#endif // defined(PRODUCT)
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_SaveCompilationTrace(uint8_t** buffer,
intptr_t* buffer_length) {
#if defined(DART_PRECOMPILED_RUNTIME)
return Api::NewError("%s: Cannot compile on an AOT runtime.", CURRENT_FUNC);
#else
Thread* thread = Thread::Current();
API_TIMELINE_DURATION(thread);
DARTSCOPE(thread);
CHECK_NULL(buffer);
CHECK_NULL(buffer_length);
CompilationTraceSaver saver(thread->zone());
ProgramVisitor::VisitFunctions(&saver);
saver.StealBuffer(buffer, buffer_length);
return Api::Success();
#endif // defined(DART_PRECOMPILED_RUNTIME)
}
DART_EXPORT
Dart_Handle Dart_LoadCompilationTrace(uint8_t* buffer, intptr_t buffer_length) {
#if defined(DART_PRECOMPILED_RUNTIME)
return Api::NewError("%s: Cannot compile on an AOT runtime.", CURRENT_FUNC);
#else
Thread* thread = Thread::Current();
API_TIMELINE_DURATION(thread);
DARTSCOPE(thread);
CHECK_NULL(buffer);
CompilationTraceLoader loader(thread);
const Object& error =
Object::Handle(loader.CompileTrace(buffer, buffer_length));
if (error.IsError()) {
return Api::NewHandle(T, Error::Cast(error).raw());
}
return Api::Success();
#endif // defined(DART_PRECOMPILED_RUNTIME)
}
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());
// 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.
Isolate::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(TARGET_ARCH_DBC)
return Api::NewError("AOT compilation is not supported on DBC.");
#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 (::Dart_IsError(result)) {
return result;
}
CHECK_CALLBACK_STATE(T);
const Error& error = Error::Handle(Precompiler::CompileAll());
if (!error.IsNull()) {
return Api::NewHandle(T, error.raw());
}
return Api::Success();
#endif
}
DART_EXPORT Dart_Handle
Dart_CreateAppAOTSnapshotAsAssembly(Dart_StreamingWriteCallback callback,
void* callback_data) {
#if defined(TARGET_ARCH_IA32)
return Api::NewError("AOT compilation is not supported on IA32.");
#elif defined(TARGET_ARCH_DBC)
return Api::NewError("AOT compilation is not supported on DBC.");
#elif defined(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);
Isolate* I = T->isolate();
if (I->compilation_allowed()) {
return Api::NewError(
"Isolate is not precompiled. "
"Did you forget to call Dart_Precompile?");
}
ASSERT(FLAG_load_deferred_eagerly);
CHECK_NULL(callback);
NOT_IN_PRODUCT(TimelineDurationScope tds2(T, Timeline::GetIsolateStream(),
"WriteAppAOTSnapshot"));
AssemblyImageWriter image_writer(T, callback, callback_data, NULL, NULL);
uint8_t* vm_snapshot_data_buffer = NULL;
uint8_t* isolate_snapshot_data_buffer = NULL;
FullSnapshotWriter writer(Snapshot::kFullAOT, &vm_snapshot_data_buffer,
&isolate_snapshot_data_buffer, ApiReallocate,
&image_writer, &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();
image_writer.Finalize();
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(TARGET_ARCH_DBC)
return Api::NewError("AOT compilation is not supported on DBC.");
#elif defined(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);
NOT_IN_PRODUCT(TimelineDurationScope tds2(T, Timeline::GetIsolateStream(),
"WriteVMAOTSnapshot"));
AssemblyImageWriter image_writer(T, callback, callback_data, NULL, NULL);
uint8_t* vm_snapshot_data_buffer = NULL;
FullSnapshotWriter writer(Snapshot::kFullAOT, &vm_snapshot_data_buffer, NULL,
ApiReallocate, &image_writer, NULL);
writer.WriteFullSnapshot();
return Api::Success();
#endif
}
DART_EXPORT Dart_Handle
Dart_CreateAppAOTSnapshotAsBlobs(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,
const uint8_t* shared_data,
const uint8_t* shared_instructions) {
#if defined(TARGET_ARCH_IA32)
return Api::NewError("AOT compilation is not supported on IA32.");
#elif defined(TARGET_ARCH_DBC)
return Api::NewError("AOT compilation is not supported on DBC.");
#elif !defined(DART_PRECOMPILER)
return Api::NewError(
"This VM was built without support for AOT compilation.");
#else
DARTSCOPE(Thread::Current());
API_TIMELINE_DURATION(T);
Isolate* I = T->isolate();
if (I->compilation_allowed()) {
return Api::NewError(
"Isolate is not precompiled. "
"Did you forget to call Dart_Precompile?");
}
ASSERT(FLAG_load_deferred_eagerly);
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);
const void* shared_data_image = NULL;
if (shared_data != NULL) {
shared_data_image = Snapshot::SetupFromBuffer(shared_data)->DataImage();
}
const void* shared_instructions_image = shared_instructions;
NOT_IN_PRODUCT(TimelineDurationScope tds2(T, Timeline::GetIsolateStream(),
"WriteAppAOTSnapshot"));
BlobImageWriter vm_image_writer(T, vm_snapshot_instructions_buffer,
ApiReallocate, 2 * MB /* initial_size */,
/*shared_objects=*/nullptr,
/*shared_instructions=*/nullptr,
/*reused_objects=*/nullptr);
BlobImageWriter isolate_image_writer(
T, isolate_snapshot_instructions_buffer, ApiReallocate,
2 * MB /* initial_size */, shared_data_image, shared_instructions_image,
/* reuse_instructions= */ nullptr);
FullSnapshotWriter writer(Snapshot::kFullAOT, vm_snapshot_data_buffer,
isolate_snapshot_data_buffer, ApiReallocate,
&vm_image_writer, &isolate_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_snapshot_data_size = writer.VmIsolateSnapshotSize();
*vm_snapshot_instructions_size = vm_image_writer.InstructionsBlobSize();
*isolate_snapshot_data_size = writer.IsolateSnapshotSize();
*isolate_snapshot_instructions_size =
isolate_image_writer.InstructionsBlobSize();
return Api::Success();
#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());
Function& func = Function::Handle(
zone, reg_exp_class.LookupFunctionAllowPrivate(execute_match_name));
ASSERT(!func.IsNull());
Code& code = Code::Handle(zone);
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);
Isolate* I = T->isolate();
if (!FLAG_load_deferred_eagerly) {
return Api::NewError(
"Creating full snapshots requires --load_deferred_eagerly");
}
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 (::Dart_IsError(state)) {
return state;
}
BackgroundCompiler::Stop(I);
DropRegExpMatchCode(Z);
ProgramVisitor::Dedup();
Symbols::Compact(I);
NOT_IN_PRODUCT(TimelineDurationScope tds2(T, Timeline::GetIsolateStream(),
"WriteCoreJITSnapshot"));
BlobImageWriter vm_image_writer(T, vm_snapshot_instructions_buffer,
ApiReallocate, 2 * MB /* initial_size */,
/*shared_objects=*/nullptr,
/*shared_instructions=*/nullptr,
/*reused_objects=*/nullptr);
BlobImageWriter isolate_image_writer(T, isolate_snapshot_instructions_buffer,
ApiReallocate, 2 * MB /* initial_size */,
/*shared_objects=*/nullptr,
/*shared_instructions=*/nullptr,
/*reused_objects=*/nullptr);
FullSnapshotWriter writer(Snapshot::kFullJIT, vm_snapshot_data_buffer,
isolate_snapshot_data_buffer, ApiReallocate,
&vm_image_writer, &isolate_image_writer);
writer.WriteFullSnapshot();
*vm_snapshot_data_size = writer.VmIsolateSnapshotSize();
*vm_snapshot_instructions_size = vm_image_writer.InstructionsBlobSize();
*isolate_snapshot_data_size = writer.IsolateSnapshotSize();
*isolate_snapshot_instructions_size =
isolate_image_writer.InstructionsBlobSize();
return Api::Success();
#endif
}
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,
const uint8_t* reused_instructions) {
#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);
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
Isolate* I = T->isolate();
if (!FLAG_load_deferred_eagerly) {
return Api::NewError(
"Creating full snapshots requires --load_deferred_eagerly");
}
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 (::Dart_IsError(state)) {
return state;
}
BackgroundCompiler::Stop(I);
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
if (reused_instructions) {
DropCodeWithoutReusableInstructions(reused_instructions);
}
ProgramVisitor::Dedup();
Symbols::Compact(I);
NOT_IN_PRODUCT(TimelineDurationScope tds2(T, Timeline::GetIsolateStream(),
"WriteAppJITSnapshot"));
BlobImageWriter isolate_image_writer(T, isolate_snapshot_instructions_buffer,
ApiReallocate, 2 * MB /* initial_size */,
/*shared_objects=*/nullptr,
/*shared_instructions=*/nullptr,
reused_instructions);
FullSnapshotWriter writer(Snapshot::kFullJIT, NULL,
isolate_snapshot_data_buffer, ApiReallocate, NULL,
&isolate_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();
*isolate_snapshot_data_size = writer.IsolateSnapshotSize();
*isolate_snapshot_instructions_size =
isolate_image_writer.InstructionsBlobSize();
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
if (reused_instructions) {
*isolate_snapshot_instructions_buffer = NULL;
}
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);
Isolate* isolate = thread->isolate();
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->obfuscation_map() != NULL) {
for (intptr_t i = 0; isolate->obfuscation_map()[i] != NULL; i++) {
if (i > 0) {
text_buffer.AddChar(',');
}
text_buffer.AddChar('"');
text_buffer.AddEscapedString(isolate->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) {
#ifndef PRODUCT
Profiler::DumpStackTrace(context);
#endif
}
} // namespace dart