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

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

Issue 2803853005: Inline Array.prototype.forEach in TurboFan (Closed)
Patch Set: Disable new array builtins by default Created 3 years, 6 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/compiler/js-call-reducer.h ('k') | src/deoptimizer.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 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<JSFunction> function,
355 Node* node) {
356 if (!FLAG_turbo_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 NodeProperties::InferReceiverMapsResult result =
374 NodeProperties::InferReceiverMaps(receiver, effect, &receiver_maps);
375 if (result != NodeProperties::kReliableReceiverMaps) {
376 return NoChange();
377 }
378 if (receiver_maps.size() != 1) return NoChange();
379 Handle<Map> receiver_map(receiver_maps[0]);
380 ElementsKind kind = receiver_map->elements_kind();
381 // TODO(danno): Handle holey Smi and Object fast elements kinds and double
382 // packed.
383 if (!IsFastPackedElementsKind(kind) || IsFastDoubleElementsKind(kind)) {
384 return NoChange();
385 }
386
387 // TODO(danno): forEach can throw. Hook up exceptional edges.
388 if (NodeProperties::IsExceptionalCall(node)) return NoChange();
389
390 Node* k = jsgraph()->ZeroConstant();
391
392 Node* original_length = graph()->NewNode(
393 simplified()->LoadField(AccessBuilder::ForJSArrayLength(FAST_ELEMENTS)),
394 receiver, effect, control);
395
396 Node* loop = control = graph()->NewNode(common()->Loop(2), control, control);
397 Node* eloop = effect =
398 graph()->NewNode(common()->EffectPhi(2), effect, effect, loop);
399 Node* vloop = k = graph()->NewNode(
400 common()->Phi(MachineRepresentation::kTagged, 2), k, k, loop);
401
402 control = loop;
403 effect = eloop;
404
405 Node* continue_test =
406 graph()->NewNode(simplified()->NumberLessThan(), k, original_length);
407 Node* continue_branch = graph()->NewNode(common()->Branch(BranchHint::kTrue),
408 continue_test, control);
409
410 Node* if_true = graph()->NewNode(common()->IfTrue(), continue_branch);
411 Node* if_false = graph()->NewNode(common()->IfFalse(), continue_branch);
412 control = if_true;
413
414 std::vector<Node*> checkpoint_params(
415 {receiver, fncallback, this_arg, k, original_length});
416 const int stack_parameters = static_cast<int>(checkpoint_params.size());
417
418 Node* frame_state = CreateJavaScriptBuiltinContinuationFrameState(
419 jsgraph(), function, Builtins::kArrayForEachLoopEagerDeoptContinuation,
420 node->InputAt(0), context, &checkpoint_params[0], stack_parameters,
421 outer_frame_state, ContinuationFrameStateMode::EAGER);
422
423 effect =
424 graph()->NewNode(common()->Checkpoint(), frame_state, effect, control);
425
426 // Make sure the map hasn't changed during the iteration
427 Node* orig_map = jsgraph()->HeapConstant(receiver_map);
428 Node* array_map = effect =
429 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
430 receiver, effect, control);
431 Node* check_map =
432 graph()->NewNode(simplified()->ReferenceEqual(), array_map, orig_map);
433 effect =
434 graph()->NewNode(simplified()->CheckIf(), check_map, effect, control);
435
436 // Make sure that the access is still in bounds, since the callback could have
437 // changed the array's size.
438 Node* length = graph()->NewNode(
439 simplified()->LoadField(AccessBuilder::ForJSArrayLength(FAST_ELEMENTS)),
440 receiver, effect, control);
441 k = effect =
442 graph()->NewNode(simplified()->CheckBounds(), k, length, effect, control);
443
444 // Reload the elements pointer before calling the callback, since the previous
445 // callback might have resized the array causing the elements buffer to be
446 // re-allocated.
447 Node* elements = graph()->NewNode(
448 simplified()->LoadField(AccessBuilder::ForJSObjectElements()), receiver,
449 effect, control);
450
451 Node* element = graph()->NewNode(
452 simplified()->LoadElement(AccessBuilder::ForFixedArrayElement()),
453 elements, k, effect, control);
454
455 Node* next_k =
456 graph()->NewNode(simplified()->NumberAdd(), k, jsgraph()->Constant(1));
457 checkpoint_params[3] = next_k;
458 frame_state = CreateJavaScriptBuiltinContinuationFrameState(
459 jsgraph(), function, Builtins::kArrayForEachLoopLazyDeoptContinuation,
460 node->InputAt(0), context, &checkpoint_params[0], stack_parameters,
461 outer_frame_state, ContinuationFrameStateMode::LAZY);
462
463 control = effect = graph()->NewNode(
464 javascript()->Call(5, p.frequency()), fncallback, this_arg, element, k,
465 receiver, context, frame_state, effect, control);
466
467 k = next_k;
468
469 loop->ReplaceInput(1, control);
470 vloop->ReplaceInput(1, k);
471 eloop->ReplaceInput(1, effect);
472
473 control = if_false;
474 effect = eloop;
475
476 ReplaceWithValue(node, jsgraph()->UndefinedConstant(), effect, control);
477 return Replace(jsgraph()->UndefinedConstant());
478 }
479
353 Reduction JSCallReducer::ReduceCallApiFunction( 480 Reduction JSCallReducer::ReduceCallApiFunction(
354 Node* node, Handle<FunctionTemplateInfo> function_template_info) { 481 Node* node, Handle<FunctionTemplateInfo> function_template_info) {
355 DCHECK_EQ(IrOpcode::kJSCall, node->opcode()); 482 DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
356 CallParameters const& p = CallParametersOf(node->op()); 483 CallParameters const& p = CallParametersOf(node->op());
357 int const argc = static_cast<int>(p.arity()) - 2; 484 int const argc = static_cast<int>(p.arity()) - 2;
358 Node* receiver = (p.convert_mode() == ConvertReceiverMode::kNullOrUndefined) 485 Node* receiver = (p.convert_mode() == ConvertReceiverMode::kNullOrUndefined)
359 ? jsgraph()->HeapConstant(global_proxy()) 486 ? jsgraph()->HeapConstant(global_proxy())
360 : NodeProperties::GetValueInput(node, 1); 487 : NodeProperties::GetValueInput(node, 1);
361 Node* effect = NodeProperties::GetEffectInput(node); 488 Node* effect = NodeProperties::GetEffectInput(node);
362 489
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after
609 case Builtins::kFunctionPrototypeHasInstance: 736 case Builtins::kFunctionPrototypeHasInstance:
610 return ReduceFunctionPrototypeHasInstance(node); 737 return ReduceFunctionPrototypeHasInstance(node);
611 case Builtins::kNumberConstructor: 738 case Builtins::kNumberConstructor:
612 return ReduceNumberConstructor(node); 739 return ReduceNumberConstructor(node);
613 case Builtins::kObjectGetPrototypeOf: 740 case Builtins::kObjectGetPrototypeOf:
614 return ReduceObjectGetPrototypeOf(node); 741 return ReduceObjectGetPrototypeOf(node);
615 case Builtins::kObjectPrototypeGetProto: 742 case Builtins::kObjectPrototypeGetProto:
616 return ReduceObjectPrototypeGetProto(node); 743 return ReduceObjectPrototypeGetProto(node);
617 case Builtins::kReflectGetPrototypeOf: 744 case Builtins::kReflectGetPrototypeOf:
618 return ReduceReflectGetPrototypeOf(node); 745 return ReduceReflectGetPrototypeOf(node);
746 case Builtins::kArrayForEach:
747 return ReduceArrayForEach(function, node);
619 default: 748 default:
620 break; 749 break;
621 } 750 }
622 751
623 // Check for the Array constructor. 752 // Check for the Array constructor.
624 if (*function == function->native_context()->array_function()) { 753 if (*function == function->native_context()->array_function()) {
625 return ReduceArrayConstructor(node); 754 return ReduceArrayConstructor(node);
626 } 755 }
627 756
628 if (!FLAG_runtime_stats && shared->IsApiFunction()) { 757 if (!FLAG_runtime_stats && shared->IsApiFunction()) {
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after
892 return jsgraph()->javascript(); 1021 return jsgraph()->javascript();
893 } 1022 }
894 1023
895 SimplifiedOperatorBuilder* JSCallReducer::simplified() const { 1024 SimplifiedOperatorBuilder* JSCallReducer::simplified() const {
896 return jsgraph()->simplified(); 1025 return jsgraph()->simplified();
897 } 1026 }
898 1027
899 } // namespace compiler 1028 } // namespace compiler
900 } // namespace internal 1029 } // namespace internal
901 } // namespace v8 1030 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/js-call-reducer.h ('k') | src/deoptimizer.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698