| 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_MIPS. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_MIPS. |
| 6 #if defined(TARGET_ARCH_MIPS) | 6 #if defined(TARGET_ARCH_MIPS) |
| 7 | 7 |
| 8 #include "vm/flow_graph_compiler.h" | 8 #include "vm/flow_graph_compiler.h" |
| 9 | 9 |
| 10 #include "lib/error.h" | 10 #include "lib/error.h" |
| 11 #include "vm/ast_printer.h" | 11 #include "vm/ast_printer.h" |
| 12 #include "vm/dart_entry.h" | 12 #include "vm/dart_entry.h" |
| 13 #include "vm/il_printer.h" | 13 #include "vm/il_printer.h" |
| 14 #include "vm/locations.h" | 14 #include "vm/locations.h" |
| 15 #include "vm/object_store.h" | 15 #include "vm/object_store.h" |
| 16 #include "vm/parser.h" | 16 #include "vm/parser.h" |
| 17 #include "vm/stub_code.h" | 17 #include "vm/stub_code.h" |
| 18 #include "vm/symbols.h" | 18 #include "vm/symbols.h" |
| 19 | 19 |
| 20 namespace dart { | 20 namespace dart { |
| 21 | 21 |
| 22 DEFINE_FLAG(bool, trap_on_deoptimization, false, "Trap on deoptimization."); |
| 22 DECLARE_FLAG(int, optimization_counter_threshold); | 23 DECLARE_FLAG(int, optimization_counter_threshold); |
| 23 DECLARE_FLAG(bool, print_ast); | 24 DECLARE_FLAG(bool, print_ast); |
| 24 DECLARE_FLAG(bool, print_scopes); | 25 DECLARE_FLAG(bool, print_scopes); |
| 25 DECLARE_FLAG(bool, enable_type_checks); | 26 DECLARE_FLAG(bool, enable_type_checks); |
| 26 DECLARE_FLAG(bool, eliminate_type_checks); | 27 DECLARE_FLAG(bool, eliminate_type_checks); |
| 27 | 28 |
| 28 | 29 |
| 29 FlowGraphCompiler::~FlowGraphCompiler() { | 30 FlowGraphCompiler::~FlowGraphCompiler() { |
| 30 // BlockInfos are zone-allocated, so their destructors are not called. | 31 // BlockInfos are zone-allocated, so their destructors are not called. |
| 31 // Verify the labels explicitly here. | 32 // Verify the labels explicitly here. |
| 32 for (int i = 0; i < block_info_.length(); ++i) { | 33 for (int i = 0; i < block_info_.length(); ++i) { |
| 33 ASSERT(!block_info_[i]->jump_label()->IsLinked()); | 34 ASSERT(!block_info_[i]->jump_label()->IsLinked()); |
| 34 } | 35 } |
| 35 } | 36 } |
| 36 | 37 |
| 37 | 38 |
| 38 bool FlowGraphCompiler::SupportsUnboxedMints() { | 39 bool FlowGraphCompiler::SupportsUnboxedMints() { |
| 39 return false; | 40 return false; |
| 40 } | 41 } |
| 41 | 42 |
| 42 | 43 |
| 43 void CompilerDeoptInfoWithStub::GenerateCode(FlowGraphCompiler* compiler, | 44 void CompilerDeoptInfoWithStub::GenerateCode(FlowGraphCompiler* compiler, |
| 44 intptr_t stub_ix) { | 45 intptr_t stub_ix) { |
| 45 UNIMPLEMENTED(); | 46 // Calls do not need stubs, they share a deoptimization trampoline. |
| 47 ASSERT(reason() != kDeoptAtCall); |
| 48 Assembler* assem = compiler->assembler(); |
| 49 #define __ assem-> |
| 50 __ Comment("Deopt stub for id %"Pd"", deopt_id()); |
| 51 __ Bind(entry_label()); |
| 52 if (FLAG_trap_on_deoptimization) __ break_(0); |
| 53 |
| 54 ASSERT(deoptimization_env() != NULL); |
| 55 |
| 56 __ BranchLink(&StubCode::DeoptimizeLabel()); |
| 57 set_pc_offset(assem->CodeSize()); |
| 58 #undef __ |
| 46 } | 59 } |
| 47 | 60 |
| 48 | 61 |
| 49 #define __ assembler()-> | 62 #define __ assembler()-> |
| 50 | 63 |
| 51 | 64 |
| 52 // Fall through if bool_register contains null. | 65 // Fall through if bool_register contains null. |
| 53 void FlowGraphCompiler::GenerateBoolToJump(Register bool_register, | 66 void FlowGraphCompiler::GenerateBoolToJump(Register bool_register, |
| 54 Label* is_true, | 67 Label* is_true, |
| 55 Label* is_false) { | 68 Label* is_false) { |
| (...skipping 1091 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1147 | 1160 |
| 1148 Address FlowGraphCompiler::ExternalElementAddressForRegIndex( | 1161 Address FlowGraphCompiler::ExternalElementAddressForRegIndex( |
| 1149 intptr_t index_scale, | 1162 intptr_t index_scale, |
| 1150 Register array, | 1163 Register array, |
| 1151 Register index) { | 1164 Register index) { |
| 1152 UNIMPLEMENTED(); | 1165 UNIMPLEMENTED(); |
| 1153 return FieldAddress(array, index); | 1166 return FieldAddress(array, index); |
| 1154 } | 1167 } |
| 1155 | 1168 |
| 1156 | 1169 |
| 1170 #undef __ |
| 1171 #define __ compiler_->assembler()-> |
| 1172 |
| 1173 |
| 1157 void ParallelMoveResolver::EmitMove(int index) { | 1174 void ParallelMoveResolver::EmitMove(int index) { |
| 1158 UNIMPLEMENTED(); | 1175 MoveOperands* move = moves_[index]; |
| 1176 const Location source = move->src(); |
| 1177 const Location destination = move->dest(); |
| 1178 |
| 1179 if (source.IsRegister()) { |
| 1180 if (destination.IsRegister()) { |
| 1181 __ mov(destination.reg(), source.reg()); |
| 1182 } else { |
| 1183 ASSERT(destination.IsStackSlot()); |
| 1184 __ sw(source.reg(), destination.ToStackSlotAddress()); |
| 1185 } |
| 1186 } else if (source.IsStackSlot()) { |
| 1187 if (destination.IsRegister()) { |
| 1188 __ lw(destination.reg(), source.ToStackSlotAddress()); |
| 1189 } else { |
| 1190 ASSERT(destination.IsStackSlot()); |
| 1191 MoveMemoryToMemory(destination.ToStackSlotAddress(), |
| 1192 source.ToStackSlotAddress()); |
| 1193 } |
| 1194 } else if (source.IsFpuRegister()) { |
| 1195 if (destination.IsFpuRegister()) { |
| 1196 __ movd(destination.fpu_reg(), source.fpu_reg()); |
| 1197 } else { |
| 1198 if (destination.IsDoubleStackSlot()) { |
| 1199 __ sdc1(source.fpu_reg(), destination.ToStackSlotAddress()); |
| 1200 } else { |
| 1201 ASSERT(destination.IsQuadStackSlot()); |
| 1202 UNIMPLEMENTED(); |
| 1203 } |
| 1204 } |
| 1205 } else if (source.IsDoubleStackSlot()) { |
| 1206 if (destination.IsFpuRegister()) { |
| 1207 __ ldc1(destination.fpu_reg(), source.ToStackSlotAddress()); |
| 1208 } else { |
| 1209 ASSERT(destination.IsDoubleStackSlot()); |
| 1210 __ ldc1(FpuTMP, source.ToStackSlotAddress()); |
| 1211 __ sdc1(FpuTMP, destination.ToStackSlotAddress()); |
| 1212 } |
| 1213 } else if (source.IsQuadStackSlot()) { |
| 1214 UNIMPLEMENTED(); |
| 1215 } else { |
| 1216 ASSERT(source.IsConstant()); |
| 1217 if (destination.IsRegister()) { |
| 1218 const Object& constant = source.constant(); |
| 1219 __ LoadObject(destination.reg(), constant); |
| 1220 } else { |
| 1221 ASSERT(destination.IsStackSlot()); |
| 1222 StoreObject(destination.ToStackSlotAddress(), source.constant()); |
| 1223 } |
| 1224 } |
| 1225 |
| 1226 move->Eliminate(); |
| 1159 } | 1227 } |
| 1160 | 1228 |
| 1161 | 1229 |
| 1162 void ParallelMoveResolver::EmitSwap(int index) { | 1230 void ParallelMoveResolver::EmitSwap(int index) { |
| 1163 UNIMPLEMENTED(); | 1231 MoveOperands* move = moves_[index]; |
| 1232 const Location source = move->src(); |
| 1233 const Location destination = move->dest(); |
| 1234 |
| 1235 if (source.IsRegister() && destination.IsRegister()) { |
| 1236 ASSERT(source.reg() != TMP1); |
| 1237 ASSERT(destination.reg() != TMP1); |
| 1238 __ mov(TMP1, source.reg()); |
| 1239 __ mov(source.reg(), destination.reg()); |
| 1240 __ mov(destination.reg(), TMP1); |
| 1241 } else if (source.IsRegister() && destination.IsStackSlot()) { |
| 1242 Exchange(source.reg(), destination.ToStackSlotAddress()); |
| 1243 } else if (source.IsStackSlot() && destination.IsRegister()) { |
| 1244 Exchange(destination.reg(), source.ToStackSlotAddress()); |
| 1245 } else if (source.IsStackSlot() && destination.IsStackSlot()) { |
| 1246 Exchange(destination.ToStackSlotAddress(), source.ToStackSlotAddress()); |
| 1247 } else if (source.IsFpuRegister() && destination.IsFpuRegister()) { |
| 1248 __ movd(FpuTMP, source.fpu_reg()); |
| 1249 __ movd(source.fpu_reg(), destination.fpu_reg()); |
| 1250 __ movd(destination.fpu_reg(), FpuTMP); |
| 1251 } else if (source.IsFpuRegister() || destination.IsFpuRegister()) { |
| 1252 ASSERT(destination.IsDoubleStackSlot() || |
| 1253 destination.IsQuadStackSlot() || |
| 1254 source.IsDoubleStackSlot() || |
| 1255 source.IsQuadStackSlot()); |
| 1256 bool double_width = destination.IsDoubleStackSlot() || |
| 1257 source.IsDoubleStackSlot(); |
| 1258 FRegister reg = source.IsFpuRegister() ? source.fpu_reg() |
| 1259 : destination.fpu_reg(); |
| 1260 const Address& slot_address = source.IsFpuRegister() |
| 1261 ? destination.ToStackSlotAddress() |
| 1262 : source.ToStackSlotAddress(); |
| 1263 |
| 1264 if (double_width) { |
| 1265 __ ldc1(FpuTMP, slot_address); |
| 1266 __ sdc1(reg, slot_address); |
| 1267 __ movd(reg, FpuTMP); |
| 1268 } else { |
| 1269 UNIMPLEMENTED(); |
| 1270 } |
| 1271 } else if (source.IsDoubleStackSlot() && destination.IsDoubleStackSlot()) { |
| 1272 const Address& source_slot_address = source.ToStackSlotAddress(); |
| 1273 const Address& destination_slot_address = destination.ToStackSlotAddress(); |
| 1274 |
| 1275 ScratchFpuRegisterScope ensure_scratch(this, FpuTMP); |
| 1276 __ ldc1(FpuTMP, source_slot_address); |
| 1277 __ ldc1(ensure_scratch.reg(), destination_slot_address); |
| 1278 __ sdc1(FpuTMP, destination_slot_address); |
| 1279 __ sdc1(ensure_scratch.reg(), source_slot_address); |
| 1280 } else if (source.IsQuadStackSlot() && destination.IsQuadStackSlot()) { |
| 1281 UNIMPLEMENTED(); |
| 1282 } else { |
| 1283 UNREACHABLE(); |
| 1284 } |
| 1285 |
| 1286 // The swap of source and destination has executed a move from source to |
| 1287 // destination. |
| 1288 move->Eliminate(); |
| 1289 |
| 1290 // Any unperformed (including pending) move with a source of either |
| 1291 // this move's source or destination needs to have their source |
| 1292 // changed to reflect the state of affairs after the swap. |
| 1293 for (int i = 0; i < moves_.length(); ++i) { |
| 1294 const MoveOperands& other_move = *moves_[i]; |
| 1295 if (other_move.Blocks(source)) { |
| 1296 moves_[i]->set_src(destination); |
| 1297 } else if (other_move.Blocks(destination)) { |
| 1298 moves_[i]->set_src(source); |
| 1299 } |
| 1300 } |
| 1164 } | 1301 } |
| 1165 | 1302 |
| 1166 | 1303 |
| 1167 void ParallelMoveResolver::MoveMemoryToMemory(const Address& dst, | 1304 void ParallelMoveResolver::MoveMemoryToMemory(const Address& dst, |
| 1168 const Address& src) { | 1305 const Address& src) { |
| 1169 UNIMPLEMENTED(); | 1306 __ lw(TMP1, src); |
| 1307 __ sw(TMP1, dst); |
| 1170 } | 1308 } |
| 1171 | 1309 |
| 1172 | 1310 |
| 1173 void ParallelMoveResolver::StoreObject(const Address& dst, const Object& obj) { | 1311 void ParallelMoveResolver::StoreObject(const Address& dst, const Object& obj) { |
| 1174 UNIMPLEMENTED(); | 1312 __ LoadObject(TMP1, obj); |
| 1313 __ sw(TMP1, dst); |
| 1175 } | 1314 } |
| 1176 | 1315 |
| 1177 | 1316 |
| 1178 void ParallelMoveResolver::Exchange(Register reg, const Address& mem) { | 1317 void ParallelMoveResolver::Exchange(Register reg, const Address& mem) { |
| 1179 UNIMPLEMENTED(); | 1318 ASSERT(reg != TMP1); |
| 1319 __ mov(TMP1, reg); |
| 1320 __ lw(reg, mem); |
| 1321 __ sw(TMP1, mem); |
| 1180 } | 1322 } |
| 1181 | 1323 |
| 1182 | 1324 |
| 1183 void ParallelMoveResolver::Exchange(const Address& mem1, const Address& mem2) { | 1325 void ParallelMoveResolver::Exchange(const Address& mem1, const Address& mem2) { |
| 1184 UNIMPLEMENTED(); | 1326 ScratchRegisterScope ensure_scratch(this, TMP1); |
| 1327 __ lw(ensure_scratch.reg(), mem1); |
| 1328 __ lw(TMP1, mem2); |
| 1329 __ sw(ensure_scratch.reg(), mem2); |
| 1330 __ sw(TMP1, mem1); |
| 1185 } | 1331 } |
| 1186 | 1332 |
| 1187 | 1333 |
| 1188 void ParallelMoveResolver::SpillScratch(Register reg) { | 1334 void ParallelMoveResolver::SpillScratch(Register reg) { |
| 1189 UNIMPLEMENTED(); | 1335 __ Push(reg); |
| 1190 } | 1336 } |
| 1191 | 1337 |
| 1192 | 1338 |
| 1193 void ParallelMoveResolver::RestoreScratch(Register reg) { | 1339 void ParallelMoveResolver::RestoreScratch(Register reg) { |
| 1194 UNIMPLEMENTED(); | 1340 __ Pop(reg); |
| 1195 } | 1341 } |
| 1196 | 1342 |
| 1197 | 1343 |
| 1198 void ParallelMoveResolver::SpillFpuScratch(FpuRegister reg) { | 1344 void ParallelMoveResolver::SpillFpuScratch(FpuRegister reg) { |
| 1199 UNIMPLEMENTED(); | 1345 __ AddImmediate(SP, -kDoubleSize); |
| 1346 __ sdc1(reg, Address(SP)); |
| 1200 } | 1347 } |
| 1201 | 1348 |
| 1202 | 1349 |
| 1203 void ParallelMoveResolver::RestoreFpuScratch(FpuRegister reg) { | 1350 void ParallelMoveResolver::RestoreFpuScratch(FpuRegister reg) { |
| 1204 UNIMPLEMENTED(); | 1351 __ ldc1(reg, Address(SP)); |
| 1352 __ AddImmediate(SP, kDoubleSize); |
| 1205 } | 1353 } |
| 1206 | 1354 |
| 1207 | 1355 |
| 1356 #undef __ |
| 1357 |
| 1358 |
| 1208 } // namespace dart | 1359 } // namespace dart |
| 1209 | 1360 |
| 1210 #endif // defined TARGET_ARCH_MIPS | 1361 #endif // defined TARGET_ARCH_MIPS |
| OLD | NEW |