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

[builtins] Add a fastpath in TypedArrayConstructByArrayBuffer.

Add a fastpath for when byteOffset is undefined, which is the common
case. We can just replace it with 0 and avoid the modulo checks. Also
add a smi-fastpath for byteOffset, which avoids calling stubs for
arithmetic when unnecessary.

BUG=chromium:701668,v8:5977

Change-Id: Id431dad46bf3796ef32ab465f6787bbebe83437c
Reviewed-on: https://chromium-review.googlesource.com/456502
Commit-Queue: Peter Marshall <petermarshall@chromium.org>
Reviewed-by: 's avatarFranziska Hinkelmann <franzih@chromium.org>
Cr-Commit-Position: refs/heads/master@{#43933}
parent 40416dfa
...@@ -349,7 +349,7 @@ TF_BUILTIN(TypedArrayConstructByLength, TypedArrayBuiltinsAssembler) { ...@@ -349,7 +349,7 @@ TF_BUILTIN(TypedArrayConstructByLength, TypedArrayBuiltinsAssembler) {
TF_BUILTIN(TypedArrayConstructByArrayBuffer, TypedArrayBuiltinsAssembler) { TF_BUILTIN(TypedArrayConstructByArrayBuffer, TypedArrayBuiltinsAssembler) {
Node* const holder = Parameter(1); Node* const holder = Parameter(1);
Node* const buffer = Parameter(2); Node* const buffer = Parameter(2);
Node* byte_offset = Parameter(3); Node* const byte_offset = Parameter(3);
Node* const length = Parameter(4); Node* const length = Parameter(4);
Node* const element_size = Parameter(5); Node* const element_size = Parameter(5);
CSA_ASSERT(this, TaggedIsSmi(element_size)); CSA_ASSERT(this, TaggedIsSmi(element_size));
...@@ -358,11 +358,14 @@ TF_BUILTIN(TypedArrayConstructByArrayBuffer, TypedArrayBuiltinsAssembler) { ...@@ -358,11 +358,14 @@ TF_BUILTIN(TypedArrayConstructByArrayBuffer, TypedArrayBuiltinsAssembler) {
Variable new_byte_length(this, MachineRepresentation::kTagged, Variable new_byte_length(this, MachineRepresentation::kTagged,
SmiConstant(0)); SmiConstant(0));
Variable offset(this, MachineRepresentation::kTagged, SmiConstant(0));
Label start_offset_error(this), byte_length_error(this), Label start_offset_error(this, Label::kDeferred),
invalid_offset_error(this); byte_length_error(this, Label::kDeferred),
Label call_init(this), invalid_length(this), length_undefined(this), invalid_offset_error(this, Label::kDeferred);
length_defined(this); Label offset_is_smi(this), offset_not_smi(this, Label::kDeferred),
check_length(this), call_init(this), invalid_length(this),
length_undefined(this), length_defined(this);
Callable add = CodeFactory::Add(isolate()); Callable add = CodeFactory::Add(isolate());
Callable div = CodeFactory::Divide(isolate()); Callable div = CodeFactory::Divide(isolate());
...@@ -372,16 +375,32 @@ TF_BUILTIN(TypedArrayConstructByArrayBuffer, TypedArrayBuiltinsAssembler) { ...@@ -372,16 +375,32 @@ TF_BUILTIN(TypedArrayConstructByArrayBuffer, TypedArrayBuiltinsAssembler) {
Callable mod = CodeFactory::Modulus(isolate()); Callable mod = CodeFactory::Modulus(isolate());
Callable sub = CodeFactory::Subtract(isolate()); Callable sub = CodeFactory::Subtract(isolate());
byte_offset = GotoIf(IsUndefined(byte_offset), &check_length);
ToInteger(context, byte_offset, CodeStubAssembler::kTruncateMinusZero);
GotoIf(IsTrue(CallStub(less_than, context, byte_offset, SmiConstant(0))),
&invalid_length);
Node* remainder = CallStub(mod, context, byte_offset, element_size); offset.Bind(
// Remainder can be a heap number. ToInteger(context, byte_offset, CodeStubAssembler::kTruncateMinusZero));
GotoIf(IsFalse(CallStub(equal, context, remainder, SmiConstant(0))), Branch(TaggedIsSmi(offset.value()), &offset_is_smi, &offset_not_smi);
// Check that the offset is a multiple of the element size.
Bind(&offset_is_smi);
{
GotoIf(SmiEqual(offset.value(), SmiConstant(0)), &check_length);
GotoIf(SmiLessThan(offset.value(), SmiConstant(0)), &invalid_length);
Node* remainder = SmiMod(offset.value(), element_size);
Branch(SmiEqual(remainder, SmiConstant(0)), &check_length,
&start_offset_error); &start_offset_error);
}
Bind(&offset_not_smi);
{
GotoIf(IsTrue(CallStub(less_than, context, offset.value(), SmiConstant(0))),
&invalid_length);
Node* remainder = CallStub(mod, context, offset.value(), element_size);
// Remainder can be a heap number.
Branch(IsTrue(CallStub(equal, context, remainder, SmiConstant(0))),
&check_length, &start_offset_error);
}
Bind(&check_length);
// TODO(petermarshall): Throw on detached typedArray. // TODO(petermarshall): Throw on detached typedArray.
Branch(IsUndefined(length), &length_undefined, &length_defined); Branch(IsUndefined(length), &length_undefined, &length_defined);
...@@ -396,7 +415,7 @@ TF_BUILTIN(TypedArrayConstructByArrayBuffer, TypedArrayBuiltinsAssembler) { ...@@ -396,7 +415,7 @@ TF_BUILTIN(TypedArrayConstructByArrayBuffer, TypedArrayBuiltinsAssembler) {
&byte_length_error); &byte_length_error);
new_byte_length.Bind( new_byte_length.Bind(
CallStub(sub, context, buffer_byte_length, byte_offset)); CallStub(sub, context, buffer_byte_length, offset.value()));
Branch(IsTrue(CallStub(less_than, context, new_byte_length.value(), Branch(IsTrue(CallStub(less_than, context, new_byte_length.value(),
SmiConstant(0))), SmiConstant(0))),
...@@ -412,7 +431,7 @@ TF_BUILTIN(TypedArrayConstructByArrayBuffer, TypedArrayBuiltinsAssembler) { ...@@ -412,7 +431,7 @@ TF_BUILTIN(TypedArrayConstructByArrayBuffer, TypedArrayBuiltinsAssembler) {
Node* buffer_byte_length = Node* buffer_byte_length =
LoadObjectField(buffer, JSArrayBuffer::kByteLengthOffset); LoadObjectField(buffer, JSArrayBuffer::kByteLengthOffset);
Node* end = CallStub(add, context, byte_offset, new_byte_length.value()); Node* end = CallStub(add, context, offset.value(), new_byte_length.value());
Branch(IsTrue(CallStub(greater_than, context, end, buffer_byte_length)), Branch(IsTrue(CallStub(greater_than, context, end, buffer_byte_length)),
&invalid_length, &call_init); &invalid_length, &call_init);
...@@ -425,7 +444,7 @@ TF_BUILTIN(TypedArrayConstructByArrayBuffer, TypedArrayBuiltinsAssembler) { ...@@ -425,7 +444,7 @@ TF_BUILTIN(TypedArrayConstructByArrayBuffer, TypedArrayBuiltinsAssembler) {
// Force the result into a Smi, or throw a range error if it doesn't fit. // Force the result into a Smi, or throw a range error if it doesn't fit.
new_length = ToSmiIndex(new_length, context, &invalid_length); new_length = ToSmiIndex(new_length, context, &invalid_length);
DoInitialize(holder, new_length, buffer, byte_offset, DoInitialize(holder, new_length, buffer, offset.value(),
new_byte_length.value(), initialize, context); new_byte_length.value(), initialize, context);
} }
......
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