Commit ead3656c authored by Peter Marshall's avatar Peter Marshall Committed by Commit Bot

[builtins] Port TypedArrayConstructByLength to CodeStubAssembler.

Part of the performance and refactoring work to move the TypedArray
constructors into CSA. This CL moves ConstructByLength from JS
to CSA.

There are still other callers to typed_array_initialize in
typedarray.js, so we share the implementation using DoInitialize.

In a later CL we can split apart DoInitialize once we have more
TA constructors written in CSA, so that we can reuse specific
parts more easily.

BUG=v8:5977

Change-Id: Ia51e8363970e9a025a82933e56a7baaf82cb1eec
Reviewed-on: https://chromium-review.googlesource.com/448220Reviewed-by: 's avatarBenedikt Meurer <bmeurer@chromium.org>
Reviewed-by: 's avatarCamillo Bruni <cbruni@chromium.org>
Commit-Queue: Peter Marshall <petermarshall@chromium.org>
Cr-Commit-Position: refs/heads/master@{#43626}
parent a9ace298
...@@ -2633,6 +2633,15 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object, ...@@ -2633,6 +2633,15 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
Builtins::kTypedArrayInitialize, 6, false); Builtins::kTypedArrayInitialize, 6, false);
InstallWithIntrinsicDefaultProto(isolate, typed_array_initialize, InstallWithIntrinsicDefaultProto(isolate, typed_array_initialize,
Context::TYPED_ARRAY_INITIALIZE_INDEX); Context::TYPED_ARRAY_INITIALIZE_INDEX);
// %typed_array_construct_by_length
Handle<JSFunction> construct_by_length = SimpleCreateFunction(
isolate,
factory->NewStringFromAsciiChecked("typedArrayConstructByLength"),
Builtins::kTypedArrayConstructByLength, 3, false);
InstallWithIntrinsicDefaultProto(
isolate, construct_by_length,
Context::TYPED_ARRAY_CONSTRUCT_BY_LENGTH_INDEX);
} }
{ // -- D a t a V i e w { // -- D a t a V i e w
......
...@@ -24,6 +24,10 @@ class TypedArrayBuiltinsAssembler : public CodeStubAssembler { ...@@ -24,6 +24,10 @@ class TypedArrayBuiltinsAssembler : public CodeStubAssembler {
void GenerateTypedArrayPrototypeIterationMethod(const char* method_name); void GenerateTypedArrayPrototypeIterationMethod(const char* method_name);
void LoadMapAndElementsSize(Node* array, Variable* typed_map, Variable* size); void LoadMapAndElementsSize(Node* array, Variable* typed_map, Variable* size);
void DoInitialize(Node* holder, Node* length, Node* maybe_buffer,
Node* byte_offset, Node* byte_length, Node* initialize,
Node* context);
}; };
void TypedArrayBuiltinsAssembler::LoadMapAndElementsSize(Node* array, void TypedArrayBuiltinsAssembler::LoadMapAndElementsSize(Node* array,
...@@ -71,15 +75,9 @@ void TypedArrayBuiltinsAssembler::LoadMapAndElementsSize(Node* array, ...@@ -71,15 +75,9 @@ void TypedArrayBuiltinsAssembler::LoadMapAndElementsSize(Node* array,
Bind(&done); Bind(&done);
} }
TF_BUILTIN(TypedArrayInitialize, TypedArrayBuiltinsAssembler) { void TypedArrayBuiltinsAssembler::DoInitialize(
Node* holder = Parameter(1); Node* holder, Node* length, Node* maybe_buffer, Node* byte_offset,
Node* length = Parameter(2); Node* byte_length, Node* initialize, Node* context) {
Node* maybe_buffer = Parameter(3);
Node* byte_offset = Parameter(4);
Node* byte_length = Parameter(5);
Node* initialize = Parameter(6);
Node* context = Parameter(9);
static const int32_t fta_base_data_offset = static const int32_t fta_base_data_offset =
FixedTypedArrayBase::kDataOffset - kHeapObjectTag; FixedTypedArrayBase::kDataOffset - kHeapObjectTag;
...@@ -244,12 +242,78 @@ TF_BUILTIN(TypedArrayInitialize, TypedArrayBuiltinsAssembler) { ...@@ -244,12 +242,78 @@ TF_BUILTIN(TypedArrayInitialize, TypedArrayBuiltinsAssembler) {
} }
Bind(&done); Bind(&done);
{ Return(UndefinedConstant()); } Return(UndefinedConstant());
}
TF_BUILTIN(TypedArrayInitialize, TypedArrayBuiltinsAssembler) {
Node* holder = Parameter(1);
Node* length = Parameter(2);
Node* maybe_buffer = Parameter(3);
Node* byte_offset = Parameter(4);
Node* byte_length = Parameter(5);
Node* initialize = Parameter(6);
Node* context = Parameter(9);
DoInitialize(holder, length, maybe_buffer, byte_offset, byte_length,
initialize, context);
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// ES6 section 22.2 TypedArray Objects // ES6 section 22.2 TypedArray Objects
// ES6 section 22.2.4.2 TypedArray ( length )
TF_BUILTIN(TypedArrayConstructByLength, TypedArrayBuiltinsAssembler) {
// We know that holder cannot be an object if this builtin was called.
Node* holder = Parameter(1);
Node* length = Parameter(2);
Node* element_size = Parameter(3);
Node* context = Parameter(6);
Variable maybe_buffer(this, MachineRepresentation::kTagged);
maybe_buffer.Bind(NullConstant());
Node* byte_offset = SmiConstant(0);
Node* initialize = BooleanConstant(true);
Label external_buffer(this), call_init(this), invalid_length(this);
length = ToInteger(context, length, CodeStubAssembler::kTruncateMinusZero);
// The maximum length of a TypedArray is MaxSmi().
// Note: this is not per spec, but rather a constraint of our current
// representation (which uses smi's).
GotoIf(TaggedIsNotSmi(length), &invalid_length);
GotoIf(SmiLessThan(length, SmiConstant(0)), &invalid_length);
// For byte_length < typed_array_max_size_in_heap, we allocate the buffer on
// the heap. Otherwise we allocate it externally and attach it.
Node* byte_length = SmiMul(length, element_size);
GotoIf(TaggedIsNotSmi(byte_length), &external_buffer);
Branch(SmiLessThanOrEqual(byte_length,
SmiConstant(FLAG_typed_array_max_size_in_heap)),
&call_init, &external_buffer);
Bind(&external_buffer);
{
Node* const buffer_constructor = LoadContextElement(
LoadNativeContext(context), Context::ARRAY_BUFFER_FUN_INDEX);
maybe_buffer.Bind(ConstructJS(CodeFactory::Construct(isolate()), context,
buffer_constructor, byte_length));
Goto(&call_init);
}
Bind(&call_init);
{
DoInitialize(holder, length, maybe_buffer.value(), byte_offset, byte_length,
initialize, context);
}
Bind(&invalid_length);
{
CallRuntime(Runtime::kThrowRangeError, context,
SmiConstant(MessageTemplate::kInvalidTypedArrayLength));
Unreachable();
}
}
// ES6 section 22.2.3.1 get %TypedArray%.prototype.buffer // ES6 section 22.2.3.1 get %TypedArray%.prototype.buffer
BUILTIN(TypedArrayPrototypeBuffer) { BUILTIN(TypedArrayPrototypeBuffer) {
HandleScope scope(isolate); HandleScope scope(isolate);
......
...@@ -807,6 +807,7 @@ class Isolate; ...@@ -807,6 +807,7 @@ class Isolate;
TFJ(SymbolPrototypeValueOf, 0) \ TFJ(SymbolPrototypeValueOf, 0) \
\ \
/* TypedArray */ \ /* TypedArray */ \
TFJ(TypedArrayConstructByLength, 3) \
TFJ(TypedArrayInitialize, 6) \ TFJ(TypedArrayInitialize, 6) \
CPP(TypedArrayPrototypeBuffer) \ CPP(TypedArrayPrototypeBuffer) \
/* ES6 section 22.2.3.2 get %TypedArray%.prototype.byteLength */ \ /* ES6 section 22.2.3.2 get %TypedArray%.prototype.byteLength */ \
......
...@@ -68,6 +68,8 @@ enum ContextLookupFlags { ...@@ -68,6 +68,8 @@ enum ContextLookupFlags {
V(REFLECT_DELETE_PROPERTY_INDEX, JSFunction, reflect_delete_property) \ V(REFLECT_DELETE_PROPERTY_INDEX, JSFunction, reflect_delete_property) \
V(SPREAD_ARGUMENTS_INDEX, JSFunction, spread_arguments) \ V(SPREAD_ARGUMENTS_INDEX, JSFunction, spread_arguments) \
V(SPREAD_ITERABLE_INDEX, JSFunction, spread_iterable) \ V(SPREAD_ITERABLE_INDEX, JSFunction, spread_iterable) \
V(TYPED_ARRAY_CONSTRUCT_BY_LENGTH_INDEX, JSFunction, \
typed_array_construct_by_length) \
V(TYPED_ARRAY_INITIALIZE_INDEX, JSFunction, typed_array_initialize) \ V(TYPED_ARRAY_INITIALIZE_INDEX, JSFunction, typed_array_initialize) \
V(MATH_FLOOR_INDEX, JSFunction, math_floor) \ V(MATH_FLOOR_INDEX, JSFunction, math_floor) \
V(MATH_POW_INDEX, JSFunction, math_pow) \ V(MATH_POW_INDEX, JSFunction, math_pow) \
......
...@@ -172,23 +172,6 @@ function NAMEConstructByArrayBuffer(obj, buffer, byteOffset, length) { ...@@ -172,23 +172,6 @@ function NAMEConstructByArrayBuffer(obj, buffer, byteOffset, length) {
%typed_array_initialize(obj, newLength, buffer, offset, newByteLength, true); %typed_array_initialize(obj, newLength, buffer, offset, newByteLength, true);
} }
function NAMEConstructByLength(obj, length) {
var l = IS_UNDEFINED(length) ?
0 : ToIndex(length, kInvalidTypedArrayLength);
if (l > %_MaxSmi()) {
// Note: this is not per spec, but rather a constraint of our current
// representation (which uses smi's).
throw %make_range_error(kInvalidTypedArrayLength);
}
var byteLength = l * ELEMENT_SIZE;
if (byteLength > %_TypedArrayMaxSizeInHeap()) {
var buffer = new GlobalArrayBuffer(byteLength);
%typed_array_initialize(obj, l, buffer, 0, byteLength, true);
} else {
%typed_array_initialize(obj, l, null, 0, byteLength, true);
}
}
function NAMEConstructByArrayLike(obj, arrayLike, length) { function NAMEConstructByArrayLike(obj, arrayLike, length) {
var l = ToPositiveInteger(length, kInvalidTypedArrayLength); var l = ToPositiveInteger(length, kInvalidTypedArrayLength);
...@@ -262,7 +245,7 @@ function NAMEConstructor(arg1, arg2, arg3) { ...@@ -262,7 +245,7 @@ function NAMEConstructor(arg1, arg2, arg3) {
NAMEConstructByIterable(this, arg1, iteratorFn); NAMEConstructByIterable(this, arg1, iteratorFn);
} }
} else { } else {
NAMEConstructByLength(this, arg1); %typed_array_construct_by_length(this, arg1, ELEMENT_SIZE);
} }
} else { } else {
throw %make_type_error(kConstructorNotFunction, "NAME") throw %make_type_error(kConstructorNotFunction, "NAME")
......
...@@ -95,23 +95,31 @@ RUNTIME_FUNCTION(Runtime_ThrowSymbolAsyncIteratorInvalid) { ...@@ -95,23 +95,31 @@ RUNTIME_FUNCTION(Runtime_ThrowSymbolAsyncIteratorInvalid) {
isolate, NewTypeError(MessageTemplate::kSymbolAsyncIteratorInvalid)); isolate, NewTypeError(MessageTemplate::kSymbolAsyncIteratorInvalid));
} }
RUNTIME_FUNCTION(Runtime_ThrowTypeError) { #define THROW_ERROR(isolate, args, call) \
HandleScope scope(isolate); HandleScope scope(isolate); \
DCHECK_LE(1, args.length()); DCHECK_LE(1, args.length()); \
CONVERT_SMI_ARG_CHECKED(message_id_smi, 0); CONVERT_SMI_ARG_CHECKED(message_id_smi, 0); \
\
Handle<Object> undefined = isolate->factory()->undefined_value(); Handle<Object> undefined = isolate->factory()->undefined_value(); \
Handle<Object> arg0 = (args.length() > 1) ? args.at(1) : undefined; Handle<Object> arg0 = (args.length() > 1) ? args.at(1) : undefined; \
Handle<Object> arg1 = (args.length() > 2) ? args.at(2) : undefined; Handle<Object> arg1 = (args.length() > 2) ? args.at(2) : undefined; \
Handle<Object> arg2 = (args.length() > 3) ? args.at(3) : undefined; Handle<Object> arg2 = (args.length() > 3) ? args.at(3) : undefined; \
\
MessageTemplate::Template message_id = MessageTemplate::Template message_id = \
static_cast<MessageTemplate::Template>(message_id_smi); static_cast<MessageTemplate::Template>(message_id_smi); \
\
THROW_NEW_ERROR_RETURN_FAILURE(isolate, call(message_id, arg0, arg1, arg2));
RUNTIME_FUNCTION(Runtime_ThrowRangeError) {
THROW_ERROR(isolate, args, NewRangeError);
}
THROW_NEW_ERROR_RETURN_FAILURE(isolate, RUNTIME_FUNCTION(Runtime_ThrowTypeError) {
NewTypeError(message_id, arg0, arg1, arg2)); THROW_ERROR(isolate, args, NewTypeError);
} }
#undef THROW_ERROR
RUNTIME_FUNCTION(Runtime_UnwindAndFindExceptionHandler) { RUNTIME_FUNCTION(Runtime_UnwindAndFindExceptionHandler) {
SealHandleScope shs(isolate); SealHandleScope shs(isolate);
DCHECK_EQ(0, args.length()); DCHECK_EQ(0, args.length());
......
...@@ -323,6 +323,7 @@ namespace internal { ...@@ -323,6 +323,7 @@ namespace internal {
F(ThrowNonObjectInInstanceOfCheck, 0, 1) \ F(ThrowNonObjectInInstanceOfCheck, 0, 1) \
F(ThrowNotConstructor, 1, 1) \ F(ThrowNotConstructor, 1, 1) \
F(ThrowNotGeneric, 1, 1) \ F(ThrowNotGeneric, 1, 1) \
F(ThrowRangeError, -1 /* >= 1 */, 1) \
F(ThrowReferenceError, 1, 1) \ F(ThrowReferenceError, 1, 1) \
F(ThrowStackOverflow, 0, 1) \ F(ThrowStackOverflow, 0, 1) \
F(ThrowSymbolAsyncIteratorInvalid, 0, 1) \ F(ThrowSymbolAsyncIteratorInvalid, 0, 1) \
......
...@@ -259,6 +259,8 @@ function TestTypedArray(constr, elementSize, typicalElement) { ...@@ -259,6 +259,8 @@ function TestTypedArray(constr, elementSize, typicalElement) {
assertThrows(function() { new constr(Symbol()); }, TypeError); assertThrows(function() { new constr(Symbol()); }, TypeError);
assertThrows(function() { new constr(-1); }, RangeError);
var jsArray = []; var jsArray = [];
for (i = 0; i < 30; i++) { for (i = 0; i < 30; i++) {
jsArray.push(typicalElement); jsArray.push(typicalElement);
......
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