Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(536)

Unified Diff: runtime/lib/typeddata.cc

Issue 12544015: Implement 'dart:typeddata' directly in the VM instead of using 'dart:scalarlist' (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | runtime/lib/typeddata.dart » ('j') | runtime/vm/object.cc » ('J')
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/lib/typeddata.cc
===================================================================
--- runtime/lib/typeddata.cc (revision 0)
+++ runtime/lib/typeddata.cc (revision 0)
@@ -0,0 +1,213 @@
+// 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 "vm/bootstrap_natives.h"
+
+#include "include/dart_api.h"
+
+#include "vm/bigint_operations.h"
+#include "vm/exceptions.h"
+#include "vm/native_entry.h"
+#include "vm/object.h"
+
+namespace dart {
+
+// TypedData.
+
+// Checks to see if offsetInBytes is in the range.
+static bool RangeCheck(intptr_t offsetInBytes, intptr_t lengthInBytes) {
+ return ((offsetInBytes >= 0) &&
+ (lengthInBytes > 0) &&
+ (offsetInBytes < lengthInBytes));
+}
+
+
+// Checks to see if a length will not result in an OOM error.
+static void LengthCheck(intptr_t len, intptr_t max) {
+ ASSERT(len >= 0);
+ if (len > max) {
+ const String& error = String::Handle(String::NewFormatted(
+ "insufficient memory to allocate a TypedData object of length (%"Pd")",
+ len));
+ const Array& args = Array::Handle(Array::New(1));
+ args.SetAt(0, error);
+ Exceptions::ThrowByType(Exceptions::kOutOfMemory, args);
+ }
+}
+
+
+static void PeerFinalizer(Dart_Handle handle, void* peer) {
+ Dart_DeletePersistentHandle(handle);
+ OS::AlignedFree(peer);
+}
+
+
+DEFINE_NATIVE_ENTRY(TypedData_length, 1) {
+ GET_NON_NULL_NATIVE_ARGUMENT(Instance, instance, arguments->NativeArgAt(0));
+ if (instance.IsTypedData()) {
+ const TypedData& array = TypedData::Cast(instance);
+ return Smi::New(array.Length());
+ }
+ ASSERT(instance.IsExternalTypedData());
Ivan Posva 2013/03/07 08:53:31 I am not sure the ASSERT here is good enough. As t
siva 2013/03/07 21:47:43 Changed the ASSERT to thrown an ArgumentError exce
+ const ExternalTypedData& array = ExternalTypedData::Cast(instance);
+ return Smi::New(array.Length());
+}
+
+
+#define TYPED_DATA_NEW(name) \
+DEFINE_NATIVE_ENTRY(TypedData_##name##_new, 1) { \
+ GET_NON_NULL_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(0)); \
+ intptr_t cid = kTypedData##name##Cid; \
+ intptr_t len = length.Value(); \
+ intptr_t max = (kSmiMax / TypedData::ElementSizeInBytes(cid)); \
Ivan Posva 2013/03/07 08:53:31 Please comment why you have this restriction here.
siva 2013/03/07 21:47:43 Done.
+ LengthCheck(len, max); \
+ return TypedData::New(cid, len); \
+} \
+
+
+#define EXT_TYPED_DATA_NEW(name) \
+DEFINE_NATIVE_ENTRY(ExternalTypedData_##name##_new, 1) { \
+ const int kAlignment = 16; \
+ GET_NON_NULL_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(0)); \
+ intptr_t cid = kExternalTypedData##name##Cid; \
+ intptr_t len = length.Value(); \
+ intptr_t max = (kSmiMax / ExternalTypedData::ElementSizeInBytes(cid)); \
Ivan Posva 2013/03/07 08:53:31 ditto
siva 2013/03/07 21:47:43 Done.
+ LengthCheck(len, max); \
+ intptr_t len_bytes = len * ExternalTypedData::ElementSizeInBytes(cid); \
+ uint8_t* data = OS::AllocateAlignedArray<uint8_t>(len_bytes, kAlignment); \
+ const ExternalTypedData& obj = \
+ ExternalTypedData::Handle(ExternalTypedData::New(cid, data, len)); \
+ obj.AddFinalizer(data, PeerFinalizer); \
+ return obj.raw(); \
+} \
+
+
+#define TYPED_DATA_NEW_NATIVE(name) \
+ TYPED_DATA_NEW(name) \
+ EXT_TYPED_DATA_NEW(name) \
+
+
+CLASS_LIST_TYPED_DATA(TYPED_DATA_NEW_NATIVE)
+
+
+#define TYPED_DATA_GETTER(getter, object) \
+DEFINE_NATIVE_ENTRY(TypedData_##getter, 2) { \
+ GET_NON_NULL_NATIVE_ARGUMENT(Instance, instance, arguments->NativeArgAt(0)); \
+ GET_NON_NULL_NATIVE_ARGUMENT(Smi, index, arguments->NativeArgAt(1)); \
+ if (instance.IsTypedData()) { \
+ const TypedData& array = TypedData::Cast(instance); \
+ intptr_t offsetInBytes = index.Value() * array.ElementSizeInBytes(); \
+ ASSERT(RangeCheck(offsetInBytes, array.LengthInBytes())); \
+ return object::New(array.getter(offsetInBytes)); \
+ } \
+ ASSERT(instance.IsExternalTypedData()); \
Ivan Posva 2013/03/07 08:53:31 ditto
siva 2013/03/07 21:47:43 Done.
+ const ExternalTypedData& array = ExternalTypedData::Cast(instance); \
+ intptr_t offsetInBytes = index.Value() * array.ElementSizeInBytes(); \
+ ASSERT(RangeCheck(offsetInBytes, array.LengthInBytes())); \
+ return object::New(array.getter(offsetInBytes)); \
+} \
+
+
+#define TYPED_DATA_SETTER(setter, object, get_object_value) \
+DEFINE_NATIVE_ENTRY(TypedData_##setter, 3) { \
+ GET_NON_NULL_NATIVE_ARGUMENT(Instance, instance, arguments->NativeArgAt(0)); \
+ GET_NON_NULL_NATIVE_ARGUMENT(Smi, index, arguments->NativeArgAt(1)); \
+ GET_NON_NULL_NATIVE_ARGUMENT(object, value, arguments->NativeArgAt(2)); \
+ if (instance.IsTypedData()) { \
+ const TypedData& array = TypedData::Cast(instance); \
+ intptr_t offsetInBytes = index.Value() * array.ElementSizeInBytes(); \
+ ASSERT(RangeCheck(offsetInBytes, array.LengthInBytes())); \
+ array.setter(offsetInBytes, value.get_object_value()); \
+ } else { \
+ ASSERT(instance.IsExternalTypedData()); \
Ivan Posva 2013/03/07 08:53:31 ditto
siva 2013/03/07 21:47:43 Done.
+ const ExternalTypedData& array = ExternalTypedData::Cast(instance); \
+ intptr_t offsetInBytes = index.Value() * array.ElementSizeInBytes(); \
+ ASSERT(RangeCheck(offsetInBytes, array.LengthInBytes())); \
+ array.setter(offsetInBytes, value.get_object_value()); \
+ } \
+ return Object::null(); \
+}
+
+
+#define TYPED_DATA_UINT64_GETTER(getter, object) \
+DEFINE_NATIVE_ENTRY(TypedData_##getter, 2) { \
+ GET_NON_NULL_NATIVE_ARGUMENT(Instance, instance, arguments->NativeArgAt(0)); \
+ GET_NON_NULL_NATIVE_ARGUMENT(Smi, index, arguments->NativeArgAt(1)); \
+ uint64_t value = 0; \
+ if (instance.IsTypedData()) { \
+ const TypedData& array = TypedData::Cast(instance); \
+ intptr_t offsetInBytes = index.Value() * array.ElementSizeInBytes(); \
+ ASSERT(RangeCheck(offsetInBytes, array.LengthInBytes())); \
+ value = array.getter(offsetInBytes); \
+ } else { \
+ ASSERT(instance.IsExternalTypedData()); \
Ivan Posva 2013/03/07 08:53:31 ditto
siva 2013/03/07 21:47:43 Done.
+ const ExternalTypedData& array = ExternalTypedData::Cast(instance); \
+ intptr_t offsetInBytes = index.Value() * array.ElementSizeInBytes(); \
+ ASSERT(RangeCheck(offsetInBytes, array.LengthInBytes())); \
+ value = array.getter(offsetInBytes); \
+ } \
+ Integer& result = Integer::Handle(); \
+ if (value > static_cast<uint64_t>(Mint::kMaxValue)) { \
+ result = BigintOperations::NewFromUint64(value); \
+ } else if (value > static_cast<uint64_t>(Smi::kMaxValue)) { \
+ result = Mint::New(value); \
+ } else { \
+ result = Smi::New(value); \
+ } \
+ return result.raw(); \
+} \
+
+
+#define TYPED_DATA_UINT64_SETTER(setter, object) \
+DEFINE_NATIVE_ENTRY(TypedData_##setter, 3) { \
+ GET_NON_NULL_NATIVE_ARGUMENT(Instance, instance, arguments->NativeArgAt(0)); \
+ GET_NON_NULL_NATIVE_ARGUMENT(Smi, index, arguments->NativeArgAt(1)); \
+ GET_NON_NULL_NATIVE_ARGUMENT(object, value, arguments->NativeArgAt(2)); \
+ uint64_t object_value; \
+ if (value.IsBigint()) { \
+ const Bigint& bigint = Bigint::Cast(value); \
+ ASSERT(BigintOperations::FitsIntoUint64(bigint)); \
Ivan Posva 2013/03/07 08:53:31 This assert is strange here. Shouldn't this just t
siva 2013/03/07 21:47:43 I don't see a truncate operation in our current bi
+ object_value = BigintOperations::AbsToUint64(bigint); \
+ } else { \
+ ASSERT(value.IsMint() || value.IsSmi()); \
+ object_value = value.AsInt64Value(); \
+ } \
+ if (instance.IsTypedData()) { \
+ const TypedData& array = TypedData::Cast(instance); \
+ intptr_t offsetInBytes = index.Value() * array.ElementSizeInBytes(); \
+ ASSERT(RangeCheck(offsetInBytes, array.LengthInBytes())); \
+ array.setter(offsetInBytes, object_value); \
+ } else { \
+ ASSERT(instance.IsExternalTypedData()); \
Ivan Posva 2013/03/07 08:53:31 ditto
siva 2013/03/07 21:47:43 Done.
+ const ExternalTypedData& array = ExternalTypedData::Cast(instance); \
+ intptr_t offsetInBytes = index.Value() * array.ElementSizeInBytes(); \
+ ASSERT(RangeCheck(offsetInBytes, array.LengthInBytes())); \
+ array.setter(offsetInBytes, object_value); \
+ } \
+ return Object::null(); \
+}
+
+
+#define TYPED_DATA_NATIVES(name, getter, setter, object, get_object_value) \
+ TYPED_DATA_GETTER(getter, object) \
+ TYPED_DATA_SETTER(setter, object, get_object_value) \
+
+
+#define TYPED_DATA_UINT64_NATIVES(name, getter, setter, object) \
+ TYPED_DATA_UINT64_GETTER(getter, object) \
+ TYPED_DATA_UINT64_SETTER(setter, object) \
+
+
+TYPED_DATA_NATIVES(Int8Array, GetInt8, SetInt8, Smi, Value)
+TYPED_DATA_NATIVES(Uint8Array, GetUint8, SetUint8, Smi, Value)
+TYPED_DATA_NATIVES(Int16Array, GetInt16, SetInt16, Smi, Value)
+TYPED_DATA_NATIVES(Uint16Array, GetUint16, SetUint16, Smi, Value)
+TYPED_DATA_NATIVES(Int32Array, GetInt32, SetInt32, Integer, AsInt64Value)
+TYPED_DATA_NATIVES(Uint32Array, GetUint32, SetUint32, Integer, AsInt64Value)
+TYPED_DATA_NATIVES(Int64Array, GetInt64, SetInt64, Integer, AsInt64Value)
+TYPED_DATA_UINT64_NATIVES(Uint64Array, GetUint64, SetUint64, Integer)
+TYPED_DATA_NATIVES(Float32Array, GetFloat32, SetFloat32, Double, value)
+TYPED_DATA_NATIVES(Float64Array, GetFloat64, SetFloat64, Double, value)
+
+} // namespace dart
« no previous file with comments | « no previous file | runtime/lib/typeddata.dart » ('j') | runtime/vm/object.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698