From bd353dc3a0652393671343d0123ae4e9ef8df3b5 Mon Sep 17 00:00:00 2001 From: "dslomov@chromium.org" Date: Fri, 28 Mar 2014 15:25:24 +0000 Subject: [PATCH] Inline internal getters for typed arrays & friends. R=hpayer@chromium.org, yangguo@chromium.org Committed: https://code.google.com/p/v8/source/detail?r=20330 Review URL: https://codereview.chromium.org/212603014 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@20338 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/arraybuffer.js | 4 +- src/hydrogen-instructions.h | 5 ++ src/hydrogen.cc | 52 +++++++++++++++++ src/runtime.cc | 53 ++++-------------- src/runtime.h | 14 ++--- src/spaces.cc | 2 +- src/typedarray.js | 108 +++++++++++++++++++++--------------- test/cctest/test-api.cc | 4 +- test/mjsunit/harmony/typedarrays.js | 5 ++ 9 files changed, 148 insertions(+), 99 deletions(-) diff --git a/src/arraybuffer.js b/src/arraybuffer.js index d5fd9ad..07924e4 100644 --- a/src/arraybuffer.js +++ b/src/arraybuffer.js @@ -45,7 +45,7 @@ function ArrayBufferGetByteLength() { throw MakeTypeError('incompatible_method_receiver', ['ArrayBuffer.prototype.byteLength', this]); } - return %ArrayBufferGetByteLength(this); + return %_ArrayBufferGetByteLength(this); } // ES6 Draft 15.13.5.5.3 @@ -60,7 +60,7 @@ function ArrayBufferSlice(start, end) { end = TO_INTEGER(end); } var first; - var byte_length = %ArrayBufferGetByteLength(this); + var byte_length = %_ArrayBufferGetByteLength(this); if (relativeStart < 0) { first = MathMax(byte_length + relativeStart, 0); } else { diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h index 1e6ac19..81ecb89 100644 --- a/src/hydrogen-instructions.h +++ b/src/hydrogen-instructions.h @@ -6025,6 +6025,11 @@ class HObjectAccess V8_FINAL { JSArrayBuffer::kBackingStoreOffset, Representation::External()); } + static HObjectAccess ForJSArrayBufferByteLength() { + return HObjectAccess::ForObservableJSObjectOffset( + JSArrayBuffer::kByteLengthOffset, Representation::Tagged()); + } + static HObjectAccess ForExternalArrayExternalPointer() { return HObjectAccess::ForObservableJSObjectOffset( ExternalArray::kExternalPointerOffset, Representation::External()); diff --git a/src/hydrogen.cc b/src/hydrogen.cc index 77e7778..80eff3b 100644 --- a/src/hydrogen.cc +++ b/src/hydrogen.cc @@ -8730,6 +8730,58 @@ void HOptimizedGraphBuilder::GenerateTypedArrayMaxSizeInHeap( } +void HOptimizedGraphBuilder::GenerateArrayBufferGetByteLength( + CallRuntime* expr) { + ASSERT(expr->arguments()->length() == 1); + CHECK_ALIVE(VisitForValue(expr->arguments()->at(0))); + HValue* buffer = Pop(); + HInstruction* result = New( + buffer, + static_cast(NULL), + HObjectAccess::ForJSArrayBufferByteLength()); + return ast_context()->ReturnInstruction(result, expr->id()); +} + + +void HOptimizedGraphBuilder::GenerateArrayBufferViewGetByteLength( + CallRuntime* expr) { + ASSERT(expr->arguments()->length() == 1); + CHECK_ALIVE(VisitForValue(expr->arguments()->at(0))); + HValue* buffer = Pop(); + HInstruction* result = New( + buffer, + static_cast(NULL), + HObjectAccess::ForJSArrayBufferViewByteLength()); + return ast_context()->ReturnInstruction(result, expr->id()); +} + + +void HOptimizedGraphBuilder::GenerateArrayBufferViewGetByteOffset( + CallRuntime* expr) { + ASSERT(expr->arguments()->length() == 1); + CHECK_ALIVE(VisitForValue(expr->arguments()->at(0))); + HValue* buffer = Pop(); + HInstruction* result = New( + buffer, + static_cast(NULL), + HObjectAccess::ForJSArrayBufferViewByteOffset()); + return ast_context()->ReturnInstruction(result, expr->id()); +} + + +void HOptimizedGraphBuilder::GenerateTypedArrayGetLength( + CallRuntime* expr) { + ASSERT(expr->arguments()->length() == 1); + CHECK_ALIVE(VisitForValue(expr->arguments()->at(0))); + HValue* buffer = Pop(); + HInstruction* result = New( + buffer, + static_cast(NULL), + HObjectAccess::ForJSTypedArrayLength()); + return ast_context()->ReturnInstruction(result, expr->id()); +} + + void HOptimizedGraphBuilder::VisitCallRuntime(CallRuntime* expr) { ASSERT(!HasStackOverflow()); ASSERT(current_block() != NULL); diff --git a/src/runtime.cc b/src/runtime.cc index 503f367..849de3c 100644 --- a/src/runtime.cc +++ b/src/runtime.cc @@ -1132,33 +1132,26 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayInitializeFromArrayLike) { } -#define TYPED_ARRAY_GETTER(getter, accessor) \ - RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayGet##getter) { \ +#define BUFFER_VIEW_GETTER(Type, getter, accessor) \ + RUNTIME_FUNCTION(MaybeObject*, Runtime_##Type##Get##getter) { \ HandleScope scope(isolate); \ ASSERT(args.length() == 1); \ - CONVERT_ARG_HANDLE_CHECKED(Object, holder, 0); \ - if (!holder->IsJSTypedArray()) \ - return isolate->Throw(*isolate->factory()->NewTypeError( \ - "not_typed_array", HandleVector(NULL, 0))); \ - Handle typed_array(JSTypedArray::cast(*holder)); \ - return typed_array->accessor(); \ + CONVERT_ARG_HANDLE_CHECKED(JS##Type, holder, 0); \ + return holder->accessor(); \ } -TYPED_ARRAY_GETTER(ByteLength, byte_length) -TYPED_ARRAY_GETTER(ByteOffset, byte_offset) -TYPED_ARRAY_GETTER(Length, length) +BUFFER_VIEW_GETTER(ArrayBufferView, ByteLength, byte_length) +BUFFER_VIEW_GETTER(ArrayBufferView, ByteOffset, byte_offset) +BUFFER_VIEW_GETTER(TypedArray, Length, length) +BUFFER_VIEW_GETTER(DataView, Buffer, buffer) -#undef TYPED_ARRAY_GETTER +#undef BUFFER_VIEW_GETTER RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayGetBuffer) { HandleScope scope(isolate); ASSERT(args.length() == 1); - CONVERT_ARG_HANDLE_CHECKED(Object, holder, 0); - if (!holder->IsJSTypedArray()) - return isolate->Throw(*isolate->factory()->NewTypeError( - "not_typed_array", HandleVector(NULL, 0))); - Handle typed_array(JSTypedArray::cast(*holder)); - return *typed_array->GetBuffer(); + CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, holder, 0); + return *holder->GetBuffer(); } @@ -1273,30 +1266,6 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DataViewInitialize) { } -RUNTIME_FUNCTION(MaybeObject*, Runtime_DataViewGetBuffer) { - HandleScope scope(isolate); - ASSERT(args.length() == 1); - CONVERT_ARG_HANDLE_CHECKED(JSDataView, data_view, 0); - return data_view->buffer(); -} - - -RUNTIME_FUNCTION(MaybeObject*, Runtime_DataViewGetByteOffset) { - HandleScope scope(isolate); - ASSERT(args.length() == 1); - CONVERT_ARG_HANDLE_CHECKED(JSDataView, data_view, 0); - return data_view->byte_offset(); -} - - -RUNTIME_FUNCTION(MaybeObject*, Runtime_DataViewGetByteLength) { - HandleScope scope(isolate); - ASSERT(args.length() == 1); - CONVERT_ARG_HANDLE_CHECKED(JSDataView, data_view, 0); - return data_view->byte_length(); -} - - inline static bool NeedToFlipBytes(bool is_little_endian) { #ifdef V8_TARGET_LITTLE_ENDIAN return !is_little_endian; diff --git a/src/runtime.h b/src/runtime.h index f56e424..be0e545 100644 --- a/src/runtime.h +++ b/src/runtime.h @@ -328,21 +328,15 @@ namespace internal { \ /* Harmony typed arrays */ \ F(ArrayBufferInitialize, 2, 1)\ - F(ArrayBufferGetByteLength, 1, 1)\ F(ArrayBufferSliceImpl, 3, 1) \ F(ArrayBufferIsView, 1, 1) \ F(ArrayBufferNeuter, 1, 1) \ \ F(TypedArrayInitializeFromArrayLike, 4, 1) \ F(TypedArrayGetBuffer, 1, 1) \ - F(TypedArrayGetByteLength, 1, 1) \ - F(TypedArrayGetByteOffset, 1, 1) \ - F(TypedArrayGetLength, 1, 1) \ F(TypedArraySetFastCases, 3, 1) \ \ F(DataViewGetBuffer, 1, 1) \ - F(DataViewGetByteLength, 1, 1) \ - F(DataViewGetByteOffset, 1, 1) \ F(DataViewGetInt8, 3, 1) \ F(DataViewGetUint8, 3, 1) \ F(DataViewGetInt16, 3, 1) \ @@ -690,13 +684,17 @@ namespace internal { // Entries have the form F(name, number of arguments, number of return values). #define INLINE_OPTIMIZED_FUNCTION_LIST(F) \ /* Typed Arrays */ \ - F(ConstructDouble, 2, 1) \ F(TypedArrayInitialize, 5, 1) \ F(DataViewInitialize, 4, 1) \ F(MaxSmi, 0, 1) \ F(TypedArrayMaxSizeInHeap, 0, 1) \ - \ + F(ArrayBufferViewGetByteLength, 1, 1) \ + F(ArrayBufferViewGetByteOffset, 1, 1) \ + F(TypedArrayGetLength, 1, 1) \ + /* ArrayBuffer */ \ + F(ArrayBufferGetByteLength, 1, 1) \ /* Maths */ \ + F(ConstructDouble, 2, 1) \ F(DoubleHi, 1, 1) \ F(DoubleLo, 1, 1) \ F(MathSqrt, 1, 1) \ diff --git a/src/spaces.cc b/src/spaces.cc index 6c03daa..2ca8c98 100644 --- a/src/spaces.cc +++ b/src/spaces.cc @@ -1051,7 +1051,7 @@ intptr_t PagedSpace::SizeOfFirstPage() { int size = 0; switch (identity()) { case OLD_POINTER_SPACE: - size = 72 * kPointerSize * KB; + size = 96 * kPointerSize * KB; break; case OLD_DATA_SPACE: size = 192 * KB; diff --git a/src/typedarray.js b/src/typedarray.js index 109d627..e86c86c 100644 --- a/src/typedarray.js +++ b/src/typedarray.js @@ -57,7 +57,7 @@ macro TYPED_ARRAY_CONSTRUCTOR(ARRAY_ID, NAME, ELEMENT_SIZE) length = ToPositiveInteger(length, "invalid_typed_array_length"); } - var bufferByteLength = %ArrayBufferGetByteLength(buffer); + var bufferByteLength = %_ArrayBufferGetByteLength(buffer); var offset; if (IS_UNDEFINED(byteOffset)) { offset = 0; @@ -125,7 +125,6 @@ macro TYPED_ARRAY_CONSTRUCTOR(ARRAY_ID, NAME, ELEMENT_SIZE) } function NAMEConstructor(arg1, arg2, arg3) { - if (%_IsConstructCall()) { if (IS_ARRAYBUFFER(arg1)) { NAMEConstructByArrayBuffer(this, arg1, arg2, arg3); @@ -139,34 +138,52 @@ macro TYPED_ARRAY_CONSTRUCTOR(ARRAY_ID, NAME, ELEMENT_SIZE) throw MakeTypeError("constructor_not_function", ["NAME"]) } } -endmacro -TYPED_ARRAYS(TYPED_ARRAY_CONSTRUCTOR) + function NAME_GetBuffer() { + if (!(%_ClassOf(this) === 'NAME')) { + throw MakeTypeError('incompatible_method_receiver', + ["NAME.buffer", this]); + } + return %TypedArrayGetBuffer(this); + } -function TypedArrayGetBuffer() { - return %TypedArrayGetBuffer(this); -} + function NAME_GetByteLength() { + if (!(%_ClassOf(this) === 'NAME')) { + throw MakeTypeError('incompatible_method_receiver', + ["NAME.byteLength", this]); + } + return %_ArrayBufferViewGetByteLength(this); + } -function TypedArrayGetByteLength() { - return %TypedArrayGetByteLength(this); -} + function NAME_GetByteOffset() { + if (!(%_ClassOf(this) === 'NAME')) { + throw MakeTypeError('incompatible_method_receiver', + ["NAME.byteOffset", this]); + } + return %_ArrayBufferViewGetByteOffset(this); + } -function TypedArrayGetByteOffset() { - return %TypedArrayGetByteOffset(this); -} + function NAME_GetLength() { + if (!(%_ClassOf(this) === 'NAME')) { + throw MakeTypeError('incompatible_method_receiver', + ["NAME.length", this]); + } + return %_TypedArrayGetLength(this); + } -function TypedArrayGetLength() { - return %TypedArrayGetLength(this); -} + var $NAME = global.NAME; -function CreateSubArray(elementSize, constructor) { - return function(begin, end) { + function NAMESubArray(begin, end) { + if (!(%_ClassOf(this) === 'NAME')) { + throw MakeTypeError('incompatible_method_receiver', + ["NAME.subarray", this]); + } var beginInt = TO_INTEGER(begin); if (!IS_UNDEFINED(end)) { end = TO_INTEGER(end); } - var srcLength = %TypedArrayGetLength(this); + var srcLength = %_TypedArrayGetLength(this); if (beginInt < 0) { beginInt = MathMax(0, srcLength + beginInt); } else { @@ -184,11 +201,14 @@ function CreateSubArray(elementSize, constructor) { } var newLength = endInt - beginInt; var beginByteOffset = - %TypedArrayGetByteOffset(this) + beginInt * elementSize; - return new constructor(%TypedArrayGetBuffer(this), - beginByteOffset, newLength); + %_ArrayBufferViewGetByteOffset(this) + beginInt * ELEMENT_SIZE; + return new $NAME(%TypedArrayGetBuffer(this), + beginByteOffset, newLength); } -} +endmacro + +TYPED_ARRAYS(TYPED_ARRAY_CONSTRUCTOR) + function TypedArraySetFromArrayLike(target, source, sourceLength, offset) { if (offset > 0) { @@ -296,34 +316,34 @@ function TypedArraySet(obj, offset) { // ------------------------------------------------------------------- -function SetupTypedArray(constructor, fun, elementSize) { +function SetupTypedArrays() { +macro SETUP_TYPED_ARRAY(ARRAY_ID, NAME, ELEMENT_SIZE) %CheckIsBootstrapping(); - %SetCode(constructor, fun); - %FunctionSetPrototype(constructor, new $Object()); + %SetCode(global.NAME, NAMEConstructor); + %FunctionSetPrototype(global.NAME, new $Object()); - %SetProperty(constructor, "BYTES_PER_ELEMENT", elementSize, + %SetProperty(global.NAME, "BYTES_PER_ELEMENT", ELEMENT_SIZE, READ_ONLY | DONT_ENUM | DONT_DELETE); - %SetProperty(constructor.prototype, - "constructor", constructor, DONT_ENUM); - %SetProperty(constructor.prototype, - "BYTES_PER_ELEMENT", elementSize, + %SetProperty(global.NAME.prototype, + "constructor", global.NAME, DONT_ENUM); + %SetProperty(global.NAME.prototype, + "BYTES_PER_ELEMENT", ELEMENT_SIZE, READ_ONLY | DONT_ENUM | DONT_DELETE); - InstallGetter(constructor.prototype, "buffer", TypedArrayGetBuffer); - InstallGetter(constructor.prototype, "byteOffset", TypedArrayGetByteOffset); - InstallGetter(constructor.prototype, "byteLength", TypedArrayGetByteLength); - InstallGetter(constructor.prototype, "length", TypedArrayGetLength); + InstallGetter(global.NAME.prototype, "buffer", NAME_GetBuffer); + InstallGetter(global.NAME.prototype, "byteOffset", NAME_GetByteOffset); + InstallGetter(global.NAME.prototype, "byteLength", NAME_GetByteLength); + InstallGetter(global.NAME.prototype, "length", NAME_GetLength); - InstallFunctions(constructor.prototype, DONT_ENUM, $Array( - "subarray", CreateSubArray(elementSize, constructor), + InstallFunctions(global.NAME.prototype, DONT_ENUM, $Array( + "subarray", NAMESubArray, "set", TypedArraySet )); -} - -macro SETUP_TYPED_ARRAY(ARRAY_ID, NAME, ELEMENT_SIZE) - SetupTypedArray (global.NAME, NAMEConstructor, ELEMENT_SIZE); endmacro TYPED_ARRAYS(SETUP_TYPED_ARRAY) +} + +SetupTypedArrays(); // --------------------------- DataView ----------------------------- @@ -341,7 +361,7 @@ function DataViewConstructor(buffer, byteOffset, byteLength) { // length = 3 byteLength = TO_INTEGER(byteLength); } - var bufferByteLength = %ArrayBufferGetByteLength(buffer); + var bufferByteLength = %_ArrayBufferGetByteLength(buffer); var offset = IS_UNDEFINED(byteOffset) ? 0 : byteOffset; if (offset > bufferByteLength) { @@ -373,7 +393,7 @@ function DataViewGetByteOffset() { throw MakeTypeError('incompatible_method_receiver', ['DataView.byteOffset', this]); } - return %DataViewGetByteOffset(this); + return %_ArrayBufferViewGetByteOffset(this); } function DataViewGetByteLength() { @@ -381,7 +401,7 @@ function DataViewGetByteLength() { throw MakeTypeError('incompatible_method_receiver', ['DataView.byteLength', this]); } - return %DataViewGetByteLength(this); + return %_ArrayBufferViewGetByteLength(this); } macro DATA_VIEW_TYPES(FUNCTION) diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc index 276663a..9a67fae 100644 --- a/test/cctest/test-api.cc +++ b/test/cctest/test-api.cc @@ -4052,7 +4052,7 @@ TEST(ApiObjectGroupsCycleForScavenger) { v8::internal::Heap* heap = reinterpret_cast( iso)->heap(); - heap->CollectGarbage(i::NEW_SPACE); + heap->CollectAllGarbage(i::Heap::kNoGCFlags); // All objects should be alive. CHECK_EQ(0, counter.NumberOfWeakCalls()); @@ -4084,7 +4084,7 @@ TEST(ApiObjectGroupsCycleForScavenger) { v8_str("x"), Local::New(iso, g1s1.handle)); } - heap->CollectGarbage(i::NEW_SPACE); + heap->CollectAllGarbage(i::Heap::kNoGCFlags); // All objects should be gone. 7 global handles in total. CHECK_EQ(7, counter.NumberOfWeakCalls()); diff --git a/test/mjsunit/harmony/typedarrays.js b/test/mjsunit/harmony/typedarrays.js index e20fbad..f26b0be 100644 --- a/test/mjsunit/harmony/typedarrays.js +++ b/test/mjsunit/harmony/typedarrays.js @@ -310,6 +310,11 @@ function TestSubArray(constructor, item) { SubarrayTestCase(constructor, item, 10,90, 100, 90); SubarrayTestCase(constructor, item, 10,90, 100, -10); + + var method = constructor.prototype.subarray; + method.call(new constructor(100), 0, 100); + var o = {}; + assertThrows(function() { method.call(o, 0, 100); }, TypeError); } TestSubArray(Uint8Array, 0xFF); -- 2.7.4