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/aot_optimizer.h" | 5 #include "vm/aot_optimizer.h" |
6 | 6 |
7 #include "vm/bit_vector.h" | 7 #include "vm/bit_vector.h" |
8 #include "vm/branch_optimizer.h" | 8 #include "vm/branch_optimizer.h" |
9 #include "vm/cha.h" | 9 #include "vm/cha.h" |
10 #include "vm/compiler.h" | 10 #include "vm/compiler.h" |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
47 static bool CanUnboxDouble() { | 47 static bool CanUnboxDouble() { |
48 return FlowGraphCompiler::SupportsUnboxedDoubles(); | 48 return FlowGraphCompiler::SupportsUnboxedDoubles(); |
49 } | 49 } |
50 | 50 |
51 | 51 |
52 static bool CanConvertUnboxedMintToDouble() { | 52 static bool CanConvertUnboxedMintToDouble() { |
53 return FlowGraphCompiler::CanConvertUnboxedMintToDouble(); | 53 return FlowGraphCompiler::CanConvertUnboxedMintToDouble(); |
54 } | 54 } |
55 | 55 |
56 | 56 |
| 57 // Returns named function that is a unique dynamic target, i.e., |
| 58 // - the target is identified by its name alone, since it occurs only once. |
| 59 // - target's class has no subclasses, and neither is subclassed, i.e., |
| 60 // the receiver type can be only the function's class. |
| 61 // Returns Function::null() if there is no unique dynamic target for |
| 62 // given 'fname'. 'fname' must be a symbol. |
| 63 static void GetUniqueDynamicTarget(Isolate* isolate, |
| 64 const String& fname, |
| 65 Object* function) { |
| 66 UniqueFunctionsSet functions_set( |
| 67 isolate->object_store()->unique_dynamic_targets()); |
| 68 ASSERT(fname.IsSymbol()); |
| 69 *function = functions_set.GetOrNull(fname); |
| 70 ASSERT(functions_set.Release().raw() == |
| 71 isolate->object_store()->unique_dynamic_targets()); |
| 72 } |
| 73 |
| 74 |
| 75 AotOptimizer::AotOptimizer(FlowGraph* flow_graph, |
| 76 bool use_speculative_inlining, |
| 77 GrowableArray<intptr_t>* inlining_black_list) |
| 78 : FlowGraphVisitor(flow_graph->reverse_postorder()), |
| 79 flow_graph_(flow_graph), |
| 80 use_speculative_inlining_(use_speculative_inlining), |
| 81 inlining_black_list_(inlining_black_list), |
| 82 has_unique_no_such_method_(false) { |
| 83 ASSERT(!use_speculative_inlining || (inlining_black_list != NULL)); |
| 84 Function& target_function = Function::Handle(); |
| 85 if (isolate()->object_store()->unique_dynamic_targets() != Array::null()) { |
| 86 GetUniqueDynamicTarget( |
| 87 isolate(), Symbols::NoSuchMethod(), &target_function); |
| 88 has_unique_no_such_method_ = !target_function.IsNull(); |
| 89 } |
| 90 } |
| 91 |
| 92 |
57 // Optimize instance calls using ICData. | 93 // Optimize instance calls using ICData. |
58 void AotOptimizer::ApplyICData() { | 94 void AotOptimizer::ApplyICData() { |
59 VisitBlocks(); | 95 VisitBlocks(); |
60 } | 96 } |
61 | 97 |
62 | 98 |
63 void AotOptimizer::PopulateWithICData() { | 99 void AotOptimizer::PopulateWithICData() { |
64 ASSERT(current_iterator_ == NULL); | 100 ASSERT(current_iterator_ == NULL); |
65 for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator(); | 101 for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator(); |
66 !block_it.Done(); | 102 !block_it.Done(); |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
116 } | 152 } |
117 } | 153 } |
118 | 154 |
119 | 155 |
120 // TODO(srdjan): Test/support other number types as well. | 156 // TODO(srdjan): Test/support other number types as well. |
121 static bool IsNumberCid(intptr_t cid) { | 157 static bool IsNumberCid(intptr_t cid) { |
122 return (cid == kSmiCid) || (cid == kDoubleCid); | 158 return (cid == kSmiCid) || (cid == kDoubleCid); |
123 } | 159 } |
124 | 160 |
125 | 161 |
126 // Returns named function that is a unique dynamic target, i.e., | |
127 // - the target is identified by its name alone, since it occurs only once. | |
128 // - target's class has no subclasses, and neither is subclassed, i.e., | |
129 // the receiver type can be only the function's class. | |
130 // Returns Function::null() if there is no unique dynamic target for | |
131 // given 'fname'. 'fname' must be a symbol. | |
132 static void GetUniqueDynamicTarget(Isolate* isolate, | |
133 const String& fname, | |
134 Object* function) { | |
135 UniqueFunctionsSet functions_set( | |
136 isolate->object_store()->unique_dynamic_targets()); | |
137 ASSERT(fname.IsSymbol()); | |
138 *function = functions_set.GetOrNull(fname); | |
139 ASSERT(functions_set.Release().raw() == | |
140 isolate->object_store()->unique_dynamic_targets()); | |
141 } | |
142 | |
143 | |
144 bool AotOptimizer::TryCreateICData(InstanceCallInstr* call) { | 162 bool AotOptimizer::TryCreateICData(InstanceCallInstr* call) { |
145 ASSERT(call->HasICData()); | 163 ASSERT(call->HasICData()); |
146 if (call->ic_data()->NumberOfUsedChecks() > 0) { | 164 if (call->ic_data()->NumberOfUsedChecks() > 0) { |
147 // This occurs when an instance call has too many checks, will be converted | 165 // This occurs when an instance call has too many checks, will be converted |
148 // to megamorphic call. | 166 // to megamorphic call. |
149 return false; | 167 return false; |
150 } | 168 } |
151 GrowableArray<intptr_t> class_ids(call->ic_data()->NumArgsTested()); | 169 GrowableArray<intptr_t> class_ids(call->ic_data()->NumArgsTested()); |
152 ASSERT(call->ic_data()->NumArgsTested() <= call->ArgumentCount()); | 170 ASSERT(call->ic_data()->NumArgsTested() <= call->ArgumentCount()); |
153 for (intptr_t i = 0; i < call->ic_data()->NumArgsTested(); i++) { | 171 for (intptr_t i = 0; i < call->ic_data()->NumArgsTested(); i++) { |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
220 | 238 |
221 if (isolate()->object_store()->unique_dynamic_targets() != Array::null()) { | 239 if (isolate()->object_store()->unique_dynamic_targets() != Array::null()) { |
222 // Check if the target is unique. | 240 // Check if the target is unique. |
223 Function& target_function = Function::Handle(Z); | 241 Function& target_function = Function::Handle(Z); |
224 GetUniqueDynamicTarget(isolate(), call->function_name(), &target_function); | 242 GetUniqueDynamicTarget(isolate(), call->function_name(), &target_function); |
225 // Calls with named arguments must be resolved/checked at runtime. | 243 // Calls with named arguments must be resolved/checked at runtime. |
226 if (!target_function.IsNull() && | 244 if (!target_function.IsNull() && |
227 !target_function.HasOptionalNamedParameters() && | 245 !target_function.HasOptionalNamedParameters() && |
228 target_function.AreValidArgumentCounts(call->ArgumentCount(), 0, | 246 target_function.AreValidArgumentCounts(call->ArgumentCount(), 0, |
229 /* error_message = */ NULL)) { | 247 /* error_message = */ NULL)) { |
230 const intptr_t cid = Class::Handle(Z, target_function.Owner()).id(); | 248 const Class& cls = Class::Handle(Z, target_function.Owner()); |
231 const ICData& ic_data = ICData::ZoneHandle(Z, | 249 if (!CHA::IsImplemented(cls) && !CHA::HasSubclasses(cls)) { |
232 ICData::NewFrom(*call->ic_data(), 1)); | 250 const ICData& ic_data = ICData::ZoneHandle(Z, |
233 ic_data.AddReceiverCheck(cid, target_function); | 251 ICData::NewFrom(*call->ic_data(), 1)); |
234 call->set_ic_data(&ic_data); | 252 ic_data.AddReceiverCheck(cls.id(), target_function); |
235 return true; | 253 call->set_ic_data(&ic_data); |
| 254 if (has_unique_no_such_method_) { |
| 255 call->set_has_unique_selector(true); |
| 256 } |
| 257 return true; |
| 258 } |
236 } | 259 } |
237 } | 260 } |
238 | 261 |
239 return false; | 262 return false; |
240 } | 263 } |
241 | 264 |
242 | 265 |
243 const ICData& AotOptimizer::TrySpecializeICData(const ICData& ic_data, | 266 const ICData& AotOptimizer::TrySpecializeICData(const ICData& ic_data, |
244 intptr_t cid) { | 267 intptr_t cid) { |
245 ASSERT(ic_data.NumArgsTested() == 1); | 268 ASSERT(ic_data.NumArgsTested() == 1); |
(...skipping 1742 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1988 PolymorphicInstanceCallInstr* call = | 2011 PolymorphicInstanceCallInstr* call = |
1989 new(Z) PolymorphicInstanceCallInstr(instr, unary_checks, | 2012 new(Z) PolymorphicInstanceCallInstr(instr, unary_checks, |
1990 /* with_checks = */ true, | 2013 /* with_checks = */ true, |
1991 /* complete = */ false); | 2014 /* complete = */ false); |
1992 instr->ReplaceWith(call, current_iterator()); | 2015 instr->ReplaceWith(call, current_iterator()); |
1993 return; | 2016 return; |
1994 } | 2017 } |
1995 } | 2018 } |
1996 | 2019 |
1997 | 2020 |
| 2021 void AotOptimizer::VisitPolymorphicInstanceCall( |
| 2022 PolymorphicInstanceCallInstr* call) { |
| 2023 if (call->with_checks()) { |
| 2024 const intptr_t receiver_cid = |
| 2025 call->PushArgumentAt(0)->value()->Type()->ToCid(); |
| 2026 if (receiver_cid != kDynamicCid) { |
| 2027 const Class& receiver_class = Class::Handle(Z, |
| 2028 isolate()->class_table()->At(receiver_cid)); |
| 2029 |
| 2030 const Array& args_desc_array = Array::Handle(Z, |
| 2031 ArgumentsDescriptor::New(call->ArgumentCount(), |
| 2032 call->instance_call()->argument_names())); |
| 2033 ArgumentsDescriptor args_desc(args_desc_array); |
| 2034 const Function& function = Function::Handle(Z, |
| 2035 Resolver::ResolveDynamicForReceiverClass( |
| 2036 receiver_class, |
| 2037 call->instance_call()->function_name(), |
| 2038 args_desc)); |
| 2039 if (!function.IsNull()) { |
| 2040 call->set_with_checks(false); |
| 2041 } |
| 2042 } |
| 2043 } |
| 2044 } |
| 2045 |
| 2046 |
1998 void AotOptimizer::VisitStaticCall(StaticCallInstr* call) { | 2047 void AotOptimizer::VisitStaticCall(StaticCallInstr* call) { |
1999 if (!IsAllowedForInlining(call->deopt_id())) { | 2048 if (!IsAllowedForInlining(call->deopt_id())) { |
2000 // Inlining disabled after a speculative inlining attempt. | 2049 // Inlining disabled after a speculative inlining attempt. |
2001 return; | 2050 return; |
2002 } | 2051 } |
2003 MethodRecognizer::Kind recognized_kind = | 2052 MethodRecognizer::Kind recognized_kind = |
2004 MethodRecognizer::RecognizeKind(call->function()); | 2053 MethodRecognizer::RecognizeKind(call->function()); |
2005 switch (recognized_kind) { | 2054 switch (recognized_kind) { |
2006 case MethodRecognizer::kObjectConstructor: | 2055 case MethodRecognizer::kObjectConstructor: |
2007 case MethodRecognizer::kObjectArrayAllocate: | 2056 case MethodRecognizer::kObjectArrayAllocate: |
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2178 check->env(), FlowGraph::kEffect); | 2227 check->env(), FlowGraph::kEffect); |
2179 current_iterator()->RemoveCurrentFromGraph(); | 2228 current_iterator()->RemoveCurrentFromGraph(); |
2180 } | 2229 } |
2181 } | 2230 } |
2182 } | 2231 } |
2183 } | 2232 } |
2184 | 2233 |
2185 #endif // DART_PRECOMPILER | 2234 #endif // DART_PRECOMPILER |
2186 | 2235 |
2187 } // namespace dart | 2236 } // namespace dart |
OLD | NEW |