Revert "[vm/ffi] Enable creating an ExternalTypedData from a Pointer."

This reverts commit ddd83d256f.

Reason for revert: Causing build failures in the Flutter engine, blocking the SDK roll. Build error:

org-dartlang-sdk:///third_party/dart/runtime/lib/ffi_patch.dart:76:3: Error: Type 'TypedData' not found.
  TypedData asExternalTypedData({int count: 1}) =>
  ^^^^^^^^^



Original change's description:
> [vm/ffi] Enable creating an ExternalTypedData from a Pointer.
> 
> Fixes dartbug.com/37738
> 
> Change-Id: I65c6741978d36cd1c255039a4dd8a06190ea4366
> Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/111736
> Commit-Queue: Samir Jindel <sjindel@google.com>
> Reviewed-by: Daco Harkes <dacoharkes@google.com>

TBR=vegorov@google.com,sjindel@google.com,dacoharkes@google.com

Change-Id: I90a9cb5e2894c0bc064e620cef0a0f51505ac05d
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/112047
Reviewed-by: Ben Konyi <bkonyi@google.com>
Commit-Queue: Ben Konyi <bkonyi@google.com>
This commit is contained in:
Ben Konyi 2019-08-06 19:52:11 +00:00 committed by commit-bot@chromium.org
parent 193985777d
commit c262cbd414
8 changed files with 4 additions and 392 deletions

View file

