Index: runtime/lib/typed_data.dart |
diff --git a/runtime/lib/typed_data.dart b/runtime/lib/typed_data.dart |
index 376acb33bdc84a791d5644389e0dbfd48ffef9c9..a7910f83061463c845659e5d6d7dc9a98d34d6c8 100644 |
--- a/runtime/lib/typed_data.dart |
+++ b/runtime/lib/typed_data.dart |
@@ -298,7 +298,7 @@ patch class Int32x4 { |
patch class ByteData { |
/* patch */ factory ByteData(int length) { |
var list = new _Uint8Array(length); |
- return new _ByteDataView(list.buffer, 0, length); |
+ return new _ByteDataView(list, 0, length); |
} |
/* patch */ factory ByteData.view(ByteBuffer buffer, |
@@ -306,8 +306,13 @@ patch class ByteData { |
if (length == null) { |
length = buffer.lengthInBytes - offsetInBytes; |
} |
- return new _ByteDataView(buffer, offsetInBytes, length); |
+ _ByteBuffer internalBuffer = buffer; |
+ return new _ByteDataView(internalBuffer._typedData, offsetInBytes, length); |
} |
+ |
+ // Called directly from C code. |
+ factory ByteData._view(TypedData typedData, int offsetInBytes, int length) |
+ => new _ByteDataView(typedData, offsetInBytes, length); |
} |
@@ -554,11 +559,14 @@ abstract class _TypedListBase { |
if (needsClamping) { |
Lists.copy(from, skipCount, this, start, count); |
return; |
- } else if (this.buffer._setRange( |
- start * elementSizeInBytes + this.offsetInBytes, |
- count * elementSizeInBytes, |
- from.buffer, |
- skipCount * elementSizeInBytes + from.offsetInBytes)) { |
+ } |
+ _ByteBuffer buffer = this.buffer; |
+ _ByteBuffer fromBuffer = from.buffer; |
+ if (buffer._typedData._setRange( |
+ start * elementSizeInBytes + this.offsetInBytes, |
+ count * elementSizeInBytes, |
+ fromBuffer._typedData, |
+ skipCount * elementSizeInBytes + from.offsetInBytes)) { |
return; |
} |
} else if (from.buffer == this.buffer) { |
@@ -607,7 +615,13 @@ abstract class _TypedListBase { |
} |
-abstract class _TypedList extends _TypedListBase implements ByteBuffer { |
+abstract class _TypedList extends _TypedListBase { |
+ // The [buffer] getter should return the same value each time. |
+ // Store it here the first time it is created. |
+ // We don't want to store it on the object, since not all typed lists |
+ // have a buffer extracted. |
+ static var _buffers = new Expando(); |
+ |
// Default method implementing parts of the TypedData interface. |
int get offsetInBytes { |
return 0; |
@@ -618,7 +632,12 @@ abstract class _TypedList extends _TypedListBase implements ByteBuffer { |
} |
ByteBuffer get buffer { |
- return this; |
+ _ByteBuffer buffer = _buffers[this]; |
+ if (buffer == null) { |
+ buffer = new _ByteBuffer(this); |
+ _buffers[this] = buffer; |
+ } |
+ return buffer; |
} |
// Methods implementing the collection interface. |
@@ -2334,11 +2353,14 @@ class _TypedListIterator<E> implements Iterator<E> { |
class _TypedListView extends _TypedListBase implements TypedData { |
+ final TypedData _typedData; |
+ final int offsetInBytes; |
+ final int length; |
+ |
_TypedListView(ByteBuffer _buffer, int _offset, int _length) |
- : _typedData = _buffer, // This assignment is type safe. |
- offsetInBytes = _offset, |
- length = _length { |
- } |
+ : _typedData = (_buffer as _ByteBuffer)._typedData, |
+ offsetInBytes = _offset, |
+ length = _length; |
// Method(s) implementing the TypedData interface. |
@@ -2349,10 +2371,6 @@ class _TypedListView extends _TypedListBase implements TypedData { |
ByteBuffer get buffer { |
return _typedData.buffer; |
} |
- |
- final TypedData _typedData; |
- final int offsetInBytes; |
- final int length; |
} |
@@ -3033,14 +3051,17 @@ class _Int32x4ArrayView extends _TypedListView implements Int32x4List { |
class _ByteDataView implements ByteData { |
- _ByteDataView(ByteBuffer _buffer, int _offsetInBytes, int _lengthInBytes) |
- : _typedData = _buffer, // _buffer is guaranteed to be a TypedData here. |
+ final TypedData _typedData; |
+ final int _offset; |
+ final int length; |
+ |
+ _ByteDataView(TypedData typedData, int _offsetInBytes, int _lengthInBytes) |
+ : _typedData = typedData, |
_offset = _offsetInBytes, |
length = _lengthInBytes { |
- _rangeCheck(_buffer.lengthInBytes, _offset, length); |
+ _rangeCheck(typedData.lengthInBytes, _offset, length); |
} |
- |
// Method(s) implementing TypedData interface. |
ByteBuffer get buffer { |
@@ -3311,11 +3332,6 @@ class _ByteDataView implements ByteData { |
native "ByteData_ToEndianFloat32"; |
static double _toEndianFloat64(double host_value, bool little_endian) |
native "ByteData_ToEndianFloat64"; |
- |
- |
- final TypedData _typedData; |
- final int _offset; |
- final int length; |
} |
@@ -3407,3 +3423,18 @@ void _throwRangeError(int index, int length) { |
String message = "$index must be in the range [0..$length)"; |
throw new RangeError(message); |
} |
+ |
+/** |
+ * Internal implementation of [ByteBuffer]. |
+ */ |
+class _ByteBuffer implements ByteBuffer { |
+ final _TypedList _typedData; |
+ |
+ _ByteBuffer(this._typedData); |
+ |
+ int get lengthInBytes => _typedData.lengthInBytes; |
+ |
+ int get hashCode => _typedData.hashCode; |
+ bool operator==(Object other) => |
+ other is _ByteBuffer && _typedData == other._typedData; |
+} |