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_ARM. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM. |
6 #if defined(TARGET_ARCH_ARM) | 6 #if defined(TARGET_ARCH_ARM) |
7 | 7 |
8 #include "vm/flow_graph_compiler.h" | 8 #include "vm/flow_graph_compiler.h" |
9 | 9 |
10 #include "vm/ast_printer.h" | 10 #include "vm/ast_printer.h" |
(...skipping 1088 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1099 | 1099 |
1100 if (is_optimizing()) { | 1100 if (is_optimizing()) { |
1101 lazy_deopt_pc_offset_ = assembler()->CodeSize(); | 1101 lazy_deopt_pc_offset_ = assembler()->CodeSize(); |
1102 __ Branch(&StubCode::DeoptimizeLazyLabel()); | 1102 __ Branch(&StubCode::DeoptimizeLazyLabel()); |
1103 } | 1103 } |
1104 } | 1104 } |
1105 | 1105 |
1106 | 1106 |
1107 void FlowGraphCompiler::GenerateCall(intptr_t token_pos, | 1107 void FlowGraphCompiler::GenerateCall(intptr_t token_pos, |
1108 const ExternalLabel* label, | 1108 const ExternalLabel* label, |
1109 PcDescriptors::Kind kind, | 1109 RawPcDescriptors::Kind kind, |
1110 LocationSummary* locs) { | 1110 LocationSummary* locs) { |
1111 __ BranchLinkPatchable(label); | 1111 __ BranchLinkPatchable(label); |
1112 AddCurrentDescriptor(kind, Isolate::kNoDeoptId, token_pos); | 1112 AddCurrentDescriptor(kind, Isolate::kNoDeoptId, token_pos); |
1113 RecordSafepoint(locs); | 1113 RecordSafepoint(locs); |
1114 } | 1114 } |
1115 | 1115 |
1116 | 1116 |
1117 void FlowGraphCompiler::GenerateDartCall(intptr_t deopt_id, | 1117 void FlowGraphCompiler::GenerateDartCall(intptr_t deopt_id, |
1118 intptr_t token_pos, | 1118 intptr_t token_pos, |
1119 const ExternalLabel* label, | 1119 const ExternalLabel* label, |
1120 PcDescriptors::Kind kind, | 1120 RawPcDescriptors::Kind kind, |
1121 LocationSummary* locs) { | 1121 LocationSummary* locs) { |
1122 __ BranchLinkPatchable(label); | 1122 __ BranchLinkPatchable(label); |
1123 AddCurrentDescriptor(kind, deopt_id, token_pos); | 1123 AddCurrentDescriptor(kind, deopt_id, token_pos); |
1124 RecordSafepoint(locs); | 1124 RecordSafepoint(locs); |
1125 // Marks either the continuation point in unoptimized code or the | 1125 // Marks either the continuation point in unoptimized code or the |
1126 // deoptimization point in optimized code, after call. | 1126 // deoptimization point in optimized code, after call. |
1127 const intptr_t deopt_id_after = Isolate::ToDeoptAfter(deopt_id); | 1127 const intptr_t deopt_id_after = Isolate::ToDeoptAfter(deopt_id); |
1128 if (is_optimizing()) { | 1128 if (is_optimizing()) { |
1129 AddDeoptIndexAtCall(deopt_id_after, token_pos); | 1129 AddDeoptIndexAtCall(deopt_id_after, token_pos); |
1130 } else { | 1130 } else { |
1131 // Add deoptimization continuation point after the call and before the | 1131 // Add deoptimization continuation point after the call and before the |
1132 // arguments are removed. | 1132 // arguments are removed. |
1133 AddCurrentDescriptor(PcDescriptors::kDeopt, deopt_id_after, token_pos); | 1133 AddCurrentDescriptor(RawPcDescriptors::kDeopt, |
| 1134 deopt_id_after, token_pos); |
1134 } | 1135 } |
1135 } | 1136 } |
1136 | 1137 |
1137 | 1138 |
1138 void FlowGraphCompiler::GenerateRuntimeCall(intptr_t token_pos, | 1139 void FlowGraphCompiler::GenerateRuntimeCall(intptr_t token_pos, |
1139 intptr_t deopt_id, | 1140 intptr_t deopt_id, |
1140 const RuntimeEntry& entry, | 1141 const RuntimeEntry& entry, |
1141 intptr_t argument_count, | 1142 intptr_t argument_count, |
1142 LocationSummary* locs) { | 1143 LocationSummary* locs) { |
1143 __ CallRuntime(entry, argument_count); | 1144 __ CallRuntime(entry, argument_count); |
1144 AddCurrentDescriptor(PcDescriptors::kOther, deopt_id, token_pos); | 1145 AddCurrentDescriptor(RawPcDescriptors::kOther, deopt_id, token_pos); |
1145 RecordSafepoint(locs); | 1146 RecordSafepoint(locs); |
1146 if (deopt_id != Isolate::kNoDeoptId) { | 1147 if (deopt_id != Isolate::kNoDeoptId) { |
1147 // Marks either the continuation point in unoptimized code or the | 1148 // Marks either the continuation point in unoptimized code or the |
1148 // deoptimization point in optimized code, after call. | 1149 // deoptimization point in optimized code, after call. |
1149 const intptr_t deopt_id_after = Isolate::ToDeoptAfter(deopt_id); | 1150 const intptr_t deopt_id_after = Isolate::ToDeoptAfter(deopt_id); |
1150 if (is_optimizing()) { | 1151 if (is_optimizing()) { |
1151 AddDeoptIndexAtCall(deopt_id_after, token_pos); | 1152 AddDeoptIndexAtCall(deopt_id_after, token_pos); |
1152 } else { | 1153 } else { |
1153 // Add deoptimization continuation point after the call and before the | 1154 // Add deoptimization continuation point after the call and before the |
1154 // arguments are removed. | 1155 // arguments are removed. |
1155 AddCurrentDescriptor(PcDescriptors::kDeopt, | 1156 AddCurrentDescriptor(RawPcDescriptors::kDeopt, |
1156 deopt_id_after, | 1157 deopt_id_after, |
1157 token_pos); | 1158 token_pos); |
1158 } | 1159 } |
1159 } | 1160 } |
1160 } | 1161 } |
1161 | 1162 |
1162 | 1163 |
1163 void FlowGraphCompiler::EmitEdgeCounter() { | 1164 void FlowGraphCompiler::EmitEdgeCounter() { |
1164 // We do not check for overflow when incrementing the edge counter. The | 1165 // We do not check for overflow when incrementing the edge counter. The |
1165 // function should normally be optimized long before the counter can | 1166 // function should normally be optimized long before the counter can |
(...skipping 23 matching lines...) Expand all Loading... |
1189 // to inlining in optimized code, that function may not correspond to the | 1190 // to inlining in optimized code, that function may not correspond to the |
1190 // top-level function (parsed_function().function()) which could be | 1191 // top-level function (parsed_function().function()) which could be |
1191 // reoptimized and which counter needs to be incremented. | 1192 // reoptimized and which counter needs to be incremented. |
1192 // Pass the function explicitly, it is used in IC stub. | 1193 // Pass the function explicitly, it is used in IC stub. |
1193 | 1194 |
1194 __ LoadObject(R6, parsed_function().function()); | 1195 __ LoadObject(R6, parsed_function().function()); |
1195 __ LoadObject(R5, ic_data); | 1196 __ LoadObject(R5, ic_data); |
1196 GenerateDartCall(deopt_id, | 1197 GenerateDartCall(deopt_id, |
1197 token_pos, | 1198 token_pos, |
1198 target_label, | 1199 target_label, |
1199 PcDescriptors::kIcCall, | 1200 RawPcDescriptors::kIcCall, |
1200 locs); | 1201 locs); |
1201 __ Drop(argument_count); | 1202 __ Drop(argument_count); |
1202 } | 1203 } |
1203 | 1204 |
1204 | 1205 |
1205 void FlowGraphCompiler::EmitInstanceCall(ExternalLabel* target_label, | 1206 void FlowGraphCompiler::EmitInstanceCall(ExternalLabel* target_label, |
1206 const ICData& ic_data, | 1207 const ICData& ic_data, |
1207 intptr_t argument_count, | 1208 intptr_t argument_count, |
1208 intptr_t deopt_id, | 1209 intptr_t deopt_id, |
1209 intptr_t token_pos, | 1210 intptr_t token_pos, |
1210 LocationSummary* locs) { | 1211 LocationSummary* locs) { |
1211 ASSERT(Array::Handle(ic_data.arguments_descriptor()).Length() > 0); | 1212 ASSERT(Array::Handle(ic_data.arguments_descriptor()).Length() > 0); |
1212 __ LoadImmediate(R4, 0); | 1213 __ LoadImmediate(R4, 0); |
1213 __ LoadObject(R5, ic_data); | 1214 __ LoadObject(R5, ic_data); |
1214 GenerateDartCall(deopt_id, | 1215 GenerateDartCall(deopt_id, |
1215 token_pos, | 1216 token_pos, |
1216 target_label, | 1217 target_label, |
1217 PcDescriptors::kIcCall, | 1218 RawPcDescriptors::kIcCall, |
1218 locs); | 1219 locs); |
1219 __ Drop(argument_count); | 1220 __ Drop(argument_count); |
1220 #if defined(DEBUG) | 1221 #if defined(DEBUG) |
1221 __ LoadImmediate(R4, kInvalidObjectPointer); | 1222 __ LoadImmediate(R4, kInvalidObjectPointer); |
1222 #endif | 1223 #endif |
1223 } | 1224 } |
1224 | 1225 |
1225 | 1226 |
1226 void FlowGraphCompiler::EmitMegamorphicInstanceCall( | 1227 void FlowGraphCompiler::EmitMegamorphicInstanceCall( |
1227 const ICData& ic_data, | 1228 const ICData& ic_data, |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1270 // proper target for the given name and arguments descriptor. If the | 1271 // proper target for the given name and arguments descriptor. If the |
1271 // illegal class id was found, the target is a cache miss handler that can | 1272 // illegal class id was found, the target is a cache miss handler that can |
1272 // be invoked as a normal Dart function. | 1273 // be invoked as a normal Dart function. |
1273 __ add(IP, R2, Operand(R3, LSL, 2)); | 1274 __ add(IP, R2, Operand(R3, LSL, 2)); |
1274 __ ldr(R0, FieldAddress(IP, base + kWordSize)); | 1275 __ ldr(R0, FieldAddress(IP, base + kWordSize)); |
1275 __ ldr(R1, FieldAddress(R0, Function::instructions_offset())); | 1276 __ ldr(R1, FieldAddress(R0, Function::instructions_offset())); |
1276 __ LoadObject(R5, ic_data); | 1277 __ LoadObject(R5, ic_data); |
1277 __ LoadObject(R4, arguments_descriptor); | 1278 __ LoadObject(R4, arguments_descriptor); |
1278 __ AddImmediate(R1, Instructions::HeaderSize() - kHeapObjectTag); | 1279 __ AddImmediate(R1, Instructions::HeaderSize() - kHeapObjectTag); |
1279 __ blx(R1); | 1280 __ blx(R1); |
1280 AddCurrentDescriptor(PcDescriptors::kOther, Isolate::kNoDeoptId, token_pos); | 1281 AddCurrentDescriptor(RawPcDescriptors::kOther, |
| 1282 Isolate::kNoDeoptId, token_pos); |
1281 RecordSafepoint(locs); | 1283 RecordSafepoint(locs); |
1282 AddDeoptIndexAtCall(Isolate::ToDeoptAfter(deopt_id), token_pos); | 1284 AddDeoptIndexAtCall(Isolate::ToDeoptAfter(deopt_id), token_pos); |
1283 __ Drop(argument_count); | 1285 __ Drop(argument_count); |
1284 } | 1286 } |
1285 | 1287 |
1286 | 1288 |
1287 void FlowGraphCompiler::EmitUnoptimizedStaticCall( | 1289 void FlowGraphCompiler::EmitUnoptimizedStaticCall( |
1288 intptr_t argument_count, | 1290 intptr_t argument_count, |
1289 intptr_t deopt_id, | 1291 intptr_t deopt_id, |
1290 intptr_t token_pos, | 1292 intptr_t token_pos, |
1291 LocationSummary* locs, | 1293 LocationSummary* locs, |
1292 const ICData& ic_data) { | 1294 const ICData& ic_data) { |
1293 uword label_address = 0; | 1295 uword label_address = 0; |
1294 if (ic_data.NumArgsTested() == 0) { | 1296 if (ic_data.NumArgsTested() == 0) { |
1295 label_address = StubCode::ZeroArgsUnoptimizedStaticCallEntryPoint(); | 1297 label_address = StubCode::ZeroArgsUnoptimizedStaticCallEntryPoint(); |
1296 } else if (ic_data.NumArgsTested() == 2) { | 1298 } else if (ic_data.NumArgsTested() == 2) { |
1297 label_address = StubCode::TwoArgsUnoptimizedStaticCallEntryPoint(); | 1299 label_address = StubCode::TwoArgsUnoptimizedStaticCallEntryPoint(); |
1298 } else { | 1300 } else { |
1299 UNIMPLEMENTED(); | 1301 UNIMPLEMENTED(); |
1300 } | 1302 } |
1301 ExternalLabel target_label(label_address); | 1303 ExternalLabel target_label(label_address); |
1302 __ LoadImmediate(R4, 0); | 1304 __ LoadImmediate(R4, 0); |
1303 __ LoadObject(R5, ic_data); | 1305 __ LoadObject(R5, ic_data); |
1304 GenerateDartCall(deopt_id, | 1306 GenerateDartCall(deopt_id, |
1305 token_pos, | 1307 token_pos, |
1306 &target_label, | 1308 &target_label, |
1307 PcDescriptors::kUnoptStaticCall, | 1309 RawPcDescriptors::kUnoptStaticCall, |
1308 locs); | 1310 locs); |
1309 __ Drop(argument_count); | 1311 __ Drop(argument_count); |
1310 #if defined(DEBUG) | 1312 #if defined(DEBUG) |
1311 __ LoadImmediate(R4, kInvalidObjectPointer); | 1313 __ LoadImmediate(R4, kInvalidObjectPointer); |
1312 #endif | 1314 #endif |
1313 } | 1315 } |
1314 | 1316 |
1315 | 1317 |
1316 void FlowGraphCompiler::EmitOptimizedStaticCall( | 1318 void FlowGraphCompiler::EmitOptimizedStaticCall( |
1317 const Function& function, | 1319 const Function& function, |
1318 const Array& arguments_descriptor, | 1320 const Array& arguments_descriptor, |
1319 intptr_t argument_count, | 1321 intptr_t argument_count, |
1320 intptr_t deopt_id, | 1322 intptr_t deopt_id, |
1321 intptr_t token_pos, | 1323 intptr_t token_pos, |
1322 LocationSummary* locs) { | 1324 LocationSummary* locs) { |
1323 __ LoadObject(R4, arguments_descriptor); | 1325 __ LoadObject(R4, arguments_descriptor); |
1324 // Do not use the code from the function, but let the code be patched so that | 1326 // Do not use the code from the function, but let the code be patched so that |
1325 // we can record the outgoing edges to other code. | 1327 // we can record the outgoing edges to other code. |
1326 GenerateDartCall(deopt_id, | 1328 GenerateDartCall(deopt_id, |
1327 token_pos, | 1329 token_pos, |
1328 &StubCode::CallStaticFunctionLabel(), | 1330 &StubCode::CallStaticFunctionLabel(), |
1329 PcDescriptors::kOptStaticCall, | 1331 RawPcDescriptors::kOptStaticCall, |
1330 locs); | 1332 locs); |
1331 AddStaticCallTarget(function); | 1333 AddStaticCallTarget(function); |
1332 __ Drop(argument_count); | 1334 __ Drop(argument_count); |
1333 } | 1335 } |
1334 | 1336 |
1335 | 1337 |
1336 void FlowGraphCompiler::EmitEqualityRegConstCompare(Register reg, | 1338 void FlowGraphCompiler::EmitEqualityRegConstCompare(Register reg, |
1337 const Object& obj, | 1339 const Object& obj, |
1338 bool needs_number_check, | 1340 bool needs_number_check, |
1339 intptr_t token_pos) { | 1341 intptr_t token_pos) { |
1340 if (needs_number_check) { | 1342 if (needs_number_check) { |
1341 ASSERT(!obj.IsMint() && !obj.IsDouble() && !obj.IsBigint()); | 1343 ASSERT(!obj.IsMint() && !obj.IsDouble() && !obj.IsBigint()); |
1342 __ Push(reg); | 1344 __ Push(reg); |
1343 __ PushObject(obj); | 1345 __ PushObject(obj); |
1344 if (is_optimizing()) { | 1346 if (is_optimizing()) { |
1345 __ BranchLinkPatchable( | 1347 __ BranchLinkPatchable( |
1346 &StubCode::OptimizedIdenticalWithNumberCheckLabel()); | 1348 &StubCode::OptimizedIdenticalWithNumberCheckLabel()); |
1347 } else { | 1349 } else { |
1348 __ BranchLinkPatchable( | 1350 __ BranchLinkPatchable( |
1349 &StubCode::UnoptimizedIdenticalWithNumberCheckLabel()); | 1351 &StubCode::UnoptimizedIdenticalWithNumberCheckLabel()); |
1350 } | 1352 } |
1351 if (token_pos != Scanner::kNoSourcePos) { | 1353 if (token_pos != Scanner::kNoSourcePos) { |
1352 AddCurrentDescriptor(PcDescriptors::kRuntimeCall, | 1354 AddCurrentDescriptor(RawPcDescriptors::kRuntimeCall, |
1353 Isolate::kNoDeoptId, | 1355 Isolate::kNoDeoptId, |
1354 token_pos); | 1356 token_pos); |
1355 } | 1357 } |
1356 __ Drop(1); // Discard constant. | 1358 __ Drop(1); // Discard constant. |
1357 __ Pop(reg); // Restore 'reg'. | 1359 __ Pop(reg); // Restore 'reg'. |
1358 return; | 1360 return; |
1359 } | 1361 } |
1360 | 1362 |
1361 __ CompareObject(reg, obj); | 1363 __ CompareObject(reg, obj); |
1362 } | 1364 } |
1363 | 1365 |
1364 | 1366 |
1365 void FlowGraphCompiler::EmitEqualityRegRegCompare(Register left, | 1367 void FlowGraphCompiler::EmitEqualityRegRegCompare(Register left, |
1366 Register right, | 1368 Register right, |
1367 bool needs_number_check, | 1369 bool needs_number_check, |
1368 intptr_t token_pos) { | 1370 intptr_t token_pos) { |
1369 if (needs_number_check) { | 1371 if (needs_number_check) { |
1370 __ Push(left); | 1372 __ Push(left); |
1371 __ Push(right); | 1373 __ Push(right); |
1372 if (is_optimizing()) { | 1374 if (is_optimizing()) { |
1373 __ BranchLinkPatchable( | 1375 __ BranchLinkPatchable( |
1374 &StubCode::OptimizedIdenticalWithNumberCheckLabel()); | 1376 &StubCode::OptimizedIdenticalWithNumberCheckLabel()); |
1375 } else { | 1377 } else { |
1376 __ LoadImmediate(R4, 0); | 1378 __ LoadImmediate(R4, 0); |
1377 __ LoadImmediate(R5, 0); | 1379 __ LoadImmediate(R5, 0); |
1378 __ BranchLinkPatchable( | 1380 __ BranchLinkPatchable( |
1379 &StubCode::UnoptimizedIdenticalWithNumberCheckLabel()); | 1381 &StubCode::UnoptimizedIdenticalWithNumberCheckLabel()); |
1380 } | 1382 } |
1381 if (token_pos != Scanner::kNoSourcePos) { | 1383 if (token_pos != Scanner::kNoSourcePos) { |
1382 AddCurrentDescriptor(PcDescriptors::kRuntimeCall, | 1384 AddCurrentDescriptor(RawPcDescriptors::kRuntimeCall, |
1383 Isolate::kNoDeoptId, | 1385 Isolate::kNoDeoptId, |
1384 token_pos); | 1386 token_pos); |
1385 } | 1387 } |
1386 #if defined(DEBUG) | 1388 #if defined(DEBUG) |
1387 if (!is_optimizing()) { | 1389 if (!is_optimizing()) { |
1388 // Do this *after* adding the pc descriptor! | 1390 // Do this *after* adding the pc descriptor! |
1389 __ LoadImmediate(R4, kInvalidObjectPointer); | 1391 __ LoadImmediate(R4, kInvalidObjectPointer); |
1390 __ LoadImmediate(R5, kInvalidObjectPointer); | 1392 __ LoadImmediate(R5, kInvalidObjectPointer); |
1391 } | 1393 } |
1392 #endif | 1394 #endif |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1496 if (is_last_check) { | 1498 if (is_last_check) { |
1497 __ b(deopt, NE); | 1499 __ b(deopt, NE); |
1498 } else { | 1500 } else { |
1499 __ b(&next_test, NE); | 1501 __ b(&next_test, NE); |
1500 } | 1502 } |
1501 // Do not use the code from the function, but let the code be patched so | 1503 // Do not use the code from the function, but let the code be patched so |
1502 // that we can record the outgoing edges to other code. | 1504 // that we can record the outgoing edges to other code. |
1503 GenerateDartCall(deopt_id, | 1505 GenerateDartCall(deopt_id, |
1504 token_index, | 1506 token_index, |
1505 &StubCode::CallStaticFunctionLabel(), | 1507 &StubCode::CallStaticFunctionLabel(), |
1506 PcDescriptors::kOptStaticCall, | 1508 RawPcDescriptors::kOptStaticCall, |
1507 locs); | 1509 locs); |
1508 const Function& function = *sorted[i].target; | 1510 const Function& function = *sorted[i].target; |
1509 AddStaticCallTarget(function); | 1511 AddStaticCallTarget(function); |
1510 __ Drop(argument_count); | 1512 __ Drop(argument_count); |
1511 if (!is_last_check) { | 1513 if (!is_last_check) { |
1512 __ b(&match_found); | 1514 __ b(&match_found); |
1513 } | 1515 } |
1514 __ Bind(&next_test); | 1516 __ Bind(&next_test); |
1515 } | 1517 } |
1516 __ Bind(&match_found); | 1518 __ Bind(&match_found); |
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1762 DRegister dreg = EvenDRegisterOf(reg); | 1764 DRegister dreg = EvenDRegisterOf(reg); |
1763 __ vldrd(dreg, Address(SP, kDoubleSize, Address::PostIndex)); | 1765 __ vldrd(dreg, Address(SP, kDoubleSize, Address::PostIndex)); |
1764 } | 1766 } |
1765 | 1767 |
1766 | 1768 |
1767 #undef __ | 1769 #undef __ |
1768 | 1770 |
1769 } // namespace dart | 1771 } // namespace dart |
1770 | 1772 |
1771 #endif // defined TARGET_ARCH_ARM | 1773 #endif // defined TARGET_ARCH_ARM |
OLD | NEW |