OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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/globals.h" // Needed here to get TARGET_ARCH_XXX. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_XXX. |
6 | 6 |
7 #include "vm/flow_graph_compiler.h" | 7 #include "vm/flow_graph_compiler.h" |
8 | 8 |
9 #include "vm/bit_vector.h" | 9 #include "vm/bit_vector.h" |
10 #include "vm/cha.h" | 10 #include "vm/cha.h" |
(...skipping 1011 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1022 *static_calls_target_table_[i]->code); | 1022 *static_calls_target_table_[i]->code); |
1023 } | 1023 } |
1024 } | 1024 } |
1025 code.set_static_calls_target_table(targets); | 1025 code.set_static_calls_target_table(targets); |
1026 INC_STAT(Thread::Current(), | 1026 INC_STAT(Thread::Current(), |
1027 total_code_size, | 1027 total_code_size, |
1028 targets.Length() * sizeof(uword)); | 1028 targets.Length() * sizeof(uword)); |
1029 } | 1029 } |
1030 | 1030 |
1031 | 1031 |
1032 // Returns 'true' if code generation for this function is complete, i.e., | 1032 // Returns 'true' if regular code generation should be skipped. |
1033 // no fall-through to regular code is needed. | 1033 bool FlowGraphCompiler::TryIntrinsify() { |
1034 void FlowGraphCompiler::TryIntrinsify() { | |
1035 // Intrinsification skips arguments checks, therefore disable if in checked | 1034 // Intrinsification skips arguments checks, therefore disable if in checked |
1036 // mode. | 1035 // mode. |
1037 if (FLAG_intrinsify && !isolate()->flags().type_checks()) { | 1036 if (FLAG_intrinsify && !isolate()->flags().type_checks()) { |
1038 if (parsed_function().function().kind() == RawFunction::kImplicitGetter) { | 1037 if (parsed_function().function().kind() == RawFunction::kImplicitGetter) { |
1039 // An implicit getter must have a specific AST structure. | 1038 // An implicit getter must have a specific AST structure. |
1040 const SequenceNode& sequence_node = *parsed_function().node_sequence(); | 1039 const SequenceNode& sequence_node = *parsed_function().node_sequence(); |
1041 ASSERT(sequence_node.length() == 1); | 1040 ASSERT(sequence_node.length() == 1); |
1042 ASSERT(sequence_node.NodeAt(0)->IsReturnNode()); | 1041 ASSERT(sequence_node.NodeAt(0)->IsReturnNode()); |
1043 const ReturnNode& return_node = *sequence_node.NodeAt(0)->AsReturnNode(); | 1042 const ReturnNode& return_node = *sequence_node.NodeAt(0)->AsReturnNode(); |
1044 ASSERT(return_node.value()->IsLoadInstanceFieldNode()); | 1043 ASSERT(return_node.value()->IsLoadInstanceFieldNode()); |
1045 const LoadInstanceFieldNode& load_node = | 1044 const LoadInstanceFieldNode& load_node = |
1046 *return_node.value()->AsLoadInstanceFieldNode(); | 1045 *return_node.value()->AsLoadInstanceFieldNode(); |
1047 // Only intrinsify getter if the field cannot contain a mutable double. | 1046 // Only intrinsify getter if the field cannot contain a mutable double. |
1048 // Reading from a mutable double box requires allocating a fresh double. | 1047 // Reading from a mutable double box requires allocating a fresh double. |
1049 if (load_node.field().guarded_cid() == kDynamicCid) { | 1048 if (load_node.field().guarded_cid() == kDynamicCid) { |
1050 GenerateInlinedGetter(load_node.field().Offset()); | 1049 GenerateInlinedGetter(load_node.field().Offset()); |
| 1050 return true; |
1051 } | 1051 } |
1052 return; | 1052 return false; |
1053 } | 1053 } |
1054 if (parsed_function().function().kind() == RawFunction::kImplicitSetter) { | 1054 if (parsed_function().function().kind() == RawFunction::kImplicitSetter) { |
1055 // An implicit setter must have a specific AST structure. | 1055 // An implicit setter must have a specific AST structure. |
1056 // Sequence node has one store node and one return NULL node. | 1056 // Sequence node has one store node and one return NULL node. |
1057 const SequenceNode& sequence_node = *parsed_function().node_sequence(); | 1057 const SequenceNode& sequence_node = *parsed_function().node_sequence(); |
1058 ASSERT(sequence_node.length() == 2); | 1058 ASSERT(sequence_node.length() == 2); |
1059 ASSERT(sequence_node.NodeAt(0)->IsStoreInstanceFieldNode()); | 1059 ASSERT(sequence_node.NodeAt(0)->IsStoreInstanceFieldNode()); |
1060 ASSERT(sequence_node.NodeAt(1)->IsReturnNode()); | 1060 ASSERT(sequence_node.NodeAt(1)->IsReturnNode()); |
1061 const StoreInstanceFieldNode& store_node = | 1061 const StoreInstanceFieldNode& store_node = |
1062 *sequence_node.NodeAt(0)->AsStoreInstanceFieldNode(); | 1062 *sequence_node.NodeAt(0)->AsStoreInstanceFieldNode(); |
1063 if (store_node.field().guarded_cid() == kDynamicCid) { | 1063 if (store_node.field().guarded_cid() == kDynamicCid) { |
1064 GenerateInlinedSetter(store_node.field().Offset()); | 1064 GenerateInlinedSetter(store_node.field().Offset()); |
1065 return; | 1065 return true; |
1066 } | 1066 } |
1067 } | 1067 } |
1068 } | 1068 } |
1069 | 1069 |
1070 EnterIntrinsicMode(); | 1070 EnterIntrinsicMode(); |
1071 | 1071 |
1072 Intrinsifier::Intrinsify(parsed_function(), this); | 1072 Intrinsifier::Intrinsify(parsed_function(), this); |
1073 | 1073 |
1074 ExitIntrinsicMode(); | 1074 ExitIntrinsicMode(); |
1075 // "Deoptimization" from intrinsic continues here. All deoptimization | 1075 // "Deoptimization" from intrinsic continues here. All deoptimization |
1076 // branches from intrinsic code redirect to here where the slow-path | 1076 // branches from intrinsic code redirect to here where the slow-path |
1077 // (normal function body) starts. | 1077 // (normal function body) starts. |
1078 // This means that there must not be any side-effects in intrinsic code | 1078 // This means that there must not be any side-effects in intrinsic code |
1079 // before any deoptimization point. | 1079 // before any deoptimization point. |
1080 ASSERT(!intrinsic_slow_path_label_.IsBound()); | 1080 ASSERT(!intrinsic_slow_path_label_.IsBound()); |
1081 assembler()->Bind(&intrinsic_slow_path_label_); | 1081 assembler()->Bind(&intrinsic_slow_path_label_); |
| 1082 return false; |
1082 } | 1083 } |
1083 | 1084 |
1084 | 1085 |
1085 void FlowGraphCompiler::GenerateInstanceCall( | 1086 void FlowGraphCompiler::GenerateInstanceCall( |
1086 intptr_t deopt_id, | 1087 intptr_t deopt_id, |
1087 intptr_t token_pos, | 1088 intptr_t token_pos, |
1088 intptr_t argument_count, | 1089 intptr_t argument_count, |
1089 LocationSummary* locs, | 1090 LocationSummary* locs, |
1090 const ICData& ic_data) { | 1091 const ICData& ic_data) { |
1091 if (FLAG_always_megamorphic_calls) { | 1092 if (FLAG_always_megamorphic_calls) { |
(...skipping 748 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1840 | 1841 |
1841 | 1842 |
1842 void FlowGraphCompiler::FrameStateClear() { | 1843 void FlowGraphCompiler::FrameStateClear() { |
1843 ASSERT(!is_optimizing()); | 1844 ASSERT(!is_optimizing()); |
1844 frame_state_.TruncateTo(0); | 1845 frame_state_.TruncateTo(0); |
1845 } | 1846 } |
1846 #endif | 1847 #endif |
1847 | 1848 |
1848 | 1849 |
1849 } // namespace dart | 1850 } // namespace dart |
OLD | NEW |