8b68d343c7
avoid overflow. For each variable size heap object, compute the maximum number of elements and use that in the ::New functions to avoid overflow. If a bad length/size reaches a ::New function, that is a FATAL error -- the problem should have been caught earlier by the dart api or by the library code. Add "border guards" in the dart api and in library calls which cause new variable size heap objects to be allocated. We check for invalid length/size and throw explanatory error messages. Review URL: https://chromiumcodereview.appspot.com//10782016 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@10130 260f80e4-7a28-3924-810f-c04153c831b5
610 lines
17 KiB
C++
610 lines
17 KiB
C++
// Copyright (c) 2012, 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 "vm/bigint_operations.h"
|
|
#include "vm/exceptions.h"
|
|
#include "vm/native_entry.h"
|
|
#include "vm/object.h"
|
|
|
|
namespace dart {
|
|
|
|
// ByteArray
|
|
|
|
// Checks to see if (index * num_bytes) is in the range
|
|
// [0..array.ByteLength()). without the risk of integer overflow. If
|
|
// the index is out of range, then an IndexOutOfRangeException is thrown.
|
|
static void RangeCheck(const ByteArray& array,
|
|
intptr_t index,
|
|
intptr_t num_bytes) {
|
|
if (!Utils::RangeCheck(index, num_bytes, array.ByteLength())) {
|
|
const String& error = String::Handle(String::NewFormatted(
|
|
"index (%ld) must be in the range [0..%ld)",
|
|
index, (array.ByteLength() / num_bytes)));
|
|
GrowableArray<const Object*> args;
|
|
args.Add(&error);
|
|
Exceptions::ThrowByType(Exceptions::kIndexOutOfRange, args);
|
|
}
|
|
}
|
|
|
|
|
|
// Checks to see if a length is in the range [0..max]. If the length
|
|
// is out of range, then an IllegalArgumentException is thrown.
|
|
static void LengthCheck(intptr_t len, intptr_t max) {
|
|
if (len < 0 || len > max) {
|
|
const String& error = String::Handle(String::NewFormatted(
|
|
"length (%ld) must be in the range [0..%ld]", len, max));
|
|
GrowableArray<const Object*> args;
|
|
args.Add(&error);
|
|
Exceptions::ThrowByType(Exceptions::kIllegalArgument, args);
|
|
}
|
|
}
|
|
|
|
|
|
#define GETTER_ARGUMENTS(ArrayT, ValueT) \
|
|
GET_NATIVE_ARGUMENT(ArrayT, array, arguments->At(0)); \
|
|
GET_NATIVE_ARGUMENT(Smi, index, arguments->At(1));
|
|
|
|
|
|
#define SETTER_ARGUMENTS(ArrayT, ObjectT, ValueT) \
|
|
GET_NATIVE_ARGUMENT(ArrayT, array, arguments->At(0)); \
|
|
GET_NATIVE_ARGUMENT(Smi, index, arguments->At(1)); \
|
|
GET_NATIVE_ARGUMENT(ObjectT, value_object, arguments->At(2));
|
|
|
|
|
|
#define GETTER(ArrayT, ObjectT, ValueT) \
|
|
GETTER_ARGUMENTS(ArrayT, ValueT); \
|
|
RangeCheck(array, index.Value() * sizeof(ValueT), sizeof(ValueT)); \
|
|
ValueT result = array.At(index.Value()); \
|
|
arguments->SetReturn(ObjectT::Handle(ObjectT::New(result)));
|
|
|
|
|
|
#define SETTER(ArrayT, ObjectT, Getter, ValueT) \
|
|
SETTER_ARGUMENTS(ArrayT, ObjectT, ValueT); \
|
|
RangeCheck(array, index.Value() * sizeof(ValueT), sizeof(ValueT)); \
|
|
ValueT value = value_object.Getter(); \
|
|
array.SetAt(index.Value(), value);
|
|
|
|
|
|
#define UNALIGNED_GETTER(ArrayT, ObjectT, ValueT) \
|
|
GETTER_ARGUMENTS(ArrayT, ValueT); \
|
|
RangeCheck(array, index.Value(), sizeof(ValueT)); \
|
|
ValueT result; \
|
|
ByteArray::Copy(&result, array, index.Value(), sizeof(ValueT)); \
|
|
arguments->SetReturn(ObjectT::Handle(ObjectT::New(result)));
|
|
|
|
|
|
#define UNALIGNED_SETTER(ArrayT, ObjectT, Getter, ValueT) \
|
|
SETTER_ARGUMENTS(ArrayT, ObjectT, ValueT); \
|
|
RangeCheck(array, index.Value(), sizeof(ValueT)); \
|
|
ValueT src = value_object.Getter(); \
|
|
ByteArray::Copy(array, index.Value(), &src, sizeof(ValueT)); \
|
|
Integer& result = Integer::Handle(); \
|
|
result ^= Integer::New(index.Value() + sizeof(ValueT)); \
|
|
arguments->SetReturn(result);
|
|
|
|
|
|
#define UINT64_TO_INTEGER(value, integer) \
|
|
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); \
|
|
}
|
|
|
|
|
|
#define GETTER_UINT64(ArrayT) \
|
|
GETTER_ARGUMENTS(ArrayT, uint64_t); \
|
|
intptr_t size = sizeof(uint64_t); \
|
|
RangeCheck(array, index.Value() * size, size); \
|
|
uint64_t value = array.At(index.Value()); \
|
|
Integer& result = Integer::Handle(); \
|
|
UINT64_TO_INTEGER(value, result); \
|
|
arguments->SetReturn(result);
|
|
|
|
|
|
#define UNALIGNED_GETTER_UINT64(ArrayT) \
|
|
GETTER_ARGUMENTS(ArrayT, uint64_t); \
|
|
RangeCheck(array, index.Value(), sizeof(uint64_t)); \
|
|
uint64_t value; \
|
|
ByteArray::Copy(&value, array, index.Value(), sizeof(uint64_t)); \
|
|
Integer& result = Integer::Handle(); \
|
|
UINT64_TO_INTEGER(value, result); \
|
|
arguments->SetReturn(result);
|
|
|
|
|
|
#define INTEGER_TO_UINT64(integer, uint64) \
|
|
if (integer.IsBigint()) { \
|
|
Bigint& bigint = Bigint::Handle(); \
|
|
bigint ^= integer.raw(); \
|
|
ASSERT(BigintOperations::FitsIntoUint64(bigint)); \
|
|
value = BigintOperations::AbsToUint64(bigint); \
|
|
} else { \
|
|
ASSERT(integer.IsMint() || integer.IsSmi()); \
|
|
value = integer.AsInt64Value(); \
|
|
} \
|
|
|
|
|
|
#define SETTER_UINT64(ArrayT) \
|
|
SETTER_ARGUMENTS(ArrayT, Integer, uint64_t); \
|
|
intptr_t size = sizeof(uint64_t); \
|
|
RangeCheck(array, index.Value() * size, size); \
|
|
uint64_t value; \
|
|
INTEGER_TO_UINT64(value_object, value); \
|
|
array.SetAt(index.Value(), value);
|
|
|
|
|
|
#define UNALIGNED_SETTER_UINT64(ArrayT) \
|
|
SETTER_ARGUMENTS(ArrayT, Integer, uint64_t); \
|
|
RangeCheck(array, index.Value(), sizeof(uint64_t)); \
|
|
uint64_t value; \
|
|
INTEGER_TO_UINT64(value_object, value); \
|
|
ByteArray::Copy(array, index.Value(), &value, sizeof(uint64_t)); \
|
|
Integer& result = Integer::Handle(); \
|
|
result ^= Integer::New(index.Value() + sizeof(uint64_t)); \
|
|
arguments->SetReturn(result);
|
|
|
|
|
|
DEFINE_NATIVE_ENTRY(ByteArray_getLength, 1) {
|
|
GET_NATIVE_ARGUMENT(ByteArray, array, arguments->At(0));
|
|
const Smi& length = Smi::Handle(Smi::New(array.Length()));
|
|
arguments->SetReturn(length);
|
|
}
|
|
|
|
|
|
DEFINE_NATIVE_ENTRY(ByteArray_getInt8, 2) {
|
|
UNALIGNED_GETTER(ByteArray, Smi, int8_t);
|
|
}
|
|
|
|
|
|
DEFINE_NATIVE_ENTRY(ByteArray_setInt8, 3) {
|
|
UNALIGNED_SETTER(ByteArray, Smi, Value, int8_t);
|
|
}
|
|
|
|
|
|
DEFINE_NATIVE_ENTRY(ByteArray_getUint8, 2) {
|
|
UNALIGNED_GETTER(ByteArray, Smi, uint8_t);
|
|
}
|
|
|
|
|
|
DEFINE_NATIVE_ENTRY(ByteArray_setUint8, 3) {
|
|
UNALIGNED_SETTER(ByteArray, Smi, Value, uint8_t);
|
|
}
|
|
|
|
|
|
DEFINE_NATIVE_ENTRY(ByteArray_getInt16, 2) {
|
|
UNALIGNED_GETTER(ByteArray, Smi, int16_t);
|
|
}
|
|
|
|
|
|
DEFINE_NATIVE_ENTRY(ByteArray_setInt16, 3) {
|
|
UNALIGNED_SETTER(ByteArray, Smi, Value, int16_t);
|
|
}
|
|
|
|
|
|
DEFINE_NATIVE_ENTRY(ByteArray_getUint16, 2) {
|
|
UNALIGNED_GETTER(ByteArray, Smi, uint16_t);
|
|
}
|
|
|
|
|
|
DEFINE_NATIVE_ENTRY(ByteArray_setUint16, 3) {
|
|
UNALIGNED_SETTER(ByteArray, Smi, Value, uint16_t);
|
|
}
|
|
|
|
|
|
DEFINE_NATIVE_ENTRY(ByteArray_getInt32, 2) {
|
|
UNALIGNED_GETTER(ByteArray, Integer, int32_t);
|
|
}
|
|
|
|
|
|
DEFINE_NATIVE_ENTRY(ByteArray_setInt32, 3) {
|
|
UNALIGNED_SETTER(ByteArray, Integer, AsInt64Value, int32_t);
|
|
}
|
|
|
|
|
|
DEFINE_NATIVE_ENTRY(ByteArray_getUint32, 2) {
|
|
UNALIGNED_GETTER(ByteArray, Integer, uint32_t);
|
|
}
|
|
|
|
|
|
DEFINE_NATIVE_ENTRY(ByteArray_setUint32, 3) {
|
|
UNALIGNED_SETTER(ByteArray, Integer, AsInt64Value, uint32_t);
|
|
}
|
|
|
|
|
|
DEFINE_NATIVE_ENTRY(ByteArray_getInt64, 2) {
|
|
UNALIGNED_GETTER(ByteArray, Integer, int64_t);
|
|
}
|
|
|
|
|
|
DEFINE_NATIVE_ENTRY(ByteArray_setInt64, 3) {
|
|
UNALIGNED_SETTER(ByteArray, Integer, AsInt64Value, int64_t);
|
|
}
|
|
|
|
|
|
DEFINE_NATIVE_ENTRY(ByteArray_getUint64, 2) {
|
|
UNALIGNED_GETTER_UINT64(ByteArray);
|
|
}
|
|
|
|
|
|
DEFINE_NATIVE_ENTRY(ByteArray_setUint64, 3) {
|
|
UNALIGNED_SETTER_UINT64(ByteArray);
|
|
}
|
|
|
|
|
|
DEFINE_NATIVE_ENTRY(ByteArray_getFloat32, 2) {
|
|
UNALIGNED_GETTER(ByteArray, Double, float);
|
|
}
|
|
|
|
|
|
DEFINE_NATIVE_ENTRY(ByteArray_setFloat32, 3) {
|
|
UNALIGNED_SETTER(ByteArray, Double, value, float);
|
|
}
|
|
|
|
|
|
DEFINE_NATIVE_ENTRY(ByteArray_getFloat64, 2) {
|
|
UNALIGNED_GETTER(ByteArray, Double, double);
|
|
}
|
|
|
|
|
|
DEFINE_NATIVE_ENTRY(ByteArray_setFloat64, 3) {
|
|
UNALIGNED_SETTER(ByteArray, Double, value, double);
|
|
}
|
|
|
|
|
|
DEFINE_NATIVE_ENTRY(ByteArray_setRange, 5) {
|
|
ByteArray& dst = ByteArray::CheckedHandle(arguments->At(0));
|
|
GET_NATIVE_ARGUMENT(Smi, dst_start, arguments->At(1));
|
|
GET_NATIVE_ARGUMENT(Smi, length, arguments->At(2));
|
|
GET_NATIVE_ARGUMENT(ByteArray, src, arguments->At(3));
|
|
GET_NATIVE_ARGUMENT(Smi, src_start, arguments->At(4));
|
|
intptr_t length_value = length.Value();
|
|
intptr_t src_start_value = src_start.Value();
|
|
intptr_t dst_start_value = dst_start.Value();
|
|
if (length_value < 0) {
|
|
const String& error = String::Handle(String::NewFormatted(
|
|
"length (%ld) must be non-negative", index));
|
|
GrowableArray<const Object*> args;
|
|
args.Add(&error);
|
|
Exceptions::ThrowByType(Exceptions::kIllegalArgument, args);
|
|
}
|
|
RangeCheck(src, src_start_value, length_value);
|
|
RangeCheck(dst, dst_start_value, length_value);
|
|
ByteArray::Copy(dst, dst_start_value, src, src_start_value, length_value);
|
|
}
|
|
|
|
|
|
// Int8Array
|
|
|
|
DEFINE_NATIVE_ENTRY(Int8Array_new, 1) {
|
|
GET_NATIVE_ARGUMENT(Smi, length, arguments->At(0));
|
|
intptr_t len = length.Value();
|
|
LengthCheck(len, Int8Array::kMaxElements);
|
|
const Int8Array& new_array = Int8Array::Handle(Int8Array::New(len));
|
|
arguments->SetReturn(new_array);
|
|
}
|
|
|
|
|
|
DEFINE_NATIVE_ENTRY(Int8Array_getIndexed, 2) {
|
|
GETTER(Int8Array, Smi, int8_t);
|
|
}
|
|
|
|
|
|
DEFINE_NATIVE_ENTRY(Int8Array_setIndexed, 3) {
|
|
SETTER(Int8Array, Smi, Value, int8_t);
|
|
}
|
|
|
|
|
|
// Uint8Array
|
|
|
|
DEFINE_NATIVE_ENTRY(Uint8Array_new, 1) {
|
|
GET_NATIVE_ARGUMENT(Smi, length, arguments->At(0));
|
|
intptr_t len = length.Value();
|
|
LengthCheck(len, Uint8Array::kMaxElements);
|
|
const Uint8Array& new_array = Uint8Array::Handle(Uint8Array::New(len));
|
|
arguments->SetReturn(new_array);
|
|
}
|
|
|
|
|
|
DEFINE_NATIVE_ENTRY(Uint8Array_getIndexed, 2) {
|
|
GETTER(Uint8Array, Smi, uint8_t);
|
|
}
|
|
|
|
|
|
DEFINE_NATIVE_ENTRY(Uint8Array_setIndexed, 3) {
|
|
SETTER(Uint8Array, Smi, Value, uint8_t);
|
|
}
|
|
|
|
|
|
// Int16Array
|
|
|
|
DEFINE_NATIVE_ENTRY(Int16Array_new, 1) {
|
|
GET_NATIVE_ARGUMENT(Smi, length, arguments->At(0));
|
|
intptr_t len = length.Value();
|
|
LengthCheck(len, Int16Array::kMaxElements);
|
|
const Int16Array& new_array = Int16Array::Handle(Int16Array::New(len));
|
|
arguments->SetReturn(new_array);
|
|
}
|
|
|
|
|
|
DEFINE_NATIVE_ENTRY(Int16Array_getIndexed, 2) {
|
|
GETTER(Int16Array, Smi, int16_t);
|
|
}
|
|
|
|
|
|
DEFINE_NATIVE_ENTRY(Int16Array_setIndexed, 3) {
|
|
SETTER(Int16Array, Smi, Value, int16_t);
|
|
}
|
|
|
|
|
|
// Uint16Array
|
|
|
|
DEFINE_NATIVE_ENTRY(Uint16Array_new, 1) {
|
|
GET_NATIVE_ARGUMENT(Smi, length, arguments->At(0));
|
|
intptr_t len = length.Value();
|
|
LengthCheck(len, Uint16Array::kMaxElements);
|
|
const Uint16Array& new_array = Uint16Array::Handle(Uint16Array::New(len));
|
|
arguments->SetReturn(new_array);
|
|
}
|
|
|
|
|
|
DEFINE_NATIVE_ENTRY(Uint16Array_getIndexed, 2) {
|
|
GETTER(Uint16Array, Smi, uint16_t);
|
|
}
|
|
|
|
|
|
DEFINE_NATIVE_ENTRY(Uint16Array_setIndexed, 3) {
|
|
SETTER(Uint16Array, Smi, Value, uint16_t);
|
|
}
|
|
|
|
|
|
// Int32Array
|
|
|
|
DEFINE_NATIVE_ENTRY(Int32Array_new, 1) {
|
|
GET_NATIVE_ARGUMENT(Smi, length, arguments->At(0));
|
|
intptr_t len = length.Value();
|
|
LengthCheck(len, Int32Array::kMaxElements);
|
|
const Int32Array& new_array = Int32Array::Handle(Int32Array::New(len));
|
|
arguments->SetReturn(new_array);
|
|
}
|
|
|
|
|
|
DEFINE_NATIVE_ENTRY(Int32Array_getIndexed, 2) {
|
|
GETTER(Int32Array, Integer, int32_t);
|
|
}
|
|
|
|
|
|
DEFINE_NATIVE_ENTRY(Int32Array_setIndexed, 3) {
|
|
SETTER(Int32Array, Integer, AsInt64Value, int32_t);
|
|
}
|
|
|
|
|
|
// Uint32Array
|
|
|
|
DEFINE_NATIVE_ENTRY(Uint32Array_new, 1) {
|
|
GET_NATIVE_ARGUMENT(Smi, length, arguments->At(0));
|
|
intptr_t len = length.Value();
|
|
LengthCheck(len, Uint32Array::kMaxElements);
|
|
const Uint32Array& new_array = Uint32Array::Handle(Uint32Array::New(len));
|
|
arguments->SetReturn(new_array);
|
|
}
|
|
|
|
|
|
DEFINE_NATIVE_ENTRY(Uint32Array_getIndexed, 2) {
|
|
GETTER(Uint32Array, Integer, uint32_t);
|
|
}
|
|
|
|
|
|
DEFINE_NATIVE_ENTRY(Uint32Array_setIndexed, 3) {
|
|
SETTER(Uint32Array, Integer, AsInt64Value, uint32_t);
|
|
}
|
|
|
|
|
|
// Int64Array
|
|
|
|
DEFINE_NATIVE_ENTRY(Int64Array_new, 1) {
|
|
GET_NATIVE_ARGUMENT(Smi, length, arguments->At(0));
|
|
intptr_t len = length.Value();
|
|
LengthCheck(len, Int64Array::kMaxElements);
|
|
const Int64Array& new_array = Int64Array::Handle(Int64Array::New(len));
|
|
arguments->SetReturn(new_array);
|
|
}
|
|
|
|
|
|
DEFINE_NATIVE_ENTRY(Int64Array_getIndexed, 2) {
|
|
GETTER(Int64Array, Integer, int64_t);
|
|
}
|
|
|
|
|
|
DEFINE_NATIVE_ENTRY(Int64Array_setIndexed, 3) {
|
|
SETTER(Int64Array, Integer, AsInt64Value, int64_t);
|
|
}
|
|
|
|
|
|
// Uint64Array
|
|
|
|
DEFINE_NATIVE_ENTRY(Uint64Array_new, 1) {
|
|
GET_NATIVE_ARGUMENT(Smi, length, arguments->At(0));
|
|
intptr_t len = length.Value();
|
|
LengthCheck(len, Uint64Array::kMaxElements);
|
|
const Uint64Array& new_array = Uint64Array::Handle(Uint64Array::New(len));
|
|
arguments->SetReturn(new_array);
|
|
}
|
|
|
|
|
|
DEFINE_NATIVE_ENTRY(Uint64Array_getIndexed, 2) {
|
|
GETTER_UINT64(Uint64Array);
|
|
}
|
|
|
|
|
|
DEFINE_NATIVE_ENTRY(Uint64Array_setIndexed, 3) {
|
|
SETTER_UINT64(Uint64Array);
|
|
}
|
|
|
|
|
|
// Float32Array
|
|
|
|
DEFINE_NATIVE_ENTRY(Float32Array_new, 1) {
|
|
GET_NATIVE_ARGUMENT(Smi, length, arguments->At(0));
|
|
intptr_t len = length.Value();
|
|
LengthCheck(len, Float32Array::kMaxElements);
|
|
const Float32Array& new_array = Float32Array::Handle(Float32Array::New(len));
|
|
arguments->SetReturn(new_array);
|
|
}
|
|
|
|
|
|
DEFINE_NATIVE_ENTRY(Float32Array_getIndexed, 2) {
|
|
GETTER(Float32Array, Double, float);
|
|
}
|
|
|
|
|
|
DEFINE_NATIVE_ENTRY(Float32Array_setIndexed, 3) {
|
|
SETTER(Float32Array, Double, value, float);
|
|
}
|
|
|
|
|
|
// Float64Array
|
|
|
|
DEFINE_NATIVE_ENTRY(Float64Array_new, 1) {
|
|
GET_NATIVE_ARGUMENT(Smi, length, arguments->At(0));
|
|
intptr_t len = length.Value();
|
|
LengthCheck(len, Float64Array::kMaxElements);
|
|
const Float64Array& new_array = Float64Array::Handle(Float64Array::New(len));
|
|
arguments->SetReturn(new_array);
|
|
}
|
|
|
|
|
|
DEFINE_NATIVE_ENTRY(Float64Array_getIndexed, 2) {
|
|
GETTER(Float64Array, Double, double);
|
|
}
|
|
|
|
|
|
DEFINE_NATIVE_ENTRY(Float64Array_setIndexed, 3) {
|
|
SETTER(Float64Array, Double, value, double);
|
|
}
|
|
|
|
|
|
// ExternalInt8Array
|
|
|
|
DEFINE_NATIVE_ENTRY(ExternalInt8Array_getIndexed, 2) {
|
|
GETTER(ExternalInt8Array, Smi, int8_t);
|
|
}
|
|
|
|
|
|
DEFINE_NATIVE_ENTRY(ExternalInt8Array_setIndexed, 3) {
|
|
SETTER(ExternalInt8Array, Smi, Value, int8_t);
|
|
}
|
|
|
|
|
|
// ExternalUint8Array
|
|
|
|
DEFINE_NATIVE_ENTRY(ExternalUint8Array_getIndexed, 2) {
|
|
UNALIGNED_GETTER(ExternalUint8Array, Smi, uint8_t);
|
|
}
|
|
|
|
|
|
DEFINE_NATIVE_ENTRY(ExternalUint8Array_setIndexed, 3) {
|
|
UNALIGNED_SETTER(ExternalUint8Array, Smi, Value, uint8_t);
|
|
}
|
|
|
|
|
|
// ExternalInt16Array
|
|
|
|
DEFINE_NATIVE_ENTRY(ExternalInt16Array_getIndexed, 2) {
|
|
GETTER(ExternalInt16Array, Smi, int16_t);
|
|
}
|
|
|
|
|
|
DEFINE_NATIVE_ENTRY(ExternalInt16Array_setIndexed, 3) {
|
|
SETTER(ExternalInt16Array, Smi, Value, int16_t);
|
|
}
|
|
|
|
|
|
// ExternalUint16Array
|
|
|
|
DEFINE_NATIVE_ENTRY(ExternalUint16Array_getIndexed, 2) {
|
|
UNALIGNED_GETTER(ExternalUint16Array, Smi, uint16_t);
|
|
}
|
|
|
|
|
|
DEFINE_NATIVE_ENTRY(ExternalUint16Array_setIndexed, 3) {
|
|
UNALIGNED_SETTER(ExternalUint16Array, Smi, Value, uint16_t);
|
|
}
|
|
|
|
|
|
// ExternalInt32Array
|
|
|
|
DEFINE_NATIVE_ENTRY(ExternalInt32Array_getIndexed, 2) {
|
|
GETTER(ExternalInt32Array, Integer, int32_t);
|
|
}
|
|
|
|
|
|
DEFINE_NATIVE_ENTRY(ExternalInt32Array_setIndexed, 3) {
|
|
SETTER(ExternalInt32Array, Integer, AsInt64Value, int32_t);
|
|
}
|
|
|
|
|
|
// ExternalUint32Array
|
|
|
|
DEFINE_NATIVE_ENTRY(ExternalUint32Array_getIndexed, 2) {
|
|
UNALIGNED_GETTER(ExternalUint32Array, Integer, uint32_t);
|
|
}
|
|
|
|
|
|
DEFINE_NATIVE_ENTRY(ExternalUint32Array_setIndexed, 3) {
|
|
UNALIGNED_SETTER(ExternalUint32Array, Integer, AsInt64Value, uint32_t);
|
|
}
|
|
|
|
|
|
// ExternalInt64Array
|
|
|
|
DEFINE_NATIVE_ENTRY(ExternalInt64Array_getIndexed, 2) {
|
|
GETTER(ExternalInt64Array, Integer, int64_t);
|
|
}
|
|
|
|
|
|
DEFINE_NATIVE_ENTRY(ExternalInt64Array_setIndexed, 3) {
|
|
SETTER(ExternalInt64Array, Integer, AsInt64Value, int64_t);
|
|
}
|
|
|
|
|
|
// ExternalUint64Array
|
|
|
|
DEFINE_NATIVE_ENTRY(ExternalUint64Array_getIndexed, 2) {
|
|
GETTER_UINT64(ExternalUint64Array);
|
|
}
|
|
|
|
|
|
DEFINE_NATIVE_ENTRY(ExternalUint64Array_setIndexed, 3) {
|
|
SETTER_UINT64(ExternalUint64Array);
|
|
}
|
|
|
|
|
|
// ExternalFloat32Array
|
|
|
|
DEFINE_NATIVE_ENTRY(ExternalFloat32Array_getIndexed, 2) {
|
|
GETTER(ExternalFloat32Array, Double, float);
|
|
}
|
|
|
|
|
|
DEFINE_NATIVE_ENTRY(ExternalFloat32Array_setIndexed, 3) {
|
|
SETTER(ExternalFloat32Array, Double, value, float);
|
|
}
|
|
|
|
|
|
// ExternalFloat64Array
|
|
|
|
DEFINE_NATIVE_ENTRY(ExternalFloat64Array_getIndexed, 2) {
|
|
GETTER(ExternalFloat64Array, Double, double);
|
|
}
|
|
|
|
|
|
DEFINE_NATIVE_ENTRY(ExternalFloat64Array_setIndexed, 3) {
|
|
SETTER(ExternalFloat64Array, Double, value, double);
|
|
}
|
|
|
|
} // namespace dart
|