Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(515)

Side by Side Diff: src/builtins/builtins-array-gen.cc

Issue 2814683002: [builtins] Implement %TypedArray%.prototype.map in the CSA (Closed)
Patch Set: added todo Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/bootstrapper.cc ('k') | src/builtins/builtins-definitions.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2017 the V8 project authors. All rights reserved. 1 // Copyright 2017 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/builtins/builtins-string-gen.h" 5 #include "src/builtins/builtins-string-gen.h"
6 #include "src/builtins/builtins-utils-gen.h" 6 #include "src/builtins/builtins-utils-gen.h"
7 #include "src/builtins/builtins.h" 7 #include "src/builtins/builtins.h"
8 #include "src/code-stub-assembler.h" 8 #include "src/code-stub-assembler.h"
9 9
10 namespace v8 { 10 namespace v8 {
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
157 to_.Bind(NumberInc(to_.value())); 157 to_.Bind(NumberInc(to_.value()));
158 Goto(&false_continue); 158 Goto(&false_continue);
159 } 159 }
160 } 160 }
161 BIND(&false_continue); 161 BIND(&false_continue);
162 return a(); 162 return a();
163 } 163 }
164 164
165 void MapResultGenerator() { ArraySpeciesCreate(len_); } 165 void MapResultGenerator() { ArraySpeciesCreate(len_); }
166 166
167 void TypedArrayMapResultGenerator() {
168 // 6. Let A be ? TypedArraySpeciesCreate(O, len).
169 Node* a = TypedArraySpeciesCreateByLength(context(), o(), len_);
170 // In the Spec and our current implementation, the length check is already
171 // performed in TypedArraySpeciesCreate. Repeating the check here to
172 // keep this invariant local.
173 // TODO(tebbi): Change this to a release mode check.
174 CSA_ASSERT(
175 this, WordEqual(len_, LoadObjectField(a, JSTypedArray::kLengthOffset)));
176 fast_typed_array_target_ = Word32Equal(LoadInstanceType(LoadElements(o_)),
177 LoadInstanceType(LoadElements(a)));
178 a_.Bind(a);
179 }
180
167 Node* SpecCompliantMapProcessor(Node* k_value, Node* k) { 181 Node* SpecCompliantMapProcessor(Node* k_value, Node* k) {
168 // i. Let kValue be ? Get(O, Pk). Performed by the caller of 182 // i. Let kValue be ? Get(O, Pk). Performed by the caller of
169 // SpecCompliantMapProcessor. 183 // SpecCompliantMapProcessor.
170 // ii. Let mappedValue be ? Call(callbackfn, T, kValue, k, O). 184 // ii. Let mappedValue be ? Call(callbackfn, T, kValue, k, O).
171 Node* mappedValue = CallJS(CodeFactory::Call(isolate()), context(), 185 Node* mappedValue = CallJS(CodeFactory::Call(isolate()), context(),
172 callbackfn(), this_arg(), k_value, k, o()); 186 callbackfn(), this_arg(), k_value, k, o());
173 187
174 // iii. Perform ? CreateDataPropertyOrThrow(A, Pk, mappedValue). 188 // iii. Perform ? CreateDataPropertyOrThrow(A, Pk, mappedValue).
175 CallRuntime(Runtime::kCreateDataProperty, context(), a(), k, mappedValue); 189 CallRuntime(Runtime::kCreateDataProperty, context(), a(), k, mappedValue);
176 return a(); 190 return a();
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
231 { 245 {
232 // iii. Perform ? CreateDataPropertyOrThrow(A, Pk, mappedValue). 246 // iii. Perform ? CreateDataPropertyOrThrow(A, Pk, mappedValue).
233 CallRuntime(Runtime::kCreateDataProperty, context(), a(), k, mappedValue); 247 CallRuntime(Runtime::kCreateDataProperty, context(), a(), k, mappedValue);
234 Goto(&finished); 248 Goto(&finished);
235 } 249 }
236 250
237 BIND(&finished); 251 BIND(&finished);
238 return a(); 252 return a();
239 } 253 }
240 254
255 // See tc39.github.io/ecma262/#sec-%typedarray%.prototype.map.
256 Node* TypedArrayMapProcessor(Node* k_value, Node* k) {
257 // 8. c. Let mappedValue be ? Call(callbackfn, T, « kValue, k, O »).
258 Node* mappedValue = CallJS(CodeFactory::Call(isolate()), context(),
259 callbackfn(), this_arg(), k_value, k, o());
260 Label fast(this), slow(this), done(this), detached(this, Label::kDeferred);
261
262 // 8. d. Perform ? Set(A, Pk, mappedValue, true).
263 // Since we know that A is a TypedArray, this always ends up in
264 // #sec-integer-indexed-exotic-objects-set-p-v-receiver and then
265 // tc39.github.io/ecma262/#sec-integerindexedelementset .
266 Branch(fast_typed_array_target_, &fast, &slow);
267
268 BIND(&fast);
269 // #sec-integerindexedelementset 3. Let numValue be ? ToNumber(value).
270 Node* num_value = ToNumber(context(), mappedValue);
271 // The only way how this can bailout is because of a detached buffer.
272 EmitElementStore(
273 a(), k, num_value, false, source_elements_kind_,
274 KeyedAccessStoreMode::STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS,
275 &detached);
276 Goto(&done);
277
278 BIND(&slow);
279 CallRuntime(Runtime::kSetProperty, context(), a(), k, mappedValue,
280 SmiConstant(STRICT));
281 Goto(&done);
282
283 BIND(&detached);
284 {
285 // tc39.github.io/ecma262/#sec-integerindexedelementset
286 // 5. If IsDetachedBuffer(buffer) is true, throw a TypeError exception.
287 CallRuntime(Runtime::kThrowTypeError, context_,
288 SmiConstant(MessageTemplate::kDetachedOperation),
289 name_string_);
290 Unreachable();
291 }
292
293 BIND(&done);
294 return a();
295 }
296
241 void NullPostLoopAction() {} 297 void NullPostLoopAction() {}
242 298
243 protected: 299 protected:
244 Node* context() { return context_; } 300 Node* context() { return context_; }
245 Node* receiver() { return receiver_; } 301 Node* receiver() { return receiver_; }
246 Node* new_target() { return new_target_; } 302 Node* new_target() { return new_target_; }
247 Node* argc() { return argc_; } 303 Node* argc() { return argc_; }
248 Node* o() { return o_; } 304 Node* o() { return o_; }
249 Node* len() { return len_; } 305 Node* len() { return len_; }
250 Node* callbackfn() { return callbackfn_; } 306 Node* callbackfn() { return callbackfn_; }
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
369 k_.Bind(initial_k); 425 k_.Bind(initial_k);
370 o_ = o; 426 o_ = o;
371 len_ = len; 427 len_ = len;
372 to_.Bind(to); 428 to_.Bind(to);
373 } 429 }
374 430
375 void GenerateIteratingTypedArrayBuiltinBody( 431 void GenerateIteratingTypedArrayBuiltinBody(
376 const char* name, const BuiltinResultGenerator& generator, 432 const char* name, const BuiltinResultGenerator& generator,
377 const CallResultProcessor& processor, const PostLoopAction& action, 433 const CallResultProcessor& processor, const PostLoopAction& action,
378 ForEachDirection direction = ForEachDirection::kForward) { 434 ForEachDirection direction = ForEachDirection::kForward) {
379 Node* name_string = 435 name_string_ =
380 HeapConstant(isolate()->factory()->NewStringFromAsciiChecked(name)); 436 HeapConstant(isolate()->factory()->NewStringFromAsciiChecked(name));
381 437
382 // ValidateTypedArray: tc39.github.io/ecma262/#sec-validatetypedarray 438 // ValidateTypedArray: tc39.github.io/ecma262/#sec-validatetypedarray
383 439
384 Label throw_not_typed_array(this, Label::kDeferred), 440 Label throw_not_typed_array(this, Label::kDeferred),
385 throw_detached(this, Label::kDeferred); 441 throw_detached(this, Label::kDeferred);
386 442
387 GotoIf(TaggedIsSmi(receiver_), &throw_not_typed_array); 443 GotoIf(TaggedIsSmi(receiver_), &throw_not_typed_array);
388 GotoIfNot(HasInstanceType(receiver_, JS_TYPED_ARRAY_TYPE), 444 GotoIfNot(HasInstanceType(receiver_, JS_TYPED_ARRAY_TYPE),
389 &throw_not_typed_array); 445 &throw_not_typed_array);
(...skipping 14 matching lines...) Expand all
404 { 460 {
405 CallRuntime(Runtime::kThrowTypeError, context_, 461 CallRuntime(Runtime::kThrowTypeError, context_,
406 SmiConstant(MessageTemplate::kNotTypedArray)); 462 SmiConstant(MessageTemplate::kNotTypedArray));
407 Unreachable(); 463 Unreachable();
408 } 464 }
409 465
410 BIND(&throw_detached); 466 BIND(&throw_detached);
411 { 467 {
412 CallRuntime(Runtime::kThrowTypeError, context_, 468 CallRuntime(Runtime::kThrowTypeError, context_,
413 SmiConstant(MessageTemplate::kDetachedOperation), 469 SmiConstant(MessageTemplate::kDetachedOperation),
414 name_string); 470 name_string_);
415 Unreachable(); 471 Unreachable();
416 } 472 }
417 473
418 BIND(&throw_not_callable); 474 BIND(&throw_not_callable);
419 { 475 {
420 CallRuntime(Runtime::kThrowTypeError, context_, 476 CallRuntime(Runtime::kThrowTypeError, context_,
421 SmiConstant(MessageTemplate::kCalledNonCallable), 477 SmiConstant(MessageTemplate::kCalledNonCallable),
422 callbackfn_); 478 callbackfn_);
423 Unreachable(); 479 Unreachable();
424 } 480 }
(...skipping 16 matching lines...) Expand all
441 label_ptrs.push_back(&label); 497 label_ptrs.push_back(&label);
442 } 498 }
443 499
444 BIND(&distinguish_types); 500 BIND(&distinguish_types);
445 501
446 if (direction == ForEachDirection::kForward) { 502 if (direction == ForEachDirection::kForward) {
447 k_.Bind(SmiConstant(0)); 503 k_.Bind(SmiConstant(0));
448 } else { 504 } else {
449 k_.Bind(NumberDec(len())); 505 k_.Bind(NumberDec(len()));
450 } 506 }
451 generator(this); 507 Node* instance_type = LoadInstanceType(LoadElements(o_));
452 Node* elements_type = LoadInstanceType(LoadElements(o_)); 508 Switch(instance_type, &unexpected_instance_type, instance_types.data(),
453 Switch(elements_type, &unexpected_instance_type, instance_types.data(),
454 label_ptrs.data(), labels.size()); 509 label_ptrs.data(), labels.size());
455 510
456 for (size_t i = 0; i < labels.size(); ++i) { 511 for (size_t i = 0; i < labels.size(); ++i) {
457 BIND(&labels[i]); 512 BIND(&labels[i]);
458 Label done(this); 513 Label done(this);
514 source_elements_kind_ = ElementsKindForInstanceType(
515 static_cast<InstanceType>(instance_types[i]));
516 generator(this);
459 // TODO(tebbi): Silently cancelling the loop on buffer detachment is a 517 // TODO(tebbi): Silently cancelling the loop on buffer detachment is a
460 // spec violation. Should go to &detached and throw a TypeError instead. 518 // spec violation. Should go to &throw_detached and throw a TypeError
461 VisitAllTypedArrayElements( 519 // instead.
462 ElementsKindForInstanceType( 520 VisitAllTypedArrayElements(array_buffer, processor, &done, direction);
463 static_cast<InstanceType>(instance_types[i])),
464 array_buffer, processor, &done, direction);
465 Goto(&done); 521 Goto(&done);
466 // No exception, return success 522 // No exception, return success
467 BIND(&done); 523 BIND(&done);
468 action(this); 524 action(this);
469 ReturnFromBuiltin(a_.value()); 525 ReturnFromBuiltin(a_.value());
470 } 526 }
471 } 527 }
472 528
473 void GenerateIteratingArrayBuiltinLoopContinuation( 529 void GenerateIteratingArrayBuiltinLoopContinuation(
474 const CallResultProcessor& processor, const PostLoopAction& action, 530 const CallResultProcessor& processor, const PostLoopAction& action,
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
533 589
534 TYPED_ARRAYS(INSTANCE_TYPE_TO_ELEMENTS_KIND) 590 TYPED_ARRAYS(INSTANCE_TYPE_TO_ELEMENTS_KIND)
535 #undef INSTANCE_TYPE_TO_ELEMENTS_KIND 591 #undef INSTANCE_TYPE_TO_ELEMENTS_KIND
536 592
537 default: 593 default:
538 UNREACHABLE(); 594 UNREACHABLE();
539 return static_cast<ElementsKind>(-1); 595 return static_cast<ElementsKind>(-1);
540 } 596 }
541 } 597 }
542 598
543 void VisitAllTypedArrayElements(ElementsKind kind, Node* array_buffer, 599 void VisitAllTypedArrayElements(Node* array_buffer,
544 const CallResultProcessor& processor, 600 const CallResultProcessor& processor,
545 Label* detached, ForEachDirection direction) { 601 Label* detached, ForEachDirection direction) {
546 VariableList list({&a_, &k_, &to_}, zone()); 602 VariableList list({&a_, &k_, &to_}, zone());
547 603
548 FastLoopBody body = [&](Node* index) { 604 FastLoopBody body = [&](Node* index) {
549 GotoIf(IsDetachedBuffer(array_buffer), detached); 605 GotoIf(IsDetachedBuffer(array_buffer), detached);
550 Node* elements = LoadElements(o_); 606 Node* elements = LoadElements(o_);
551 Node* base_ptr = 607 Node* base_ptr =
552 LoadObjectField(elements, FixedTypedArrayBase::kBasePointerOffset); 608 LoadObjectField(elements, FixedTypedArrayBase::kBasePointerOffset);
553 Node* external_ptr = 609 Node* external_ptr =
554 LoadObjectField(elements, FixedTypedArrayBase::kExternalPointerOffset, 610 LoadObjectField(elements, FixedTypedArrayBase::kExternalPointerOffset,
555 MachineType::Pointer()); 611 MachineType::Pointer());
556 Node* data_ptr = IntPtrAdd(BitcastTaggedToWord(base_ptr), external_ptr); 612 Node* data_ptr = IntPtrAdd(BitcastTaggedToWord(base_ptr), external_ptr);
557 Node* value = LoadFixedTypedArrayElementAsTagged(data_ptr, index, kind, 613 Node* value = LoadFixedTypedArrayElementAsTagged(
558 SMI_PARAMETERS); 614 data_ptr, index, source_elements_kind_, SMI_PARAMETERS);
559 k_.Bind(index); 615 k_.Bind(index);
560 a_.Bind(processor(this, value, index)); 616 a_.Bind(processor(this, value, index));
561 }; 617 };
562 Node* start = SmiConstant(0); 618 Node* start = SmiConstant(0);
563 Node* end = len_; 619 Node* end = len_;
564 IndexAdvanceMode advance_mode = IndexAdvanceMode::kPost; 620 IndexAdvanceMode advance_mode = IndexAdvanceMode::kPost;
565 int incr = 1; 621 int incr = 1;
566 if (direction == ForEachDirection::kReverse) { 622 if (direction == ForEachDirection::kReverse) {
567 std::swap(start, end); 623 std::swap(start, end);
568 advance_mode = IndexAdvanceMode::kPre; 624 advance_mode = IndexAdvanceMode::kPre;
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after
733 } 789 }
734 790
735 Node* callbackfn_ = nullptr; 791 Node* callbackfn_ = nullptr;
736 Node* o_ = nullptr; 792 Node* o_ = nullptr;
737 Node* this_arg_ = nullptr; 793 Node* this_arg_ = nullptr;
738 Node* len_ = nullptr; 794 Node* len_ = nullptr;
739 Node* context_ = nullptr; 795 Node* context_ = nullptr;
740 Node* receiver_ = nullptr; 796 Node* receiver_ = nullptr;
741 Node* new_target_ = nullptr; 797 Node* new_target_ = nullptr;
742 Node* argc_ = nullptr; 798 Node* argc_ = nullptr;
799 Node* fast_typed_array_target_ = nullptr;
800 Node* name_string_ = nullptr;
743 Variable k_; 801 Variable k_;
744 Variable a_; 802 Variable a_;
745 Variable to_; 803 Variable to_;
746 Label fully_spec_compliant_; 804 Label fully_spec_compliant_;
805 ElementsKind source_elements_kind_ = ElementsKind::NO_ELEMENTS;
747 }; 806 };
748 807
749 TF_BUILTIN(FastArrayPop, CodeStubAssembler) { 808 TF_BUILTIN(FastArrayPop, CodeStubAssembler) {
750 Node* argc = Parameter(BuiltinDescriptor::kArgumentsCount); 809 Node* argc = Parameter(BuiltinDescriptor::kArgumentsCount);
751 Node* context = Parameter(BuiltinDescriptor::kContext); 810 Node* context = Parameter(BuiltinDescriptor::kContext);
752 CSA_ASSERT(this, WordEqual(Parameter(BuiltinDescriptor::kNewTarget), 811 CSA_ASSERT(this, WordEqual(Parameter(BuiltinDescriptor::kNewTarget),
753 UndefinedConstant())); 812 UndefinedConstant()));
754 813
755 CodeStubArguments args(this, ChangeInt32ToIntPtr(argc)); 814 CodeStubArguments args(this, ChangeInt32ToIntPtr(argc));
756 Node* receiver = args.GetReceiver(); 815 Node* receiver = args.GetReceiver();
(...skipping 584 matching lines...) Expand 10 before | Expand all | Expand 10 after
1341 InitIteratingArrayBuiltinBody(context, receiver, callbackfn, this_arg, 1400 InitIteratingArrayBuiltinBody(context, receiver, callbackfn, this_arg,
1342 new_target, argc); 1401 new_target, argc);
1343 1402
1344 GenerateIteratingArrayBuiltinBody( 1403 GenerateIteratingArrayBuiltinBody(
1345 "Array.prototype.map", &ArrayBuiltinCodeStubAssembler::MapResultGenerator, 1404 "Array.prototype.map", &ArrayBuiltinCodeStubAssembler::MapResultGenerator,
1346 &ArrayBuiltinCodeStubAssembler::FastMapProcessor, 1405 &ArrayBuiltinCodeStubAssembler::FastMapProcessor,
1347 &ArrayBuiltinCodeStubAssembler::NullPostLoopAction, 1406 &ArrayBuiltinCodeStubAssembler::NullPostLoopAction,
1348 Builtins::CallableFor(isolate(), Builtins::kArrayMapLoopContinuation)); 1407 Builtins::CallableFor(isolate(), Builtins::kArrayMapLoopContinuation));
1349 } 1408 }
1350 1409
1410 TF_BUILTIN(TypedArrayPrototypeMap, ArrayBuiltinCodeStubAssembler) {
1411 Node* argc =
1412 ChangeInt32ToIntPtr(Parameter(BuiltinDescriptor::kArgumentsCount));
1413 CodeStubArguments args(this, argc);
1414 Node* context = Parameter(BuiltinDescriptor::kContext);
1415 Node* new_target = Parameter(BuiltinDescriptor::kNewTarget);
1416 Node* receiver = args.GetReceiver();
1417 Node* callbackfn = args.GetOptionalArgumentValue(0, UndefinedConstant());
1418 Node* this_arg = args.GetOptionalArgumentValue(1, UndefinedConstant());
1419
1420 InitIteratingArrayBuiltinBody(context, receiver, callbackfn, this_arg,
1421 new_target, argc);
1422
1423 GenerateIteratingTypedArrayBuiltinBody(
1424 "%TypedArray%.prototype.map",
1425 &ArrayBuiltinCodeStubAssembler::TypedArrayMapResultGenerator,
1426 &ArrayBuiltinCodeStubAssembler::TypedArrayMapProcessor,
1427 &ArrayBuiltinCodeStubAssembler::NullPostLoopAction);
1428 }
1429
1351 TF_BUILTIN(ArrayIsArray, CodeStubAssembler) { 1430 TF_BUILTIN(ArrayIsArray, CodeStubAssembler) {
1352 Node* object = Parameter(Descriptor::kArg); 1431 Node* object = Parameter(Descriptor::kArg);
1353 Node* context = Parameter(Descriptor::kContext); 1432 Node* context = Parameter(Descriptor::kContext);
1354 1433
1355 Label call_runtime(this), return_true(this), return_false(this); 1434 Label call_runtime(this), return_true(this), return_false(this);
1356 1435
1357 GotoIf(TaggedIsSmi(object), &return_false); 1436 GotoIf(TaggedIsSmi(object), &return_false);
1358 Node* instance_type = LoadInstanceType(object); 1437 Node* instance_type = LoadInstanceType(object);
1359 1438
1360 GotoIf(Word32Equal(instance_type, Int32Constant(JS_ARRAY_TYPE)), 1439 GotoIf(Word32Equal(instance_type, Int32Constant(JS_ARRAY_TYPE)),
(...skipping 857 matching lines...) Expand 10 before | Expand all | Expand 10 after
2218 { 2297 {
2219 Node* message = SmiConstant(MessageTemplate::kDetachedOperation); 2298 Node* message = SmiConstant(MessageTemplate::kDetachedOperation);
2220 CallRuntime(Runtime::kThrowTypeError, context, message, 2299 CallRuntime(Runtime::kThrowTypeError, context, message,
2221 HeapConstant(operation)); 2300 HeapConstant(operation));
2222 Unreachable(); 2301 Unreachable();
2223 } 2302 }
2224 } 2303 }
2225 2304
2226 } // namespace internal 2305 } // namespace internal
2227 } // namespace v8 2306 } // namespace v8
OLDNEW
« no previous file with comments | « src/bootstrapper.cc ('k') | src/builtins/builtins-definitions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698