Index: runtime/vm/dart_api_impl.cc |
=================================================================== |
--- runtime/vm/dart_api_impl.cc (revision 36461) |
+++ runtime/vm/dart_api_impl.cc (working copy) |
@@ -81,6 +81,142 @@ |
} |
+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; |
+ } |
+ Isolate* isolate = arguments->isolate(); |
+ ASSERT(isolate == Isolate::Current()); |
+ *peer = NULL; |
+ REUSABLE_OBJECT_HANDLESCOPE(isolate); |
+ Object& obj = isolate->ObjectHandle(); |
+ obj = arguments->NativeArgAt(arg_index); |
+ if (RawObject::IsStringClassId(obj.GetClassId())) { |
+ ASSERT(isolate->api_state() && |
+ isolate->api_state()->top_scope() != NULL); |
+ *str = Api::NewHandle(isolate, obj.raw()); |
+ 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); |
+ if (Api::GetNativeIntegerArgument(arguments, arg_index, value)) { |
+ return true; |
+ } |
+ Isolate* isolate = arguments->isolate(); |
+ ASSERT(isolate == Isolate::Current()); |
+ REUSABLE_OBJECT_HANDLESCOPE(isolate); |
+ Object& obj = isolate->ObjectHandle(); |
+ obj = arguments->NativeArgAt(arg_index); |
+ intptr_t cid = obj.GetClassId(); |
+ if (cid == kBigintCid) { |
+ const Bigint& bigint = Bigint::Cast(obj); |
+ if (BigintOperations::FitsIntoInt64(bigint)) { |
+ *value = BigintOperations::ToInt64(bigint); |
+ return true; |
+ } |
+ } |
+ return false; |
+} |
+ |
+ |
+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; |
+ } |
+ Isolate* isolate = arguments->isolate(); |
+ ASSERT(isolate == Isolate::Current()); |
+ REUSABLE_OBJECT_HANDLESCOPE(isolate); |
+ Object& obj = isolate->ObjectHandle(); |
+ obj = arguments->NativeArgAt(arg_index); |
+ intptr_t cid = obj.GetClassId(); |
+ if (cid == kBigintCid) { |
+ const Bigint& bigint = Bigint::Cast(obj); |
+ if (BigintOperations::FitsIntoUint64(bigint)) { |
+ *value = BigintOperations::ToUint64(bigint); |
+ return true; |
+ } |
+ } |
+ return false; |
+} |
+ |
+ |
+static bool GetNativeDoubleArgument(NativeArguments* arguments, |
+ int arg_index, |
+ double* value) { |
+ ASSERT(value != NULL); |
+ if (Api::GetNativeDoubleArgument(arguments, arg_index, value)) { |
+ return true; |
+ } |
+ Isolate* isolate = arguments->isolate(); |
+ ASSERT(isolate == Isolate::Current()); |
+ REUSABLE_OBJECT_HANDLESCOPE(isolate); |
+ Object& obj = isolate->ObjectHandle(); |
+ obj = arguments->NativeArgAt(arg_index); |
+ intptr_t cid = obj.GetClassId(); |
+ if (cid == kBigintCid) { |
+ *value = Bigint::Cast(obj).AsDoubleValue(); |
+ return true; |
+ } |
+ return false; |
+} |
+ |
+ |
+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, |
+ field_values)) { |
+ return Api::Success(); |
+ } |
+ Isolate* isolate = arguments->isolate(); |
+ ASSERT(isolate == Isolate::Current()); |
+ REUSABLE_OBJECT_HANDLESCOPE(isolate); |
+ Object& obj = isolate->ObjectHandle(); |
+ 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); |
+ } |
+ 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); |
+} |
+ |
+ |
Heap::Space SpaceForExternal(Isolate* isolate, intptr_t size) { |
Heap* heap = isolate->heap(); |
// If 'size' would be a significant fraction of new space, then use old. |
@@ -356,6 +492,74 @@ |
} |
+bool Api::GetNativeIntegerArgument(NativeArguments* arguments, |
+ int arg_index, |
+ int64_t* value) { |
+ NoGCScope no_gc_scope; |
+ 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) { |
+ NoGCScope no_gc_scope; |
+ 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) { |
+ NoGCScope no_gc_scope; |
+ RawObject* raw_obj = arguments->NativeArgAt(arg_index); |
+ if (raw_obj->IsHeapObject()) { |
+ intptr_t cid = raw_obj->GetClassId(); |
+ if (cid > kNumPredefinedCids) { |
+ 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, |
+ (num_fields * sizeof(field_values[0]))); |
+ } |
+ return true; |
+ } |
+ } |
+ return false; |
+} |
+ |
+ |
void Api::SetWeakHandleReturnValue(NativeArguments* args, |
Dart_WeakPersistentHandle retval) { |
args->SetReturnUnsafe(FinalizablePersistentHandle::Cast(retval)->raw()); |
@@ -4014,6 +4218,140 @@ |
} |
+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); |
+ ASSERT(arguments->isolate() == Isolate::Current()); |
+ 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); |
+ 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, |
+ &(native_value->as_bool))) { |
+ return Api::NewError("%s: expects argument at index %d to be of" |
+ " type Boolean.", CURRENT_FUNC, i); |
+ } |
+ 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); |
+ } |
+ 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); |
+ } |
+ 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); |
+ } |
+ 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); |
+ } |
+ native_value->as_uint64 = value; |
+ break; |
+ } |
+ |
+ case Dart_NativeArgument_kDouble: |
+ if (!GetNativeDoubleArgument(arguments, |
+ arg_index, |
+ &(native_value->as_double))) { |
+ return Api::NewError("%s: expects argument at index %d to be of" |
+ " type Double.", CURRENT_FUNC, i); |
+ } |
+ break; |
+ |
+ case Dart_NativeArgument_kString: |
+ if (!GetNativeStringArgument(arguments, |
+ arg_index, |
+ &(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); |
+ } |
+ 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); |
+ if (result != Api::Success()) { |
+ return result; |
+ } |
+ break; |
+ } |
+ |
+ case Dart_NativeArgument_kInstance: { |
+ Isolate* isolate = arguments->isolate(); |
+ ASSERT(isolate == Isolate::Current()); |
+ ASSERT(isolate->api_state() && |
+ isolate->api_state()->top_scope() != NULL); |
+ native_value->as_instance = |
+ Api::NewHandle(isolate, arguments->NativeArgAt(arg_index)); |
+ break; |
+ } |
+ |
+ default: |
+ return Api::NewError("%s: invalid argument type %d.", |
+ CURRENT_FUNC, arg_type); |
+ } |
+ } |
+ return Api::Success(); |
+} |
+ |
+ |
DART_EXPORT Dart_Handle Dart_GetNativeArgument(Dart_NativeArguments args, |
int index) { |
TRACE_API_CALL(CURRENT_FUNC); |
@@ -4048,30 +4386,11 @@ |
if (field_values == NULL) { |
RETURN_NULL_ERROR(field_values); |
} |
- Isolate* isolate = arguments->isolate(); |
- ASSERT(isolate == Isolate::Current()); |
- REUSABLE_OBJECT_HANDLESCOPE(isolate); |
- Object& obj = isolate->ObjectHandle(); |
- obj = arguments->NativeArgAt(arg_index); |
- if (obj.IsNull()) { |
- for (intptr_t i = 0; i < num_fields; i++) { |
- field_values[i] = 0; |
- } |
- return Api::Success(); |
- } |
- if (!obj.IsInstance()) { |
- return Api::NewError("%s expects argument at index '%d' to be of" |
- " type Instance.", CURRENT_FUNC, arg_index); |
- } |
- const Instance& instance = Instance::Cast(obj); |
- uint16_t field_count = instance.NumNativeFields(); |
- if (num_fields != field_count) { |
- return Api::NewError( |
- "%s: invalid 'field_values' array specified for returning field values", |
- CURRENT_FUNC); |
- } |
- instance.GetNativeFields(num_fields, field_values); |
- return Api::Success(); |
+ return GetNativeFieldsOfArgument(arguments, |
+ arg_index, |
+ num_fields, |
+ field_values, |
+ CURRENT_FUNC); |
} |
@@ -4094,23 +4413,12 @@ |
int arg_index, |
void** peer) { |
NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args); |
- Isolate* isolate = arguments->isolate(); |
- ASSERT(isolate == Isolate::Current()); |
- if (Api::StringGetPeerHelper(arguments, arg_index, peer)) { |
- return Api::Success(); |
+ 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); |
} |
- *peer = NULL; |
- REUSABLE_OBJECT_HANDLESCOPE(isolate); |
- Object& obj = isolate->ObjectHandle(); |
- obj = arguments->NativeArgAt(arg_index); |
- if (RawObject::IsStringClassId(obj.GetClassId())) { |
- return Api::NewHandle(isolate, obj.raw()); |
- } |
- if (obj.IsNull()) { |
- return Api::Null(); |
- } |
- return Api::NewError("%s expects argument to be of" |
- " type String.", CURRENT_FUNC); |
+ return result; |
} |
@@ -4124,33 +4432,11 @@ |
"%s: argument 'index' out of range. Expected 0..%d but saw %d.", |
CURRENT_FUNC, arguments->NativeArgCount() - 1, index); |
} |
- Isolate* isolate = arguments->isolate(); |
- ASSERT(isolate == Isolate::Current()); |
- REUSABLE_OBJECT_HANDLESCOPE(isolate); |
- Object& obj = isolate->ObjectHandle(); |
- obj = arguments->NativeArgAt(index); |
- intptr_t cid = obj.GetClassId(); |
- if (cid == kSmiCid) { |
- *value = Smi::Cast(obj).Value(); |
- return Api::Success(); |
+ if (!GetNativeIntegerArgument(arguments, index, value)) { |
+ return Api::NewError("%s: expects argument at %d to be of" |
+ " type Integer.", CURRENT_FUNC, index); |
} |
- if (cid == kMintCid) { |
- *value = Mint::Cast(obj).value(); |
- return Api::Success(); |
- } |
- if (cid == kBigintCid) { |
- const Bigint& bigint = Bigint::Cast(obj); |
- if (BigintOperations::FitsIntoInt64(bigint)) { |
- *value = BigintOperations::ToInt64(bigint); |
- return Api::Success(); |
- } |
- return Api::NewError( |
- "%s: argument %d is a big integer that does not fit in 'value'.", |
- CURRENT_FUNC, index); |
- } |
- return Api::NewError( |
- "%s: argument %d is not an Integer argument.", |
- CURRENT_FUNC, index); |
+ return Api::Success(); |
} |
@@ -4164,11 +4450,11 @@ |
"%s: argument 'index' out of range. Expected 0..%d but saw %d.", |
CURRENT_FUNC, arguments->NativeArgCount() - 1, index); |
} |
- if (Api::GetNativeBooleanArgument(arguments, index, value)) { |
- return Api::Success(); |
+ if (!Api::GetNativeBooleanArgument(arguments, index, value)) { |
+ return Api::NewError("%s: expects argument at %d to be of type Boolean.", |
+ CURRENT_FUNC, index); |
} |
- return Api::NewError("%s: argument %d is not a Boolean argument.", |
- CURRENT_FUNC, index); |
+ return Api::Success(); |
} |
@@ -4182,31 +4468,11 @@ |
"%s: argument 'index' out of range. Expected 0..%d but saw %d.", |
CURRENT_FUNC, arguments->NativeArgCount() - 1, index); |
} |
- Isolate* isolate = arguments->isolate(); |
- ASSERT(isolate == Isolate::Current()); |
- REUSABLE_OBJECT_HANDLESCOPE(isolate); |
- Object& obj = isolate->ObjectHandle(); |
- obj = arguments->NativeArgAt(index); |
- intptr_t cid = obj.GetClassId(); |
- if (cid == kDoubleCid) { |
- *value = Double::Cast(obj).value(); |
- return Api::Success(); |
+ if (!GetNativeDoubleArgument(arguments, index, value)) { |
+ return Api::NewError("%s: expects argument at %d to be of" |
+ " type Double.", CURRENT_FUNC, index); |
} |
- if (cid == kSmiCid) { |
- *value = Smi::Cast(obj).AsDoubleValue(); |
- return Api::Success(); |
- } |
- if (cid == kMintCid) { |
- *value = Mint::Cast(obj).AsDoubleValue(); |
- return Api::Success(); |
- } |
- if (cid == kBigintCid) { |
- *value = Bigint::Cast(obj).AsDoubleValue(); |
- return Api::Success(); |
- } |
- return Api::NewError( |
- "%s: argument %d is not a Double argument.", |
- CURRENT_FUNC, index); |
+ return Api::Success(); |
} |