OLD | NEW |
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/compiler/ast-graph-builder.h" | 5 #include "src/compiler/ast-graph-builder.h" |
6 | 6 |
7 #include "src/compiler.h" | 7 #include "src/compiler.h" |
8 #include "src/compiler/ast-loop-assignment-analyzer.h" | 8 #include "src/compiler/ast-loop-assignment-analyzer.h" |
9 #include "src/compiler/control-builders.h" | 9 #include "src/compiler/control-builders.h" |
10 #include "src/compiler/linkage.h" | 10 #include "src/compiler/linkage.h" |
(...skipping 3313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3324 const VectorSlotPair& feedback, | 3324 const VectorSlotPair& feedback, |
3325 OutputFrameStateCombine combine, | 3325 OutputFrameStateCombine combine, |
3326 TypeofMode typeof_mode) { | 3326 TypeofMode typeof_mode) { |
3327 Node* the_hole = jsgraph()->TheHoleConstant(); | 3327 Node* the_hole = jsgraph()->TheHoleConstant(); |
3328 VariableMode mode = variable->mode(); | 3328 VariableMode mode = variable->mode(); |
3329 switch (variable->location()) { | 3329 switch (variable->location()) { |
3330 case VariableLocation::GLOBAL: | 3330 case VariableLocation::GLOBAL: |
3331 case VariableLocation::UNALLOCATED: { | 3331 case VariableLocation::UNALLOCATED: { |
3332 // Global var, const, or let variable. | 3332 // Global var, const, or let variable. |
3333 Handle<Name> name = variable->name(); | 3333 Handle<Name> name = variable->name(); |
3334 Handle<Object> constant_value = | 3334 if (Node* node = TryLoadGlobalConstant(name)) return node; |
3335 jsgraph()->isolate()->factory()->GlobalConstantFor(name); | |
3336 if (!constant_value.is_null()) { | |
3337 // Optimize global constants like "undefined", "Infinity", and "NaN". | |
3338 return jsgraph()->Constant(constant_value); | |
3339 } | |
3340 Node* value = BuildGlobalLoad(name, feedback, typeof_mode); | 3335 Node* value = BuildGlobalLoad(name, feedback, typeof_mode); |
3341 states.AddToNode(value, bailout_id, combine); | 3336 states.AddToNode(value, bailout_id, combine); |
3342 return value; | 3337 return value; |
3343 } | 3338 } |
3344 case VariableLocation::PARAMETER: | 3339 case VariableLocation::PARAMETER: |
3345 case VariableLocation::LOCAL: { | 3340 case VariableLocation::LOCAL: { |
3346 // Local var, const, or let variable. | 3341 // Local var, const, or let variable. |
3347 Node* value = environment()->Lookup(variable); | 3342 Node* value = environment()->Lookup(variable); |
3348 if (mode == CONST_LEGACY) { | 3343 if (mode == CONST_LEGACY) { |
3349 // Perform check for uninitialized legacy const variables. | 3344 // Perform check for uninitialized legacy const variables. |
(...skipping 397 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3747 Node* AstGraphBuilder::BuildStoreExternal(ExternalReference reference, | 3742 Node* AstGraphBuilder::BuildStoreExternal(ExternalReference reference, |
3748 MachineType type, Node* value) { | 3743 MachineType type, Node* value) { |
3749 StoreRepresentation representation(type, kNoWriteBarrier); | 3744 StoreRepresentation representation(type, kNoWriteBarrier); |
3750 return NewNode(jsgraph()->machine()->Store(representation), | 3745 return NewNode(jsgraph()->machine()->Store(representation), |
3751 jsgraph()->ExternalConstant(reference), | 3746 jsgraph()->ExternalConstant(reference), |
3752 jsgraph()->IntPtrConstant(0), value); | 3747 jsgraph()->IntPtrConstant(0), value); |
3753 } | 3748 } |
3754 | 3749 |
3755 | 3750 |
3756 Node* AstGraphBuilder::BuildToBoolean(Node* input) { | 3751 Node* AstGraphBuilder::BuildToBoolean(Node* input) { |
3757 // TODO(bmeurer, mstarzinger): Refactor this into a separate optimization | 3752 if (Node* node = TryFastToBoolean(input)) return node; |
3758 // method. | |
3759 switch (input->opcode()) { | |
3760 case IrOpcode::kNumberConstant: { | |
3761 NumberMatcher m(input); | |
3762 return jsgraph_->BooleanConstant(!m.Is(0) && !m.IsNaN()); | |
3763 } | |
3764 case IrOpcode::kHeapConstant: { | |
3765 Handle<HeapObject> object = HeapObjectMatcher(input).Value(); | |
3766 return jsgraph_->BooleanConstant(object->BooleanValue()); | |
3767 } | |
3768 case IrOpcode::kJSEqual: | |
3769 case IrOpcode::kJSNotEqual: | |
3770 case IrOpcode::kJSStrictEqual: | |
3771 case IrOpcode::kJSStrictNotEqual: | |
3772 case IrOpcode::kJSLessThan: | |
3773 case IrOpcode::kJSLessThanOrEqual: | |
3774 case IrOpcode::kJSGreaterThan: | |
3775 case IrOpcode::kJSGreaterThanOrEqual: | |
3776 case IrOpcode::kJSUnaryNot: | |
3777 case IrOpcode::kJSToBoolean: | |
3778 case IrOpcode::kJSDeleteProperty: | |
3779 case IrOpcode::kJSHasProperty: | |
3780 case IrOpcode::kJSInstanceOf: | |
3781 return input; | |
3782 default: | |
3783 break; | |
3784 } | |
3785 return NewNode(javascript()->ToBoolean(), input); | 3753 return NewNode(javascript()->ToBoolean(), input); |
3786 } | 3754 } |
3787 | 3755 |
3788 | 3756 |
3789 Node* AstGraphBuilder::BuildToName(Node* input, BailoutId bailout_id) { | 3757 Node* AstGraphBuilder::BuildToName(Node* input, BailoutId bailout_id) { |
3790 // TODO(turbofan): Possible optimization is to NOP on name constants. But the | 3758 if (Node* node = TryFastToName(input)) return node; |
3791 // same caveat as with BuildToBoolean applies, and it should be factored out | |
3792 // into a JSOperatorReducer. | |
3793 Node* name = NewNode(javascript()->ToName(), input); | 3759 Node* name = NewNode(javascript()->ToName(), input); |
3794 PrepareFrameState(name, bailout_id); | 3760 PrepareFrameState(name, bailout_id); |
3795 return name; | 3761 return name; |
3796 } | 3762 } |
3797 | 3763 |
3798 | 3764 |
3799 Node* AstGraphBuilder::BuildToObject(Node* input, BailoutId bailout_id) { | 3765 Node* AstGraphBuilder::BuildToObject(Node* input, BailoutId bailout_id) { |
3800 Node* object = NewNode(javascript()->ToObject(), input); | 3766 Node* object = NewNode(javascript()->ToObject(), input); |
3801 PrepareFrameState(object, bailout_id, OutputFrameStateCombine::Push()); | 3767 PrepareFrameState(object, bailout_id, OutputFrameStateCombine::Push()); |
3802 return object; | 3768 return object; |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3926 js_op = javascript()->Modulus(language_mode()); | 3892 js_op = javascript()->Modulus(language_mode()); |
3927 break; | 3893 break; |
3928 default: | 3894 default: |
3929 UNREACHABLE(); | 3895 UNREACHABLE(); |
3930 js_op = NULL; | 3896 js_op = NULL; |
3931 } | 3897 } |
3932 return NewNode(js_op, left, right); | 3898 return NewNode(js_op, left, right); |
3933 } | 3899 } |
3934 | 3900 |
3935 | 3901 |
| 3902 Node* AstGraphBuilder::TryLoadGlobalConstant(Handle<Name> name) { |
| 3903 // Optimize global constants like "undefined", "Infinity", and "NaN". |
| 3904 Handle<Object> constant_value = isolate()->factory()->GlobalConstantFor(name); |
| 3905 if (!constant_value.is_null()) return jsgraph()->Constant(constant_value); |
| 3906 return nullptr; |
| 3907 } |
| 3908 |
| 3909 |
| 3910 Node* AstGraphBuilder::TryFastToBoolean(Node* input) { |
| 3911 switch (input->opcode()) { |
| 3912 case IrOpcode::kNumberConstant: { |
| 3913 NumberMatcher m(input); |
| 3914 return jsgraph_->BooleanConstant(!m.Is(0) && !m.IsNaN()); |
| 3915 } |
| 3916 case IrOpcode::kHeapConstant: { |
| 3917 Handle<HeapObject> object = HeapObjectMatcher(input).Value(); |
| 3918 return jsgraph_->BooleanConstant(object->BooleanValue()); |
| 3919 } |
| 3920 case IrOpcode::kJSEqual: |
| 3921 case IrOpcode::kJSNotEqual: |
| 3922 case IrOpcode::kJSStrictEqual: |
| 3923 case IrOpcode::kJSStrictNotEqual: |
| 3924 case IrOpcode::kJSLessThan: |
| 3925 case IrOpcode::kJSLessThanOrEqual: |
| 3926 case IrOpcode::kJSGreaterThan: |
| 3927 case IrOpcode::kJSGreaterThanOrEqual: |
| 3928 case IrOpcode::kJSUnaryNot: |
| 3929 case IrOpcode::kJSToBoolean: |
| 3930 case IrOpcode::kJSDeleteProperty: |
| 3931 case IrOpcode::kJSHasProperty: |
| 3932 case IrOpcode::kJSInstanceOf: |
| 3933 return input; |
| 3934 default: |
| 3935 break; |
| 3936 } |
| 3937 return nullptr; |
| 3938 } |
| 3939 |
| 3940 |
| 3941 Node* AstGraphBuilder::TryFastToName(Node* input) { |
| 3942 switch (input->opcode()) { |
| 3943 case IrOpcode::kHeapConstant: { |
| 3944 Handle<HeapObject> object = HeapObjectMatcher(input).Value(); |
| 3945 if (object->IsName()) return input; |
| 3946 break; |
| 3947 } |
| 3948 case IrOpcode::kJSToString: |
| 3949 case IrOpcode::kJSToName: |
| 3950 case IrOpcode::kJSTypeOf: |
| 3951 return input; |
| 3952 default: |
| 3953 break; |
| 3954 } |
| 3955 return nullptr; |
| 3956 } |
| 3957 |
| 3958 |
3936 bool AstGraphBuilder::CheckOsrEntry(IterationStatement* stmt) { | 3959 bool AstGraphBuilder::CheckOsrEntry(IterationStatement* stmt) { |
3937 if (info()->osr_ast_id() == stmt->OsrEntryId()) { | 3960 if (info()->osr_ast_id() == stmt->OsrEntryId()) { |
3938 info()->set_osr_expr_stack_height(std::max( | 3961 info()->set_osr_expr_stack_height(std::max( |
3939 environment()->stack_height(), info()->osr_expr_stack_height())); | 3962 environment()->stack_height(), info()->osr_expr_stack_height())); |
3940 return true; | 3963 return true; |
3941 } | 3964 } |
3942 return false; | 3965 return false; |
3943 } | 3966 } |
3944 | 3967 |
3945 | 3968 |
(...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4259 // Phi does not exist yet, introduce one. | 4282 // Phi does not exist yet, introduce one. |
4260 value = NewPhi(inputs, value, control); | 4283 value = NewPhi(inputs, value, control); |
4261 value->ReplaceInput(inputs - 1, other); | 4284 value->ReplaceInput(inputs - 1, other); |
4262 } | 4285 } |
4263 return value; | 4286 return value; |
4264 } | 4287 } |
4265 | 4288 |
4266 } // namespace compiler | 4289 } // namespace compiler |
4267 } // namespace internal | 4290 } // namespace internal |
4268 } // namespace v8 | 4291 } // namespace v8 |
OLD | NEW |