From c2969bfb1a9e4289bbc87363ac9bedd01002981e Mon Sep 17 00:00:00 2001 From: "ager@chromium.org" Date: Mon, 21 Feb 2011 15:59:23 +0000 Subject: [PATCH] Implement pixel array elements access in the presence of an interceptor that does not handle the elements load. Review URL: http://codereview.chromium.org/6551001 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@6869 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/objects.cc | 75 +++++++++++++++++++++++++++++++------------------ src/objects.h | 5 ++++ test/cctest/test-api.cc | 47 +++++++++++++++++++++++++++++++ 3 files changed, 99 insertions(+), 28 deletions(-) diff --git a/src/objects.cc b/src/objects.cc index e56c917..2d10052 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -6666,7 +6666,6 @@ bool JSObject::HasElementPostInterceptor(JSObject* receiver, uint32_t index) { break; } case PIXEL_ELEMENTS: { - // TODO(iposva): Add testcase. PixelArray* pixels = PixelArray::cast(elements()); if (index < static_cast(pixels->length())) { return true; @@ -6680,7 +6679,6 @@ bool JSObject::HasElementPostInterceptor(JSObject* receiver, uint32_t index) { case EXTERNAL_INT_ELEMENTS: case EXTERNAL_UNSIGNED_INT_ELEMENTS: case EXTERNAL_FLOAT_ELEMENTS: { - // TODO(kbr): Add testcase. ExternalArray* array = ExternalArray::cast(elements()); if (index < static_cast(array->length())) { return true; @@ -7271,11 +7269,7 @@ MaybeObject* JSObject::GetElementPostInterceptor(Object* receiver, } break; } - case PIXEL_ELEMENTS: { - // TODO(iposva): Add testcase and implement. - UNIMPLEMENTED(); - break; - } + case PIXEL_ELEMENTS: case EXTERNAL_BYTE_ELEMENTS: case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: case EXTERNAL_SHORT_ELEMENTS: @@ -7283,8 +7277,8 @@ MaybeObject* JSObject::GetElementPostInterceptor(Object* receiver, case EXTERNAL_INT_ELEMENTS: case EXTERNAL_UNSIGNED_INT_ELEMENTS: case EXTERNAL_FLOAT_ELEMENTS: { - // TODO(kbr): Add testcase and implement. - UNIMPLEMENTED(); + MaybeObject* value = GetExternalElement(index); + if (!value->ToObjectUnchecked()->IsUndefined()) return value; break; } case DICTIONARY_ELEMENTS: { @@ -7372,6 +7366,46 @@ MaybeObject* JSObject::GetElementWithReceiver(Object* receiver, } break; } + case PIXEL_ELEMENTS: + case EXTERNAL_BYTE_ELEMENTS: + case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: + case EXTERNAL_SHORT_ELEMENTS: + case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: + case EXTERNAL_INT_ELEMENTS: + case EXTERNAL_UNSIGNED_INT_ELEMENTS: + case EXTERNAL_FLOAT_ELEMENTS: { + MaybeObject* value = GetExternalElement(index); + if (!value->ToObjectUnchecked()->IsUndefined()) return value; + break; + } + case DICTIONARY_ELEMENTS: { + NumberDictionary* dictionary = element_dictionary(); + int entry = dictionary->FindEntry(index); + if (entry != NumberDictionary::kNotFound) { + Object* element = dictionary->ValueAt(entry); + PropertyDetails details = dictionary->DetailsAt(entry); + if (details.type() == CALLBACKS) { + return GetElementWithCallback(receiver, + element, + index, + this); + } + return element; + } + break; + } + } + + Object* pt = GetPrototype(); + if (pt == Heap::null_value()) return Heap::undefined_value(); + return pt->GetElementWithReceiver(receiver, index); +} + + +MaybeObject* JSObject::GetExternalElement(uint32_t index) { + // Get element works for both JSObject and JSArray since + // JSArray::length cannot change. + switch (GetElementsKind()) { case PIXEL_ELEMENTS: { PixelArray* pixels = PixelArray::cast(elements()); if (index < static_cast(pixels->length())) { @@ -7439,27 +7473,12 @@ MaybeObject* JSObject::GetElementWithReceiver(Object* receiver, } break; } - case DICTIONARY_ELEMENTS: { - NumberDictionary* dictionary = element_dictionary(); - int entry = dictionary->FindEntry(index); - if (entry != NumberDictionary::kNotFound) { - Object* element = dictionary->ValueAt(entry); - PropertyDetails details = dictionary->DetailsAt(entry); - if (details.type() == CALLBACKS) { - return GetElementWithCallback(receiver, - element, - index, - this); - } - return element; - } + case FAST_ELEMENTS: + case DICTIONARY_ELEMENTS: + UNREACHABLE(); break; - } } - - Object* pt = GetPrototype(); - if (pt == Heap::null_value()) return Heap::undefined_value(); - return pt->GetElementWithReceiver(receiver, index); + return Heap::undefined_value(); } diff --git a/src/objects.h b/src/objects.h index d6349e6..fbfc5fd 100644 --- a/src/objects.h +++ b/src/objects.h @@ -1549,6 +1549,11 @@ class JSObject: public HeapObject { MaybeObject* GetElementWithReceiver(Object* receiver, uint32_t index); MaybeObject* GetElementWithInterceptor(Object* receiver, uint32_t index); + // Get external element value at index if there is one and undefined + // otherwise. Can return a failure if allocation of a heap number + // failed. + MaybeObject* GetExternalElement(uint32_t index); + MUST_USE_RESULT MaybeObject* SetFastElementsCapacityAndLength(int capacity, int length); MUST_USE_RESULT MaybeObject* SetSlowElements(Object* length); diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc index 0b6a2b7..0da3f1c 100644 --- a/test/cctest/test-api.cc +++ b/test/cctest/test-api.cc @@ -10883,6 +10883,53 @@ THREADED_TEST(PixelArrayInfo) { } +static v8::Handle NotHandledIndexedPropertyGetter( + uint32_t index, + const AccessorInfo& info) { + ApiTestFuzzer::Fuzz(); + return v8::Handle(); +} + + +static v8::Handle NotHandledIndexedPropertySetter( + uint32_t index, + Local value, + const AccessorInfo& info) { + ApiTestFuzzer::Fuzz(); + return v8::Handle(); +} + + +THREADED_TEST(PixelArrayWithInterceptor) { + v8::HandleScope scope; + LocalContext context; + const int kElementCount = 260; + uint8_t* pixel_data = reinterpret_cast(malloc(kElementCount)); + i::Handle pixels = + i::Factory::NewPixelArray(kElementCount, pixel_data); + for (int i = 0; i < kElementCount; i++) { + pixels->set(i, i % 256); + } + v8::Handle templ = v8::ObjectTemplate::New(); + templ->SetIndexedPropertyHandler(NotHandledIndexedPropertyGetter, + NotHandledIndexedPropertySetter); + v8::Handle obj = templ->NewInstance(); + obj->SetIndexedPropertiesToPixelData(pixel_data, kElementCount); + context->Global()->Set(v8_str("pixels"), obj); + v8::Handle result = CompileRun("pixels[1]"); + CHECK_EQ(1, result->Int32Value()); + result = CompileRun("var sum = 0;" + "for (var i = 0; i < 8; i++) {" + " sum += pixels[i] = pixels[i] = -i;" + "}" + "sum;"); + CHECK_EQ(-28, result->Int32Value()); + result = CompileRun("pixels.hasOwnProperty('1')"); + CHECK(result->BooleanValue()); + free(pixel_data); +} + + static int ExternalArrayElementSize(v8::ExternalArrayType array_type) { switch (array_type) { case v8::kExternalByteArray: -- 2.7.4