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 #ifndef DART_PRECOMPILED_RUNTIME | 4 #ifndef DART_PRECOMPILED_RUNTIME |
5 #include "vm/jit_optimizer.h" | 5 #include "vm/jit_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" |
11 #include "vm/cpu.h" | 11 #include "vm/cpu.h" |
12 #include "vm/dart_entry.h" | 12 #include "vm/dart_entry.h" |
13 #include "vm/exceptions.h" | 13 #include "vm/exceptions.h" |
14 #include "vm/flow_graph_builder.h" | 14 #include "vm/flow_graph_builder.h" |
15 #include "vm/flow_graph_compiler.h" | 15 #include "vm/flow_graph_compiler.h" |
16 #include "vm/flow_graph_inliner.h" | 16 #include "vm/flow_graph_inliner.h" |
17 #include "vm/flow_graph_range_analysis.h" | 17 #include "vm/flow_graph_range_analysis.h" |
18 #include "vm/hash_map.h" | 18 #include "vm/hash_map.h" |
19 #include "vm/il_printer.h" | 19 #include "vm/il_printer.h" |
20 #include "vm/intermediate_language.h" | 20 #include "vm/intermediate_language.h" |
21 #include "vm/object_store.h" | 21 #include "vm/object_store.h" |
| 22 #include "vm/optimizer.h" |
22 #include "vm/parser.h" | 23 #include "vm/parser.h" |
23 #include "vm/resolver.h" | 24 #include "vm/resolver.h" |
24 #include "vm/scopes.h" | 25 #include "vm/scopes.h" |
25 #include "vm/stack_frame.h" | 26 #include "vm/stack_frame.h" |
26 #include "vm/symbols.h" | 27 #include "vm/symbols.h" |
27 | 28 |
28 namespace dart { | 29 namespace dart { |
29 | 30 |
30 // Quick access to the current isolate and zone. | 31 // Quick access to the current isolate and zone. |
31 #define I (isolate()) | 32 #define I (isolate()) |
(...skipping 1202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1234 const TypeArguments& type_arguments = | 1235 const TypeArguments& type_arguments = |
1235 TypeArguments::Handle(type.arguments()); | 1236 TypeArguments::Handle(type.arguments()); |
1236 const bool is_raw_type = type_arguments.IsNull() || | 1237 const bool is_raw_type = type_arguments.IsNull() || |
1237 type_arguments.IsRaw(from_index, num_type_params); | 1238 type_arguments.IsRaw(from_index, num_type_params); |
1238 return is_raw_type; | 1239 return is_raw_type; |
1239 } | 1240 } |
1240 return true; | 1241 return true; |
1241 } | 1242 } |
1242 | 1243 |
1243 | 1244 |
1244 static bool CidTestResultsContains(const ZoneGrowableArray<intptr_t>& results, | |
1245 intptr_t test_cid) { | |
1246 for (intptr_t i = 0; i < results.length(); i += 2) { | |
1247 if (results[i] == test_cid) return true; | |
1248 } | |
1249 return false; | |
1250 } | |
1251 | |
1252 | |
1253 static void TryAddTest(ZoneGrowableArray<intptr_t>* results, | |
1254 intptr_t test_cid, | |
1255 bool result) { | |
1256 if (!CidTestResultsContains(*results, test_cid)) { | |
1257 results->Add(test_cid); | |
1258 results->Add(result); | |
1259 } | |
1260 } | |
1261 | |
1262 | |
1263 // Tries to add cid tests to 'results' so that no deoptimization is | |
1264 // necessary. | |
1265 // TODO(srdjan): Do also for other than 'int' type. | |
1266 static bool TryExpandTestCidsResult(ZoneGrowableArray<intptr_t>* results, | |
1267 const AbstractType& type) { | |
1268 ASSERT(results->length() >= 2); // At least on eentry. | |
1269 const ClassTable& class_table = *Isolate::Current()->class_table(); | |
1270 if ((*results)[0] != kSmiCid) { | |
1271 const Class& cls = Class::Handle(class_table.At(kSmiCid)); | |
1272 const Class& type_class = Class::Handle(type.type_class()); | |
1273 const bool smi_is_subtype = | |
1274 cls.IsSubtypeOf(Object::null_type_arguments(), type_class, | |
1275 Object::null_type_arguments(), NULL, NULL, Heap::kOld); | |
1276 results->Add((*results)[results->length() - 2]); | |
1277 results->Add((*results)[results->length() - 2]); | |
1278 for (intptr_t i = results->length() - 3; i > 1; --i) { | |
1279 (*results)[i] = (*results)[i - 2]; | |
1280 } | |
1281 (*results)[0] = kSmiCid; | |
1282 (*results)[1] = smi_is_subtype; | |
1283 } | |
1284 | |
1285 ASSERT(type.IsInstantiated() && !type.IsMalformedOrMalbounded()); | |
1286 ASSERT(results->length() >= 2); | |
1287 if (type.IsIntType()) { | |
1288 ASSERT((*results)[0] == kSmiCid); | |
1289 TryAddTest(results, kMintCid, true); | |
1290 TryAddTest(results, kBigintCid, true); | |
1291 // Cannot deoptimize since all tests returning true have been added. | |
1292 return false; | |
1293 } | |
1294 | |
1295 return true; // May deoptimize since we have not identified all 'true' tests. | |
1296 } | |
1297 | |
1298 | |
1299 // TODO(srdjan): Use ICData to check if always true or false. | 1245 // TODO(srdjan): Use ICData to check if always true or false. |
1300 void JitOptimizer::ReplaceWithInstanceOf(InstanceCallInstr* call) { | 1246 void JitOptimizer::ReplaceWithInstanceOf(InstanceCallInstr* call) { |
1301 ASSERT(Token::IsTypeTestOperator(call->token_kind())); | 1247 ASSERT(Token::IsTypeTestOperator(call->token_kind())); |
1302 Definition* left = call->ArgumentAt(0); | 1248 Definition* left = call->ArgumentAt(0); |
1303 Definition* instantiator_type_args = NULL; | 1249 Definition* instantiator_type_args = NULL; |
1304 Definition* function_type_args = NULL; | 1250 Definition* function_type_args = NULL; |
1305 AbstractType& type = AbstractType::ZoneHandle(Z); | 1251 AbstractType& type = AbstractType::ZoneHandle(Z); |
1306 if (call->ArgumentCount() == 2) { | 1252 if (call->ArgumentCount() == 2) { |
1307 instantiator_type_args = flow_graph()->constant_null(); | 1253 instantiator_type_args = flow_graph()->constant_null(); |
1308 function_type_args = flow_graph()->constant_null(); | 1254 function_type_args = flow_graph()->constant_null(); |
1309 ASSERT(call->MatchesCoreName(Symbols::_simpleInstanceOf())); | 1255 ASSERT(call->MatchesCoreName(Symbols::_simpleInstanceOf())); |
1310 type = AbstractType::Cast(call->ArgumentAt(1)->AsConstant()->value()).raw(); | 1256 type = AbstractType::Cast(call->ArgumentAt(1)->AsConstant()->value()).raw(); |
1311 } else { | 1257 } else { |
1312 instantiator_type_args = call->ArgumentAt(1); | 1258 instantiator_type_args = call->ArgumentAt(1); |
1313 function_type_args = call->ArgumentAt(2); | 1259 function_type_args = call->ArgumentAt(2); |
1314 type = AbstractType::Cast(call->ArgumentAt(3)->AsConstant()->value()).raw(); | 1260 type = AbstractType::Cast(call->ArgumentAt(3)->AsConstant()->value()).raw(); |
1315 } | 1261 } |
1316 const ICData& unary_checks = | 1262 const ICData& unary_checks = |
1317 ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecks()); | 1263 ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecks()); |
1318 const intptr_t number_of_checks = unary_checks.NumberOfChecks(); | 1264 const intptr_t number_of_checks = unary_checks.NumberOfChecks(); |
1319 if ((number_of_checks > 0) && | 1265 if ((number_of_checks > 0) && |
1320 (number_of_checks <= FLAG_max_polymorphic_checks)) { | 1266 (number_of_checks <= FLAG_max_polymorphic_checks)) { |
1321 ZoneGrowableArray<intptr_t>* results = | 1267 ZoneGrowableArray<intptr_t>* results = |
1322 new (Z) ZoneGrowableArray<intptr_t>(number_of_checks * 2); | 1268 new (Z) ZoneGrowableArray<intptr_t>(number_of_checks * 2); |
1323 Bool& as_bool = | 1269 Bool& as_bool = |
1324 Bool::ZoneHandle(Z, InstanceOfAsBool(unary_checks, type, results)); | 1270 Bool::ZoneHandle(Z, InstanceOfAsBool(unary_checks, type, results)); |
1325 if (as_bool.IsNull()) { | 1271 if (as_bool.IsNull()) { |
1326 if (results->length() == number_of_checks * 2) { | 1272 if (results->length() == number_of_checks * 2) { |
1327 const bool can_deopt = TryExpandTestCidsResult(results, type); | 1273 const bool can_deopt = |
| 1274 Optimizer::SpecializeTestCidsForNumericTypes(results, type); |
1328 TestCidsInstr* test_cids = new (Z) TestCidsInstr( | 1275 TestCidsInstr* test_cids = new (Z) TestCidsInstr( |
1329 call->token_pos(), Token::kIS, new (Z) Value(left), *results, | 1276 call->token_pos(), Token::kIS, new (Z) Value(left), *results, |
1330 can_deopt ? call->deopt_id() : Thread::kNoDeoptId); | 1277 can_deopt ? call->deopt_id() : Thread::kNoDeoptId); |
1331 // Remove type. | 1278 // Remove type. |
1332 ReplaceCall(call, test_cids); | 1279 ReplaceCall(call, test_cids); |
1333 return; | 1280 return; |
1334 } | 1281 } |
1335 } else { | 1282 } else { |
1336 // TODO(srdjan): Use TestCidsInstr also for this case. | 1283 // TODO(srdjan): Use TestCidsInstr also for this case. |
1337 // One result only. | 1284 // One result only. |
(...skipping 434 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1772 // Discard the environment from the original instruction because the store | 1719 // Discard the environment from the original instruction because the store |
1773 // can't deoptimize. | 1720 // can't deoptimize. |
1774 instr->RemoveEnvironment(); | 1721 instr->RemoveEnvironment(); |
1775 ReplaceCall(instr, store); | 1722 ReplaceCall(instr, store); |
1776 return true; | 1723 return true; |
1777 } | 1724 } |
1778 | 1725 |
1779 | 1726 |
1780 } // namespace dart | 1727 } // namespace dart |
1781 #endif // DART_PRECOMPILED_RUNTIME | 1728 #endif // DART_PRECOMPILED_RUNTIME |
OLD | NEW |