| 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 |