Index: src/builtins/builtins-array-gen.cc |
diff --git a/src/builtins/builtins-array-gen.cc b/src/builtins/builtins-array-gen.cc |
index 36f9b142b15329fb88eb5105501a32609f259867..28cf251eb3710228d90598bc7466d809c8f6a5f7 100644 |
--- a/src/builtins/builtins-array-gen.cc |
+++ b/src/builtins/builtins-array-gen.cc |
@@ -164,6 +164,20 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler { |
void MapResultGenerator() { ArraySpeciesCreate(len_); } |
+ void TypedArrayMapResultGenerator() { |
+ // 6. Let A be ? TypedArraySpeciesCreate(O, len). |
+ Node* a = TypedArraySpeciesCreateByLength(context(), o(), len_); |
+ // In the Spec and our current implementation, the length check is already |
+ // performed in TypedArraySpeciesCreate. Repeating the check here to |
+ // keep this invariant local. |
+ // TODO(tebbi): Change this to a release mode check. |
+ CSA_ASSERT( |
+ this, WordEqual(len_, LoadObjectField(a, JSTypedArray::kLengthOffset))); |
+ fast_typed_array_target_ = Word32Equal(LoadInstanceType(LoadElements(o_)), |
+ LoadInstanceType(LoadElements(a))); |
+ a_.Bind(a); |
+ } |
+ |
Node* SpecCompliantMapProcessor(Node* k_value, Node* k) { |
// i. Let kValue be ? Get(O, Pk). Performed by the caller of |
// SpecCompliantMapProcessor. |
@@ -238,6 +252,48 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler { |
return a(); |
} |
+ // See tc39.github.io/ecma262/#sec-%typedarray%.prototype.map. |
+ Node* TypedArrayMapProcessor(Node* k_value, Node* k) { |
+ // 8. c. Let mappedValue be ? Call(callbackfn, T, « kValue, k, O »). |
+ Node* mappedValue = CallJS(CodeFactory::Call(isolate()), context(), |
+ callbackfn(), this_arg(), k_value, k, o()); |
+ Label fast(this), slow(this), done(this), detached(this, Label::kDeferred); |
+ |
+ // 8. d. Perform ? Set(A, Pk, mappedValue, true). |
+ // Since we know that A is a TypedArray, this always ends up in |
+ // #sec-integer-indexed-exotic-objects-set-p-v-receiver and then |
+ // tc39.github.io/ecma262/#sec-integerindexedelementset . |
+ Branch(fast_typed_array_target_, &fast, &slow); |
+ |
+ BIND(&fast); |
+ // #sec-integerindexedelementset 3. Let numValue be ? ToNumber(value). |
+ Node* num_value = ToNumber(context(), mappedValue); |
+ // The only way how this can bailout is because of a detached buffer. |
+ EmitElementStore( |
+ a(), k, num_value, false, source_elements_kind_, |
+ KeyedAccessStoreMode::STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS, |
+ &detached); |
+ Goto(&done); |
+ |
+ BIND(&slow); |
+ CallRuntime(Runtime::kSetProperty, context(), a(), k, mappedValue, |
+ SmiConstant(STRICT)); |
+ Goto(&done); |
+ |
+ BIND(&detached); |
+ { |
+ // tc39.github.io/ecma262/#sec-integerindexedelementset |
+ // 5. If IsDetachedBuffer(buffer) is true, throw a TypeError exception. |
+ CallRuntime(Runtime::kThrowTypeError, context_, |
+ SmiConstant(MessageTemplate::kDetachedOperation), |
+ name_string_); |
+ Unreachable(); |
+ } |
+ |
+ BIND(&done); |
+ return a(); |
+ } |
+ |
void NullPostLoopAction() {} |
protected: |
@@ -376,7 +432,7 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler { |
const char* name, const BuiltinResultGenerator& generator, |
const CallResultProcessor& processor, const PostLoopAction& action, |
ForEachDirection direction = ForEachDirection::kForward) { |
- Node* name_string = |
+ name_string_ = |
HeapConstant(isolate()->factory()->NewStringFromAsciiChecked(name)); |
// ValidateTypedArray: tc39.github.io/ecma262/#sec-validatetypedarray |
@@ -411,7 +467,7 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler { |
{ |
CallRuntime(Runtime::kThrowTypeError, context_, |
SmiConstant(MessageTemplate::kDetachedOperation), |
- name_string); |
+ name_string_); |
Unreachable(); |
} |
@@ -448,20 +504,20 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler { |
} else { |
k_.Bind(NumberDec(len())); |
} |
- generator(this); |
- Node* elements_type = LoadInstanceType(LoadElements(o_)); |
- Switch(elements_type, &unexpected_instance_type, instance_types.data(), |
+ Node* instance_type = LoadInstanceType(LoadElements(o_)); |
+ Switch(instance_type, &unexpected_instance_type, instance_types.data(), |
label_ptrs.data(), labels.size()); |
for (size_t i = 0; i < labels.size(); ++i) { |
BIND(&labels[i]); |
Label done(this); |
+ source_elements_kind_ = ElementsKindForInstanceType( |
+ static_cast<InstanceType>(instance_types[i])); |
+ generator(this); |
// TODO(tebbi): Silently cancelling the loop on buffer detachment is a |
- // spec violation. Should go to &detached and throw a TypeError instead. |
- VisitAllTypedArrayElements( |
- ElementsKindForInstanceType( |
- static_cast<InstanceType>(instance_types[i])), |
- array_buffer, processor, &done, direction); |
+ // spec violation. Should go to &throw_detached and throw a TypeError |
+ // instead. |
+ VisitAllTypedArrayElements(array_buffer, processor, &done, direction); |
Goto(&done); |
// No exception, return success |
BIND(&done); |
@@ -540,7 +596,7 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler { |
} |
} |
- void VisitAllTypedArrayElements(ElementsKind kind, Node* array_buffer, |
+ void VisitAllTypedArrayElements(Node* array_buffer, |
const CallResultProcessor& processor, |
Label* detached, ForEachDirection direction) { |
VariableList list({&a_, &k_, &to_}, zone()); |
@@ -554,8 +610,8 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler { |
LoadObjectField(elements, FixedTypedArrayBase::kExternalPointerOffset, |
MachineType::Pointer()); |
Node* data_ptr = IntPtrAdd(BitcastTaggedToWord(base_ptr), external_ptr); |
- Node* value = LoadFixedTypedArrayElementAsTagged(data_ptr, index, kind, |
- SMI_PARAMETERS); |
+ Node* value = LoadFixedTypedArrayElementAsTagged( |
+ data_ptr, index, source_elements_kind_, SMI_PARAMETERS); |
k_.Bind(index); |
a_.Bind(processor(this, value, index)); |
}; |
@@ -740,10 +796,13 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler { |
Node* receiver_ = nullptr; |
Node* new_target_ = nullptr; |
Node* argc_ = nullptr; |
+ Node* fast_typed_array_target_ = nullptr; |
+ Node* name_string_ = nullptr; |
Variable k_; |
Variable a_; |
Variable to_; |
Label fully_spec_compliant_; |
+ ElementsKind source_elements_kind_ = ElementsKind::NO_ELEMENTS; |
}; |
TF_BUILTIN(FastArrayPop, CodeStubAssembler) { |
@@ -1348,6 +1407,26 @@ TF_BUILTIN(ArrayMap, ArrayBuiltinCodeStubAssembler) { |
Builtins::CallableFor(isolate(), Builtins::kArrayMapLoopContinuation)); |
} |
+TF_BUILTIN(TypedArrayPrototypeMap, ArrayBuiltinCodeStubAssembler) { |
+ Node* argc = |
+ ChangeInt32ToIntPtr(Parameter(BuiltinDescriptor::kArgumentsCount)); |
+ CodeStubArguments args(this, argc); |
+ Node* context = Parameter(BuiltinDescriptor::kContext); |
+ Node* new_target = Parameter(BuiltinDescriptor::kNewTarget); |
+ Node* receiver = args.GetReceiver(); |
+ Node* callbackfn = args.GetOptionalArgumentValue(0, UndefinedConstant()); |
+ Node* this_arg = args.GetOptionalArgumentValue(1, UndefinedConstant()); |
+ |
+ InitIteratingArrayBuiltinBody(context, receiver, callbackfn, this_arg, |
+ new_target, argc); |
+ |
+ GenerateIteratingTypedArrayBuiltinBody( |
+ "%TypedArray%.prototype.map", |
+ &ArrayBuiltinCodeStubAssembler::TypedArrayMapResultGenerator, |
+ &ArrayBuiltinCodeStubAssembler::TypedArrayMapProcessor, |
+ &ArrayBuiltinCodeStubAssembler::NullPostLoopAction); |
+} |
+ |
TF_BUILTIN(ArrayIsArray, CodeStubAssembler) { |
Node* object = Parameter(Descriptor::kArg); |
Node* context = Parameter(Descriptor::kContext); |