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

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

Issue 2814683002: [builtins] Implement %TypedArray%.prototype.map in the CSA (Closed)
Patch Set: added spec comments Created 3 years, 8 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-utils-gen.h" 5 #include "src/builtins/builtins-utils-gen.h"
6 #include "src/builtins/builtins.h" 6 #include "src/builtins/builtins.h"
7 #include "src/code-stub-assembler.h" 7 #include "src/code-stub-assembler.h"
8 8
9 namespace v8 { 9 namespace v8 {
10 namespace internal { 10 namespace internal {
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
147 } 147 }
148 BIND(&false_continue); 148 BIND(&false_continue);
149 return a(); 149 return a();
150 } 150 }
151 151
152 Node* MapResultGenerator() { 152 Node* MapResultGenerator() {
153 // 5. Let A be ? ArraySpeciesCreate(O, len). 153 // 5. Let A be ? ArraySpeciesCreate(O, len).
154 return ArraySpeciesCreate(context(), o(), len_); 154 return ArraySpeciesCreate(context(), o(), len_);
155 } 155 }
156 156
157 Node* TypedArrayMapResultGenerator() {
158 // 6. Let A be ? TypedArraySpeciesCreate(O, len).
159 Node* A = TypedArraySpeciesCreateByLength(context(), o(), len_);
160 // In the Spec and our current implementation, the length check is already
161 // performed in TypedArraySpeciesCreate. Repeating the check here to
162 // keep this invariant local.
163 fast_typed_array_target_ = WordAnd(
164 WordEqual(LoadInstanceType(LoadElements(o_)),
165 LoadInstanceType(LoadElements(A))),
166 WordEqual(len_, LoadObjectField(A, JSTypedArray::kLengthOffset)));
167 return A;
168 }
169
157 Node* MapProcessor(Node* k_value, Node* k) { 170 Node* MapProcessor(Node* k_value, Node* k) {
158 // i. Let kValue be ? Get(O, Pk). Performed by the caller of MapProcessor. 171 // i. Let kValue be ? Get(O, Pk). Performed by the caller of MapProcessor.
159 // ii. Let mappedValue be ? Call(callbackfn, T, kValue, k, O). 172 // ii. Let mappedValue be ? Call(callbackfn, T, kValue, k, O).
160 Node* mappedValue = CallJS(CodeFactory::Call(isolate()), context(), 173 Node* mappedValue = CallJS(CodeFactory::Call(isolate()), context(),
161 callbackfn(), this_arg(), k_value, k, o()); 174 callbackfn(), this_arg(), k_value, k, o());
162 175
163 // iii. Perform ? CreateDataPropertyOrThrow(A, Pk, mappedValue). 176 // iii. Perform ? CreateDataPropertyOrThrow(A, Pk, mappedValue).
164 CallRuntime(Runtime::kCreateDataProperty, context(), a(), k, mappedValue); 177 CallRuntime(Runtime::kCreateDataProperty, context(), a(), k, mappedValue);
165 return a(); 178 return a();
166 } 179 }
167 180
181 // See tc39.github.io/ecma262/#sec-%typedarray%.prototype.map.
182 Node* TypedArrayMapProcessor(Node* k_value, Node* k) {
183 // 8. c. Let mappedValue be ? Call(callbackfn, T, « kValue, k, O »).
184 Node* mappedValue = CallJS(CodeFactory::Call(isolate()), context(),
185 callbackfn(), this_arg(), k_value, k, o());
186 Label fast(this), slow(this), done(this), detached(this, Label::kDeferred);
187
188 // 8. d. Perform ? Set(A, Pk, mappedValue, true).
189 // Since we know that A is a TypedArray, this always ends up in
190 // #sec-integer-indexed-exotic-objects-set-p-v-receiver and then
191 // tc39.github.io/ecma262/#sec-integerindexedelementset .
192 Branch(fast_typed_array_target_, &fast, &slow);
193
194 Bind(&fast);
Camillo Bruni 2017/04/11 13:16:06 drive-by-comment: Could you upgrade your implement
195 // #sec-integerindexedelementset 3. Let numValue be ? ToNumber(value).
196 Node* num_value = ToNumber(context(), mappedValue);
197 // The only way how this can bailout is because of a detached buffer.
198 EmitElementStore(
199 a(), k, num_value, false, source_elements_kind_,
200 KeyedAccessStoreMode::STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS,
201 &detached);
202 Goto(&done);
203
204 Bind(&slow);
205 CallRuntime(Runtime::kSetProperty, context(), a(), k, mappedValue,
206 SmiConstant(STRICT));
207 Goto(&done);
208
209 Bind(&detached);
210 {
211 // tc39.github.io/ecma262/#sec-integerindexedelementset
212 // 5. If IsDetachedBuffer(buffer) is true, throw a TypeError exception.
213 CallRuntime(Runtime::kThrowTypeError, context_,
214 SmiConstant(MessageTemplate::kDetachedOperation),
215 name_string_);
216 Unreachable();
217 }
218
219 Bind(&done);
220 return a();
221 }
222
168 void NullPostLoopAction() {} 223 void NullPostLoopAction() {}
169 224
170 protected: 225 protected:
171 Node* context() { return context_; } 226 Node* context() { return context_; }
172 Node* receiver() { return receiver_; } 227 Node* receiver() { return receiver_; }
173 Node* new_target() { return new_target_; } 228 Node* new_target() { return new_target_; }
174 Node* o() { return o_; } 229 Node* o() { return o_; }
175 Node* len() { return len_; } 230 Node* len() { return len_; }
176 Node* callbackfn() { return callbackfn_; } 231 Node* callbackfn() { return callbackfn_; }
177 Node* this_arg() { return this_arg_; } 232 Node* this_arg() { return this_arg_; }
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
288 k_.Bind(initial_k); 343 k_.Bind(initial_k);
289 o_ = o; 344 o_ = o;
290 len_ = len; 345 len_ = len;
291 to_.Bind(to); 346 to_.Bind(to);
292 } 347 }
293 348
294 void GenerateIteratingTypedArrayBuiltinBody( 349 void GenerateIteratingTypedArrayBuiltinBody(
295 const char* name, const BuiltinResultGenerator& generator, 350 const char* name, const BuiltinResultGenerator& generator,
296 const CallResultProcessor& processor, const PostLoopAction& action, 351 const CallResultProcessor& processor, const PostLoopAction& action,
297 ForEachDirection direction = ForEachDirection::kForward) { 352 ForEachDirection direction = ForEachDirection::kForward) {
298 Node* name_string = 353 name_string_ =
299 HeapConstant(isolate()->factory()->NewStringFromAsciiChecked(name)); 354 HeapConstant(isolate()->factory()->NewStringFromAsciiChecked(name));
300 355
301 // ValidateTypedArray: tc39.github.io/ecma262/#sec-validatetypedarray 356 // ValidateTypedArray: tc39.github.io/ecma262/#sec-validatetypedarray
302 357
303 Label throw_not_typed_array(this, Label::kDeferred), 358 Label throw_not_typed_array(this, Label::kDeferred),
304 throw_detached(this, Label::kDeferred); 359 throw_detached(this, Label::kDeferred);
305 360
306 GotoIf(TaggedIsSmi(receiver_), &throw_not_typed_array); 361 GotoIf(TaggedIsSmi(receiver_), &throw_not_typed_array);
307 GotoIfNot(HasInstanceType(receiver_, JS_TYPED_ARRAY_TYPE), 362 GotoIfNot(HasInstanceType(receiver_, JS_TYPED_ARRAY_TYPE),
308 &throw_not_typed_array); 363 &throw_not_typed_array);
(...skipping 14 matching lines...) Expand all
323 { 378 {
324 CallRuntime(Runtime::kThrowTypeError, context_, 379 CallRuntime(Runtime::kThrowTypeError, context_,
325 SmiConstant(MessageTemplate::kNotTypedArray)); 380 SmiConstant(MessageTemplate::kNotTypedArray));
326 Unreachable(); 381 Unreachable();
327 } 382 }
328 383
329 BIND(&throw_detached); 384 BIND(&throw_detached);
330 { 385 {
331 CallRuntime(Runtime::kThrowTypeError, context_, 386 CallRuntime(Runtime::kThrowTypeError, context_,
332 SmiConstant(MessageTemplate::kDetachedOperation), 387 SmiConstant(MessageTemplate::kDetachedOperation),
333 name_string); 388 name_string_);
334 Unreachable(); 389 Unreachable();
335 } 390 }
336 391
337 BIND(&throw_not_callable); 392 BIND(&throw_not_callable);
338 { 393 {
339 CallRuntime(Runtime::kThrowTypeError, context_, 394 CallRuntime(Runtime::kThrowTypeError, context_,
340 SmiConstant(MessageTemplate::kCalledNonCallable), 395 SmiConstant(MessageTemplate::kCalledNonCallable),
341 callbackfn_); 396 callbackfn_);
342 Unreachable(); 397 Unreachable();
343 } 398 }
(...skipping 16 matching lines...) Expand all
360 label_ptrs.push_back(&label); 415 label_ptrs.push_back(&label);
361 } 416 }
362 417
363 BIND(&distinguish_types); 418 BIND(&distinguish_types);
364 419
365 if (direction == ForEachDirection::kForward) { 420 if (direction == ForEachDirection::kForward) {
366 k_.Bind(SmiConstant(0)); 421 k_.Bind(SmiConstant(0));
367 } else { 422 } else {
368 k_.Bind(NumberDec(len())); 423 k_.Bind(NumberDec(len()));
369 } 424 }
370 a_.Bind(generator(this)); 425 Node* instance_type = LoadInstanceType(LoadElements(o_));
371 Node* elements_type = LoadInstanceType(LoadElements(o_)); 426 Switch(instance_type, &unexpected_instance_type, instance_types.data(),
372 Switch(elements_type, &unexpected_instance_type, instance_types.data(),
373 label_ptrs.data(), labels.size()); 427 label_ptrs.data(), labels.size());
374 428
375 for (size_t i = 0; i < labels.size(); ++i) { 429 for (size_t i = 0; i < labels.size(); ++i) {
376 BIND(&labels[i]); 430 BIND(&labels[i]);
377 Label done(this); 431 Label done(this);
432 source_elements_kind_ = ElementsKindForInstanceType(
433 static_cast<InstanceType>(instance_types[i]));
434 a_.Bind(generator(this));
378 // TODO(tebbi): Silently cancelling the loop on buffer detachment is a 435 // TODO(tebbi): Silently cancelling the loop on buffer detachment is a
379 // spec violation. Should go to &detached and throw a TypeError instead. 436 // spec violation. Should go to &throw_detached_ and throw a TypeError
380 VisitAllTypedArrayElements( 437 // instead.
381 ElementsKindForInstanceType( 438 VisitAllTypedArrayElements(array_buffer, processor, &done, direction);
382 static_cast<InstanceType>(instance_types[i])),
383 array_buffer, processor, &done, direction);
384 Goto(&done); 439 Goto(&done);
385 // No exception, return success 440 // No exception, return success
386 BIND(&done); 441 BIND(&done);
387 action(this); 442 action(this);
388 Return(a_.value()); 443 Return(a_.value());
389 } 444 }
390 } 445 }
391 446
392 void GenerateIteratingArrayBuiltinLoopContinuation( 447 void GenerateIteratingArrayBuiltinLoopContinuation(
393 const CallResultProcessor& processor, const PostLoopAction& action, 448 const CallResultProcessor& processor, const PostLoopAction& action,
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
452 507
453 TYPED_ARRAYS(INSTANCE_TYPE_TO_ELEMENTS_KIND) 508 TYPED_ARRAYS(INSTANCE_TYPE_TO_ELEMENTS_KIND)
454 #undef INSTANCE_TYPE_TO_ELEMENTS_KIND 509 #undef INSTANCE_TYPE_TO_ELEMENTS_KIND
455 510
456 default: 511 default:
457 UNREACHABLE(); 512 UNREACHABLE();
458 return static_cast<ElementsKind>(-1); 513 return static_cast<ElementsKind>(-1);
459 } 514 }
460 } 515 }
461 516
462 void VisitAllTypedArrayElements(ElementsKind kind, Node* array_buffer, 517 void VisitAllTypedArrayElements(Node* array_buffer,
463 const CallResultProcessor& processor, 518 const CallResultProcessor& processor,
464 Label* detached, ForEachDirection direction) { 519 Label* detached, ForEachDirection direction) {
465 VariableList list({&a_, &k_, &to_}, zone()); 520 VariableList list({&a_, &k_, &to_}, zone());
466 521
467 FastLoopBody body = [&](Node* index) { 522 FastLoopBody body = [&](Node* index) {
468 GotoIf(IsDetachedBuffer(array_buffer), detached); 523 GotoIf(IsDetachedBuffer(array_buffer), detached);
469 Node* elements = LoadElements(o_); 524 Node* elements = LoadElements(o_);
470 Node* base_ptr = 525 Node* base_ptr =
471 LoadObjectField(elements, FixedTypedArrayBase::kBasePointerOffset); 526 LoadObjectField(elements, FixedTypedArrayBase::kBasePointerOffset);
472 Node* external_ptr = 527 Node* external_ptr =
473 LoadObjectField(elements, FixedTypedArrayBase::kExternalPointerOffset, 528 LoadObjectField(elements, FixedTypedArrayBase::kExternalPointerOffset,
474 MachineType::Pointer()); 529 MachineType::Pointer());
475 Node* data_ptr = IntPtrAdd(BitcastTaggedToWord(base_ptr), external_ptr); 530 Node* data_ptr = IntPtrAdd(BitcastTaggedToWord(base_ptr), external_ptr);
476 Node* value = LoadFixedTypedArrayElementAsTagged(data_ptr, index, kind, 531 Node* value = LoadFixedTypedArrayElementAsTagged(
477 SMI_PARAMETERS); 532 data_ptr, index, source_elements_kind_, SMI_PARAMETERS);
478 k_.Bind(index); 533 k_.Bind(index);
479 a_.Bind(processor(this, value, index)); 534 a_.Bind(processor(this, value, index));
480 }; 535 };
481 Node* start = SmiConstant(0); 536 Node* start = SmiConstant(0);
482 Node* end = len_; 537 Node* end = len_;
483 IndexAdvanceMode advance_mode = IndexAdvanceMode::kPost; 538 IndexAdvanceMode advance_mode = IndexAdvanceMode::kPost;
484 int incr = 1; 539 int incr = 1;
485 if (direction == ForEachDirection::kReverse) { 540 if (direction == ForEachDirection::kReverse) {
486 std::swap(start, end); 541 std::swap(start, end);
487 advance_mode = IndexAdvanceMode::kPre; 542 advance_mode = IndexAdvanceMode::kPre;
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
606 } 661 }
607 } 662 }
608 663
609 Node* callbackfn_ = nullptr; 664 Node* callbackfn_ = nullptr;
610 Node* o_ = nullptr; 665 Node* o_ = nullptr;
611 Node* this_arg_ = nullptr; 666 Node* this_arg_ = nullptr;
612 Node* len_ = nullptr; 667 Node* len_ = nullptr;
613 Node* context_ = nullptr; 668 Node* context_ = nullptr;
614 Node* receiver_ = nullptr; 669 Node* receiver_ = nullptr;
615 Node* new_target_ = nullptr; 670 Node* new_target_ = nullptr;
671 Node* fast_typed_array_target_ = nullptr;
672 Node* name_string_ = nullptr;
616 Variable k_; 673 Variable k_;
617 Variable a_; 674 Variable a_;
618 Variable to_; 675 Variable to_;
676 ElementsKind source_elements_kind_ = ElementsKind::NO_ELEMENTS;
619 }; 677 };
620 678
621 TF_BUILTIN(FastArrayPush, CodeStubAssembler) { 679 TF_BUILTIN(FastArrayPush, CodeStubAssembler) {
622 VARIABLE(arg_index, MachineType::PointerRepresentation()); 680 VARIABLE(arg_index, MachineType::PointerRepresentation());
623 Label default_label(this, &arg_index); 681 Label default_label(this, &arg_index);
624 Label smi_transition(this); 682 Label smi_transition(this);
625 Label object_push_pre(this); 683 Label object_push_pre(this);
626 Label object_push(this, &arg_index); 684 Label object_push(this, &arg_index);
627 Label double_push(this, &arg_index); 685 Label double_push(this, &arg_index);
628 Label double_transition(this); 686 Label double_transition(this);
(...skipping 474 matching lines...) Expand 10 before | Expand all | Expand 10 after
1103 InitIteratingArrayBuiltinBody(context, receiver, callbackfn, this_arg, 1161 InitIteratingArrayBuiltinBody(context, receiver, callbackfn, this_arg,
1104 new_target); 1162 new_target);
1105 1163
1106 GenerateIteratingArrayBuiltinBody( 1164 GenerateIteratingArrayBuiltinBody(
1107 "Array.prototype.map", &ArrayBuiltinCodeStubAssembler::MapResultGenerator, 1165 "Array.prototype.map", &ArrayBuiltinCodeStubAssembler::MapResultGenerator,
1108 &ArrayBuiltinCodeStubAssembler::MapProcessor, 1166 &ArrayBuiltinCodeStubAssembler::MapProcessor,
1109 &ArrayBuiltinCodeStubAssembler::NullPostLoopAction, 1167 &ArrayBuiltinCodeStubAssembler::NullPostLoopAction,
1110 CodeFactory::ArrayMapLoopContinuation(isolate())); 1168 CodeFactory::ArrayMapLoopContinuation(isolate()));
1111 } 1169 }
1112 1170
1171 TF_BUILTIN(TypedArrayPrototypeMap, ArrayBuiltinCodeStubAssembler) {
1172 Node* context = Parameter(Descriptor::kContext);
1173 Node* receiver = Parameter(Descriptor::kReceiver);
1174 Node* callbackfn = Parameter(Descriptor::kCallbackFn);
1175 Node* this_arg = Parameter(Descriptor::kThisArg);
1176 Node* new_target = Parameter(Descriptor::kNewTarget);
1177
1178 InitIteratingArrayBuiltinBody(context, receiver, callbackfn, this_arg,
1179 new_target);
1180
1181 GenerateIteratingTypedArrayBuiltinBody(
1182 "%TypedArray%.prototype.map",
1183 &ArrayBuiltinCodeStubAssembler::TypedArrayMapResultGenerator,
1184 &ArrayBuiltinCodeStubAssembler::TypedArrayMapProcessor,
1185 &ArrayBuiltinCodeStubAssembler::NullPostLoopAction);
1186 }
1187
1113 TF_BUILTIN(ArrayIsArray, CodeStubAssembler) { 1188 TF_BUILTIN(ArrayIsArray, CodeStubAssembler) {
1114 Node* object = Parameter(Descriptor::kArg); 1189 Node* object = Parameter(Descriptor::kArg);
1115 Node* context = Parameter(Descriptor::kContext); 1190 Node* context = Parameter(Descriptor::kContext);
1116 1191
1117 Label call_runtime(this), return_true(this), return_false(this); 1192 Label call_runtime(this), return_true(this), return_false(this);
1118 1193
1119 GotoIf(TaggedIsSmi(object), &return_false); 1194 GotoIf(TaggedIsSmi(object), &return_false);
1120 Node* instance_type = LoadInstanceType(object); 1195 Node* instance_type = LoadInstanceType(object);
1121 1196
1122 GotoIf(Word32Equal(instance_type, Int32Constant(JS_ARRAY_TYPE)), 1197 GotoIf(Word32Equal(instance_type, Int32Constant(JS_ARRAY_TYPE)),
(...skipping 1041 matching lines...) Expand 10 before | Expand all | Expand 10 after
2164 { 2239 {
2165 Node* message = SmiConstant(MessageTemplate::kDetachedOperation); 2240 Node* message = SmiConstant(MessageTemplate::kDetachedOperation);
2166 CallRuntime(Runtime::kThrowTypeError, context, message, 2241 CallRuntime(Runtime::kThrowTypeError, context, message,
2167 HeapConstant(operation)); 2242 HeapConstant(operation));
2168 Unreachable(); 2243 Unreachable();
2169 } 2244 }
2170 } 2245 }
2171 2246
2172 } // namespace internal 2247 } // namespace internal
2173 } // namespace v8 2248 } // 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