| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/flow_graph_builder.h" | 5 #include "vm/flow_graph_builder.h" |
| 6 | 6 |
| 7 #include "lib/invocation_mirror.h" | 7 #include "lib/invocation_mirror.h" |
| 8 #include "vm/ast_printer.h" | 8 #include "vm/ast_printer.h" |
| 9 #include "vm/bit_vector.h" | 9 #include "vm/bit_vector.h" |
| 10 #include "vm/class_finalizer.h" | 10 #include "vm/class_finalizer.h" |
| (...skipping 415 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 426 call_block->try_index()); | 426 call_block->try_index()); |
| 427 false_block->InheritDeoptTargetAfter(call_); | 427 false_block->InheritDeoptTargetAfter(call_); |
| 428 false_block->LinkTo(call_->next()); | 428 false_block->LinkTo(call_->next()); |
| 429 call_block->ReplaceAsPredecessorWith(false_block); | 429 call_block->ReplaceAsPredecessorWith(false_block); |
| 430 | 430 |
| 431 ConstantInstr* true_const = caller_graph_->GetConstant(Bool::True()); | 431 ConstantInstr* true_const = caller_graph_->GetConstant(Bool::True()); |
| 432 BranchInstr* branch = | 432 BranchInstr* branch = |
| 433 new BranchInstr(new StrictCompareInstr(call_block->start_pos(), | 433 new BranchInstr(new StrictCompareInstr(call_block->start_pos(), |
| 434 Token::kEQ_STRICT, | 434 Token::kEQ_STRICT, |
| 435 new Value(true_const), | 435 new Value(true_const), |
| 436 new Value(true_const))); | 436 new Value(true_const), |
| 437 false)); // No number check. |
| 437 branch->InheritDeoptTarget(call_); | 438 branch->InheritDeoptTarget(call_); |
| 438 *branch->true_successor_address() = callee_entry; | 439 *branch->true_successor_address() = callee_entry; |
| 439 *branch->false_successor_address() = false_block; | 440 *branch->false_successor_address() = false_block; |
| 440 | 441 |
| 441 call_->previous()->AppendInstruction(branch); | 442 call_->previous()->AppendInstruction(branch); |
| 442 call_block->set_last_instruction(branch); | 443 call_block->set_last_instruction(branch); |
| 443 | 444 |
| 444 // Update dominator tree. | 445 // Update dominator tree. |
| 445 call_block->AddDominatedBlock(callee_entry); | 446 call_block->AddDominatedBlock(callee_entry); |
| 446 call_block->AddDominatedBlock(false_block); | 447 call_block->AddDominatedBlock(false_block); |
| (...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 826 | 827 |
| 827 void TestGraphVisitor::ReturnValue(Value* value) { | 828 void TestGraphVisitor::ReturnValue(Value* value) { |
| 828 if (FLAG_enable_type_checks) { | 829 if (FLAG_enable_type_checks) { |
| 829 value = Bind(new AssertBooleanInstr(condition_token_pos(), value)); | 830 value = Bind(new AssertBooleanInstr(condition_token_pos(), value)); |
| 830 } | 831 } |
| 831 Value* constant_true = Bind(new ConstantInstr(Bool::True())); | 832 Value* constant_true = Bind(new ConstantInstr(Bool::True())); |
| 832 StrictCompareInstr* comp = | 833 StrictCompareInstr* comp = |
| 833 new StrictCompareInstr(condition_token_pos(), | 834 new StrictCompareInstr(condition_token_pos(), |
| 834 Token::kEQ_STRICT, | 835 Token::kEQ_STRICT, |
| 835 value, | 836 value, |
| 836 constant_true); | 837 constant_true, |
| 837 comp->set_needs_number_check(false); | 838 false); // No number check. |
| 838 BranchInstr* branch = new BranchInstr(comp); | 839 BranchInstr* branch = new BranchInstr(comp); |
| 839 AddInstruction(branch); | 840 AddInstruction(branch); |
| 840 CloseFragment(); | 841 CloseFragment(); |
| 841 | 842 |
| 842 true_successor_addresses_.Add(branch->true_successor_address()); | 843 true_successor_addresses_.Add(branch->true_successor_address()); |
| 843 false_successor_addresses_.Add(branch->false_successor_address()); | 844 false_successor_addresses_.Add(branch->false_successor_address()); |
| 844 } | 845 } |
| 845 | 846 |
| 846 | 847 |
| 847 void TestGraphVisitor::MergeBranchWithComparison(ComparisonInstr* comp) { | 848 void TestGraphVisitor::MergeBranchWithComparison(ComparisonInstr* comp) { |
| 848 BranchInstr* branch; | 849 BranchInstr* branch; |
| 849 if (Token::IsStrictEqualityOperator(comp->kind())) { | 850 if (Token::IsStrictEqualityOperator(comp->kind())) { |
| 850 ASSERT(comp->IsStrictCompare()); | 851 ASSERT(comp->IsStrictCompare()); |
| 851 branch = new BranchInstr(comp); | 852 branch = new BranchInstr(comp); |
| 852 } else if (Token::IsEqualityOperator(comp->kind()) && | 853 } else if (Token::IsEqualityOperator(comp->kind()) && |
| 853 (comp->left()->BindsToConstantNull() || | 854 (comp->left()->BindsToConstantNull() || |
| 854 comp->right()->BindsToConstantNull())) { | 855 comp->right()->BindsToConstantNull())) { |
| 855 branch = new BranchInstr(new StrictCompareInstr( | 856 branch = new BranchInstr(new StrictCompareInstr( |
| 856 comp->token_pos(), | 857 comp->token_pos(), |
| 857 (comp->kind() == Token::kEQ) ? Token::kEQ_STRICT : Token::kNE_STRICT, | 858 (comp->kind() == Token::kEQ) ? Token::kEQ_STRICT : Token::kNE_STRICT, |
| 858 comp->left(), | 859 comp->left(), |
| 859 comp->right())); | 860 comp->right(), |
| 861 false)); // No number check. |
| 860 } else { | 862 } else { |
| 861 branch = new BranchInstr(comp, FLAG_enable_type_checks); | 863 branch = new BranchInstr(comp, FLAG_enable_type_checks); |
| 862 } | 864 } |
| 863 AddInstruction(branch); | 865 AddInstruction(branch); |
| 864 CloseFragment(); | 866 CloseFragment(); |
| 865 true_successor_addresses_.Add(branch->true_successor_address()); | 867 true_successor_addresses_.Add(branch->true_successor_address()); |
| 866 false_successor_addresses_.Add(branch->false_successor_address()); | 868 false_successor_addresses_.Add(branch->false_successor_address()); |
| 867 } | 869 } |
| 868 | 870 |
| 869 | 871 |
| 870 void TestGraphVisitor::MergeBranchWithNegate(BooleanNegateInstr* neg) { | 872 void TestGraphVisitor::MergeBranchWithNegate(BooleanNegateInstr* neg) { |
| 871 ASSERT(!FLAG_enable_type_checks); | 873 ASSERT(!FLAG_enable_type_checks); |
| 872 Value* constant_true = Bind(new ConstantInstr(Bool::True())); | 874 Value* constant_true = Bind(new ConstantInstr(Bool::True())); |
| 873 StrictCompareInstr* comp = | 875 StrictCompareInstr* comp = |
| 874 new StrictCompareInstr(condition_token_pos(), | 876 new StrictCompareInstr(condition_token_pos(), |
| 875 Token::kNE_STRICT, | 877 Token::kNE_STRICT, |
| 876 neg->value(), | 878 neg->value(), |
| 877 constant_true); | 879 constant_true, |
| 878 comp->set_needs_number_check(false); | 880 false); // No number check. |
| 879 BranchInstr* branch = new BranchInstr(comp); | 881 BranchInstr* branch = new BranchInstr(comp); |
| 880 AddInstruction(branch); | 882 AddInstruction(branch); |
| 881 CloseFragment(); | 883 CloseFragment(); |
| 882 true_successor_addresses_.Add(branch->true_successor_address()); | 884 true_successor_addresses_.Add(branch->true_successor_address()); |
| 883 false_successor_addresses_.Add(branch->false_successor_address()); | 885 false_successor_addresses_.Add(branch->false_successor_address()); |
| 884 } | 886 } |
| 885 | 887 |
| 886 | 888 |
| 887 void TestGraphVisitor::ReturnDefinition(Definition* definition) { | 889 void TestGraphVisitor::ReturnDefinition(Definition* definition) { |
| 888 ComparisonInstr* comp = definition->AsComparison(); | 890 ComparisonInstr* comp = definition->AsComparison(); |
| (...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1194 if (FLAG_enable_type_checks) { | 1196 if (FLAG_enable_type_checks) { |
| 1195 right_value = | 1197 right_value = |
| 1196 for_right.Bind(new AssertBooleanInstr(node->right()->token_pos(), | 1198 for_right.Bind(new AssertBooleanInstr(node->right()->token_pos(), |
| 1197 right_value)); | 1199 right_value)); |
| 1198 } | 1200 } |
| 1199 Value* constant_true = for_right.Bind(new ConstantInstr(Bool::True())); | 1201 Value* constant_true = for_right.Bind(new ConstantInstr(Bool::True())); |
| 1200 Value* compare = | 1202 Value* compare = |
| 1201 for_right.Bind(new StrictCompareInstr(node->token_pos(), | 1203 for_right.Bind(new StrictCompareInstr(node->token_pos(), |
| 1202 Token::kEQ_STRICT, | 1204 Token::kEQ_STRICT, |
| 1203 right_value, | 1205 right_value, |
| 1204 constant_true)); | 1206 constant_true, |
| 1207 false)); // No number check. |
| 1205 for_right.Do(BuildStoreExprTemp(compare)); | 1208 for_right.Do(BuildStoreExprTemp(compare)); |
| 1206 | 1209 |
| 1207 if (node->kind() == Token::kAND) { | 1210 if (node->kind() == Token::kAND) { |
| 1208 ValueGraphVisitor for_false(owner()); | 1211 ValueGraphVisitor for_false(owner()); |
| 1209 Value* constant_false = for_false.Bind(new ConstantInstr(Bool::False())); | 1212 Value* constant_false = for_false.Bind(new ConstantInstr(Bool::False())); |
| 1210 for_false.Do(BuildStoreExprTemp(constant_false)); | 1213 for_false.Do(BuildStoreExprTemp(constant_false)); |
| 1211 Join(for_test, for_right, for_false); | 1214 Join(for_test, for_right, for_false); |
| 1212 } else { | 1215 } else { |
| 1213 ASSERT(node->kind() == Token::kOR); | 1216 ASSERT(node->kind() == Token::kOR); |
| 1214 ValueGraphVisitor for_true(owner()); | 1217 ValueGraphVisitor for_true(owner()); |
| (...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1529 intptr_t token_pos) { | 1532 intptr_t token_pos) { |
| 1530 ValueGraphVisitor for_left_value(owner()); | 1533 ValueGraphVisitor for_left_value(owner()); |
| 1531 left->Visit(&for_left_value); | 1534 left->Visit(&for_left_value); |
| 1532 Append(for_left_value); | 1535 Append(for_left_value); |
| 1533 ValueGraphVisitor for_right_value(owner()); | 1536 ValueGraphVisitor for_right_value(owner()); |
| 1534 right->Visit(&for_right_value); | 1537 right->Visit(&for_right_value); |
| 1535 Append(for_right_value); | 1538 Append(for_right_value); |
| 1536 StrictCompareInstr* comp = new StrictCompareInstr(token_pos, | 1539 StrictCompareInstr* comp = new StrictCompareInstr(token_pos, |
| 1537 kind, | 1540 kind, |
| 1538 for_left_value.value(), | 1541 for_left_value.value(), |
| 1539 for_right_value.value()); | 1542 for_right_value.value(), |
| 1543 true); // Number check. |
| 1540 return comp; | 1544 return comp; |
| 1541 } | 1545 } |
| 1542 | 1546 |
| 1543 | 1547 |
| 1544 // <Expression> :: Comparison { kind: Token::Kind | 1548 // <Expression> :: Comparison { kind: Token::Kind |
| 1545 // left: <Expression> | 1549 // left: <Expression> |
| 1546 // right: <Expression> } | 1550 // right: <Expression> } |
| 1547 // TODO(srdjan): Implement new equality. | 1551 // TODO(srdjan): Implement new equality. |
| 1548 void EffectGraphVisitor::VisitComparisonNode(ComparisonNode* node) { | 1552 void EffectGraphVisitor::VisitComparisonNode(ComparisonNode* node) { |
| 1549 if (Token::IsTypeTestOperator(node->kind())) { | 1553 if (Token::IsTypeTestOperator(node->kind())) { |
| (...skipping 1533 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3083 const Function& function = owner()->parsed_function()->function(); | 3087 const Function& function = owner()->parsed_function()->function(); |
| 3084 if (!function.IsClosureFunction()) { | 3088 if (!function.IsClosureFunction()) { |
| 3085 MethodRecognizer::Kind kind = MethodRecognizer::RecognizeKind(function); | 3089 MethodRecognizer::Kind kind = MethodRecognizer::RecognizeKind(function); |
| 3086 switch (kind) { | 3090 switch (kind) { |
| 3087 case MethodRecognizer::kObjectEquals: { | 3091 case MethodRecognizer::kObjectEquals: { |
| 3088 Value* receiver = Bind(BuildLoadThisVar(node->scope())); | 3092 Value* receiver = Bind(BuildLoadThisVar(node->scope())); |
| 3089 LocalVariable* other_var = | 3093 LocalVariable* other_var = |
| 3090 node->scope()->LookupVariable(Symbols::Other(), | 3094 node->scope()->LookupVariable(Symbols::Other(), |
| 3091 true); // Test only. | 3095 true); // Test only. |
| 3092 Value* other = Bind(new LoadLocalInstr(*other_var)); | 3096 Value* other = Bind(new LoadLocalInstr(*other_var)); |
| 3097 // Receiver is not a number because numbers override equality. |
| 3098 const bool kNoNumberCheck = false; |
| 3093 StrictCompareInstr* compare = | 3099 StrictCompareInstr* compare = |
| 3094 new StrictCompareInstr(node->token_pos(), | 3100 new StrictCompareInstr(node->token_pos(), |
| 3095 Token::kEQ_STRICT, | 3101 Token::kEQ_STRICT, |
| 3096 receiver, | 3102 receiver, |
| 3097 other); | 3103 other, |
| 3098 // Receiver is not a number because numbers override equality. | 3104 kNoNumberCheck); |
| 3099 compare->set_needs_number_check(false); | |
| 3100 return ReturnDefinition(compare); | 3105 return ReturnDefinition(compare); |
| 3101 } | 3106 } |
| 3102 case MethodRecognizer::kStringBaseLength: | 3107 case MethodRecognizer::kStringBaseLength: |
| 3103 case MethodRecognizer::kStringBaseIsEmpty: { | 3108 case MethodRecognizer::kStringBaseIsEmpty: { |
| 3104 Value* receiver = Bind(BuildLoadThisVar(node->scope())); | 3109 Value* receiver = Bind(BuildLoadThisVar(node->scope())); |
| 3105 // Treat length loads as mutable (i.e. affected by side effects) to | 3110 // Treat length loads as mutable (i.e. affected by side effects) to |
| 3106 // avoid hoisting them since we can't hoist the preceding class-check. | 3111 // avoid hoisting them since we can't hoist the preceding class-check. |
| 3107 // This is because of externalization of strings that affects their | 3112 // This is because of externalization of strings that affects their |
| 3108 // class-id. | 3113 // class-id. |
| 3109 const bool is_immutable = false; | 3114 const bool is_immutable = false; |
| 3110 LoadFieldInstr* load = new LoadFieldInstr( | 3115 LoadFieldInstr* load = new LoadFieldInstr( |
| 3111 receiver, | 3116 receiver, |
| 3112 String::length_offset(), | 3117 String::length_offset(), |
| 3113 Type::ZoneHandle(Type::SmiType()), | 3118 Type::ZoneHandle(Type::SmiType()), |
| 3114 is_immutable); | 3119 is_immutable); |
| 3115 load->set_result_cid(kSmiCid); | 3120 load->set_result_cid(kSmiCid); |
| 3116 load->set_recognized_kind(MethodRecognizer::kStringBaseLength); | 3121 load->set_recognized_kind(MethodRecognizer::kStringBaseLength); |
| 3117 if (kind == MethodRecognizer::kStringBaseLength) { | 3122 if (kind == MethodRecognizer::kStringBaseLength) { |
| 3118 return ReturnDefinition(load); | 3123 return ReturnDefinition(load); |
| 3119 } | 3124 } |
| 3120 ASSERT(kind == MethodRecognizer::kStringBaseIsEmpty); | 3125 ASSERT(kind == MethodRecognizer::kStringBaseIsEmpty); |
| 3121 Value* zero_val = Bind(new ConstantInstr(Smi::ZoneHandle(Smi::New(0)))); | 3126 Value* zero_val = Bind(new ConstantInstr(Smi::ZoneHandle(Smi::New(0)))); |
| 3122 Value* load_val = Bind(load); | 3127 Value* load_val = Bind(load); |
| 3123 StrictCompareInstr* compare = | 3128 StrictCompareInstr* compare = |
| 3124 new StrictCompareInstr(node->token_pos(), | 3129 new StrictCompareInstr(node->token_pos(), |
| 3125 Token::kEQ_STRICT, | 3130 Token::kEQ_STRICT, |
| 3126 load_val, | 3131 load_val, |
| 3127 zero_val); | 3132 zero_val, |
| 3133 false); // No number check. |
| 3128 return ReturnDefinition(compare); | 3134 return ReturnDefinition(compare); |
| 3129 } | 3135 } |
| 3130 case MethodRecognizer::kGrowableArrayLength: | 3136 case MethodRecognizer::kGrowableArrayLength: |
| 3131 case MethodRecognizer::kObjectArrayLength: | 3137 case MethodRecognizer::kObjectArrayLength: |
| 3132 case MethodRecognizer::kImmutableArrayLength: | 3138 case MethodRecognizer::kImmutableArrayLength: |
| 3133 case MethodRecognizer::kTypedDataLength: { | 3139 case MethodRecognizer::kTypedDataLength: { |
| 3134 Value* receiver = Bind(BuildLoadThisVar(node->scope())); | 3140 Value* receiver = Bind(BuildLoadThisVar(node->scope())); |
| 3135 const bool is_immutable = | 3141 const bool is_immutable = |
| 3136 (kind != MethodRecognizer::kGrowableArrayLength); | 3142 (kind != MethodRecognizer::kGrowableArrayLength); |
| 3137 LoadFieldInstr* load = new LoadFieldInstr( | 3143 LoadFieldInstr* load = new LoadFieldInstr( |
| (...skipping 896 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4034 LanguageError::kError, | 4040 LanguageError::kError, |
| 4035 Heap::kNew, | 4041 Heap::kNew, |
| 4036 "FlowGraphBuilder Bailout: %s %s", | 4042 "FlowGraphBuilder Bailout: %s %s", |
| 4037 String::Handle(function.name()).ToCString(), | 4043 String::Handle(function.name()).ToCString(), |
| 4038 reason)); | 4044 reason)); |
| 4039 Isolate::Current()->long_jump_base()->Jump(1, error); | 4045 Isolate::Current()->long_jump_base()->Jump(1, error); |
| 4040 } | 4046 } |
| 4041 | 4047 |
| 4042 | 4048 |
| 4043 } // namespace dart | 4049 } // namespace dart |
| OLD | NEW |