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,
Builtins::kTypedArrayInitialize, 6, false);
InstallWithIntrinsicDefaultProto(isolate, typed_array_initialize,
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
......
......@@ -24,6 +24,10 @@ class TypedArrayBuiltinsAssembler : public CodeStubAssembler {
void GenerateTypedArrayPrototypeIterationMethod(const char* method_name);
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,
......@@ -71,15 +75,9 @@ void TypedArrayBuiltinsAssembler::LoadMapAndElementsSize(Node* array,
Bind(&done);
}
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);
void TypedArrayBuiltinsAssembler::DoInitialize(
Node* holder, Node* length, Node* maybe_buffer, Node* byte_offset,
Node* byte_length, Node* initialize, Node* context) {
static const int32_t fta_base_data_offset =
FixedTypedArrayBase::kDataOffset - kHeapObjectTag;
......@@ -244,12 +242,78 @@ TF_BUILTIN(TypedArrayInitialize, TypedArrayBuiltinsAssembler) {
}
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.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
BUILTIN(TypedArrayPrototypeBuffer) {
HandleScope scope(isolate);
......
......@@ -807,6 +807,7 @@ class Isolate;
TFJ(SymbolPrototypeValueOf, 0) \
\
/* TypedArray */ \
TFJ(TypedArrayConstructByLength, 3) \
TFJ(TypedArrayInitialize, 6) \
CPP(TypedArrayPrototypeBuffer) \
/* ES6 section 22.2.3.2 get %TypedArray%.prototype.byteLength */ \
......
......@@ -68,6 +68,8 @@ enum ContextLookupFlags {
V(REFLECT_DELETE_PROPERTY_INDEX, JSFunction, reflect_delete_property) \
V(SPREAD_ARGUMENTS_INDEX, JSFunction, spread_arguments) \
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(MATH_FLOOR_INDEX, JSFunction, math_floor) \
V(MATH_POW_INDEX, JSFunction, math_pow) \
......
......@@ -172,23 +172,6 @@ function NAMEConstructByArrayBuffer(obj, buffer, byteOffset, length) {
%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) {
var l = ToPositiveInteger(length, kInvalidTypedArrayLength);
......@@ -262,7 +245,7 @@ function NAMEConstructor(arg1, arg2, arg3) {
NAMEConstructByIterable(this, arg1, iteratorFn);
}
} else {
NAMEConstructByLength(this, arg1);
%typed_array_construct_by_length(this, arg1, ELEMENT_SIZE);
}
} else {
throw %make_type_error(kConstructorNotFunction, "NAME")
......
......@@ -95,23 +95,31 @@ RUNTIME_FUNCTION(Runtime_ThrowSymbolAsyncIteratorInvalid) {
isolate, NewTypeError(MessageTemplate::kSymbolAsyncIteratorInvalid));
}
RUNTIME_FUNCTION(Runtime_ThrowTypeError) {
HandleScope scope(isolate);
DCHECK_LE(1, args.length());
CONVERT_SMI_ARG_CHECKED(message_id_smi, 0);
Handle<Object> undefined = isolate->factory()->undefined_value();
Handle<Object> arg0 = (args.length() > 1) ? args.at(1) : undefined;
Handle<Object> arg1 = (args.length() > 2) ? args.at(2) : undefined;
Handle<Object> arg2 = (args.length() > 3) ? args.at(3) : undefined;
MessageTemplate::Template message_id =
static_cast<MessageTemplate::Template>(message_id_smi);
#define THROW_ERROR(isolate, args, call) \
HandleScope scope(isolate); \
DCHECK_LE(1, args.length()); \
CONVERT_SMI_ARG_CHECKED(message_id_smi, 0); \
\
Handle<Object> undefined = isolate->factory()->undefined_value(); \
Handle<Object> arg0 = (args.length() > 1) ? args.at(1) : undefined; \
Handle<Object> arg1 = (args.length() > 2) ? args.at(2) : undefined; \
Handle<Object> arg2 = (args.length() > 3) ? args.at(3) : undefined; \
\
MessageTemplate::Template message_id = \
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,
NewTypeError(message_id, arg0, arg1, arg2));
RUNTIME_FUNCTION(Runtime_ThrowTypeError) {
THROW_ERROR(isolate, args, NewTypeError);
}
#undef THROW_ERROR
RUNTIME_FUNCTION(Runtime_UnwindAndFindExceptionHandler) {
SealHandleScope shs(isolate);
DCHECK_EQ(0, args.length());
......
......@@ -323,6 +323,7 @@ namespace internal {
F(ThrowNonObjectInInstanceOfCheck, 0, 1) \
F(ThrowNotConstructor, 1, 1) \
F(ThrowNotGeneric, 1, 1) \
F(ThrowRangeError, -1 /* >= 1 */, 1) \
F(ThrowReferenceError, 1, 1) \
F(ThrowStackOverflow, 0, 1) \
F(ThrowSymbolAsyncIteratorInvalid, 0, 1) \
......
......@@ -259,6 +259,8 @@ function TestTypedArray(constr, elementSize, typicalElement) {
assertThrows(function() { new constr(Symbol()); }, TypeError);
assertThrows(function() { new constr(-1); }, RangeError);
var jsArray = [];
for (i = 0; i < 30; i++) {
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