[typedarray] Port TypedArray#slice to Torque.
Bug: v8:8906 Change-Id: I7a07482d2d5de13de11fa2611e3c6ae18439e820 Reviewed-on: https://chromium-review.googlesource.com/c/1493136 Commit-Queue: Peter Wong <peter.wm.wong@gmail.com> Reviewed-by: Simon Zünd <szuend@chromium.org> Reviewed-by: Michael Stanton <mvstanton@chromium.org> Reviewed-by: Jakob Gruber <jgruber@chromium.org> Cr-Commit-Position: refs/heads/master@{#60007}
This commit is contained in:
parent
683cf6f43b
commit
acdaa4c713
2
BUILD.gn
2
BUILD.gn
@ -928,6 +928,7 @@ torque_files = [
|
|||||||
"src/builtins/typed-array-foreach.tq",
|
"src/builtins/typed-array-foreach.tq",
|
||||||
"src/builtins/typed-array-reduce.tq",
|
"src/builtins/typed-array-reduce.tq",
|
||||||
"src/builtins/typed-array-reduceright.tq",
|
"src/builtins/typed-array-reduceright.tq",
|
||||||
|
"src/builtins/typed-array-slice.tq",
|
||||||
"src/builtins/typed-array-subarray.tq",
|
"src/builtins/typed-array-subarray.tq",
|
||||||
"test/torque/test-torque.tq",
|
"test/torque/test-torque.tq",
|
||||||
"third_party/v8/builtins/array-sort.tq",
|
"third_party/v8/builtins/array-sort.tq",
|
||||||
@ -962,6 +963,7 @@ torque_namespaces = [
|
|||||||
"typed-array-foreach",
|
"typed-array-foreach",
|
||||||
"typed-array-reduce",
|
"typed-array-reduce",
|
||||||
"typed-array-reduceright",
|
"typed-array-reduceright",
|
||||||
|
"typed-array-slice",
|
||||||
"typed-array-subarray",
|
"typed-array-subarray",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -481,6 +481,10 @@ const kReduceNoInitial: constexpr MessageTemplate
|
|||||||
generates 'MessageTemplate::kReduceNoInitial';
|
generates 'MessageTemplate::kReduceNoInitial';
|
||||||
const kFirstArgumentNotRegExp: constexpr MessageTemplate
|
const kFirstArgumentNotRegExp: constexpr MessageTemplate
|
||||||
generates 'MessageTemplate::kFirstArgumentNotRegExp';
|
generates 'MessageTemplate::kFirstArgumentNotRegExp';
|
||||||
|
const kBigIntMixedTypes: constexpr MessageTemplate
|
||||||
|
generates 'MessageTemplate::kBigIntMixedTypes';
|
||||||
|
const kTypedArrayTooShort: constexpr MessageTemplate
|
||||||
|
generates 'MessageTemplate::kTypedArrayTooShort';
|
||||||
|
|
||||||
const kMaxArrayIndex:
|
const kMaxArrayIndex:
|
||||||
constexpr uint32 generates 'JSArray::kMaxArrayIndex';
|
constexpr uint32 generates 'JSArray::kMaxArrayIndex';
|
||||||
@ -846,6 +850,8 @@ extern operator '|' macro Word32Or(int32, int32): int32;
|
|||||||
extern operator '|' macro Word32Or(uint32, uint32): uint32;
|
extern operator '|' macro Word32Or(uint32, uint32): uint32;
|
||||||
extern operator '&' macro Word32And(bool, bool): bool;
|
extern operator '&' macro Word32And(bool, bool): bool;
|
||||||
extern operator '|' macro Word32Or(bool, bool): bool;
|
extern operator '|' macro Word32Or(bool, bool): bool;
|
||||||
|
extern operator '==' macro Word32Equal(bool, bool): bool;
|
||||||
|
extern operator '!=' macro Word32NotEqual(bool, bool): bool;
|
||||||
|
|
||||||
extern operator '+' macro Float64Add(float64, float64): float64;
|
extern operator '+' macro Float64Add(float64, float64): float64;
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include "src/objects/allocation-site-inl.h"
|
#include "src/objects/allocation-site-inl.h"
|
||||||
#include "src/objects/arguments-inl.h"
|
#include "src/objects/arguments-inl.h"
|
||||||
#include "src/objects/property-cell.h"
|
#include "src/objects/property-cell.h"
|
||||||
|
#include "torque-generated/builtins-typed-array-createtypedarray-from-dsl-gen.h"
|
||||||
|
|
||||||
namespace v8 {
|
namespace v8 {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
@ -96,9 +97,9 @@ Node* ArrayBuiltinsAssembler::FindProcessor(Node* k_value, Node* k) {
|
|||||||
TNode<Smi> length = CAST(len_);
|
TNode<Smi> length = CAST(len_);
|
||||||
const char* method_name = "%TypedArray%.prototype.map";
|
const char* method_name = "%TypedArray%.prototype.map";
|
||||||
|
|
||||||
TypedArrayBuiltinsAssembler typedarray_asm(state());
|
TypedArrayCreatetypedarrayBuiltinsFromDSLAssembler typedarray_asm(state());
|
||||||
TNode<JSTypedArray> a = typedarray_asm.TypedArraySpeciesCreateByLength(
|
TNode<JSTypedArray> a = typedarray_asm.TypedArraySpeciesCreateByLength(
|
||||||
context(), original_array, length, method_name);
|
context(), method_name, original_array, length);
|
||||||
// In the Spec and our current implementation, the length check is already
|
// In the Spec and our current implementation, the length check is already
|
||||||
// performed in TypedArraySpeciesCreate.
|
// performed in TypedArraySpeciesCreate.
|
||||||
CSA_ASSERT(this, SmiLessThanOrEqual(CAST(len_), LoadJSTypedArrayLength(a)));
|
CSA_ASSERT(this, SmiLessThanOrEqual(CAST(len_), LoadJSTypedArrayLength(a)));
|
||||||
|
@ -1140,9 +1140,6 @@ namespace internal {
|
|||||||
CPP(TypedArrayPrototypeReverse) \
|
CPP(TypedArrayPrototypeReverse) \
|
||||||
/* ES6 %TypedArray%.prototype.set */ \
|
/* ES6 %TypedArray%.prototype.set */ \
|
||||||
TFJ(TypedArrayPrototypeSet, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
|
TFJ(TypedArrayPrototypeSet, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
|
||||||
/* ES6 #sec-%typedarray%.prototype.slice */ \
|
|
||||||
TFJ(TypedArrayPrototypeSlice, \
|
|
||||||
SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
|
|
||||||
/* ES6 #sec-get-%typedarray%.prototype-@@tostringtag */ \
|
/* ES6 #sec-get-%typedarray%.prototype-@@tostringtag */ \
|
||||||
TFJ(TypedArrayPrototypeToStringTag, 0, kReceiver) \
|
TFJ(TypedArrayPrototypeToStringTag, 0, kReceiver) \
|
||||||
/* ES6 %TypedArray%.prototype.every */ \
|
/* ES6 %TypedArray%.prototype.every */ \
|
||||||
|
@ -147,9 +147,9 @@ TNode<FixedTypedArrayBase> TypedArrayBuiltinsAssembler::AllocateOnHeapElements(
|
|||||||
return CAST(elements);
|
return CAST(elements);
|
||||||
}
|
}
|
||||||
|
|
||||||
Node* TypedArrayBuiltinsAssembler::LoadDataPtr(Node* typed_array) {
|
TNode<RawPtrT> TypedArrayBuiltinsAssembler::LoadDataPtr(
|
||||||
CSA_ASSERT(this, IsJSTypedArray(typed_array));
|
TNode<JSTypedArray> typed_array) {
|
||||||
Node* elements = LoadElements(typed_array);
|
TNode<FixedArrayBase> elements = LoadElements(typed_array);
|
||||||
CSA_ASSERT(this, IsFixedTypedArray(elements));
|
CSA_ASSERT(this, IsFixedTypedArray(elements));
|
||||||
return LoadFixedTypedArrayBackingStore(CAST(elements));
|
return LoadFixedTypedArrayBackingStore(CAST(elements));
|
||||||
}
|
}
|
||||||
@ -306,22 +306,6 @@ TNode<JSFunction> TypedArrayBuiltinsAssembler::GetDefaultConstructor(
|
|||||||
LoadContextElement(LoadNativeContext(context), context_slot.value()));
|
LoadContextElement(LoadNativeContext(context), context_slot.value()));
|
||||||
}
|
}
|
||||||
|
|
||||||
TNode<JSTypedArray>
|
|
||||||
TypedArrayBuiltinsAssembler::TypedArraySpeciesCreateByLength(
|
|
||||||
TNode<Context> context, TNode<JSTypedArray> exemplar, TNode<Smi> len,
|
|
||||||
const char* method_name) {
|
|
||||||
CSA_ASSERT(this, TaggedIsPositiveSmi(len));
|
|
||||||
|
|
||||||
TypedArrayCreatetypedarrayBuiltinsFromDSLAssembler typedarray_asm(state());
|
|
||||||
const int31_t kNumArgs = 1;
|
|
||||||
TNode<JSTypedArray> new_typed_array = typedarray_asm.TypedArraySpeciesCreate(
|
|
||||||
context, method_name, kNumArgs, exemplar, len, UndefinedConstant(),
|
|
||||||
UndefinedConstant());
|
|
||||||
|
|
||||||
ThrowIfLengthLessThan(context, new_typed_array, len);
|
|
||||||
return new_typed_array;
|
|
||||||
}
|
|
||||||
|
|
||||||
TNode<JSTypedArray> TypedArrayBuiltinsAssembler::TypedArrayCreateByLength(
|
TNode<JSTypedArray> TypedArrayBuiltinsAssembler::TypedArrayCreateByLength(
|
||||||
TNode<Context> context, TNode<Object> constructor, TNode<Smi> len,
|
TNode<Context> context, TNode<Object> constructor, TNode<Smi> len,
|
||||||
const char* method_name) {
|
const char* method_name) {
|
||||||
@ -408,8 +392,8 @@ void TypedArrayBuiltinsAssembler::SetTypedArraySource(
|
|||||||
|
|
||||||
// Grab pointers and byte lengths we need later on.
|
// Grab pointers and byte lengths we need later on.
|
||||||
|
|
||||||
TNode<IntPtrT> target_data_ptr = UncheckedCast<IntPtrT>(LoadDataPtr(target));
|
TNode<RawPtrT> target_data_ptr = LoadDataPtr(target);
|
||||||
TNode<IntPtrT> source_data_ptr = UncheckedCast<IntPtrT>(LoadDataPtr(source));
|
TNode<RawPtrT> source_data_ptr = LoadDataPtr(source);
|
||||||
|
|
||||||
TNode<Word32T> source_el_kind = LoadElementsKind(source);
|
TNode<Word32T> source_el_kind = LoadElementsKind(source);
|
||||||
TNode<Word32T> target_el_kind = LoadElementsKind(target);
|
TNode<Word32T> target_el_kind = LoadElementsKind(target);
|
||||||
@ -434,9 +418,9 @@ void TypedArrayBuiltinsAssembler::SetTypedArraySource(
|
|||||||
|
|
||||||
BIND(&call_memmove);
|
BIND(&call_memmove);
|
||||||
{
|
{
|
||||||
TNode<IntPtrT> target_start =
|
TNode<RawPtrT> target_start =
|
||||||
IntPtrAdd(target_data_ptr, IntPtrMul(offset, target_el_size));
|
RawPtrAdd(target_data_ptr, IntPtrMul(offset, target_el_size));
|
||||||
CallCMemmove(target_start, source_data_ptr, source_byte_length);
|
CallCMemmove(target_start, source_data_ptr, Unsigned(source_byte_length));
|
||||||
Goto(&out);
|
Goto(&out);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -506,9 +490,9 @@ void TypedArrayBuiltinsAssembler::SetJSArraySource(
|
|||||||
BIND(&out);
|
BIND(&out);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TypedArrayBuiltinsAssembler::CallCMemmove(TNode<IntPtrT> dest_ptr,
|
void TypedArrayBuiltinsAssembler::CallCMemmove(TNode<RawPtrT> dest_ptr,
|
||||||
TNode<IntPtrT> src_ptr,
|
TNode<RawPtrT> src_ptr,
|
||||||
TNode<IntPtrT> byte_length) {
|
TNode<UintPtrT> byte_length) {
|
||||||
TNode<ExternalReference> memmove =
|
TNode<ExternalReference> memmove =
|
||||||
ExternalConstant(ExternalReference::libc_memmove_function());
|
ExternalConstant(ExternalReference::libc_memmove_function());
|
||||||
CallCFunction3(MachineType::AnyTagged(), MachineType::Pointer(),
|
CallCFunction3(MachineType::AnyTagged(), MachineType::Pointer(),
|
||||||
@ -698,118 +682,6 @@ TF_BUILTIN(TypedArrayPrototypeSet, TypedArrayBuiltinsAssembler) {
|
|||||||
ThrowTypeError(context, MessageTemplate::kNotTypedArray);
|
ThrowTypeError(context, MessageTemplate::kNotTypedArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ES %TypedArray%.prototype.slice
|
|
||||||
TF_BUILTIN(TypedArrayPrototypeSlice, TypedArrayBuiltinsAssembler) {
|
|
||||||
const char* method_name = "%TypedArray%.prototype.slice";
|
|
||||||
Label call_c(this), call_memmove(this), if_count_is_not_zero(this),
|
|
||||||
if_bigint_mixed_types(this, Label::kDeferred);
|
|
||||||
|
|
||||||
TNode<Context> context = CAST(Parameter(Descriptor::kContext));
|
|
||||||
CodeStubArguments args(
|
|
||||||
this,
|
|
||||||
ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount)));
|
|
||||||
|
|
||||||
TNode<Object> receiver = args.GetReceiver();
|
|
||||||
TNode<JSTypedArray> source =
|
|
||||||
ValidateTypedArray(context, receiver, method_name);
|
|
||||||
|
|
||||||
TNode<Smi> source_length = LoadJSTypedArrayLength(source);
|
|
||||||
|
|
||||||
// Convert start offset argument to integer, and calculate relative offset.
|
|
||||||
TNode<Object> start = args.GetOptionalArgumentValue(0, SmiConstant(0));
|
|
||||||
TNode<Smi> start_index =
|
|
||||||
SmiTag(ConvertToRelativeIndex(context, start, SmiUntag(source_length)));
|
|
||||||
|
|
||||||
// Convert end offset argument to integer, and calculate relative offset.
|
|
||||||
// If end offset is not given or undefined is given, set source_length to
|
|
||||||
// "end_index".
|
|
||||||
TNode<Object> end = args.GetOptionalArgumentValue(1, UndefinedConstant());
|
|
||||||
TNode<Smi> end_index =
|
|
||||||
Select<Smi>(IsUndefined(end), [=] { return source_length; },
|
|
||||||
[=] {
|
|
||||||
return SmiTag(ConvertToRelativeIndex(
|
|
||||||
context, end, SmiUntag(source_length)));
|
|
||||||
});
|
|
||||||
|
|
||||||
// Create a result array by invoking TypedArraySpeciesCreate.
|
|
||||||
TNode<Smi> count = SmiMax(SmiSub(end_index, start_index), SmiConstant(0));
|
|
||||||
TNode<JSTypedArray> result_array =
|
|
||||||
TypedArraySpeciesCreateByLength(context, source, count, method_name);
|
|
||||||
|
|
||||||
// If count is zero, return early.
|
|
||||||
GotoIf(SmiGreaterThan(count, SmiConstant(0)), &if_count_is_not_zero);
|
|
||||||
args.PopAndReturn(result_array);
|
|
||||||
|
|
||||||
BIND(&if_count_is_not_zero);
|
|
||||||
// Check the source array is detached or not. We don't need to check if the
|
|
||||||
// result array is detached or not since TypedArraySpeciesCreate checked it.
|
|
||||||
CSA_ASSERT(this, Word32BinaryNot(IsDetachedBuffer(LoadObjectField(
|
|
||||||
result_array, JSTypedArray::kBufferOffset))));
|
|
||||||
TNode<JSArrayBuffer> receiver_buffer =
|
|
||||||
LoadJSArrayBufferViewBuffer(CAST(receiver));
|
|
||||||
ThrowIfArrayBufferIsDetached(context, receiver_buffer, method_name);
|
|
||||||
|
|
||||||
// result_array could be a different type from source or share the same
|
|
||||||
// buffer with the source because of custom species constructor.
|
|
||||||
// If the types of source and result array are the same and they are not
|
|
||||||
// sharing the same buffer, use memmove.
|
|
||||||
TNode<Word32T> source_el_kind = LoadElementsKind(source);
|
|
||||||
TNode<Word32T> target_el_kind = LoadElementsKind(result_array);
|
|
||||||
GotoIfNot(Word32Equal(source_el_kind, target_el_kind), &call_c);
|
|
||||||
|
|
||||||
TNode<Object> target_buffer =
|
|
||||||
LoadObjectField(result_array, JSTypedArray::kBufferOffset);
|
|
||||||
Branch(WordEqual(receiver_buffer, target_buffer), &call_c, &call_memmove);
|
|
||||||
|
|
||||||
BIND(&call_memmove);
|
|
||||||
{
|
|
||||||
GotoIfForceSlowPath(&call_c);
|
|
||||||
|
|
||||||
TNode<IntPtrT> target_data_ptr =
|
|
||||||
UncheckedCast<IntPtrT>(LoadDataPtr(result_array));
|
|
||||||
TNode<IntPtrT> source_data_ptr =
|
|
||||||
UncheckedCast<IntPtrT>(LoadDataPtr(source));
|
|
||||||
|
|
||||||
TNode<IntPtrT> source_el_size = GetTypedArrayElementSize(source_el_kind);
|
|
||||||
TNode<IntPtrT> source_start_bytes =
|
|
||||||
IntPtrMul(SmiToIntPtr(start_index), source_el_size);
|
|
||||||
TNode<IntPtrT> source_start =
|
|
||||||
IntPtrAdd(source_data_ptr, source_start_bytes);
|
|
||||||
|
|
||||||
TNode<IntPtrT> count_bytes = IntPtrMul(SmiToIntPtr(count), source_el_size);
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
TNode<UintPtrT> target_byte_length =
|
|
||||||
LoadJSArrayBufferViewByteLength(result_array);
|
|
||||||
CSA_ASSERT(this, UintPtrLessThanOrEqual(Unsigned(count_bytes),
|
|
||||||
target_byte_length));
|
|
||||||
TNode<UintPtrT> source_byte_length =
|
|
||||||
LoadJSArrayBufferViewByteLength(source);
|
|
||||||
TNode<UintPtrT> source_size_in_bytes =
|
|
||||||
UintPtrSub(source_byte_length, Unsigned(source_start_bytes));
|
|
||||||
CSA_ASSERT(this, UintPtrLessThanOrEqual(Unsigned(count_bytes),
|
|
||||||
source_size_in_bytes));
|
|
||||||
#endif // DEBUG
|
|
||||||
|
|
||||||
CallCMemmove(target_data_ptr, source_start, count_bytes);
|
|
||||||
args.PopAndReturn(result_array);
|
|
||||||
}
|
|
||||||
|
|
||||||
BIND(&call_c);
|
|
||||||
{
|
|
||||||
GotoIf(Word32NotEqual(IsBigInt64ElementsKind(source_el_kind),
|
|
||||||
IsBigInt64ElementsKind(target_el_kind)),
|
|
||||||
&if_bigint_mixed_types);
|
|
||||||
|
|
||||||
CallCCopyTypedArrayElementsSlice(
|
|
||||||
source, result_array, SmiToIntPtr(start_index), SmiToIntPtr(end_index));
|
|
||||||
args.PopAndReturn(result_array);
|
|
||||||
}
|
|
||||||
|
|
||||||
BIND(&if_bigint_mixed_types);
|
|
||||||
ThrowTypeError(context, MessageTemplate::kBigIntMixedTypes);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ES #sec-get-%typedarray%.prototype-@@tostringtag
|
// ES #sec-get-%typedarray%.prototype-@@tostringtag
|
||||||
TF_BUILTIN(TypedArrayPrototypeToStringTag, TypedArrayBuiltinsAssembler) {
|
TF_BUILTIN(TypedArrayPrototypeToStringTag, TypedArrayBuiltinsAssembler) {
|
||||||
Node* receiver = Parameter(Descriptor::kReceiver);
|
Node* receiver = Parameter(Descriptor::kReceiver);
|
||||||
@ -1289,8 +1161,10 @@ TF_BUILTIN(TypedArrayPrototypeFilter, TypedArrayBuiltinsAssembler) {
|
|||||||
TNode<Smi> captured = LoadFastJSArrayLength(values_array);
|
TNode<Smi> captured = LoadFastJSArrayLength(values_array);
|
||||||
|
|
||||||
// 10. Let A be ? TypedArraySpeciesCreate(O, captured).
|
// 10. Let A be ? TypedArraySpeciesCreate(O, captured).
|
||||||
|
TypedArrayCreatetypedarrayBuiltinsFromDSLAssembler typedarray_asm(state());
|
||||||
TNode<JSTypedArray> result_array =
|
TNode<JSTypedArray> result_array =
|
||||||
TypedArraySpeciesCreateByLength(context, source, captured, method_name);
|
typedarray_asm.TypedArraySpeciesCreateByLength(context, method_name,
|
||||||
|
source, captured);
|
||||||
|
|
||||||
// 11. Let n be 0.
|
// 11. Let n be 0.
|
||||||
// 12. For each element e of kept, do
|
// 12. For each element e of kept, do
|
||||||
|
@ -24,10 +24,6 @@ class TypedArrayBuiltinsAssembler : public CodeStubAssembler {
|
|||||||
TNode<JSTypedArray> exemplar,
|
TNode<JSTypedArray> exemplar,
|
||||||
TArgs... args);
|
TArgs... args);
|
||||||
|
|
||||||
TNode<JSTypedArray> TypedArraySpeciesCreateByLength(
|
|
||||||
TNode<Context> context, TNode<JSTypedArray> exemplar, TNode<Smi> len,
|
|
||||||
const char* method_name);
|
|
||||||
|
|
||||||
void GenerateTypedArrayPrototypeIterationMethod(TNode<Context> context,
|
void GenerateTypedArrayPrototypeIterationMethod(TNode<Context> context,
|
||||||
TNode<Object> receiver,
|
TNode<Object> receiver,
|
||||||
const char* method_name,
|
const char* method_name,
|
||||||
@ -52,7 +48,7 @@ class TypedArrayBuiltinsAssembler : public CodeStubAssembler {
|
|||||||
TNode<BoolT> IsMockArrayBufferAllocatorFlag();
|
TNode<BoolT> IsMockArrayBufferAllocatorFlag();
|
||||||
TNode<UintPtrT> CalculateExternalPointer(TNode<UintPtrT> backing_store,
|
TNode<UintPtrT> CalculateExternalPointer(TNode<UintPtrT> backing_store,
|
||||||
TNode<UintPtrT> byte_offset);
|
TNode<UintPtrT> byte_offset);
|
||||||
Node* LoadDataPtr(Node* typed_array);
|
TNode<RawPtrT> LoadDataPtr(TNode<JSTypedArray> typed_array);
|
||||||
|
|
||||||
// Returns true if kind is either UINT8_ELEMENTS or UINT8_CLAMPED_ELEMENTS.
|
// Returns true if kind is either UINT8_ELEMENTS or UINT8_CLAMPED_ELEMENTS.
|
||||||
TNode<Word32T> IsUint8ElementsKind(TNode<Word32T> kind);
|
TNode<Word32T> IsUint8ElementsKind(TNode<Word32T> kind);
|
||||||
@ -95,8 +91,8 @@ class TypedArrayBuiltinsAssembler : public CodeStubAssembler {
|
|||||||
TNode<JSTypedArray> target, TNode<IntPtrT> offset,
|
TNode<JSTypedArray> target, TNode<IntPtrT> offset,
|
||||||
Label* call_runtime, Label* if_source_too_large);
|
Label* call_runtime, Label* if_source_too_large);
|
||||||
|
|
||||||
void CallCMemmove(TNode<IntPtrT> dest_ptr, TNode<IntPtrT> src_ptr,
|
void CallCMemmove(TNode<RawPtrT> dest_ptr, TNode<RawPtrT> src_ptr,
|
||||||
TNode<IntPtrT> byte_length);
|
TNode<UintPtrT> byte_length);
|
||||||
|
|
||||||
void CallCMemcpy(TNode<RawPtrT> dest_ptr, TNode<RawPtrT> src_ptr,
|
void CallCMemcpy(TNode<RawPtrT> dest_ptr, TNode<RawPtrT> src_ptr,
|
||||||
TNode<UintPtrT> byte_length);
|
TNode<UintPtrT> byte_length);
|
||||||
|
@ -370,4 +370,19 @@ namespace typed_array_createtypedarray {
|
|||||||
return typed_array::ValidateTypedArray(context, newObj, methodName);
|
return typed_array::ValidateTypedArray(context, newObj, methodName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
transitioning macro TypedArraySpeciesCreateByLength(implicit context:
|
||||||
|
Context)(
|
||||||
|
methodName: constexpr string, exemplar: JSTypedArray,
|
||||||
|
length: Smi): JSTypedArray {
|
||||||
|
assert(Is<PositiveSmi>(length));
|
||||||
|
const numArgs: constexpr int31 = 1;
|
||||||
|
const typedArray: JSTypedArray = TypedArraySpeciesCreate(
|
||||||
|
methodName, numArgs, exemplar, length, Undefined, Undefined);
|
||||||
|
if (typedArray.length < length) deferred {
|
||||||
|
ThrowTypeError(kTypedArrayTooShort);
|
||||||
|
}
|
||||||
|
|
||||||
|
return typedArray;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
107
src/builtins/typed-array-slice.tq
Normal file
107
src/builtins/typed-array-slice.tq
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
// Copyright 2019 the V8 project authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#include 'src/builtins/builtins-typed-array-gen.h'
|
||||||
|
|
||||||
|
namespace typed_array_slice {
|
||||||
|
const kBuiltinName: constexpr string = '%TypedArray%.prototype.slice';
|
||||||
|
|
||||||
|
extern macro TypedArrayBuiltinsAssembler::CallCCopyTypedArrayElementsSlice(
|
||||||
|
JSTypedArray, JSTypedArray, intptr, intptr): void;
|
||||||
|
|
||||||
|
macro FastCopy(
|
||||||
|
src: typed_array::AttachedJSTypedArray, dest: JSTypedArray, k: intptr,
|
||||||
|
count: PositiveSmi) labels IfSlow {
|
||||||
|
GotoIfForceSlowPath() otherwise IfSlow;
|
||||||
|
|
||||||
|
const srcKind: ElementsKind = src.elements_kind;
|
||||||
|
const destInfo = typed_array::GetTypedArrayElementsInfo(dest);
|
||||||
|
|
||||||
|
// dest could be a different type from src or share the same buffer
|
||||||
|
// with the src because of custom species constructor. If the types
|
||||||
|
// of src and result array are the same and they are not sharing the
|
||||||
|
// same buffer, use memmove.
|
||||||
|
if (srcKind != destInfo.kind) goto IfSlow;
|
||||||
|
if (BitcastTaggedToWord(dest.buffer) == BitcastTaggedToWord(src.buffer)) {
|
||||||
|
goto IfSlow;
|
||||||
|
}
|
||||||
|
|
||||||
|
const countBytes: uintptr =
|
||||||
|
destInfo.CalculateByteLength(count) otherwise unreachable;
|
||||||
|
const startOffset: uintptr =
|
||||||
|
destInfo.CalculateByteLength(Convert<PositiveSmi>(k))
|
||||||
|
otherwise unreachable;
|
||||||
|
const srcPtr: RawPtr = src.data_ptr + Convert<intptr>(startOffset);
|
||||||
|
|
||||||
|
assert(countBytes <= dest.byte_length);
|
||||||
|
assert(countBytes <= src.byte_length - startOffset);
|
||||||
|
|
||||||
|
typed_array::CallCMemmove(dest.data_ptr, srcPtr, countBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
macro SlowCopy(implicit context: Context)(
|
||||||
|
src: JSTypedArray, dest: JSTypedArray, k: intptr, final: intptr) {
|
||||||
|
if (typed_array::IsBigInt64ElementsKind(src.elements_kind) !=
|
||||||
|
typed_array::IsBigInt64ElementsKind(dest.elements_kind))
|
||||||
|
deferred {
|
||||||
|
ThrowTypeError(kBigIntMixedTypes);
|
||||||
|
}
|
||||||
|
|
||||||
|
CallCCopyTypedArrayElementsSlice(src, dest, k, final);
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://tc39.github.io/ecma262/#sec-%typedarray%.prototype.slice
|
||||||
|
transitioning javascript builtin TypedArrayPrototypeSlice(
|
||||||
|
context: Context, receiver: Object, ...arguments): Object {
|
||||||
|
// arguments[0] = start
|
||||||
|
// arguments[1] = end
|
||||||
|
|
||||||
|
// 1. Let O be the this value.
|
||||||
|
// 2. Perform ? ValidateTypedArray(O).
|
||||||
|
const src: JSTypedArray =
|
||||||
|
typed_array::ValidateTypedArray(context, receiver, kBuiltinName);
|
||||||
|
|
||||||
|
// 3. Let len be O.[[ArrayLength]].
|
||||||
|
const len = Convert<intptr>(src.length);
|
||||||
|
|
||||||
|
// 4. Let relativeStart be ? ToInteger(start).
|
||||||
|
// 5. If relativeStart < 0, let k be max((len + relativeStart), 0);
|
||||||
|
// else let k be min(relativeStart, len).
|
||||||
|
const start = arguments[0];
|
||||||
|
const k: intptr =
|
||||||
|
start != Undefined ? ConvertToRelativeIndex(start, len) : 0;
|
||||||
|
|
||||||
|
// 6. If end is undefined, let relativeEnd be len;
|
||||||
|
// else let relativeEnd be ? ToInteger(end).
|
||||||
|
// 7. If relativeEnd < 0, let final be max((len + relativeEnd), 0);
|
||||||
|
// else let final be min(relativeEnd, len).
|
||||||
|
const end = arguments[1];
|
||||||
|
const final: intptr =
|
||||||
|
end != Undefined ? ConvertToRelativeIndex(end, len) : len;
|
||||||
|
|
||||||
|
// 8. Let count be max(final - k, 0).
|
||||||
|
const count = Convert<PositiveSmi>(IntPtrMax(final - k, 0));
|
||||||
|
|
||||||
|
// 9. Let A be ? TypedArraySpeciesCreate(O, « count »).
|
||||||
|
const dest: JSTypedArray =
|
||||||
|
typed_array_createtypedarray::TypedArraySpeciesCreateByLength(
|
||||||
|
kBuiltinName, src, count);
|
||||||
|
|
||||||
|
if (count > 0) {
|
||||||
|
try {
|
||||||
|
const srcAttached = typed_array::EnsureAttached(src)
|
||||||
|
otherwise IfDetached;
|
||||||
|
FastCopy(srcAttached, dest, k, count) otherwise IfSlow;
|
||||||
|
}
|
||||||
|
label IfDetached deferred {
|
||||||
|
ThrowTypeError(kDetachedOperation, kBuiltinName);
|
||||||
|
}
|
||||||
|
label IfSlow deferred {
|
||||||
|
SlowCopy(src, dest, k, final);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
}
|
@ -43,12 +43,16 @@ namespace typed_array {
|
|||||||
|
|
||||||
extern macro TypedArrayBuiltinsAssembler::CallCMemcpy(
|
extern macro TypedArrayBuiltinsAssembler::CallCMemcpy(
|
||||||
RawPtr, RawPtr, uintptr): void;
|
RawPtr, RawPtr, uintptr): void;
|
||||||
|
extern macro TypedArrayBuiltinsAssembler::CallCMemmove(
|
||||||
|
RawPtr, RawPtr, uintptr): void;
|
||||||
extern macro TypedArrayBuiltinsAssembler::CallCMemset(
|
extern macro TypedArrayBuiltinsAssembler::CallCMemset(
|
||||||
RawPtr, intptr, uintptr): void;
|
RawPtr, intptr, uintptr): void;
|
||||||
extern macro TypedArrayBuiltinsAssembler::GetBuffer(
|
extern macro TypedArrayBuiltinsAssembler::GetBuffer(
|
||||||
implicit context: Context)(JSTypedArray): JSArrayBuffer;
|
implicit context: Context)(JSTypedArray): JSArrayBuffer;
|
||||||
extern macro TypedArrayBuiltinsAssembler::GetTypedArrayElementsInfo(
|
extern macro TypedArrayBuiltinsAssembler::GetTypedArrayElementsInfo(
|
||||||
JSTypedArray): TypedArrayElementsInfo;
|
JSTypedArray): TypedArrayElementsInfo;
|
||||||
|
extern macro TypedArrayBuiltinsAssembler::IsBigInt64ElementsKind(
|
||||||
|
ElementsKind): bool;
|
||||||
extern macro LoadFixedTypedArrayElementAsTagged(
|
extern macro LoadFixedTypedArrayElementAsTagged(
|
||||||
RawPtr, Smi, constexpr ElementsKind, constexpr ParameterMode): Object;
|
RawPtr, Smi, constexpr ElementsKind, constexpr ParameterMode): Object;
|
||||||
extern macro StoreFixedTypedArrayElementFromTagged(
|
extern macro StoreFixedTypedArrayElementFromTagged(
|
||||||
|
Loading…
Reference in New Issue
Block a user