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

Side by Side Diff: src/compiler/js-generic-lowering.cc

Issue 1160983004: [turbofan] First step towards sanitizing for-in and making it optimizable. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Add some comments. Created 5 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/control-builders.cc ('k') | src/compiler/js-operator.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 2014 the V8 project authors. All rights reserved. 1 // Copyright 2014 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/code-factory.h" 5 #include "src/code-factory.h"
6 #include "src/code-stubs.h" 6 #include "src/code-stubs.h"
7 #include "src/compiler/common-operator.h" 7 #include "src/compiler/common-operator.h"
8 #include "src/compiler/js-generic-lowering.h" 8 #include "src/compiler/js-generic-lowering.h"
9 #include "src/compiler/js-graph.h" 9 #include "src/compiler/js-graph.h"
10 #include "src/compiler/machine-operator.h" 10 #include "src/compiler/machine-operator.h"
(...skipping 540 matching lines...) Expand 10 before | Expand all | Expand 10 after
551 node->set_op(common()->Call(desc)); 551 node->set_op(common()->Call(desc));
552 } 552 }
553 553
554 554
555 void JSGenericLowering::LowerJSCallRuntime(Node* node) { 555 void JSGenericLowering::LowerJSCallRuntime(Node* node) {
556 const CallRuntimeParameters& p = CallRuntimeParametersOf(node->op()); 556 const CallRuntimeParameters& p = CallRuntimeParametersOf(node->op());
557 ReplaceWithRuntimeCall(node, p.id(), static_cast<int>(p.arity())); 557 ReplaceWithRuntimeCall(node, p.id(), static_cast<int>(p.arity()));
558 } 558 }
559 559
560 560
561 void JSGenericLowering::LowerJSForInDone(Node* node) {
562 ReplaceWithRuntimeCall(node, Runtime::kForInDone);
563 }
564
565
566 void JSGenericLowering::LowerJSForInNext(Node* node) {
567 ReplaceWithRuntimeCall(node, Runtime::kForInNext);
568 }
569
570
571 void JSGenericLowering::LowerJSForInPrepare(Node* node) {
572 Node* object = NodeProperties::GetValueInput(node, 0);
573 Node* context = NodeProperties::GetContextInput(node);
574 Node* effect = NodeProperties::GetEffectInput(node);
575 Node* control = NodeProperties::GetControlInput(node);
576 Node* frame_state = NodeProperties::GetFrameStateInput(node, 0);
577
578 // Get the set of properties to enumerate.
579 Runtime::Function const* function =
580 Runtime::FunctionForId(Runtime::kGetPropertyNamesFast);
581 CallDescriptor const* descriptor = Linkage::GetRuntimeCallDescriptor(
582 zone(), function->function_id, 1, Operator::kNoProperties);
583 Node* cache_type = effect = graph()->NewNode(
584 common()->Call(descriptor),
585 jsgraph()->CEntryStubConstant(function->result_size), object,
586 jsgraph()->ExternalConstant(
587 ExternalReference(function->function_id, isolate())),
588 jsgraph()->Int32Constant(1), context, frame_state, effect, control);
589 control = graph()->NewNode(common()->IfSuccess(), cache_type);
590
591 Node* object_map = effect = graph()->NewNode(
592 machine()->Load(kMachAnyTagged), object,
593 jsgraph()->IntPtrConstant(HeapObject::kMapOffset - kHeapObjectTag),
594 effect, control);
595 Node* cache_type_map = effect = graph()->NewNode(
596 machine()->Load(kMachAnyTagged), cache_type,
597 jsgraph()->IntPtrConstant(HeapObject::kMapOffset - kHeapObjectTag),
598 effect, control);
599 Node* meta_map = jsgraph()->HeapConstant(isolate()->factory()->meta_map());
600
601 // If we got a map from the GetPropertyNamesFast runtime call, we can do a
602 // fast modification check. Otherwise, we got a fixed array, and we have to
603 // perform a slow check on every iteration.
604 Node* check0 =
605 graph()->NewNode(machine()->WordEqual(), cache_type_map, meta_map);
606 Node* branch0 =
607 graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control);
608
609 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
610 Node* cache_array_true0;
611 Node* cache_length_true0;
612 Node* cache_type_true0;
613 Node* etrue0;
614 {
615 // Enum cache case.
616 Node* cache_type_enum_length = etrue0 = graph()->NewNode(
617 machine()->Load(kMachUint32), cache_type,
618 jsgraph()->IntPtrConstant(Map::kBitField3Offset - kHeapObjectTag),
619 effect, if_true0);
620 cache_type_enum_length =
621 graph()->NewNode(machine()->Word32And(), cache_type_enum_length,
622 jsgraph()->Uint32Constant(Map::EnumLengthBits::kMask));
623
624 Node* check1 =
625 graph()->NewNode(machine()->Word32Equal(), cache_type_enum_length,
626 jsgraph()->Int32Constant(0));
627 Node* branch1 =
628 graph()->NewNode(common()->Branch(BranchHint::kTrue), check1, if_true0);
629
630 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
631 Node* cache_array_true1;
632 Node* etrue1;
633 {
634 // No properties to enumerate.
635 cache_array_true1 =
636 jsgraph()->HeapConstant(isolate()->factory()->empty_fixed_array());
637 etrue1 = etrue0;
638 }
639
640 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
641 Node* cache_array_false1;
642 Node* efalse1;
643 {
644 // Load the enumeration cache from the instance descriptors of {object}.
645 Node* object_map_descriptors = efalse1 = graph()->NewNode(
646 machine()->Load(kMachAnyTagged), object_map,
647 jsgraph()->IntPtrConstant(Map::kDescriptorsOffset - kHeapObjectTag),
648 etrue0, if_false1);
649 Node* object_map_enum_cache = efalse1 = graph()->NewNode(
650 machine()->Load(kMachAnyTagged), object_map_descriptors,
651 jsgraph()->IntPtrConstant(DescriptorArray::kEnumCacheOffset -
652 kHeapObjectTag),
653 efalse1, if_false1);
654 cache_array_false1 = efalse1 = graph()->NewNode(
655 machine()->Load(kMachAnyTagged), object_map_enum_cache,
656 jsgraph()->IntPtrConstant(
657 DescriptorArray::kEnumCacheBridgeCacheOffset - kHeapObjectTag),
658 efalse1, if_false1);
659 }
660
661 if_true0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
662 etrue0 =
663 graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_true0);
664 cache_array_true0 =
665 graph()->NewNode(common()->Phi(kMachAnyTagged, 2), cache_array_true1,
666 cache_array_false1, if_true0);
667
668 cache_length_true0 = graph()->NewNode(
669 machine()->WordShl(),
670 machine()->Is64()
671 ? graph()->NewNode(machine()->ChangeUint32ToUint64(),
672 cache_type_enum_length)
673 : cache_type_enum_length,
674 jsgraph()->Int32Constant(kSmiShiftSize + kSmiTagSize));
675 cache_type_true0 = cache_type;
676 }
677
678 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
679 Node* cache_array_false0;
680 Node* cache_length_false0;
681 Node* cache_type_false0;
682 Node* efalse0;
683 {
684 // FixedArray case.
685 Node* object_instance_type = efalse0 = graph()->NewNode(
686 machine()->Load(kMachUint8), object_map,
687 jsgraph()->IntPtrConstant(Map::kInstanceTypeOffset - kHeapObjectTag),
688 effect, if_false0);
689
690 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
691 Node* check1 = graph()->NewNode(
692 machine()->Uint32LessThanOrEqual(), object_instance_type,
693 jsgraph()->Uint32Constant(LAST_JS_PROXY_TYPE));
694 Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
695 check1, if_false0);
696
697 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
698 Node* cache_type_true1 = jsgraph()->ZeroConstant(); // Zero indicates proxy
699
700 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
701 Node* cache_type_false1 = jsgraph()->OneConstant(); // One means slow check
702
703 if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
704 cache_type_false0 =
705 graph()->NewNode(common()->Phi(kMachAnyTagged, 2), cache_type_true1,
706 cache_type_false1, if_false0);
707
708 cache_array_false0 = cache_type;
709 cache_length_false0 = efalse0 = graph()->NewNode(
710 machine()->Load(kMachAnyTagged), cache_array_false0,
711 jsgraph()->IntPtrConstant(FixedArray::kLengthOffset - kHeapObjectTag),
712 efalse0, if_false0);
713 }
714
715 control = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
716 effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control);
717 Node* cache_array =
718 graph()->NewNode(common()->Phi(kMachAnyTagged, 2), cache_array_true0,
719 cache_array_false0, control);
720 Node* cache_length =
721 graph()->NewNode(common()->Phi(kMachAnyTagged, 2), cache_length_true0,
722 cache_length_false0, control);
723 cache_type = graph()->NewNode(common()->Phi(kMachAnyTagged, 2),
724 cache_type_true0, cache_type_false0, control);
725
726 for (auto edge : node->use_edges()) {
727 if (NodeProperties::IsEffectEdge(edge)) {
728 edge.UpdateTo(effect);
729 } else if (NodeProperties::IsControlEdge(edge)) {
730 Node* const use = edge.from();
731 DCHECK_EQ(IrOpcode::kIfSuccess, use->opcode());
732 use->ReplaceUses(control);
733 use->Kill();
734 } else {
735 Node* const use = edge.from();
736 DCHECK(NodeProperties::IsValueEdge(edge));
737 DCHECK_EQ(IrOpcode::kProjection, use->opcode());
738 switch (ProjectionIndexOf(use->op())) {
739 case 0:
740 use->ReplaceUses(cache_type);
741 break;
742 case 1:
743 use->ReplaceUses(cache_array);
744 break;
745 case 2:
746 use->ReplaceUses(cache_length);
747 break;
748 default:
749 UNREACHABLE();
750 break;
751 }
752 use->Kill();
753 }
754 }
755 }
756
757
758 void JSGenericLowering::LowerJSForInStep(Node* node) {
759 ReplaceWithRuntimeCall(node, Runtime::kForInStep);
760 }
761
762
561 void JSGenericLowering::LowerJSStackCheck(Node* node) { 763 void JSGenericLowering::LowerJSStackCheck(Node* node) {
562 Node* effect = NodeProperties::GetEffectInput(node); 764 Node* effect = NodeProperties::GetEffectInput(node);
563 Node* control = NodeProperties::GetControlInput(node); 765 Node* control = NodeProperties::GetControlInput(node);
564 766
565 Node* limit = graph()->NewNode( 767 Node* limit = graph()->NewNode(
566 machine()->Load(kMachPtr), 768 machine()->Load(kMachPtr),
567 jsgraph()->ExternalConstant( 769 jsgraph()->ExternalConstant(
568 ExternalReference::address_of_stack_limit(isolate())), 770 ExternalReference::address_of_stack_limit(isolate())),
569 jsgraph()->IntPtrConstant(0), effect, control); 771 jsgraph()->IntPtrConstant(0), effect, control);
570 Node* pointer = graph()->NewNode(machine()->LoadStackPointer()); 772 Node* pointer = graph()->NewNode(machine()->LoadStackPointer());
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
606 } 808 }
607 809
608 810
609 MachineOperatorBuilder* JSGenericLowering::machine() const { 811 MachineOperatorBuilder* JSGenericLowering::machine() const {
610 return jsgraph()->machine(); 812 return jsgraph()->machine();
611 } 813 }
612 814
613 } // namespace compiler 815 } // namespace compiler
614 } // namespace internal 816 } // namespace internal
615 } // namespace v8 817 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/control-builders.cc ('k') | src/compiler/js-operator.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698