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

Side by Side Diff: src/compiler/js-call-reducer.cc

Issue 2803853005: Inline Array.prototype.forEach in TurboFan (Closed)
Patch Set: fix v8heapconst.py 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
OLDNEW
1 // Copyright 2015 the V8 project authors. All rights reserved. 1 // Copyright 2015 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/compiler/js-call-reducer.h" 5 #include "src/compiler/js-call-reducer.h"
6 6
7 #include "src/code-factory.h" 7 #include "src/code-factory.h"
8 #include "src/code-stubs.h" 8 #include "src/code-stubs.h"
9 #include "src/compilation-dependencies.h" 9 #include "src/compilation-dependencies.h"
10 #include "src/compiler/access-builder.h"
10 #include "src/compiler/js-graph.h" 11 #include "src/compiler/js-graph.h"
11 #include "src/compiler/linkage.h" 12 #include "src/compiler/linkage.h"
12 #include "src/compiler/node-matchers.h" 13 #include "src/compiler/node-matchers.h"
13 #include "src/compiler/simplified-operator.h" 14 #include "src/compiler/simplified-operator.h"
14 #include "src/feedback-vector-inl.h" 15 #include "src/feedback-vector-inl.h"
15 #include "src/ic/call-optimization.h" 16 #include "src/ic/call-optimization.h"
16 #include "src/objects-inl.h" 17 #include "src/objects-inl.h"
17 18
18 namespace v8 { 19 namespace v8 {
19 namespace internal { 20 namespace internal {
(...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after
343 344
344 // ES6 section 26.1.7 Reflect.getPrototypeOf ( target ) 345 // ES6 section 26.1.7 Reflect.getPrototypeOf ( target )
345 Reduction JSCallReducer::ReduceReflectGetPrototypeOf(Node* node) { 346 Reduction JSCallReducer::ReduceReflectGetPrototypeOf(Node* node) {
346 DCHECK_EQ(IrOpcode::kJSCall, node->opcode()); 347 DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
347 Node* target = (node->op()->ValueInputCount() >= 3) 348 Node* target = (node->op()->ValueInputCount() >= 3)
348 ? NodeProperties::GetValueInput(node, 2) 349 ? NodeProperties::GetValueInput(node, 2)
349 : jsgraph()->UndefinedConstant(); 350 : jsgraph()->UndefinedConstant();
350 return ReduceObjectGetPrototype(node, target); 351 return ReduceObjectGetPrototype(node, target);
351 } 352 }
352 353
354 Reduction JSCallReducer::ReduceArrayForEach(Handle<SharedFunctionInfo> shared,
355 Node* node) {
356 if (!FLAG_inline_array_builtins) return NoChange();
357 DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
358 Node* outer_frame_state = NodeProperties::GetFrameStateInput(node);
359 Node* effect = NodeProperties::GetEffectInput(node);
360 Node* control = NodeProperties::GetControlInput(node);
361 Node* context = NodeProperties::GetContextInput(node);
362 CallParameters const& p = CallParametersOf(node->op());
363
364 // Try to determine the {receiver} map.
365 Node* receiver = NodeProperties::GetValueInput(node, 1);
366 Node* fncallback = node->op()->ValueInputCount() > 2
367 ? NodeProperties::GetValueInput(node, 2)
368 : jsgraph()->UndefinedConstant();
369 Node* this_arg = node->op()->ValueInputCount() > 3
370 ? NodeProperties::GetValueInput(node, 3)
371 : jsgraph()->UndefinedConstant();
372 ZoneHandleSet<Map> receiver_maps;
373 if (!NodeProperties::InferReceiverMaps(receiver, effect, &receiver_maps)) {
Benedikt Meurer 2017/05/22 19:29:40 This returns an enum. You only want to deal with r
danno 2017/06/06 12:04:52 Done.
374 return NoChange();
375 }
376 if (receiver_maps.size() != 1) return NoChange();
377 Handle<Map> receiver_map(receiver_maps[0]);
378 ElementsKind kind = receiver_map->elements_kind();
379 // TODO(danno): Handle holey Smi and Object fast elements kinds and double
380 // packed.
381 if (!IsFastPackedElementsKind(kind) || IsFastDoubleElementsKind(kind)) {
382 return NoChange();
383 }
384
385 Node* k = jsgraph()->Constant(0);
Jarin 2017/05/24 06:41:22 a.k.a. ZeroConstant()
danno 2017/06/06 12:04:52 Done.
386
387 Node* original_length = graph()->NewNode(
388 simplified()->LoadField(AccessBuilder::ForJSArrayLength(FAST_ELEMENTS)),
389 receiver, effect, control);
390
391 Node* loop = control = graph()->NewNode(common()->Loop(2), control, control);
392 Node* eloop = effect =
393 graph()->NewNode(common()->EffectPhi(2), effect, effect, loop);
394 Node* vloop = k = graph()->NewNode(
395 common()->Phi(MachineRepresentation::kTagged, 2), k, k, loop);
396
397 control = loop;
398 effect = eloop;
399
400 Node* continue_test =
401 graph()->NewNode(simplified()->NumberLessThan(), k, original_length);
402 Node* continue_branch = graph()->NewNode(common()->Branch(BranchHint::kTrue),
403 continue_test, control);
404
405 Node* if_true = graph()->NewNode(common()->IfTrue(), continue_branch);
406 Node* if_false = graph()->NewNode(common()->IfFalse(), continue_branch);
407 control = if_true;
408
409 std::vector<Node*> checkpoint_params(
410 {receiver, fncallback, this_arg, k, original_length});
411 const int stack_parameters = static_cast<int>(checkpoint_params.size());
412
413 Node* frame_state = CreateJavaScriptBuiltinContinuationFrameState(
414 jsgraph(), shared, Builtins::kArrayForEachLoopEagerDeoptContinuation,
415 node->InputAt(0), context, &checkpoint_params[0], stack_parameters,
416 outer_frame_state, ContinuationFrameStateMode::EAGER);
417
418 effect =
419 graph()->NewNode(common()->Checkpoint(), frame_state, effect, control);
420
421 // Make sure the map hasn't changed during the iteration
422 Node* orig_map = jsgraph()->HeapConstant(receiver_map);
423 Node* array_map = effect =
424 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
425 receiver, effect, control);
426 Node* check_map =
427 graph()->NewNode(simplified()->ReferenceEqual(), array_map, orig_map);
428 effect =
429 graph()->NewNode(simplified()->CheckIf(), check_map, effect, control);
430
431 // Make sure that the access is still in bounds, since the callback could have
432 // changed the array's size.
433 Node* length = graph()->NewNode(
434 simplified()->LoadField(AccessBuilder::ForJSArrayLength(FAST_ELEMENTS)),
435 receiver, effect, control);
436 k = effect =
437 graph()->NewNode(simplified()->CheckBounds(), k, length, effect, control);
438 USE(length);
Benedikt Meurer 2017/05/22 19:29:40 This is unnecessary.
danno 2017/06/06 12:04:52 Done.
439
440 // Reload the elements pointer before calling the callback, since the previous
441 // callback might have resized the array causing the elements buffer to be
442 // re-allocated.
443 Node* elements = graph()->NewNode(
444 simplified()->LoadField(AccessBuilder::ForJSObjectElements()), receiver,
445 effect, control);
446
447 Node* element = graph()->NewNode(
448 simplified()->LoadElement(AccessBuilder::ForFixedArrayElement()),
449 elements, k, effect, control);
450
451 Node* next_k =
452 graph()->NewNode(simplified()->NumberAdd(), k, jsgraph()->Constant(1));
453 checkpoint_params[3] = next_k;
454 frame_state = CreateJavaScriptBuiltinContinuationFrameState(
455 jsgraph(), shared, Builtins::kArrayForEachLoopLazyDeoptContinuation,
456 node->InputAt(0), context, &checkpoint_params[0], stack_parameters,
457 outer_frame_state, ContinuationFrameStateMode::LAZY);
458
459 Node* call_back = control = effect = graph()->NewNode(
460 javascript()->Call(5, p.frequency()), fncallback, this_arg, element, k,
Benedikt Meurer 2017/05/22 19:29:40 This doesn't properly rewire IfException edges. Ca
danno 2017/06/06 12:04:52 Done.
461 receiver, context, frame_state, effect, control);
462 USE(call_back);
Benedikt Meurer 2017/05/22 19:29:40 You don't seem to need the call_back variable.
danno 2017/06/06 12:04:52 Done.
463 USE(this_arg);
Benedikt Meurer 2017/05/22 19:29:40 This is unnecessary.
danno 2017/06/06 12:04:52 Done.
464
465 k = next_k;
466
467 loop->ReplaceInput(1, control);
468 vloop->ReplaceInput(1, k);
469 eloop->ReplaceInput(1, effect);
470
471 control = if_false;
472 effect = eloop;
473
474 NodeProperties::ReplaceUses(node, jsgraph()->UndefinedConstant(), effect,
Benedikt Meurer 2017/05/22 19:29:40 Can you use ReplaceWithValue instead of this magic
Michael Starzinger 2017/05/24 13:54:59 +1, otherwise we might run into similar issues as
danno 2017/06/06 12:04:52 Done.
danno 2017/06/06 12:04:52 Done.
475 control);
476
477 node->TrimInputCount(0);
478 NodeProperties::ChangeOp(node, common()->Dead());
479 return Changed(node);
480 }
481
353 Reduction JSCallReducer::ReduceCallApiFunction( 482 Reduction JSCallReducer::ReduceCallApiFunction(
354 Node* node, Handle<FunctionTemplateInfo> function_template_info) { 483 Node* node, Handle<FunctionTemplateInfo> function_template_info) {
355 DCHECK_EQ(IrOpcode::kJSCall, node->opcode()); 484 DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
356 CallParameters const& p = CallParametersOf(node->op()); 485 CallParameters const& p = CallParametersOf(node->op());
357 int const argc = static_cast<int>(p.arity()) - 2; 486 int const argc = static_cast<int>(p.arity()) - 2;
358 Node* receiver = (p.convert_mode() == ConvertReceiverMode::kNullOrUndefined) 487 Node* receiver = (p.convert_mode() == ConvertReceiverMode::kNullOrUndefined)
359 ? jsgraph()->HeapConstant(global_proxy()) 488 ? jsgraph()->HeapConstant(global_proxy())
360 : NodeProperties::GetValueInput(node, 1); 489 : NodeProperties::GetValueInput(node, 1);
361 Node* effect = NodeProperties::GetEffectInput(node); 490 Node* effect = NodeProperties::GetEffectInput(node);
362 491
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after
609 case Builtins::kFunctionPrototypeHasInstance: 738 case Builtins::kFunctionPrototypeHasInstance:
610 return ReduceFunctionPrototypeHasInstance(node); 739 return ReduceFunctionPrototypeHasInstance(node);
611 case Builtins::kNumberConstructor: 740 case Builtins::kNumberConstructor:
612 return ReduceNumberConstructor(node); 741 return ReduceNumberConstructor(node);
613 case Builtins::kObjectGetPrototypeOf: 742 case Builtins::kObjectGetPrototypeOf:
614 return ReduceObjectGetPrototypeOf(node); 743 return ReduceObjectGetPrototypeOf(node);
615 case Builtins::kObjectPrototypeGetProto: 744 case Builtins::kObjectPrototypeGetProto:
616 return ReduceObjectPrototypeGetProto(node); 745 return ReduceObjectPrototypeGetProto(node);
617 case Builtins::kReflectGetPrototypeOf: 746 case Builtins::kReflectGetPrototypeOf:
618 return ReduceReflectGetPrototypeOf(node); 747 return ReduceReflectGetPrototypeOf(node);
748 case Builtins::kArrayForEach:
749 return ReduceArrayForEach(shared, node);
619 default: 750 default:
620 break; 751 break;
621 } 752 }
622 753
623 // Check for the Array constructor. 754 // Check for the Array constructor.
624 if (*function == function->native_context()->array_function()) { 755 if (*function == function->native_context()->array_function()) {
625 return ReduceArrayConstructor(node); 756 return ReduceArrayConstructor(node);
626 } 757 }
627 758
628 if (!FLAG_runtime_stats && shared->IsApiFunction()) { 759 if (!FLAG_runtime_stats && shared->IsApiFunction()) {
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after
892 return jsgraph()->javascript(); 1023 return jsgraph()->javascript();
893 } 1024 }
894 1025
895 SimplifiedOperatorBuilder* JSCallReducer::simplified() const { 1026 SimplifiedOperatorBuilder* JSCallReducer::simplified() const {
896 return jsgraph()->simplified(); 1027 return jsgraph()->simplified();
897 } 1028 }
898 1029
899 } // namespace compiler 1030 } // namespace compiler
900 } // namespace internal 1031 } // namespace internal
901 } // namespace v8 1032 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698