Inline internal getters for typed arrays & friends.

R=hpayer@chromium.org, yangguo@chromium.org

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@20330 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
dslomov@chromium.org 2014-03-28 12:02:52 +00:00
parent a72e3525fc
commit 6d91c1e77f
8 changed files with 146 additions and 97 deletions

View File

@ -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 {

View File

@ -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());

View File

@ -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<HLoadNamedField>(
buffer,
static_cast<HValue*>(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<HLoadNamedField>(
buffer,
static_cast<HValue*>(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<HLoadNamedField>(
buffer,
static_cast<HValue*>(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<HLoadNamedField>(
buffer,
static_cast<HValue*>(NULL),
HObjectAccess::ForJSTypedArrayLength());
return ast_context()->ReturnInstruction(result, expr->id());
}
void HOptimizedGraphBuilder::VisitCallRuntime(CallRuntime* expr) {
ASSERT(!HasStackOverflow());
ASSERT(current_block() != NULL);

View File

@ -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<Object>(NULL, 0))); \
Handle<JSTypedArray> 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<Object>(NULL, 0)));
Handle<JSTypedArray> 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;

View File

@ -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) \

View File

@ -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;

View File

@ -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 TypedArrayGetBuffer() {
function NAME_GetBuffer() {
if (!(%_ClassOf(this) === 'NAME')) {
throw MakeTypeError('incompatible_method_receiver',
["NAME.buffer", this]);
}
return %TypedArrayGetBuffer(this);
}
}
function TypedArrayGetByteLength() {
return %TypedArrayGetByteLength(this);
}
function NAME_GetByteLength() {
if (!(%_ClassOf(this) === 'NAME')) {
throw MakeTypeError('incompatible_method_receiver',
["NAME.byteLength", this]);
}
return %_ArrayBufferViewGetByteLength(this);
}
function TypedArrayGetByteOffset() {
return %TypedArrayGetByteOffset(this);
}
function NAME_GetByteOffset() {
if (!(%_ClassOf(this) === 'NAME')) {
throw MakeTypeError('incompatible_method_receiver',
["NAME.byteOffset", this]);
}
return %_ArrayBufferViewGetByteOffset(this);
}
function TypedArrayGetLength() {
return %TypedArrayGetLength(this);
}
function NAME_GetLength() {
if (!(%_ClassOf(this) === 'NAME')) {
throw MakeTypeError('incompatible_method_receiver',
["NAME.length", this]);
}
return %_TypedArrayGetLength(this);
}
function CreateSubArray(elementSize, constructor) {
return function(begin, end) {
var $NAME = global.NAME;
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),
%_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)

View File

@ -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);