First cut at API for native Typed Arrays.
R=rossberg@chromium.org Review URL: https://codereview.chromium.org/14195034 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@14476 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
17af6ee031
commit
3fd6bb51f0
238
include/v8.h
238
include/v8.h
@ -2046,6 +2046,170 @@ class V8EXPORT ArrayBuffer : public Object {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A base class for an instance of TypedArray series of constructors
|
||||
* (ES6 draft 15.13.6).
|
||||
* This API is experimental and may change significantly.
|
||||
*/
|
||||
class V8EXPORT TypedArray : public Object {
|
||||
public:
|
||||
/**
|
||||
* Returns underlying ArrayBuffer.
|
||||
*/
|
||||
Local<ArrayBuffer> Buffer();
|
||||
/**
|
||||
* Byte offset in |Buffer|
|
||||
*/
|
||||
size_t ByteOffset();
|
||||
/**
|
||||
* Numbe of elements in this typed array.
|
||||
*/
|
||||
size_t Length();
|
||||
/**
|
||||
* Size of typed array in bytes (e.g. for Int16Array, 2*|Length|).
|
||||
*/
|
||||
size_t ByteLength();
|
||||
/**
|
||||
* Base address of typed array.
|
||||
*/
|
||||
void* BaseAddress();
|
||||
|
||||
V8_INLINE(static TypedArray* Cast(Value* obj));
|
||||
|
||||
private:
|
||||
TypedArray();
|
||||
static void CheckCast(Value* obj);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* An instance of Uint8Array constructor (ES6 draft 15.13.6).
|
||||
* This API is experimental and may change significantly.
|
||||
*/
|
||||
class V8EXPORT Uint8Array : public TypedArray {
|
||||
public:
|
||||
static Local<Uint8Array> New(Handle<ArrayBuffer> array_buffer,
|
||||
size_t byte_offset, size_t length);
|
||||
V8_INLINE(static Uint8Array* Cast(Value* obj));
|
||||
|
||||
private:
|
||||
Uint8Array();
|
||||
static void CheckCast(Value* obj);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* An instance of Int8Array constructor (ES6 draft 15.13.6).
|
||||
* This API is experimental and may change significantly.
|
||||
*/
|
||||
class V8EXPORT Int8Array : public TypedArray {
|
||||
public:
|
||||
static Local<Int8Array> New(Handle<ArrayBuffer> array_buffer,
|
||||
size_t byte_offset, size_t length);
|
||||
V8_INLINE(static Int8Array* Cast(Value* obj));
|
||||
|
||||
private:
|
||||
Int8Array();
|
||||
static void CheckCast(Value* obj);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* An instance of Uint16Array constructor (ES6 draft 15.13.6).
|
||||
* This API is experimental and may change significantly.
|
||||
*/
|
||||
class V8EXPORT Uint16Array : public TypedArray {
|
||||
public:
|
||||
static Local<Uint16Array> New(Handle<ArrayBuffer> array_buffer,
|
||||
size_t byte_offset, size_t length);
|
||||
V8_INLINE(static Uint16Array* Cast(Value* obj));
|
||||
|
||||
private:
|
||||
Uint16Array();
|
||||
static void CheckCast(Value* obj);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* An instance of Int16Array constructor (ES6 draft 15.13.6).
|
||||
* This API is experimental and may change significantly.
|
||||
*/
|
||||
class V8EXPORT Int16Array : public TypedArray {
|
||||
public:
|
||||
static Local<Int16Array> New(Handle<ArrayBuffer> array_buffer,
|
||||
size_t byte_offset, size_t length);
|
||||
V8_INLINE(static Int16Array* Cast(Value* obj));
|
||||
|
||||
private:
|
||||
Int16Array();
|
||||
static void CheckCast(Value* obj);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* An instance of Uint32Array constructor (ES6 draft 15.13.6).
|
||||
* This API is experimental and may change significantly.
|
||||
*/
|
||||
class V8EXPORT Uint32Array : public TypedArray {
|
||||
public:
|
||||
static Local<Uint32Array> New(Handle<ArrayBuffer> array_buffer,
|
||||
size_t byte_offset, size_t length);
|
||||
V8_INLINE(static Uint32Array* Cast(Value* obj));
|
||||
|
||||
private:
|
||||
Uint32Array();
|
||||
static void CheckCast(Value* obj);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* An instance of Int32Array constructor (ES6 draft 15.13.6).
|
||||
* This API is experimental and may change significantly.
|
||||
*/
|
||||
class V8EXPORT Int32Array : public TypedArray {
|
||||
public:
|
||||
static Local<Int32Array> New(Handle<ArrayBuffer> array_buffer,
|
||||
size_t byte_offset, size_t length);
|
||||
V8_INLINE(static Int32Array* Cast(Value* obj));
|
||||
|
||||
private:
|
||||
Int32Array();
|
||||
static void CheckCast(Value* obj);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* An instance of Float32Array constructor (ES6 draft 15.13.6).
|
||||
* This API is experimental and may change significantly.
|
||||
*/
|
||||
class V8EXPORT Float32Array : public TypedArray {
|
||||
public:
|
||||
static Local<Float32Array> New(Handle<ArrayBuffer> array_buffer,
|
||||
size_t byte_offset, size_t length);
|
||||
V8_INLINE(static Float32Array* Cast(Value* obj));
|
||||
|
||||
private:
|
||||
Float32Array();
|
||||
static void CheckCast(Value* obj);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* An instance of Float64Array constructor (ES6 draft 15.13.6).
|
||||
* This API is experimental and may change significantly.
|
||||
*/
|
||||
class V8EXPORT Float64Array : public TypedArray {
|
||||
public:
|
||||
static Local<Float64Array> New(Handle<ArrayBuffer> array_buffer,
|
||||
size_t byte_offset, size_t length);
|
||||
V8_INLINE(static Float64Array* Cast(Value* obj));
|
||||
|
||||
private:
|
||||
Float64Array();
|
||||
static void CheckCast(Value* obj);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* An instance of the built-in Date constructor (ECMA-262, 15.9).
|
||||
*/
|
||||
@ -4543,7 +4707,7 @@ class Internals {
|
||||
static const int kJSObjectHeaderSize = 3 * kApiPointerSize;
|
||||
static const int kFixedArrayHeaderSize = 2 * kApiPointerSize;
|
||||
static const int kContextHeaderSize = 2 * kApiPointerSize;
|
||||
static const int kContextEmbedderDataIndex = 56;
|
||||
static const int kContextEmbedderDataIndex = 64;
|
||||
static const int kFullStringRepresentationMask = 0x07;
|
||||
static const int kStringEncodingMask = 0x4;
|
||||
static const int kExternalTwoByteRepresentationTag = 0x02;
|
||||
@ -5224,6 +5388,78 @@ ArrayBuffer* ArrayBuffer::Cast(v8::Value* value) {
|
||||
}
|
||||
|
||||
|
||||
TypedArray* TypedArray::Cast(v8::Value* value) {
|
||||
#ifdef V8_ENABLE_CHECKS
|
||||
CheckCast(value);
|
||||
#endif
|
||||
return static_cast<TypedArray*>(value);
|
||||
}
|
||||
|
||||
|
||||
Uint8Array* Uint8Array::Cast(v8::Value* value) {
|
||||
#ifdef V8_ENABLE_CHECKS
|
||||
CheckCast(value);
|
||||
#endif
|
||||
return static_cast<Uint8Array*>(value);
|
||||
}
|
||||
|
||||
|
||||
Int8Array* Int8Array::Cast(v8::Value* value) {
|
||||
#ifdef V8_ENABLE_CHECKS
|
||||
CheckCast(value);
|
||||
#endif
|
||||
return static_cast<Int8Array*>(value);
|
||||
}
|
||||
|
||||
|
||||
Uint16Array* Uint16Array::Cast(v8::Value* value) {
|
||||
#ifdef V8_ENABLE_CHECKS
|
||||
CheckCast(value);
|
||||
#endif
|
||||
return static_cast<Uint16Array*>(value);
|
||||
}
|
||||
|
||||
|
||||
Int16Array* Int16Array::Cast(v8::Value* value) {
|
||||
#ifdef V8_ENABLE_CHECKS
|
||||
CheckCast(value);
|
||||
#endif
|
||||
return static_cast<Int16Array*>(value);
|
||||
}
|
||||
|
||||
|
||||
Uint32Array* Uint32Array::Cast(v8::Value* value) {
|
||||
#ifdef V8_ENABLE_CHECKS
|
||||
CheckCast(value);
|
||||
#endif
|
||||
return static_cast<Uint32Array*>(value);
|
||||
}
|
||||
|
||||
|
||||
Int32Array* Int32Array::Cast(v8::Value* value) {
|
||||
#ifdef V8_ENABLE_CHECKS
|
||||
CheckCast(value);
|
||||
#endif
|
||||
return static_cast<Int32Array*>(value);
|
||||
}
|
||||
|
||||
|
||||
Float32Array* Float32Array::Cast(v8::Value* value) {
|
||||
#ifdef V8_ENABLE_CHECKS
|
||||
CheckCast(value);
|
||||
#endif
|
||||
return static_cast<Float32Array*>(value);
|
||||
}
|
||||
|
||||
|
||||
Float64Array* Float64Array::Cast(v8::Value* value) {
|
||||
#ifdef V8_ENABLE_CHECKS
|
||||
CheckCast(value);
|
||||
#endif
|
||||
return static_cast<Float64Array*>(value);
|
||||
}
|
||||
|
||||
|
||||
Function* Function::Cast(v8::Value* value) {
|
||||
#ifdef V8_ENABLE_CHECKS
|
||||
CheckCast(value);
|
||||
|
156
src/api.cc
156
src/api.cc
@ -2755,6 +2755,39 @@ void v8::ArrayBuffer::CheckCast(Value* that) {
|
||||
}
|
||||
|
||||
|
||||
void v8::TypedArray::CheckCast(Value* that) {
|
||||
if (IsDeadCheck(i::Isolate::Current(), "v8::TypedArray::Cast()")) return;
|
||||
i::Handle<i::Object> obj = Utils::OpenHandle(that);
|
||||
ApiCheck(obj->IsJSTypedArray(),
|
||||
"v8::TypedArray::Cast()",
|
||||
"Could not convert to TypedArray");
|
||||
}
|
||||
|
||||
|
||||
#define CHECK_TYPED_ARRAY_CAST(ApiClass, typeConst) \
|
||||
void v8::ApiClass::CheckCast(Value* that) { \
|
||||
if (IsDeadCheck(i::Isolate::Current(), "v8::" #ApiClass "::Cast()")) \
|
||||
return; \
|
||||
i::Handle<i::Object> obj = Utils::OpenHandle(that); \
|
||||
ApiCheck(obj->IsJSTypedArray() && \
|
||||
i::JSTypedArray::cast(*obj)->type() == typeConst, \
|
||||
"v8::" #ApiClass "::Cast()", \
|
||||
"Could not convert to " #ApiClass); \
|
||||
}
|
||||
|
||||
|
||||
CHECK_TYPED_ARRAY_CAST(Uint8Array, kExternalUnsignedByteArray)
|
||||
CHECK_TYPED_ARRAY_CAST(Int8Array, kExternalByteArray)
|
||||
CHECK_TYPED_ARRAY_CAST(Uint16Array, kExternalUnsignedShortArray)
|
||||
CHECK_TYPED_ARRAY_CAST(Int16Array, kExternalShortArray)
|
||||
CHECK_TYPED_ARRAY_CAST(Uint32Array, kExternalUnsignedIntArray)
|
||||
CHECK_TYPED_ARRAY_CAST(Int32Array, kExternalIntArray)
|
||||
CHECK_TYPED_ARRAY_CAST(Float32Array, kExternalFloatArray)
|
||||
CHECK_TYPED_ARRAY_CAST(Float64Array, kExternalDoubleArray)
|
||||
|
||||
#undef CHECK_TYPED_ARRAY_CAST
|
||||
|
||||
|
||||
void v8::Date::CheckCast(v8::Value* that) {
|
||||
i::Isolate* isolate = i::Isolate::Current();
|
||||
if (IsDeadCheck(isolate, "v8::Date::Cast()")) return;
|
||||
@ -5806,6 +5839,129 @@ Local<ArrayBuffer> v8::ArrayBuffer::New(void* data, size_t byte_length) {
|
||||
}
|
||||
|
||||
|
||||
Local<ArrayBuffer> v8::TypedArray::Buffer() {
|
||||
i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
|
||||
if (IsDeadCheck(isolate, "v8::TypedArray::Buffer()"))
|
||||
return Local<ArrayBuffer>();
|
||||
i::Handle<i::JSTypedArray> obj = Utils::OpenHandle(this);
|
||||
ASSERT(obj->buffer()->IsJSArrayBuffer());
|
||||
i::Handle<i::JSArrayBuffer> buffer(i::JSArrayBuffer::cast(obj->buffer()));
|
||||
return Utils::ToLocal(buffer);
|
||||
}
|
||||
|
||||
|
||||
size_t v8::TypedArray::ByteOffset() {
|
||||
i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
|
||||
if (IsDeadCheck(isolate, "v8::TypedArray::ByteOffset()")) return 0;
|
||||
i::Handle<i::JSTypedArray> obj = Utils::OpenHandle(this);
|
||||
return static_cast<size_t>(obj->byte_offset()->Number());
|
||||
}
|
||||
|
||||
|
||||
size_t v8::TypedArray::ByteLength() {
|
||||
i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
|
||||
if (IsDeadCheck(isolate, "v8::TypedArray::ByteLength()")) return 0;
|
||||
i::Handle<i::JSTypedArray> obj = Utils::OpenHandle(this);
|
||||
return static_cast<size_t>(obj->byte_length()->Number());
|
||||
}
|
||||
|
||||
|
||||
size_t v8::TypedArray::Length() {
|
||||
i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
|
||||
if (IsDeadCheck(isolate, "v8::TypedArray::Length()")) return 0;
|
||||
i::Handle<i::JSTypedArray> obj = Utils::OpenHandle(this);
|
||||
return static_cast<size_t>(obj->length()->Number());
|
||||
}
|
||||
|
||||
|
||||
void* v8::TypedArray::BaseAddress() {
|
||||
i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
|
||||
if (IsDeadCheck(isolate, "v8::TypedArray::BaseAddress()")) return NULL;
|
||||
i::Handle<i::JSTypedArray> obj = Utils::OpenHandle(this);
|
||||
i::Handle<i::JSArrayBuffer> buffer(i::JSArrayBuffer::cast(obj->buffer()));
|
||||
void* buffer_data = buffer->backing_store();
|
||||
size_t byte_offset = static_cast<size_t>(obj->byte_offset()->Number());
|
||||
return static_cast<uint8_t*>(buffer_data) + byte_offset;
|
||||
}
|
||||
|
||||
|
||||
template<typename ElementType,
|
||||
ExternalArrayType array_type,
|
||||
i::ElementsKind elements_kind>
|
||||
i::Handle<i::JSTypedArray> NewTypedArray(
|
||||
i::Isolate* isolate,
|
||||
Handle<ArrayBuffer> array_buffer, size_t byte_offset, size_t length) {
|
||||
i::Handle<i::JSTypedArray> obj =
|
||||
isolate->factory()->NewJSTypedArray(array_type);
|
||||
i::Handle<i::JSArrayBuffer> buffer = Utils::OpenHandle(*array_buffer);
|
||||
|
||||
ASSERT(byte_offset % sizeof(ElementType) == 0);
|
||||
ASSERT(byte_offset + length * sizeof(ElementType) <=
|
||||
static_cast<size_t>(buffer->byte_length()->Number()));
|
||||
|
||||
obj->set_buffer(*buffer);
|
||||
|
||||
i::Handle<i::Object> byte_offset_object = isolate->factory()->NewNumber(
|
||||
static_cast<double>(byte_offset));
|
||||
obj->set_byte_offset(*byte_offset_object);
|
||||
|
||||
i::Handle<i::Object> byte_length_object = isolate->factory()->NewNumber(
|
||||
static_cast<double>(length * sizeof(ElementType)));
|
||||
obj->set_byte_length(*byte_length_object);
|
||||
|
||||
i::Handle<i::Object> length_object = isolate->factory()->NewNumber(
|
||||
static_cast<double>(length));
|
||||
obj->set_length(*length_object);
|
||||
|
||||
i::Handle<i::ExternalArray> elements =
|
||||
isolate->factory()->NewExternalArray(
|
||||
static_cast<int>(length), array_type,
|
||||
static_cast<uint8_t*>(buffer->backing_store()) + byte_offset);
|
||||
i::Handle<i::Map> map =
|
||||
isolate->factory()->GetElementsTransitionMap(
|
||||
obj, elements_kind);
|
||||
obj->set_map(*map);
|
||||
obj->set_elements(*elements);
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
||||
#define TYPED_ARRAY_NEW(TypedArray, element_type, array_type, elements_kind) \
|
||||
Local<TypedArray> TypedArray::New(Handle<ArrayBuffer> array_buffer, \
|
||||
size_t byte_offset, size_t length) { \
|
||||
i::Isolate* isolate = i::Isolate::Current(); \
|
||||
EnsureInitializedForIsolate(isolate, \
|
||||
"v8::" #TypedArray "::New(Handle<ArrayBuffer>, size_t, size_t)"); \
|
||||
LOG_API(isolate, \
|
||||
"v8::" #TypedArray "::New(Handle<ArrayBuffer>, size_t, size_t)"); \
|
||||
ENTER_V8(isolate); \
|
||||
i::Handle<i::JSTypedArray> obj = \
|
||||
NewTypedArray<element_type, array_type, elements_kind>( \
|
||||
isolate, array_buffer, byte_offset, length); \
|
||||
return Utils::ToLocal##TypedArray(obj); \
|
||||
}
|
||||
|
||||
|
||||
TYPED_ARRAY_NEW(Uint8Array, uint8_t, kExternalUnsignedByteArray,
|
||||
i::EXTERNAL_UNSIGNED_BYTE_ELEMENTS)
|
||||
TYPED_ARRAY_NEW(Int8Array, int8_t, kExternalByteArray,
|
||||
i::EXTERNAL_BYTE_ELEMENTS)
|
||||
TYPED_ARRAY_NEW(Uint16Array, uint16_t, kExternalUnsignedShortArray,
|
||||
i::EXTERNAL_UNSIGNED_SHORT_ELEMENTS)
|
||||
TYPED_ARRAY_NEW(Int16Array, int16_t, kExternalShortArray,
|
||||
i::EXTERNAL_SHORT_ELEMENTS)
|
||||
TYPED_ARRAY_NEW(Uint32Array, uint32_t, kExternalUnsignedIntArray,
|
||||
i::EXTERNAL_UNSIGNED_INT_ELEMENTS)
|
||||
TYPED_ARRAY_NEW(Int32Array, int32_t, kExternalIntArray,
|
||||
i::EXTERNAL_INT_ELEMENTS)
|
||||
TYPED_ARRAY_NEW(Float32Array, float, kExternalFloatArray,
|
||||
i::EXTERNAL_FLOAT_ELEMENTS)
|
||||
TYPED_ARRAY_NEW(Float64Array, double, kExternalDoubleArray,
|
||||
i::EXTERNAL_DOUBLE_ELEMENTS)
|
||||
|
||||
#undef TYPED_ARRAY_NEW
|
||||
|
||||
|
||||
Local<Symbol> v8::Symbol::New(Isolate* isolate) {
|
||||
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
|
||||
EnsureInitializedForIsolate(i_isolate, "v8::Symbol::New()");
|
||||
|
52
src/api.h
52
src/api.h
@ -171,6 +171,15 @@ class RegisteredExtension {
|
||||
V(Object, JSObject) \
|
||||
V(Array, JSArray) \
|
||||
V(ArrayBuffer, JSArrayBuffer) \
|
||||
V(TypedArray, JSTypedArray) \
|
||||
V(Uint8Array, JSTypedArray) \
|
||||
V(Int8Array, JSTypedArray) \
|
||||
V(Uint16Array, JSTypedArray) \
|
||||
V(Int16Array, JSTypedArray) \
|
||||
V(Uint32Array, JSTypedArray) \
|
||||
V(Int32Array, JSTypedArray) \
|
||||
V(Float32Array, JSTypedArray) \
|
||||
V(Float64Array, JSTypedArray) \
|
||||
V(String, String) \
|
||||
V(Symbol, Symbol) \
|
||||
V(Script, Object) \
|
||||
@ -208,6 +217,26 @@ class Utils {
|
||||
v8::internal::Handle<v8::internal::JSArray> obj);
|
||||
static inline Local<ArrayBuffer> ToLocal(
|
||||
v8::internal::Handle<v8::internal::JSArrayBuffer> obj);
|
||||
|
||||
static inline Local<TypedArray> ToLocal(
|
||||
v8::internal::Handle<v8::internal::JSTypedArray> obj);
|
||||
static inline Local<Uint8Array> ToLocalUint8Array(
|
||||
v8::internal::Handle<v8::internal::JSTypedArray> obj);
|
||||
static inline Local<Int8Array> ToLocalInt8Array(
|
||||
v8::internal::Handle<v8::internal::JSTypedArray> obj);
|
||||
static inline Local<Uint16Array> ToLocalUint16Array(
|
||||
v8::internal::Handle<v8::internal::JSTypedArray> obj);
|
||||
static inline Local<Int16Array> ToLocalInt16Array(
|
||||
v8::internal::Handle<v8::internal::JSTypedArray> obj);
|
||||
static inline Local<Uint32Array> ToLocalUint32Array(
|
||||
v8::internal::Handle<v8::internal::JSTypedArray> obj);
|
||||
static inline Local<Int32Array> ToLocalInt32Array(
|
||||
v8::internal::Handle<v8::internal::JSTypedArray> obj);
|
||||
static inline Local<Float32Array> ToLocalFloat32Array(
|
||||
v8::internal::Handle<v8::internal::JSTypedArray> obj);
|
||||
static inline Local<Float64Array> ToLocalFloat64Array(
|
||||
v8::internal::Handle<v8::internal::JSTypedArray> obj);
|
||||
|
||||
static inline Local<Message> MessageToLocal(
|
||||
v8::internal::Handle<v8::internal::Object> obj);
|
||||
static inline Local<StackTrace> StackTraceToLocal(
|
||||
@ -270,6 +299,17 @@ v8::internal::Handle<T> v8::internal::Handle<T>::EscapeFrom(
|
||||
return Local<To>(reinterpret_cast<To*>(obj.location())); \
|
||||
}
|
||||
|
||||
|
||||
#define MAKE_TO_LOCAL_TYPED_ARRAY(TypedArray, typeConst) \
|
||||
Local<v8::TypedArray> Utils::ToLocal##TypedArray( \
|
||||
v8::internal::Handle<v8::internal::JSTypedArray> obj) { \
|
||||
ASSERT(obj.is_null() || !obj->IsTheHole()); \
|
||||
ASSERT(obj->type() == typeConst); \
|
||||
return Local<v8::TypedArray>( \
|
||||
reinterpret_cast<v8::TypedArray*>(obj.location())); \
|
||||
}
|
||||
|
||||
|
||||
MAKE_TO_LOCAL(ToLocal, Context, Context)
|
||||
MAKE_TO_LOCAL(ToLocal, Object, Value)
|
||||
MAKE_TO_LOCAL(ToLocal, JSFunction, Function)
|
||||
@ -279,6 +319,17 @@ MAKE_TO_LOCAL(ToLocal, JSRegExp, RegExp)
|
||||
MAKE_TO_LOCAL(ToLocal, JSObject, Object)
|
||||
MAKE_TO_LOCAL(ToLocal, JSArray, Array)
|
||||
MAKE_TO_LOCAL(ToLocal, JSArrayBuffer, ArrayBuffer)
|
||||
MAKE_TO_LOCAL(ToLocal, JSTypedArray, TypedArray)
|
||||
|
||||
MAKE_TO_LOCAL_TYPED_ARRAY(Uint8Array, kExternalUnsignedByteArray)
|
||||
MAKE_TO_LOCAL_TYPED_ARRAY(Int8Array, kExternalByteArray)
|
||||
MAKE_TO_LOCAL_TYPED_ARRAY(Uint16Array, kExternalUnsignedShortArray)
|
||||
MAKE_TO_LOCAL_TYPED_ARRAY(Int16Array, kExternalShortArray)
|
||||
MAKE_TO_LOCAL_TYPED_ARRAY(Uint32Array, kExternalUnsignedIntArray)
|
||||
MAKE_TO_LOCAL_TYPED_ARRAY(Int32Array, kExternalIntArray)
|
||||
MAKE_TO_LOCAL_TYPED_ARRAY(Float32Array, kExternalFloatArray)
|
||||
MAKE_TO_LOCAL_TYPED_ARRAY(Float64Array, kExternalDoubleArray)
|
||||
|
||||
MAKE_TO_LOCAL(ToLocal, FunctionTemplateInfo, FunctionTemplate)
|
||||
MAKE_TO_LOCAL(ToLocal, ObjectTemplateInfo, ObjectTemplate)
|
||||
MAKE_TO_LOCAL(ToLocal, SignatureInfo, Signature)
|
||||
@ -293,6 +344,7 @@ MAKE_TO_LOCAL(Uint32ToLocal, Object, Uint32)
|
||||
MAKE_TO_LOCAL(ExternalToLocal, JSObject, External)
|
||||
MAKE_TO_LOCAL(ToLocal, DeclaredAccessorDescriptor, DeclaredAccessorDescriptor)
|
||||
|
||||
#undef MAKE_TO_LOCAL_TYPED_ARRAY
|
||||
#undef MAKE_TO_LOCAL
|
||||
|
||||
|
||||
|
@ -201,7 +201,7 @@ class Genesis BASE_EMBEDDED {
|
||||
ElementsKind elements_kind);
|
||||
bool InstallNatives();
|
||||
|
||||
void InstallTypedArray(const char* name);
|
||||
Handle<JSFunction> InstallTypedArray(const char* name);
|
||||
bool InstallExperimentalNatives();
|
||||
void InstallBuiltinFunctionIds();
|
||||
void InstallJSFunctionResultCaches();
|
||||
@ -1276,11 +1276,11 @@ bool Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
|
||||
}
|
||||
|
||||
|
||||
void Genesis::InstallTypedArray(const char* name) {
|
||||
Handle<JSFunction> Genesis::InstallTypedArray(const char* name) {
|
||||
Handle<JSObject> global = Handle<JSObject>(native_context()->global_object());
|
||||
InstallFunction(global, name, JS_TYPED_ARRAY_TYPE,
|
||||
JSTypedArray::kSize, isolate()->initial_object_prototype(),
|
||||
Builtins::kIllegal, true);
|
||||
return InstallFunction(global, name, JS_TYPED_ARRAY_TYPE,
|
||||
JSTypedArray::kSize, isolate()->initial_object_prototype(),
|
||||
Builtins::kIllegal, true);
|
||||
}
|
||||
|
||||
|
||||
@ -1328,14 +1328,22 @@ void Genesis::InitializeExperimentalGlobal() {
|
||||
}
|
||||
{
|
||||
// -- T y p e d A r r a y s
|
||||
InstallTypedArray("__Int8Array");
|
||||
InstallTypedArray("__Uint8Array");
|
||||
InstallTypedArray("__Int16Array");
|
||||
InstallTypedArray("__Uint16Array");
|
||||
InstallTypedArray("__Int32Array");
|
||||
InstallTypedArray("__Uint32Array");
|
||||
InstallTypedArray("__Float32Array");
|
||||
InstallTypedArray("__Float64Array");
|
||||
native_context()->set_int8_array_fun(
|
||||
*InstallTypedArray("__Int8Array"));
|
||||
native_context()->set_uint8_array_fun(
|
||||
*InstallTypedArray("__Uint8Array"));
|
||||
native_context()->set_int16_array_fun(
|
||||
*InstallTypedArray("__Int16Array"));
|
||||
native_context()->set_uint16_array_fun(
|
||||
*InstallTypedArray("__Uint16Array"));
|
||||
native_context()->set_int32_array_fun(
|
||||
*InstallTypedArray("__Int32Array"));
|
||||
native_context()->set_uint32_array_fun(
|
||||
*InstallTypedArray("__Uint32Array"));
|
||||
native_context()->set_float_array_fun(
|
||||
*InstallTypedArray("__Float32Array"));
|
||||
native_context()->set_double_array_fun(
|
||||
*InstallTypedArray("__Float64Array"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -124,6 +124,14 @@ enum BindingFlags {
|
||||
V(INSTANTIATE_FUN_INDEX, JSFunction, instantiate_fun) \
|
||||
V(CONFIGURE_INSTANCE_FUN_INDEX, JSFunction, configure_instance_fun) \
|
||||
V(ARRAY_BUFFER_FUN_INDEX, JSFunction, array_buffer_fun) \
|
||||
V(UINT8_ARRAY_FUN_INDEX, JSFunction, uint8_array_fun) \
|
||||
V(INT8_ARRAY_FUN_INDEX, JSFunction, int8_array_fun) \
|
||||
V(UINT16_ARRAY_FUN_INDEX, JSFunction, uint16_array_fun) \
|
||||
V(INT16_ARRAY_FUN_INDEX, JSFunction, int16_array_fun) \
|
||||
V(UINT32_ARRAY_FUN_INDEX, JSFunction, uint32_array_fun) \
|
||||
V(INT32_ARRAY_FUN_INDEX, JSFunction, int32_array_fun) \
|
||||
V(FLOAT_ARRAY_FUN_INDEX, JSFunction, float_array_fun) \
|
||||
V(DOUBLE_ARRAY_FUN_INDEX, JSFunction, double_array_fun) \
|
||||
V(FUNCTION_MAP_INDEX, Map, function_map) \
|
||||
V(STRICT_MODE_FUNCTION_MAP_INDEX, Map, strict_mode_function_map) \
|
||||
V(FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX, Map, function_without_prototype_map) \
|
||||
@ -278,6 +286,14 @@ class Context: public FixedArray {
|
||||
INSTANTIATE_FUN_INDEX,
|
||||
CONFIGURE_INSTANCE_FUN_INDEX,
|
||||
ARRAY_BUFFER_FUN_INDEX,
|
||||
UINT8_ARRAY_FUN_INDEX,
|
||||
INT8_ARRAY_FUN_INDEX,
|
||||
UINT16_ARRAY_FUN_INDEX,
|
||||
INT16_ARRAY_FUN_INDEX,
|
||||
UINT32_ARRAY_FUN_INDEX,
|
||||
INT32_ARRAY_FUN_INDEX,
|
||||
FLOAT_ARRAY_FUN_INDEX,
|
||||
DOUBLE_ARRAY_FUN_INDEX,
|
||||
MESSAGE_LISTENERS_INDEX,
|
||||
MAKE_MESSAGE_FUN_INDEX,
|
||||
GET_STACK_TRACE_LINE_INDEX,
|
||||
|
@ -1056,6 +1056,54 @@ Handle<JSArrayBuffer> Factory::NewJSArrayBuffer() {
|
||||
}
|
||||
|
||||
|
||||
Handle<JSTypedArray> Factory::NewJSTypedArray(ExternalArrayType type) {
|
||||
JSFunction* typed_array_fun;
|
||||
Context* native_context = isolate()->context()->native_context();
|
||||
switch (type) {
|
||||
case kExternalUnsignedByteArray:
|
||||
typed_array_fun = native_context->uint8_array_fun();
|
||||
break;
|
||||
|
||||
case kExternalByteArray:
|
||||
typed_array_fun = native_context->int8_array_fun();
|
||||
break;
|
||||
|
||||
case kExternalUnsignedShortArray:
|
||||
typed_array_fun = native_context->uint16_array_fun();
|
||||
break;
|
||||
|
||||
case kExternalShortArray:
|
||||
typed_array_fun = native_context->int16_array_fun();
|
||||
break;
|
||||
|
||||
case kExternalUnsignedIntArray:
|
||||
typed_array_fun = native_context->uint32_array_fun();
|
||||
break;
|
||||
|
||||
case kExternalIntArray:
|
||||
typed_array_fun = native_context->int32_array_fun();
|
||||
break;
|
||||
|
||||
case kExternalFloatArray:
|
||||
typed_array_fun = native_context->float_array_fun();
|
||||
break;
|
||||
|
||||
case kExternalDoubleArray:
|
||||
typed_array_fun = native_context->double_array_fun();
|
||||
break;
|
||||
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return Handle<JSTypedArray>();
|
||||
}
|
||||
|
||||
CALL_HEAP_FUNCTION(
|
||||
isolate(),
|
||||
isolate()->heap()->AllocateJSObject(typed_array_fun),
|
||||
JSTypedArray);
|
||||
}
|
||||
|
||||
|
||||
Handle<JSProxy> Factory::NewJSProxy(Handle<Object> handler,
|
||||
Handle<Object> prototype) {
|
||||
CALL_HEAP_FUNCTION(
|
||||
|
@ -315,6 +315,8 @@ class Factory {
|
||||
|
||||
Handle<JSArrayBuffer> NewJSArrayBuffer();
|
||||
|
||||
Handle<JSTypedArray> NewJSTypedArray(ExternalArrayType type);
|
||||
|
||||
Handle<JSProxy> NewJSProxy(Handle<Object> handler, Handle<Object> prototype);
|
||||
|
||||
// Change the type of the argument into a JS object/function and reinitialize.
|
||||
|
@ -13372,6 +13372,31 @@ MaybeObject* JSObject::PrepareElementsForSort(uint32_t limit) {
|
||||
return result_double;
|
||||
}
|
||||
|
||||
ExternalArrayType JSTypedArray::type() {
|
||||
switch (elements()->map()->instance_type()) {
|
||||
case EXTERNAL_BYTE_ARRAY_TYPE:
|
||||
return kExternalByteArray;
|
||||
case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
|
||||
return kExternalUnsignedByteArray;
|
||||
case EXTERNAL_SHORT_ARRAY_TYPE:
|
||||
return kExternalShortArray;
|
||||
case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
|
||||
return kExternalUnsignedShortArray;
|
||||
case EXTERNAL_INT_ARRAY_TYPE:
|
||||
return kExternalIntArray;
|
||||
case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
|
||||
return kExternalUnsignedIntArray;
|
||||
case EXTERNAL_FLOAT_ARRAY_TYPE:
|
||||
return kExternalFloatArray;
|
||||
case EXTERNAL_DOUBLE_ARRAY_TYPE:
|
||||
return kExternalDoubleArray;
|
||||
case EXTERNAL_PIXEL_ARRAY_TYPE:
|
||||
return kExternalPixelArray;
|
||||
default:
|
||||
return static_cast<ExternalArrayType>(-1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Object* ExternalPixelArray::SetValue(uint32_t index, Object* value) {
|
||||
uint8_t clamped_value = 0;
|
||||
|
@ -8707,6 +8707,8 @@ class JSTypedArray: public JSObject {
|
||||
// Casting.
|
||||
static inline JSTypedArray* cast(Object* obj);
|
||||
|
||||
ExternalArrayType type();
|
||||
|
||||
// Dispatched behavior.
|
||||
DECLARE_PRINTER(JSTypedArray)
|
||||
DECLARE_VERIFIER(JSTypedArray)
|
||||
|
@ -2315,7 +2315,6 @@ THREADED_TEST(ArrayBuffer) {
|
||||
result = CompileRun("u8_b[0] + u8_b[1]");
|
||||
CHECK_EQ(0xDD, result->Int32Value());
|
||||
|
||||
|
||||
delete[] my_data;
|
||||
}
|
||||
|
||||
@ -12295,10 +12294,11 @@ THREADED_TEST(ExternalAllocatedMemory) {
|
||||
CHECK(!env.IsEmpty());
|
||||
const intptr_t kSize = 1024*1024;
|
||||
v8::Isolate* isolate = env->GetIsolate();
|
||||
CHECK_EQ(cast(isolate->AdjustAmountOfExternalAllocatedMemory(kSize)),
|
||||
cast(kSize));
|
||||
CHECK_EQ(cast(isolate->AdjustAmountOfExternalAllocatedMemory(-kSize)),
|
||||
cast(0));
|
||||
int64_t baseline = cast(isolate->AdjustAmountOfExternalAllocatedMemory(0));
|
||||
CHECK_EQ(baseline + cast(kSize),
|
||||
cast(isolate->AdjustAmountOfExternalAllocatedMemory(kSize)));
|
||||
CHECK_EQ(baseline,
|
||||
cast(isolate->AdjustAmountOfExternalAllocatedMemory(-kSize)));
|
||||
}
|
||||
|
||||
|
||||
@ -14435,39 +14435,13 @@ static int ExternalArrayElementSize(v8::ExternalArrayType array_type) {
|
||||
|
||||
|
||||
template <class ExternalArrayClass, class ElementType>
|
||||
static void ExternalArrayTestHelper(v8::ExternalArrayType array_type,
|
||||
int64_t low,
|
||||
int64_t high) {
|
||||
LocalContext context;
|
||||
v8::HandleScope scope(context->GetIsolate());
|
||||
const int kElementCount = 40;
|
||||
int element_size = ExternalArrayElementSize(array_type);
|
||||
ElementType* array_data =
|
||||
static_cast<ElementType*>(malloc(kElementCount * element_size));
|
||||
i::Handle<ExternalArrayClass> array =
|
||||
i::Handle<ExternalArrayClass>::cast(
|
||||
FACTORY->NewExternalArray(kElementCount, array_type, array_data));
|
||||
// Force GC to trigger verification.
|
||||
HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
|
||||
for (int i = 0; i < kElementCount; i++) {
|
||||
array->set(i, static_cast<ElementType>(i));
|
||||
}
|
||||
// Force GC to trigger verification.
|
||||
HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
|
||||
for (int i = 0; i < kElementCount; i++) {
|
||||
CHECK_EQ(static_cast<int64_t>(i),
|
||||
static_cast<int64_t>(array->get_scalar(i)));
|
||||
CHECK_EQ(static_cast<int64_t>(i), static_cast<int64_t>(array_data[i]));
|
||||
}
|
||||
|
||||
v8::Handle<v8::Object> obj = v8::Object::New();
|
||||
static void ObjectWithExternalArrayTestHelper(
|
||||
Handle<Context> context,
|
||||
v8::Handle<Object> obj,
|
||||
int element_count,
|
||||
v8::ExternalArrayType array_type,
|
||||
int64_t low, int64_t high) {
|
||||
i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
|
||||
// Set the elements to be the external array.
|
||||
obj->SetIndexedPropertiesToExternalArrayData(array_data,
|
||||
array_type,
|
||||
kElementCount);
|
||||
CHECK_EQ(
|
||||
1, static_cast<int>(jsobj->GetElement(1)->ToObjectChecked()->Number()));
|
||||
obj->Set(v8_str("field"), v8::Int32::New(1503));
|
||||
context->Global()->Set(v8_str("ext_array"), obj);
|
||||
v8::Handle<v8::Value> result = CompileRun("ext_array.field");
|
||||
@ -14584,7 +14558,7 @@ static void ExternalArrayTestHelper(v8::ExternalArrayType array_type,
|
||||
" caught_exception = true;"
|
||||
"}"
|
||||
"caught_exception;",
|
||||
kElementCount);
|
||||
element_count);
|
||||
result = CompileRun(test_buf.start());
|
||||
CHECK_EQ(false, result->BooleanValue());
|
||||
|
||||
@ -14597,7 +14571,7 @@ static void ExternalArrayTestHelper(v8::ExternalArrayType array_type,
|
||||
" caught_exception = true;"
|
||||
"}"
|
||||
"caught_exception;",
|
||||
kElementCount);
|
||||
element_count);
|
||||
result = CompileRun(test_buf.start());
|
||||
CHECK_EQ(false, result->BooleanValue());
|
||||
|
||||
@ -14698,9 +14672,12 @@ static void ExternalArrayTestHelper(v8::ExternalArrayType array_type,
|
||||
CHECK_EQ(true, result->BooleanValue());
|
||||
}
|
||||
|
||||
for (int i = 0; i < kElementCount; i++) {
|
||||
i::Handle<ExternalArrayClass> array(
|
||||
ExternalArrayClass::cast(jsobj->elements()));
|
||||
for (int i = 0; i < element_count; i++) {
|
||||
array->set(i, static_cast<ElementType>(i));
|
||||
}
|
||||
|
||||
// Test complex assignments
|
||||
result = CompileRun("function ee_op_test_complex_func(sum) {"
|
||||
" for (var i = 0; i < 40; ++i) {"
|
||||
@ -14757,6 +14734,48 @@ static void ExternalArrayTestHelper(v8::ExternalArrayType array_type,
|
||||
|
||||
result = CompileRun("ext_array[1] = 23;");
|
||||
CHECK_EQ(23, result->Int32Value());
|
||||
}
|
||||
|
||||
|
||||
template <class ExternalArrayClass, class ElementType>
|
||||
static void ExternalArrayTestHelper(v8::ExternalArrayType array_type,
|
||||
int64_t low,
|
||||
int64_t high) {
|
||||
LocalContext context;
|
||||
v8::HandleScope scope(context->GetIsolate());
|
||||
const int kElementCount = 40;
|
||||
int element_size = ExternalArrayElementSize(array_type);
|
||||
ElementType* array_data =
|
||||
static_cast<ElementType*>(malloc(kElementCount * element_size));
|
||||
i::Handle<ExternalArrayClass> array =
|
||||
i::Handle<ExternalArrayClass>::cast(
|
||||
FACTORY->NewExternalArray(kElementCount, array_type, array_data));
|
||||
// Force GC to trigger verification.
|
||||
HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
|
||||
for (int i = 0; i < kElementCount; i++) {
|
||||
array->set(i, static_cast<ElementType>(i));
|
||||
}
|
||||
// Force GC to trigger verification.
|
||||
HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
|
||||
for (int i = 0; i < kElementCount; i++) {
|
||||
CHECK_EQ(static_cast<int64_t>(i),
|
||||
static_cast<int64_t>(array->get_scalar(i)));
|
||||
CHECK_EQ(static_cast<int64_t>(i), static_cast<int64_t>(array_data[i]));
|
||||
}
|
||||
|
||||
v8::Handle<v8::Object> obj = v8::Object::New();
|
||||
i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
|
||||
// Set the elements to be the external array.
|
||||
obj->SetIndexedPropertiesToExternalArrayData(array_data,
|
||||
array_type,
|
||||
kElementCount);
|
||||
CHECK_EQ(
|
||||
1, static_cast<int>(jsobj->GetElement(1)->ToObjectChecked()->Number()));
|
||||
|
||||
ObjectWithExternalArrayTestHelper<ExternalArrayClass, ElementType>(
|
||||
context.local(), obj, kElementCount, array_type, low, high);
|
||||
|
||||
v8::Handle<v8::Value> result;
|
||||
|
||||
// Test more complex manipulations which cause eax to contain values
|
||||
// that won't be completely overwritten by loads from the arrays.
|
||||
@ -15074,6 +15093,87 @@ TEST(ExternalArrayLimits) {
|
||||
}
|
||||
|
||||
|
||||
template <typename ElementType, typename TypedArray,
|
||||
class ExternalArrayClass>
|
||||
void TypedArrayTestHelper(v8::ExternalArrayType array_type,
|
||||
int64_t low, int64_t high) {
|
||||
const int kElementCount = 50;
|
||||
i::FLAG_harmony_typed_arrays = true;
|
||||
|
||||
LocalContext env;
|
||||
v8::Isolate* isolate = env->GetIsolate();
|
||||
v8::HandleScope handle_scope(isolate);
|
||||
|
||||
Local<v8::ArrayBuffer> ab =
|
||||
v8::ArrayBuffer::New((kElementCount+2)*sizeof(ElementType));
|
||||
Local<TypedArray> ta =
|
||||
TypedArray::New(ab, 2*sizeof(ElementType), kElementCount);
|
||||
CHECK_EQ(kElementCount, static_cast<int>(ta->Length()));
|
||||
CHECK_EQ(2*sizeof(ElementType), static_cast<int>(ta->ByteOffset()));
|
||||
CHECK_EQ(kElementCount*sizeof(ElementType),
|
||||
static_cast<int>(ta->ByteLength()));
|
||||
CHECK_EQ(ab, ta->Buffer());
|
||||
|
||||
ElementType* data = static_cast<ElementType*>(ab->Data()) + 2;
|
||||
for (int i = 0; i < kElementCount; i++) {
|
||||
data[i] = static_cast<ElementType>(i);
|
||||
}
|
||||
|
||||
ObjectWithExternalArrayTestHelper<ExternalArrayClass, ElementType>(
|
||||
env.local(), ta, kElementCount, array_type, low, high);
|
||||
}
|
||||
|
||||
|
||||
THREADED_TEST(Uint8Array) {
|
||||
TypedArrayTestHelper<uint8_t, v8::Uint8Array, i::ExternalUnsignedByteArray>(
|
||||
v8::kExternalUnsignedByteArray, 0, 0xFF);
|
||||
}
|
||||
|
||||
|
||||
THREADED_TEST(Int8Array) {
|
||||
TypedArrayTestHelper<int8_t, v8::Int8Array, i::ExternalByteArray>(
|
||||
v8::kExternalByteArray, -0x80, 0x7F);
|
||||
}
|
||||
|
||||
|
||||
THREADED_TEST(Uint16Array) {
|
||||
TypedArrayTestHelper<uint16_t,
|
||||
v8::Uint16Array,
|
||||
i::ExternalUnsignedShortArray>(
|
||||
v8::kExternalUnsignedShortArray, 0, 0xFFFF);
|
||||
}
|
||||
|
||||
|
||||
THREADED_TEST(Int16Array) {
|
||||
TypedArrayTestHelper<int16_t, v8::Int16Array, i::ExternalShortArray>(
|
||||
v8::kExternalShortArray, -0x8000, 0x7FFF);
|
||||
}
|
||||
|
||||
|
||||
THREADED_TEST(Uint32Array) {
|
||||
TypedArrayTestHelper<uint32_t, v8::Uint32Array, i::ExternalUnsignedIntArray>(
|
||||
v8::kExternalUnsignedIntArray, 0, UINT_MAX);
|
||||
}
|
||||
|
||||
|
||||
THREADED_TEST(Int32Array) {
|
||||
TypedArrayTestHelper<int32_t, v8::Int32Array, i::ExternalIntArray>(
|
||||
v8::kExternalIntArray, INT_MIN, INT_MAX);
|
||||
}
|
||||
|
||||
|
||||
THREADED_TEST(Float32Array) {
|
||||
TypedArrayTestHelper<float, v8::Float32Array, i::ExternalFloatArray>(
|
||||
v8::kExternalFloatArray, -500, 500);
|
||||
}
|
||||
|
||||
|
||||
THREADED_TEST(Float64Array) {
|
||||
TypedArrayTestHelper<double, v8::Float64Array, i::ExternalDoubleArray>(
|
||||
v8::kExternalDoubleArray, -500, 500);
|
||||
}
|
||||
|
||||
|
||||
THREADED_TEST(ScriptContextDependence) {
|
||||
LocalContext c1;
|
||||
v8::HandleScope scope(c1->GetIsolate());
|
||||
|
Loading…
Reference in New Issue
Block a user