@ -608,75 +608,6 @@ DEFINE_NATIVE_ENTRY(Ffi_fromFunction, 1, 2) {
#endif
}
DEFINE_NATIVE_ENTRY(Ffi_asExternalTypedData, 0, 2) {
GET_NON_NULL_NATIVE_ARGUMENT(Pointer, pointer, arguments->NativeArgAt(0));
GET_NON_NULL_NATIVE_ARGUMENT(Integer, count, arguments->NativeArgAt(1));
const AbstractType& pointer_type_arg =
AbstractType::Handle(pointer.type_argument());
const classid_t type_cid = pointer_type_arg.type_class_id();
classid_t cid = 0;
switch (type_cid) {
case kFfiInt8Cid:
cid = kExternalTypedDataInt8ArrayCid;
break;
case kFfiUint8Cid:
cid = kExternalTypedDataUint8ArrayCid;
break;
case kFfiInt16Cid:
cid = kExternalTypedDataInt16ArrayCid;
break;
case kFfiUint16Cid:
cid = kExternalTypedDataUint16ArrayCid;
break;
case kFfiInt32Cid:
cid = kExternalTypedDataInt32ArrayCid;
break;
case kFfiUint32Cid:
cid = kExternalTypedDataUint32ArrayCid;
break;
case kFfiInt64Cid:
cid = kExternalTypedDataInt64ArrayCid;
break;
case kFfiUint64Cid:
cid = kExternalTypedDataUint64ArrayCid;
break;
case kFfiIntPtrCid:
cid = kWordSize == 4 ? kExternalTypedDataInt32ArrayCid
: kExternalTypedDataInt64ArrayCid;
break;
case kFfiFloatCid:
cid = kExternalTypedDataFloat32ArrayCid;
break;
case kFfiDoubleCid:
cid = kExternalTypedDataFloat64ArrayCid;
break;
default: {
const String& error = String::Handle(
String::NewFormatted("Cannot create a TypedData from a Pointer to %s",
pointer_type_arg.ToCString()));
Exceptions::ThrowArgumentError(error);
UNREACHABLE();
}
}
const intptr_t element_count = count.AsInt64Value();
if (element_count < 0 ||
element_count > ExternalTypedData::MaxElements(cid)) {
const String& error = String::Handle(
String::NewFormatted("Count must be in the range [0, %" Pd "].",
ExternalTypedData::MaxElements(cid)));
Exceptions::ThrowArgumentError(error);
}
const intptr_t element_size = ExternalTypedData::ElementSizeInBytes(cid);
const size_t byte_length = count.AsInt64Value() * element_size;
return ExternalTypedData::New(
cid, reinterpret_cast<uint8_t*>(pointer.NativeAddress()),
count.AsInt64Value(), thread->heap()->SpaceForExternal(byte_length));
}
#if defined(TARGET_ARCH_DBC)
void FfiMarshalledArguments::SetFunctionAddress(uint64_t value) const {

View file

@ -3,7 +3,6 @@
// BSD-style license that can be found in the LICENSE file.
import "dart:_internal" show patch;
import 'dart:typed_data' show TypedData;
@patch
int sizeOf<T extends NativeType>() native "Ffi_sizeOf";
@ -18,9 +17,6 @@ Pointer<T> _fromAddress<T extends NativeType>(int ptr) native "Ffi_fromAddress";
DS _asFunctionInternal<DS extends Function, NS extends Function>(
Pointer<NativeFunction<NS>> ptr) native "Ffi_asFunctionInternal";
dynamic _asExternalTypedData(Pointer ptr, int count)
native "Ffi_asExternalTypedData";
@patch
@pragma("vm:entry-point")
class Pointer<T extends NativeType> {
@ -71,8 +67,4 @@ class Pointer<T extends NativeType> {
@patch
void free() native "Ffi_free";
@patch
TypedData asExternalTypedData({int count: 1}) =>
_asExternalTypedData(this, count);
}

View file

@ -388,7 +388,6 @@ namespace dart {
V(Ffi_dl_open, 1) \
V(Ffi_dl_lookup, 2) \
V(Ffi_dl_getHandle, 1) \
V(Ffi_asExternalTypedData, 2) \
V(TransferableTypedData_factory, 2) \
V(TransferableTypedData_materialize, 1)

View file

@ -6,8 +6,6 @@
/// {@nodoc}
library dart.ffi;
import 'dart:typed_data' show TypedData;
part "native_type.dart";
part "annotations.dart";
part "dynamic_library.dart";
@ -93,29 +91,6 @@ class Pointer<T extends NativeType> extends NativeType {
/// Note that this zeros out the address.
external void free();
/// Creates an *external* typed data array backed by this pointer.
///
/// The typed data array returned is only valid for as long as the backing
/// [Pointer]. Accessing any element of the type data array after this
/// [Pointer] has been [Pointer.free()]d will cause undefined behavior.
///
/// Since [Pointer]s do not know their length, the size of the typed data is
/// controlled by `count`, in units of the size of the native type for this
/// [Pointer] (similarly to [Pointer.allocate]).
///
/// The kind of TypedData produced depends on the native type:
///
/// Pointer<Int8> -> Int8List
/// Pointer<Uint8> -> Uint8List
/// etc. up to Int64/Uint64
/// Pointer<IntPtr> -> Int32List/Int64List depending on platform word size
/// Pointer<Float> -> Float32List
/// Pointer<Double> -> Float64List
///
/// Creation of a [Uint8ClampedList] is not supported. Creation of a typed
/// data from a [Pointer] to any other native type is not supported.
external TypedData asExternalTypedData({int count: 1});
/// Equality for Pointers only depends on their address.
bool operator ==(other) {
if (other == null) return false;

View file

@ -65,9 +65,9 @@
},
"ffi": {
"patches": [
"../../runtime/lib/ffi_patch.dart",
"../../runtime/lib/ffi_dynamic_library_patch.dart",
"../../runtime/lib/ffi_native_type_patch.dart"
"../../runtime/lib/ffi_native_type_patch.dart",
"../../runtime/lib/ffi_patch.dart"
],
"uri": "ffi/ffi.dart"
},

View file

@ -90,9 +90,9 @@ vm:
ffi:
uri: "ffi/ffi.dart"
patches:
- "../../runtime/lib/ffi_patch.dart"
- "../../runtime/lib/ffi_dynamic_library_patch.dart"
- "../../runtime/lib/ffi_native_type_patch.dart"
- "../../runtime/lib/ffi_patch.dart"
_http:
uri: "_http/http.dart"

View file

@ -1,285 +0,0 @@
// Copyright (c) 2019, 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.
import 'dart:ffi';
import 'dart:math';
import 'dart:typed_data';
import 'package:expect/expect.dart';
main() {
testInt8Load();
testInt8Store();
testUint8Load();
testUint8Store();
testInt16Load();
testInt16Store();
testUint16Load();
testUint16Store();
testInt32Load();
testInt32Store();
testUint32Load();
testUint32Store();
testInt64Load();
testInt64Store();
testUint64Load();
testUint64Store();
testIntPtr();
testFloatLoad();
testFloatStore();
testDoubleLoad();
testDoubleStore();
testArrayLoad();
testArrayStore();
testNegativeArray();
}
// For signed int tests, we store 0xf* and load -1 to check sign-extension.
// For unsigned int tests, we store 0xf* and load the same to check truncation.
void testInt8Load() {
// Load
Pointer<Int8> ptr = Pointer.allocate();
ptr.store(0xff);
Int8List list = ptr.asExternalTypedData();
Expect.equals(list[0], -1);
Expect.equals(list.length, 1);
ptr.free();
}
void testInt8Store() {
// Store
Pointer<Int8> ptr = Pointer.allocate();
Int8List list = ptr.asExternalTypedData();
list[0] = 0xff;
Expect.equals(list.length, 1);
Expect.equals(ptr.load<int>(), -1);
ptr.free();
}
void testUint8Load() {
// Load
Pointer<Uint8> ptr = Pointer.allocate();
ptr.store(0xff);
Uint8List list = ptr.asExternalTypedData();
Expect.equals(list[0], 0xff);
Expect.equals(list.length, 1);
ptr.free();
}
void testUint8Store() {
// Store
Pointer<Uint8> ptr = Pointer.allocate();
Uint8List list = ptr.asExternalTypedData();
list[0] = 0xff;
Expect.equals(list.length, 1);
Expect.equals(ptr.load<int>(), 0xff);
ptr.free();
}
void testInt16Load() {
// Load
Pointer<Int16> ptr = Pointer.allocate();
ptr.store(0xffff);
Int16List list = ptr.asExternalTypedData();
Expect.equals(list[0], -1);
Expect.equals(list.length, 1);
ptr.free();
}
void testInt16Store() {
// Store
Pointer<Int16> ptr = Pointer.allocate();
Int16List list = ptr.asExternalTypedData();
list[0] = 0xffff;
Expect.equals(list.length, 1);
Expect.equals(ptr.load<int>(), -1);
ptr.free();
}
void testUint16Load() {
// Load
Pointer<Uint16> ptr = Pointer.allocate();
ptr.store(0xffff);
Uint16List list = ptr.asExternalTypedData();
Expect.equals(list[0], 0xffff);
Expect.equals(list.length, 1);
ptr.free();
}
void testUint16Store() {
// Store
Pointer<Uint16> ptr = Pointer.allocate();
Uint16List list = ptr.asExternalTypedData();
list[0] = 0xffff;
Expect.equals(list.length, 1);
Expect.equals(ptr.load<int>(), 0xffff);
ptr.free();
}
void testInt32Load() {
// Load
Pointer<Int32> ptr = Pointer.allocate();
ptr.store(0xffffffff);
Int32List list = ptr.asExternalTypedData();
Expect.equals(list[0], -1);
Expect.equals(list.length, 1);
ptr.free();
}
void testInt32Store() {
// Store
Pointer<Int32> ptr = Pointer.allocate();
Int32List list = ptr.asExternalTypedData();
list[0] = 0xffffffff;
Expect.equals(list.length, 1);
Expect.equals(ptr.load<int>(), -1);
ptr.free();
}
void testUint32Load() {
// Load
Pointer<Uint32> ptr = Pointer.allocate();
ptr.store(0xffffffff);
Uint32List list = ptr.asExternalTypedData();
Expect.equals(list[0], 0xffffffff);
Expect.equals(list.length, 1);
ptr.free();
}
void testUint32Store() {
// Store
Pointer<Uint32> ptr = Pointer.allocate();
Uint32List list = ptr.asExternalTypedData();
list[0] = 0xffffffff;
Expect.equals(list.length, 1);
Expect.equals(ptr.load<int>(), 0xffffffff);
ptr.free();
}
void testInt64Load() {
// Load
Pointer<Int64> ptr = Pointer.allocate();
ptr.store(0xffffffffffffffff);
Int64List list = ptr.asExternalTypedData();
Expect.equals(list[0], -1);
Expect.equals(list.length, 1);
ptr.free();
}
void testInt64Store() {
// Store
Pointer<Int64> ptr = Pointer.allocate();
Int64List list = ptr.asExternalTypedData();
list[0] = 0xffffffffffffffff;
Expect.equals(list.length, 1);
Expect.equals(ptr.load<int>(), -1);
ptr.free();
}
void testUint64Load() {
// Load
Pointer<Uint64> ptr = Pointer.allocate();
ptr.store(0xffffffffffffffff);
Uint64List list = ptr.asExternalTypedData();
Expect.equals(list[0], 0xffffffffffffffff);
Expect.equals(list.length, 1);
ptr.free();
}
void testUint64Store() {
// Store
Pointer<Uint64> ptr = Pointer.allocate();
Uint64List list = ptr.asExternalTypedData();
list[0] = 0xffffffffffffffff;
Expect.equals(list.length, 1);
Expect.equals(ptr.load<int>(), 0xffffffffffffffff);
ptr.free();
}
void testIntPtr() {
bool is32Bit = sizeOf<IntPtr>() == 4;
Pointer<IntPtr> ptr = Pointer.allocate();
final array = ptr.asExternalTypedData();
if (is32Bit) {
Expect.type<Int32List>(array);
} else {
Expect.type<Int64List>(array);
}
ptr.free();
}
double maxFloat = (2 - pow(2, -23)) * pow(2, 127);
double maxDouble = (2 - pow(2, -52)) * pow(2, pow(2, 10) - 1);
void testFloatLoad() {
// Load
Pointer<Float> ptr = Pointer.allocate();
ptr.store(maxFloat);
Float32List list = ptr.asExternalTypedData();
Expect.equals(list[0], maxFloat);
Expect.equals(list.length, 1);
ptr.free();
}
void testFloatStore() {
// Store
Pointer<Float> ptr = Pointer.allocate();
Float32List list = ptr.asExternalTypedData();
list[0] = maxFloat;
Expect.equals(list.length, 1);
Expect.equals(ptr.load<double>(), maxFloat);
ptr.free();
}
void testDoubleLoad() {
// Load
Pointer<Double> ptr = Pointer.allocate();
ptr.store(maxDouble);
Float64List list = ptr.asExternalTypedData();
Expect.equals(list[0], maxDouble);
Expect.equals(list.length, 1);
ptr.free();
}
void testDoubleStore() {
// Store
Pointer<Double> ptr = Pointer.allocate();
Float64List list = ptr.asExternalTypedData();
list[0] = maxDouble;
Expect.equals(list.length, 1);
Expect.equals(ptr.load<double>(), maxDouble);
ptr.free();
}
void testArrayLoad() {
const int count = 0x100;
Pointer<Int32> ptr = Pointer.allocate(count: count);
for (int i = 0; i < count; ++i) {
ptr.elementAt(i).store(i);
}
Int32List array = ptr.asExternalTypedData(count: count);
for (int i = 0; i < count; ++i) {
Expect.equals(array[i], i);
}
ptr.free();
}
void testArrayStore() {
const int count = 0x100;
Pointer<Int32> ptr = Pointer.allocate(count: count);
Int32List array = ptr.asExternalTypedData(count: count);
for (int i = 0; i < count; ++i) {
array[i] = i;
}
for (int i = 0; i < count; ++i) {
Expect.equals(ptr.elementAt(i).load<int>(), i);
}
ptr.free();
}
void testNegativeArray() {
Pointer<Int32> ptr = nullptr.cast();
Expect.throws<ArgumentError>(() => ptr.asExternalTypedData(count: -1));
}

View file

@ -25,7 +25,7 @@ function_callbacks_test: Skip # Issue dartbug.com/37295
*: Skip # "hardfp" calling convention is not yet supported (iOS is also supported but not tested): dartbug.com/36309
[ $arch == simdbc64 && $system != linux && $system != macos ]
*: Skip # DBC is only supported on MacOS and Linux for testing
*: Skip # FFI not yet supported outside x64 Linux: dartbug.com/36809
[ $runtime != dart_precompiled && $runtime != vm ]
*: SkipByDesign # FFI is a VM-only feature. (This test suite is part of the default set.)