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

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

Issue 2803853005: Inline Array.prototype.forEach in TurboFan (Closed)
Patch Set: Add comments 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 316 matching lines...) Expand 10 before | Expand all | Expand 10 after
336 337
337 // ES6 section 26.1.7 Reflect.getPrototypeOf ( target ) 338 // ES6 section 26.1.7 Reflect.getPrototypeOf ( target )
338 Reduction JSCallReducer::ReduceReflectGetPrototypeOf(Node* node) { 339 Reduction JSCallReducer::ReduceReflectGetPrototypeOf(Node* node) {
339 DCHECK_EQ(IrOpcode::kJSCall, node->opcode()); 340 DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
340 Node* target = (node->op()->ValueInputCount() >= 3) 341 Node* target = (node->op()->ValueInputCount() >= 3)
341 ? NodeProperties::GetValueInput(node, 2) 342 ? NodeProperties::GetValueInput(node, 2)
342 : jsgraph()->UndefinedConstant(); 343 : jsgraph()->UndefinedConstant();
343 return ReduceObjectGetPrototype(node, target); 344 return ReduceObjectGetPrototype(node, target);
344 } 345 }
345 346
347 std::pair<Node*, Node*>
348 JSCallReducer::CreateJavaScriptBuiltinContinuationFrameState(
349 Handle<SharedFunctionInfo> shared, Builtins::Name name, Node* target,
350 Node* context, Node** stack_parameters, int stack_parameter_count,
351 Node* effect, Node* control, Node* outer_frame_state, CheckpointMode mode) {
352 BailoutId bailout_id = Builtins::GetContinuationBailoutId(name);
353 Callable callable = Builtins::CallableFor(isolate(), name);
354
355 // Lazy deopt points where the frame state is assocated with a call get an
356 // additional parameter for the return result from the call that's added by
357 // the deoptimizer and not explicitly specified in the frame state. Check that
358 // there is not a mismatch between the number of frame state parameters and
359 // the stack parameters required by the builtin taking this into account.
360 DCHECK_EQ(
361 Builtins::GetStackParameterCount(isolate(), name) + 1, // add receiver
362 stack_parameter_count + (mode == CREATE_CHECKPOINT ? 0 : 1));
363
364 NodeVector params(local_zone_);
365 // target
366 params.push_back(target);
367 // new target
368 params.push_back(jsgraph()->UndefinedConstant());
369 // argc, remove receiver and add in return value for lazy deopts from calls
370 params.push_back(jsgraph()->Constant(stack_parameter_count -
371 (mode == CREATE_CHECKPOINT ? 1 : 0)));
372 // context
373 params.push_back(context);
374
375 for (int i = 0; i < stack_parameter_count; ++i) {
376 params.push_back(stack_parameters[i]);
377 }
378
379 const Operator* op_param = common()->StateValues(
380 static_cast<int>(params.size()), SparseInputMask::Dense());
381 Node* params_node = graph()->NewNode(
382 op_param, static_cast<int>(params.size()), &params.front());
383
384 // Add the context to the total parameter count, it is implicit in the
385 // descriptor.
386 const int total_parameter_count =
387 stack_parameter_count +
388 callable.descriptor().GetRegisterParameterCount() + 1;
389 const FrameStateFunctionInfo* state_info =
390 common()->CreateFrameStateFunctionInfo(
391 FrameStateType::kBuiltinContinuation, total_parameter_count, 0,
392 shared);
393 const Operator* op = common()->FrameState(
394 bailout_id, OutputFrameStateCombine::Ignore(), state_info);
395 const Operator* op0 = common()->StateValues(0, SparseInputMask::Dense());
396 Node* node0 = graph()->NewNode(op0);
397
398 Node* frame_state = graph()->NewNode(op, params_node, node0, node0,
399 jsgraph()->UndefinedConstant(), target,
400 outer_frame_state);
401
402 return std::make_pair(
403 frame_state, mode == CREATE_CHECKPOINT
404 ? graph()->NewNode(common()->Checkpoint(), frame_state,
405 effect, control)
406 : effect);
407 }
408
409 Reduction JSCallReducer::ReduceArrayForEach(Handle<SharedFunctionInfo> shared,
410 Node* node) {
411 DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
412 Node* outer_frame_state = NodeProperties::GetFrameStateInput(node);
413 Node* effect = NodeProperties::GetEffectInput(node);
414 Node* control = NodeProperties::GetControlInput(node);
415 Node* context = NodeProperties::GetContextInput(node);
416
417 // Try to determine the {receiver} map.
418 Node* receiver = NodeProperties::GetValueInput(node, 1);
419 Node* fncallback = node->op()->ValueInputCount() > 2
420 ? NodeProperties::GetValueInput(node, 2)
421 : jsgraph()->UndefinedConstant();
422 Node* this_arg = node->op()->ValueInputCount() > 3
423 ? NodeProperties::GetValueInput(node, 3)
424 : jsgraph()->UndefinedConstant();
425 ZoneHandleSet<Map> receiver_maps;
426 if (!NodeProperties::InferReceiverMaps(receiver, effect, &receiver_maps)) {
427 return NoChange();
428 }
429 if (receiver_maps.size() != 1) return NoChange();
430 Handle<Map> receiver_map(receiver_maps[0]);
431 ElementsKind kind = receiver_map->elements_kind();
432 // TODO(danno): Handle holey Smi and Object fast elements kinds and double
433 // packed.
434 if (!IsFastPackedElementsKind(kind) || IsFastDoubleElementsKind(kind)) {
435 return NoChange();
436 }
437
438 Node* k = jsgraph()->Constant(0);
439
440 Node* original_length = graph()->NewNode(
441 simplified()->LoadField(AccessBuilder::ForJSArrayLength(FAST_ELEMENTS)),
442 receiver, effect, control);
443
444 Node* loop = control = graph()->NewNode(common()->Loop(2), control, control);
445 Node* eloop = effect =
446 graph()->NewNode(common()->EffectPhi(2), effect, effect, loop);
447 Node* vloop = k = graph()->NewNode(
448 common()->Phi(MachineRepresentation::kTagged, 2), k, k, loop);
449
450 control = loop;
451 effect = eloop;
452
453 Node* continue_test =
454 graph()->NewNode(simplified()->NumberLessThan(), k, original_length);
455 Node* continue_branch = graph()->NewNode(common()->Branch(BranchHint::kTrue),
456 continue_test, control);
457
458 Node* if_true = graph()->NewNode(common()->IfTrue(), continue_branch);
459 Node* if_false = graph()->NewNode(common()->IfFalse(), continue_branch);
460 control = if_true;
461
462 NodeVector checkpoint_params(local_zone_);
463 checkpoint_params.push_back(receiver);
464 checkpoint_params.push_back(fncallback);
465 checkpoint_params.push_back(this_arg);
466 checkpoint_params.push_back(k);
467 checkpoint_params.push_back(original_length);
468 const int stack_parameters = static_cast<int>(checkpoint_params.size());
469
470 Node* frame_state;
471 std::tie(frame_state, effect) = CreateJavaScriptBuiltinContinuationFrameState(
472 shared, Builtins::kArrayForEachLoopEagerDeoptContinuation,
473 node->InputAt(0), context, &checkpoint_params[0], stack_parameters,
474 effect, control, outer_frame_state, CREATE_CHECKPOINT);
475
476 // Make sure the map hasn't changed during the iteration
477 Node* orig_map = jsgraph()->HeapConstant(receiver_map);
478 Node* array_map = effect =
479 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
480 receiver, effect, control);
481 Node* check_map =
482 graph()->NewNode(simplified()->ReferenceEqual(), array_map, orig_map);
483 effect =
484 graph()->NewNode(simplified()->CheckIf(), check_map, effect, control);
485
486 // Make sure that the access is still in bounds, since the callback could have
487 // changed the array's size.
488 Node* length = graph()->NewNode(
489 simplified()->LoadField(AccessBuilder::ForJSArrayLength(FAST_ELEMENTS)),
490 receiver, effect, control);
491 k = effect =
492 graph()->NewNode(simplified()->CheckBounds(), k, length, effect, control);
493 USE(length);
494
495 // Reload the elements pointer before calling the callback, since the previous
496 // callback might have resized the array causing the elements buffer to be
497 // re-allocated.
498 Node* elements = graph()->NewNode(
499 simplified()->LoadField(AccessBuilder::ForJSObjectElements()), receiver,
500 effect, control);
501
502 Node* element = graph()->NewNode(
503 simplified()->LoadElement(AccessBuilder::ForFixedArrayElement()),
504 elements, k, effect, control);
505
506 Node* next_k =
507 graph()->NewNode(simplified()->NumberAdd(), k, jsgraph()->Constant(1));
508 checkpoint_params[3] = next_k;
509 std::tie(frame_state, effect) = CreateJavaScriptBuiltinContinuationFrameState(
510 shared, Builtins::kArrayForEachLoopLazyDeoptContinuation,
511 node->InputAt(0), context, &checkpoint_params[0], stack_parameters,
512 effect, control, outer_frame_state, DONT_CREATE_CHECKPOINT);
513
514 Node* call_back = control = effect =
515 graph()->NewNode(javascript()->Call(5, 1), fncallback, this_arg, element,
516 k, receiver, context, frame_state, effect, control);
517 USE(call_back);
518 USE(this_arg);
519
520 k = next_k;
521
522 loop->ReplaceInput(1, control);
523 vloop->ReplaceInput(1, k);
524 eloop->ReplaceInput(1, effect);
525
526 control = if_false;
527 effect = eloop;
528
529 NodeProperties::ReplaceUses(node, jsgraph()->UndefinedConstant(), effect,
530 control);
531
532 node->TrimInputCount(0);
533 NodeProperties::ChangeOp(node, common()->Dead());
534 return Changed(node);
535 }
536
346 Reduction JSCallReducer::ReduceCallApiFunction( 537 Reduction JSCallReducer::ReduceCallApiFunction(
347 Node* node, Handle<FunctionTemplateInfo> function_template_info) { 538 Node* node, Handle<FunctionTemplateInfo> function_template_info) {
348 DCHECK_EQ(IrOpcode::kJSCall, node->opcode()); 539 DCHECK_EQ(IrOpcode::kJSCall, node->opcode());
349 CallParameters const& p = CallParametersOf(node->op()); 540 CallParameters const& p = CallParametersOf(node->op());
350 int const argc = static_cast<int>(p.arity()) - 2; 541 int const argc = static_cast<int>(p.arity()) - 2;
351 Node* receiver = (p.convert_mode() == ConvertReceiverMode::kNullOrUndefined) 542 Node* receiver = (p.convert_mode() == ConvertReceiverMode::kNullOrUndefined)
352 ? jsgraph()->HeapConstant(global_proxy()) 543 ? jsgraph()->HeapConstant(global_proxy())
353 : NodeProperties::GetValueInput(node, 1); 544 : NodeProperties::GetValueInput(node, 1);
354 Node* effect = NodeProperties::GetEffectInput(node); 545 Node* effect = NodeProperties::GetEffectInput(node);
355 546
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after
568 case Builtins::kFunctionPrototypeHasInstance: 759 case Builtins::kFunctionPrototypeHasInstance:
569 return ReduceFunctionPrototypeHasInstance(node); 760 return ReduceFunctionPrototypeHasInstance(node);
570 case Builtins::kNumberConstructor: 761 case Builtins::kNumberConstructor:
571 return ReduceNumberConstructor(node); 762 return ReduceNumberConstructor(node);
572 case Builtins::kObjectGetPrototypeOf: 763 case Builtins::kObjectGetPrototypeOf:
573 return ReduceObjectGetPrototypeOf(node); 764 return ReduceObjectGetPrototypeOf(node);
574 case Builtins::kObjectPrototypeGetProto: 765 case Builtins::kObjectPrototypeGetProto:
575 return ReduceObjectPrototypeGetProto(node); 766 return ReduceObjectPrototypeGetProto(node);
576 case Builtins::kReflectGetPrototypeOf: 767 case Builtins::kReflectGetPrototypeOf:
577 return ReduceReflectGetPrototypeOf(node); 768 return ReduceReflectGetPrototypeOf(node);
769 case Builtins::kArrayForEach:
770 return ReduceArrayForEach(shared, node);
578 default: 771 default:
579 break; 772 break;
580 } 773 }
581 774
582 // Check for the Array constructor. 775 // Check for the Array constructor.
583 if (*function == function->native_context()->array_function()) { 776 if (*function == function->native_context()->array_function()) {
584 return ReduceArrayConstructor(node); 777 return ReduceArrayConstructor(node);
585 } 778 }
586 779
587 if (!FLAG_runtime_stats && shared->IsApiFunction()) { 780 if (!FLAG_runtime_stats && shared->IsApiFunction()) {
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after
851 return jsgraph()->javascript(); 1044 return jsgraph()->javascript();
852 } 1045 }
853 1046
854 SimplifiedOperatorBuilder* JSCallReducer::simplified() const { 1047 SimplifiedOperatorBuilder* JSCallReducer::simplified() const {
855 return jsgraph()->simplified(); 1048 return jsgraph()->simplified();
856 } 1049 }
857 1050
858 } // namespace compiler 1051 } // namespace compiler
859 } // namespace internal 1052 } // namespace internal
860 } // namespace v8 1053 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/js-call-reducer.h ('k') | src/compiler/pipeline.cc » ('j') | src/deoptimizer.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698