Index: src/builtins/builtins-array-gen.cc |
diff --git a/src/builtins/builtins-array-gen.cc b/src/builtins/builtins-array-gen.cc |
index aad31db8a17d8bbb65347533377e61299e455279..d5b4865124d5243548ef84a1227a731d93314c7d 100644 |
--- a/src/builtins/builtins-array-gen.cc |
+++ b/src/builtins/builtins-array-gen.cc |
@@ -154,6 +154,19 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler { |
return ArraySpeciesCreate(context(), o(), len_); |
} |
+ Node* 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. |
+ fast_typed_array_target_ = WordAnd( |
+ WordEqual(LoadInstanceType(LoadElements(o_)), |
+ LoadInstanceType(LoadElements(A))), |
+ WordEqual(len_, LoadObjectField(A, JSTypedArray::kLengthOffset))); |
+ return A; |
+ } |
+ |
Node* MapProcessor(Node* k_value, Node* k) { |
// i. Let kValue be ? Get(O, Pk). Performed by the caller of MapProcessor. |
// ii. Let mappedValue be ? Call(callbackfn, T, kValue, k, O). |
@@ -165,6 +178,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); |
Camillo Bruni
2017/04/11 13:16:06
drive-by-comment: Could you upgrade your implement
|
+ // #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: |
@@ -295,7 +350,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 |
@@ -330,7 +385,7 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler { |
{ |
CallRuntime(Runtime::kThrowTypeError, context_, |
SmiConstant(MessageTemplate::kDetachedOperation), |
- name_string); |
+ name_string_); |
Unreachable(); |
} |
@@ -367,20 +422,20 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler { |
} else { |
k_.Bind(NumberDec(len())); |
} |
- a_.Bind(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])); |
+ a_.Bind(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); |
@@ -459,7 +514,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()); |
@@ -473,8 +528,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)); |
}; |
@@ -613,9 +668,12 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler { |
Node* context_ = nullptr; |
Node* receiver_ = nullptr; |
Node* new_target_ = nullptr; |
+ Node* fast_typed_array_target_ = nullptr; |
+ Node* name_string_ = nullptr; |
Variable k_; |
Variable a_; |
Variable to_; |
+ ElementsKind source_elements_kind_ = ElementsKind::NO_ELEMENTS; |
}; |
TF_BUILTIN(FastArrayPush, CodeStubAssembler) { |
@@ -1110,6 +1168,23 @@ TF_BUILTIN(ArrayMap, ArrayBuiltinCodeStubAssembler) { |
CodeFactory::ArrayMapLoopContinuation(isolate())); |
} |
+TF_BUILTIN(TypedArrayPrototypeMap, ArrayBuiltinCodeStubAssembler) { |
+ Node* context = Parameter(Descriptor::kContext); |
+ Node* receiver = Parameter(Descriptor::kReceiver); |
+ Node* callbackfn = Parameter(Descriptor::kCallbackFn); |
+ Node* this_arg = Parameter(Descriptor::kThisArg); |
+ Node* new_target = Parameter(Descriptor::kNewTarget); |
+ |
+ InitIteratingArrayBuiltinBody(context, receiver, callbackfn, this_arg, |
+ new_target); |
+ |
+ GenerateIteratingTypedArrayBuiltinBody( |
+ "%TypedArray%.prototype.map", |
+ &ArrayBuiltinCodeStubAssembler::TypedArrayMapResultGenerator, |
+ &ArrayBuiltinCodeStubAssembler::TypedArrayMapProcessor, |
+ &ArrayBuiltinCodeStubAssembler::NullPostLoopAction); |
+} |
+ |
TF_BUILTIN(ArrayIsArray, CodeStubAssembler) { |
Node* object = Parameter(Descriptor::kArg); |
Node* context = Parameter(Descriptor::kContext); |