Commit 7e0ee530 authored by dslomov@chromium.org's avatar dslomov@chromium.org

Add internal fields to JSArrayBufferViews (JSTypedArray and JSDataView)

In Blink, JSTypedArray and JSDataView objects act as "wrappers" for C++
objects. Wrapping protocol in Blink requires all wrapper JavaScript objects
to have a certain amount of internal fields that Blink uses for
book-keeping (essentially a pointer to C++ object and some type
information). This change adds those internal fields to JSTypedArray and
JSDataView, in a similiar way to how it is done for JSArrayBuffer.

R=titzer@chromium.org

Review URL: https://codereview.chromium.org/18695004

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@15511 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 02674ee4
...@@ -2377,6 +2377,7 @@ class V8EXPORT Function : public Object { ...@@ -2377,6 +2377,7 @@ class V8EXPORT Function : public Object {
}; };
#ifndef V8_ARRAY_BUFFER_INTERNAL_FIELD_COUNT #ifndef V8_ARRAY_BUFFER_INTERNAL_FIELD_COUNT
// The number of required internal fields can be defined by embedder.
#define V8_ARRAY_BUFFER_INTERNAL_FIELD_COUNT 2 #define V8_ARRAY_BUFFER_INTERNAL_FIELD_COUNT 2
#endif #endif
...@@ -2489,6 +2490,12 @@ class V8EXPORT ArrayBuffer : public Object { ...@@ -2489,6 +2490,12 @@ class V8EXPORT ArrayBuffer : public Object {
}; };
#ifndef V8_ARRAY_BUFFER_VIEW_INTERNAL_FIELD_COUNT
// The number of required internal fields can be defined by embedder.
#define V8_ARRAY_BUFFER_VIEW_INTERNAL_FIELD_COUNT 2
#endif
/** /**
* A base class for an instance of one of "views" over ArrayBuffer, * A base class for an instance of one of "views" over ArrayBuffer,
* including TypedArrays and DataView (ES6 draft 15.13). * including TypedArrays and DataView (ES6 draft 15.13).
...@@ -2516,6 +2523,9 @@ class V8EXPORT ArrayBufferView : public Object { ...@@ -2516,6 +2523,9 @@ class V8EXPORT ArrayBufferView : public Object {
V8_INLINE(static ArrayBufferView* Cast(Value* obj)); V8_INLINE(static ArrayBufferView* Cast(Value* obj));
static const int kInternalFieldCount =
V8_ARRAY_BUFFER_VIEW_INTERNAL_FIELD_COUNT;
private: private:
ArrayBufferView(); ArrayBufferView();
static void CheckCast(Value* obj); static void CheckCast(Value* obj);
......
...@@ -1289,7 +1289,7 @@ Handle<JSFunction> Genesis::InstallTypedArray( ...@@ -1289,7 +1289,7 @@ Handle<JSFunction> Genesis::InstallTypedArray(
Builtins::kIllegal, false, true); Builtins::kIllegal, false, true);
Handle<Map> initial_map = isolate()->factory()->NewMap( Handle<Map> initial_map = isolate()->factory()->NewMap(
JS_TYPED_ARRAY_TYPE, JSTypedArray::kSize, elementsKind); JS_TYPED_ARRAY_TYPE, JSTypedArray::kSizeWithInternalFields, elementsKind);
result->set_initial_map(*initial_map); result->set_initial_map(*initial_map);
initial_map->set_constructor(*result); initial_map->set_constructor(*result);
return result; return result;
...@@ -1373,7 +1373,7 @@ void Genesis::InitializeExperimentalGlobal() { ...@@ -1373,7 +1373,7 @@ void Genesis::InitializeExperimentalGlobal() {
Handle<JSFunction> data_view_fun = Handle<JSFunction> data_view_fun =
InstallFunction( InstallFunction(
global, "DataView", JS_DATA_VIEW_TYPE, global, "DataView", JS_DATA_VIEW_TYPE,
JSDataView::kSize, JSDataView::kSizeWithInternalFields,
isolate()->initial_object_prototype(), isolate()->initial_object_prototype(),
Builtins::kIllegal, true, true); Builtins::kIllegal, true, true);
native_context()->set_data_view_fun(*data_view_fun); native_context()->set_data_view_fun(*data_view_fun);
......
...@@ -136,8 +136,8 @@ int StaticNewSpaceVisitor<StaticVisitor>::VisitJSTypedArray( ...@@ -136,8 +136,8 @@ int StaticNewSpaceVisitor<StaticVisitor>::VisitJSTypedArray(
map->GetHeap(), map->GetHeap(),
HeapObject::RawField(object, HeapObject::RawField(object,
JSTypedArray::kWeakNextOffset + kPointerSize), JSTypedArray::kWeakNextOffset + kPointerSize),
HeapObject::RawField(object, JSTypedArray::kSize)); HeapObject::RawField(object, JSTypedArray::kSizeWithInternalFields));
return JSTypedArray::kSize; return JSTypedArray::kSizeWithInternalFields;
} }
...@@ -152,8 +152,8 @@ int StaticNewSpaceVisitor<StaticVisitor>::VisitJSDataView( ...@@ -152,8 +152,8 @@ int StaticNewSpaceVisitor<StaticVisitor>::VisitJSDataView(
map->GetHeap(), map->GetHeap(),
HeapObject::RawField(object, HeapObject::RawField(object,
JSDataView::kWeakNextOffset + kPointerSize), JSDataView::kWeakNextOffset + kPointerSize),
HeapObject::RawField(object, JSDataView::kSize)); HeapObject::RawField(object, JSDataView::kSizeWithInternalFields));
return JSDataView::kSize; return JSDataView::kSizeWithInternalFields;
} }
...@@ -522,7 +522,7 @@ void StaticMarkingVisitor<StaticVisitor>::VisitJSTypedArray( ...@@ -522,7 +522,7 @@ void StaticMarkingVisitor<StaticVisitor>::VisitJSTypedArray(
map->GetHeap(), map->GetHeap(),
HeapObject::RawField(object, HeapObject::RawField(object,
JSTypedArray::kWeakNextOffset + kPointerSize), JSTypedArray::kWeakNextOffset + kPointerSize),
HeapObject::RawField(object, JSTypedArray::kSize)); HeapObject::RawField(object, JSTypedArray::kSizeWithInternalFields));
} }
...@@ -537,7 +537,7 @@ void StaticMarkingVisitor<StaticVisitor>::VisitJSDataView( ...@@ -537,7 +537,7 @@ void StaticMarkingVisitor<StaticVisitor>::VisitJSDataView(
map->GetHeap(), map->GetHeap(),
HeapObject::RawField(object, HeapObject::RawField(object,
JSDataView::kWeakNextOffset + kPointerSize), JSDataView::kWeakNextOffset + kPointerSize),
HeapObject::RawField(object, JSDataView::kSize)); HeapObject::RawField(object, JSDataView::kSizeWithInternalFields));
} }
......
...@@ -8918,6 +8918,9 @@ class JSTypedArray: public JSArrayBufferView { ...@@ -8918,6 +8918,9 @@ class JSTypedArray: public JSArrayBufferView {
static const int kLengthOffset = kViewSize + kPointerSize; static const int kLengthOffset = kViewSize + kPointerSize;
static const int kSize = kLengthOffset + kPointerSize; static const int kSize = kLengthOffset + kPointerSize;
static const int kSizeWithInternalFields =
kSize + v8::ArrayBufferView::kInternalFieldCount * kPointerSize;
private: private:
DISALLOW_IMPLICIT_CONSTRUCTORS(JSTypedArray); DISALLOW_IMPLICIT_CONSTRUCTORS(JSTypedArray);
}; };
...@@ -8937,6 +8940,9 @@ class JSDataView: public JSArrayBufferView { ...@@ -8937,6 +8940,9 @@ class JSDataView: public JSArrayBufferView {
static const int kSize = kViewSize; static const int kSize = kViewSize;
static const int kSizeWithInternalFields =
kSize + v8::ArrayBufferView::kInternalFieldCount * kPointerSize;
private: private:
DISALLOW_IMPLICIT_CONSTRUCTORS(JSDataView); DISALLOW_IMPLICIT_CONSTRUCTORS(JSDataView);
}; };
......
...@@ -796,6 +796,12 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayInitialize) { ...@@ -796,6 +796,12 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayInitialize) {
CONVERT_ARG_HANDLE_CHECKED(Object, byte_offset_object, 3); CONVERT_ARG_HANDLE_CHECKED(Object, byte_offset_object, 3);
CONVERT_ARG_HANDLE_CHECKED(Object, byte_length_object, 4); CONVERT_ARG_HANDLE_CHECKED(Object, byte_length_object, 4);
ASSERT(holder->GetInternalFieldCount() ==
v8::ArrayBufferView::kInternalFieldCount);
for (int i = 0; i < v8::ArrayBufferView::kInternalFieldCount; i++) {
holder->SetInternalField(i, Smi::FromInt(0));
}
ExternalArrayType arrayType; ExternalArrayType arrayType;
size_t elementSize; size_t elementSize;
switch (arrayId) { switch (arrayId) {
...@@ -1012,6 +1018,12 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DataViewInitialize) { ...@@ -1012,6 +1018,12 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DataViewInitialize) {
CONVERT_ARG_HANDLE_CHECKED(Object, byte_offset, 2); CONVERT_ARG_HANDLE_CHECKED(Object, byte_offset, 2);
CONVERT_ARG_HANDLE_CHECKED(Object, byte_length, 3); CONVERT_ARG_HANDLE_CHECKED(Object, byte_length, 3);
ASSERT(holder->GetInternalFieldCount() ==
v8::ArrayBufferView::kInternalFieldCount);
for (int i = 0; i < v8::ArrayBufferView::kInternalFieldCount; i++) {
holder->SetInternalField(i, Smi::FromInt(0));
}
holder->set_buffer(*buffer); holder->set_buffer(*buffer);
ASSERT(byte_offset->IsNumber()); ASSERT(byte_offset->IsNumber());
ASSERT( ASSERT(
......
...@@ -2572,6 +2572,14 @@ class ScopedArrayBufferContents { ...@@ -2572,6 +2572,14 @@ class ScopedArrayBufferContents {
const v8::ArrayBuffer::Contents contents_; const v8::ArrayBuffer::Contents contents_;
}; };
template <typename T>
static void CheckInternalFieldsAreZero(v8::Handle<T> value) {
CHECK_EQ(T::kInternalFieldCount, value->InternalFieldCount());
for (int i = 0; i < value->InternalFieldCount(); i++) {
CHECK_EQ(0, value->GetInternalField(i)->Int32Value());
}
}
THREADED_TEST(ArrayBuffer_ApiInternalToExternal) { THREADED_TEST(ArrayBuffer_ApiInternalToExternal) {
i::FLAG_harmony_array_buffer = true; i::FLAG_harmony_array_buffer = true;
...@@ -2582,6 +2590,7 @@ THREADED_TEST(ArrayBuffer_ApiInternalToExternal) { ...@@ -2582,6 +2590,7 @@ THREADED_TEST(ArrayBuffer_ApiInternalToExternal) {
v8::HandleScope handle_scope(isolate); v8::HandleScope handle_scope(isolate);
Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(1024); Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(1024);
CheckInternalFieldsAreZero(ab);
CHECK_EQ(1024, static_cast<int>(ab->ByteLength())); CHECK_EQ(1024, static_cast<int>(ab->ByteLength()));
CHECK(!ab->IsExternal()); CHECK(!ab->IsExternal());
HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
...@@ -2626,6 +2635,7 @@ THREADED_TEST(ArrayBuffer_JSInternalToExternal) { ...@@ -2626,6 +2635,7 @@ THREADED_TEST(ArrayBuffer_JSInternalToExternal) {
"u8_a[0] = 0xAA;" "u8_a[0] = 0xAA;"
"u8_a[1] = 0xFF; u8_a.buffer"); "u8_a[1] = 0xFF; u8_a.buffer");
Local<v8::ArrayBuffer> ab1 = Local<v8::ArrayBuffer>::Cast(result); Local<v8::ArrayBuffer> ab1 = Local<v8::ArrayBuffer>::Cast(result);
CheckInternalFieldsAreZero(ab1);
CHECK_EQ(2, static_cast<int>(ab1->ByteLength())); CHECK_EQ(2, static_cast<int>(ab1->ByteLength()));
CHECK(!ab1->IsExternal()); CHECK(!ab1->IsExternal());
ScopedArrayBufferContents ab1_contents(ab1->Externalize()); ScopedArrayBufferContents ab1_contents(ab1->Externalize());
...@@ -2666,6 +2676,7 @@ THREADED_TEST(ArrayBuffer_External) { ...@@ -2666,6 +2676,7 @@ THREADED_TEST(ArrayBuffer_External) {
i::ScopedVector<uint8_t> my_data(100); i::ScopedVector<uint8_t> my_data(100);
memset(my_data.start(), 0, 100); memset(my_data.start(), 0, 100);
Local<v8::ArrayBuffer> ab3 = v8::ArrayBuffer::New(my_data.start(), 100); Local<v8::ArrayBuffer> ab3 = v8::ArrayBuffer::New(my_data.start(), 100);
CheckInternalFieldsAreZero(ab3);
CHECK_EQ(100, static_cast<int>(ab3->ByteLength())); CHECK_EQ(100, static_cast<int>(ab3->ByteLength()));
CHECK(ab3->IsExternal()); CHECK(ab3->IsExternal());
...@@ -2718,6 +2729,7 @@ static Handle<TypedArray> CreateAndCheck(Handle<v8::ArrayBuffer> ab, ...@@ -2718,6 +2729,7 @@ static Handle<TypedArray> CreateAndCheck(Handle<v8::ArrayBuffer> ab,
int byteOffset, int byteOffset,
int length) { int length) {
v8::Handle<TypedArray> ta = TypedArray::New(ab, byteOffset, length); v8::Handle<TypedArray> ta = TypedArray::New(ab, byteOffset, length);
CheckInternalFieldsAreZero<v8::ArrayBufferView>(ta);
CHECK_EQ(byteOffset, static_cast<int>(ta->ByteOffset())); CHECK_EQ(byteOffset, static_cast<int>(ta->ByteOffset()));
CHECK_EQ(length, static_cast<int>(ta->Length())); CHECK_EQ(length, static_cast<int>(ta->Length()));
CHECK_EQ(length * kElementSize, static_cast<int>(ta->ByteLength())); CHECK_EQ(length * kElementSize, static_cast<int>(ta->ByteLength()));
...@@ -2755,6 +2767,7 @@ THREADED_TEST(ArrayBuffer_NeuteringApi) { ...@@ -2755,6 +2767,7 @@ THREADED_TEST(ArrayBuffer_NeuteringApi) {
CreateAndCheck<v8::Float64Array, 8>(buffer, 8, 127); CreateAndCheck<v8::Float64Array, 8>(buffer, 8, 127);
v8::Handle<v8::DataView> dv = v8::DataView::New(buffer, 1, 1023); v8::Handle<v8::DataView> dv = v8::DataView::New(buffer, 1, 1023);
CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
CHECK_EQ(1, static_cast<int>(dv->ByteOffset())); CHECK_EQ(1, static_cast<int>(dv->ByteOffset()));
CHECK_EQ(1023, static_cast<int>(dv->ByteLength())); CHECK_EQ(1023, static_cast<int>(dv->ByteLength()));
...@@ -15783,6 +15796,7 @@ void TypedArrayTestHelper(v8::ExternalArrayType array_type, ...@@ -15783,6 +15796,7 @@ void TypedArrayTestHelper(v8::ExternalArrayType array_type,
backing_store.start(), (kElementCount+2)*sizeof(ElementType)); backing_store.start(), (kElementCount+2)*sizeof(ElementType));
Local<TypedArray> ta = Local<TypedArray> ta =
TypedArray::New(ab, 2*sizeof(ElementType), kElementCount); TypedArray::New(ab, 2*sizeof(ElementType), kElementCount);
CheckInternalFieldsAreZero<v8::ArrayBufferView>(ta);
CHECK_EQ(kElementCount, static_cast<int>(ta->Length())); CHECK_EQ(kElementCount, static_cast<int>(ta->Length()));
CHECK_EQ(2*sizeof(ElementType), static_cast<int>(ta->ByteOffset())); CHECK_EQ(2*sizeof(ElementType), static_cast<int>(ta->ByteOffset()));
CHECK_EQ(kElementCount*sizeof(ElementType), CHECK_EQ(kElementCount*sizeof(ElementType),
...@@ -15868,6 +15882,7 @@ THREADED_TEST(DataView) { ...@@ -15868,6 +15882,7 @@ THREADED_TEST(DataView) {
backing_store.start(), 2 + kSize); backing_store.start(), 2 + kSize);
Local<v8::DataView> dv = Local<v8::DataView> dv =
v8::DataView::New(ab, 2, kSize); v8::DataView::New(ab, 2, kSize);
CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
CHECK_EQ(2, static_cast<int>(dv->ByteOffset())); CHECK_EQ(2, static_cast<int>(dv->ByteOffset()));
CHECK_EQ(kSize, static_cast<int>(dv->ByteLength())); CHECK_EQ(kSize, static_cast<int>(dv->ByteLength()));
CHECK_EQ(ab, dv->Buffer()); CHECK_EQ(ab, dv->Buffer());
...@@ -15887,6 +15902,7 @@ THREADED_TEST(DataView) { ...@@ -15887,6 +15902,7 @@ THREADED_TEST(DataView) {
"new " #View "(ab)"); \ "new " #View "(ab)"); \
CHECK(result->IsArrayBufferView()); \ CHECK(result->IsArrayBufferView()); \
CHECK(result->Is##View()); \ CHECK(result->Is##View()); \
CheckInternalFieldsAreZero<v8::ArrayBufferView>(result.As<v8::View>()); \
} }
IS_ARRAY_BUFFER_VIEW_TEST(Uint8Array) IS_ARRAY_BUFFER_VIEW_TEST(Uint8Array)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment