Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(428)

Side by Side Diff: src/a64/simulator-a64.cc

Issue 138913010: A64: Make the simulator sampling friendly. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/a64
Patch Set: Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/a64/simulator-a64.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 1217 matching lines...) Expand 10 before | Expand all | Expand 10 after
1228 int64_t offset = ExtendValue(kXRegSize, xreg(instr->Rm()), ext, 1228 int64_t offset = ExtendValue(kXRegSize, xreg(instr->Rm()), ext,
1229 shift_amount); 1229 shift_amount);
1230 LoadStoreHelper(instr, offset, Offset); 1230 LoadStoreHelper(instr, offset, Offset);
1231 } 1231 }
1232 1232
1233 1233
1234 void Simulator::LoadStoreHelper(Instruction* instr, 1234 void Simulator::LoadStoreHelper(Instruction* instr,
1235 int64_t offset, 1235 int64_t offset,
1236 AddrMode addrmode) { 1236 AddrMode addrmode) {
1237 unsigned srcdst = instr->Rt(); 1237 unsigned srcdst = instr->Rt();
1238 uint8_t* address = AddressModeHelper(instr->Rn(), offset, addrmode); 1238 unsigned addr_reg = instr->Rn();
1239 uint8_t* address = LoadStoreAddress(addr_reg, offset, addrmode);
1239 int num_bytes = 1 << instr->SizeLS(); 1240 int num_bytes = 1 << instr->SizeLS();
1241 uint8_t* stack = NULL;
1240 1242
1241 // Accesses below the stack pointer (but above the platform stack limit) are 1243 // Handle the writeback for stores before the store. On a CPU the writeback
1242 // not allowed in the ABI. 1244 // and the store are atomic, but when running on the simulator it is possible
1243 uint64_t access_address = reinterpret_cast<uint64_t>(address); 1245 // to be interrupted in between. The simulator is not thread safe and V8 does
1244 uint64_t stack_limit = reinterpret_cast<uint64_t>(stack_limit_); 1246 // not require it to be to run JavaScript therefore the profiler may sample
1245 uint64_t stack_address = sp(); 1247 // the "simulated" CPU in the middle of load/store with writeback. The code
1246 if ((access_address >= stack_limit) && (access_address < stack_address)) { 1248 // below ensures that push operations are safe even when interrupted: the
1247 fprintf(stream_, "ACCESS BELOW STACK POINTER:\n"); 1249 // stack pointer will be decremented before adding an element to the stack.
1248 fprintf(stream_, " sp is here: 0x%016" PRIx64 "\n", 1250 if (instr->IsStore()) {
1249 stack_address); 1251 LoadStoreWriteBack(addr_reg, offset, addrmode);
1250 fprintf(stream_, " access was here: 0x%016" PRIx64 "\n", 1252
1251 access_address); 1253 // For store the address post writeback is used to check access below the
1252 fprintf(stream_, " stack limit is here: 0x%016" PRIx64 "\n", stack_limit); 1254 // stack.
1253 fprintf(stream_, "\n"); 1255 stack = reinterpret_cast<uint8_t*>(sp());
1254 ABORT();
1255 } 1256 }
1256 1257
1257 LoadStoreOp op = static_cast<LoadStoreOp>(instr->Mask(LoadStoreOpMask)); 1258 LoadStoreOp op = static_cast<LoadStoreOp>(instr->Mask(LoadStoreOpMask));
1258 switch (op) { 1259 switch (op) {
1259 case LDRB_w: 1260 case LDRB_w:
1260 case LDRH_w: 1261 case LDRH_w:
1261 case LDR_w: 1262 case LDR_w:
1262 case LDR_x: set_xreg(srcdst, MemoryRead(address, num_bytes)); break; 1263 case LDR_x: set_xreg(srcdst, MemoryRead(address, num_bytes)); break;
1263 case STRB_w: 1264 case STRB_w:
1264 case STRH_w: 1265 case STRH_w:
(...skipping 18 matching lines...) Expand all
1283 case LDRSW_x: { 1284 case LDRSW_x: {
1284 set_xreg(srcdst, ExtendValue(kXRegSize, MemoryRead32(address), SXTW)); 1285 set_xreg(srcdst, ExtendValue(kXRegSize, MemoryRead32(address), SXTW));
1285 break; 1286 break;
1286 } 1287 }
1287 case LDR_s: set_sreg(srcdst, MemoryReadFP32(address)); break; 1288 case LDR_s: set_sreg(srcdst, MemoryReadFP32(address)); break;
1288 case LDR_d: set_dreg(srcdst, MemoryReadFP64(address)); break; 1289 case LDR_d: set_dreg(srcdst, MemoryReadFP64(address)); break;
1289 case STR_s: MemoryWriteFP32(address, sreg(srcdst)); break; 1290 case STR_s: MemoryWriteFP32(address, sreg(srcdst)); break;
1290 case STR_d: MemoryWriteFP64(address, dreg(srcdst)); break; 1291 case STR_d: MemoryWriteFP64(address, dreg(srcdst)); break;
1291 default: UNIMPLEMENTED(); 1292 default: UNIMPLEMENTED();
1292 } 1293 }
1294
1295 // Handle the writeback for loads after the load to ensure safe pop
1296 // operation even when interrupted in the middle of it. The stack pointer
1297 // is only updated after the load so pop(fp) will never break the invariant
1298 // sp <= fp expected while walking the stack in the sampler.
1299 if (instr->IsLoad()) {
1300 // For loads the address pre writeback is used to check access below the
1301 // stack.
1302 stack = reinterpret_cast<uint8_t*>(sp());
1303
1304 LoadStoreWriteBack(addr_reg, offset, addrmode);
1305 }
1306
1307 // Accesses below the stack pointer (but above the platform stack limit) are
1308 // not allowed in the ABI.
1309 CheckMemoryAccess(address, stack);
1293 } 1310 }
1294 1311
1295 1312
1296 void Simulator::VisitLoadStorePairOffset(Instruction* instr) { 1313 void Simulator::VisitLoadStorePairOffset(Instruction* instr) {
1297 LoadStorePairHelper(instr, Offset); 1314 LoadStorePairHelper(instr, Offset);
1298 } 1315 }
1299 1316
1300 1317
1301 void Simulator::VisitLoadStorePairPreIndex(Instruction* instr) { 1318 void Simulator::VisitLoadStorePairPreIndex(Instruction* instr) {
1302 LoadStorePairHelper(instr, PreIndex); 1319 LoadStorePairHelper(instr, PreIndex);
1303 } 1320 }
1304 1321
1305 1322
1306 void Simulator::VisitLoadStorePairPostIndex(Instruction* instr) { 1323 void Simulator::VisitLoadStorePairPostIndex(Instruction* instr) {
1307 LoadStorePairHelper(instr, PostIndex); 1324 LoadStorePairHelper(instr, PostIndex);
1308 } 1325 }
1309 1326
1310 1327
1311 void Simulator::VisitLoadStorePairNonTemporal(Instruction* instr) { 1328 void Simulator::VisitLoadStorePairNonTemporal(Instruction* instr) {
1312 LoadStorePairHelper(instr, Offset); 1329 LoadStorePairHelper(instr, Offset);
1313 } 1330 }
1314 1331
1315 1332
1316 void Simulator::LoadStorePairHelper(Instruction* instr, 1333 void Simulator::LoadStorePairHelper(Instruction* instr,
1317 AddrMode addrmode) { 1334 AddrMode addrmode) {
1318 unsigned rt = instr->Rt(); 1335 unsigned rt = instr->Rt();
1319 unsigned rt2 = instr->Rt2(); 1336 unsigned rt2 = instr->Rt2();
1337 unsigned addr_reg = instr->Rn();
1320 int offset = instr->ImmLSPair() << instr->SizeLSPair(); 1338 int offset = instr->ImmLSPair() << instr->SizeLSPair();
1321 uint8_t* address = AddressModeHelper(instr->Rn(), offset, addrmode); 1339 uint8_t* address = LoadStoreAddress(addr_reg, offset, addrmode);
1340 uint8_t* stack = NULL;
1341
1342 // Handle the writeback for stores before the store. On a CPU the writeback
1343 // and the store are atomic, but when running on the simulator it is possible
1344 // to be interrupted in between. The simulator is not thread safe and V8 does
1345 // not require it to be to run JavaScript therefore the profiler may sample
1346 // the "simulated" CPU in the middle of load/store with writeback. The code
1347 // below ensures that push operations are safe even when interrupted: the
1348 // stack pointer will be decremented before adding an element to the stack.
1349 if (instr->IsStore()) {
1350 LoadStoreWriteBack(addr_reg, offset, addrmode);
1351
1352 // For store the address post writeback is used to check access below the
1353 // stack.
1354 stack = reinterpret_cast<uint8_t*>(sp());
1355 }
1322 1356
1323 LoadStorePairOp op = 1357 LoadStorePairOp op =
1324 static_cast<LoadStorePairOp>(instr->Mask(LoadStorePairMask)); 1358 static_cast<LoadStorePairOp>(instr->Mask(LoadStorePairMask));
1325 1359
1326 // 'rt' and 'rt2' can only be aliased for stores. 1360 // 'rt' and 'rt2' can only be aliased for stores.
1327 ASSERT(((op & LoadStorePairLBit) == 0) || (rt != rt2)); 1361 ASSERT(((op & LoadStorePairLBit) == 0) || (rt != rt2));
1328 1362
1329 switch (op) { 1363 switch (op) {
1330 case LDP_w: { 1364 case LDP_w: {
1331 set_wreg(rt, MemoryRead32(address)); 1365 set_wreg(rt, MemoryRead32(address));
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
1368 MemoryWrite64(address + kXRegSizeInBytes, xreg(rt2)); 1402 MemoryWrite64(address + kXRegSizeInBytes, xreg(rt2));
1369 break; 1403 break;
1370 } 1404 }
1371 case STP_d: { 1405 case STP_d: {
1372 MemoryWriteFP64(address, dreg(rt)); 1406 MemoryWriteFP64(address, dreg(rt));
1373 MemoryWriteFP64(address + kDRegSizeInBytes, dreg(rt2)); 1407 MemoryWriteFP64(address + kDRegSizeInBytes, dreg(rt2));
1374 break; 1408 break;
1375 } 1409 }
1376 default: UNREACHABLE(); 1410 default: UNREACHABLE();
1377 } 1411 }
1412
1413 // Handle the writeback for loads after the load to ensure safe pop
1414 // operation even when interrupted in the middle of it. The stack pointer
1415 // is only updated after the load so pop(fp) will never break the invariant
1416 // sp <= fp expected while walking the stack in the sampler.
1417 if (instr->IsLoad()) {
1418 // For loads the address pre writeback is used to check access below the
1419 // stack.
1420 stack = reinterpret_cast<uint8_t*>(sp());
1421
1422 LoadStoreWriteBack(addr_reg, offset, addrmode);
1423 }
1424
1425 // Accesses below the stack pointer (but above the platform stack limit) are
1426 // not allowed in the ABI.
1427 CheckMemoryAccess(address, stack);
1378 } 1428 }
1379 1429
1380 1430
1381 void Simulator::VisitLoadLiteral(Instruction* instr) { 1431 void Simulator::VisitLoadLiteral(Instruction* instr) {
1382 uint8_t* address = instr->LiteralAddress(); 1432 uint8_t* address = instr->LiteralAddress();
1383 unsigned rt = instr->Rt(); 1433 unsigned rt = instr->Rt();
1384 1434
1385 switch (instr->Mask(LoadLiteralMask)) { 1435 switch (instr->Mask(LoadLiteralMask)) {
1386 case LDR_w_lit: set_wreg(rt, MemoryRead32(address)); break; 1436 case LDR_w_lit: set_wreg(rt, MemoryRead32(address)); break;
1387 case LDR_x_lit: set_xreg(rt, MemoryRead64(address)); break; 1437 case LDR_x_lit: set_xreg(rt, MemoryRead64(address)); break;
1388 case LDR_s_lit: set_sreg(rt, MemoryReadFP32(address)); break; 1438 case LDR_s_lit: set_sreg(rt, MemoryReadFP32(address)); break;
1389 case LDR_d_lit: set_dreg(rt, MemoryReadFP64(address)); break; 1439 case LDR_d_lit: set_dreg(rt, MemoryReadFP64(address)); break;
1390 default: UNREACHABLE(); 1440 default: UNREACHABLE();
1391 } 1441 }
1392 } 1442 }
1393 1443
1394 1444
1395 uint8_t* Simulator::AddressModeHelper(unsigned addr_reg, 1445 uint8_t* Simulator::LoadStoreAddress(unsigned addr_reg,
1396 int64_t offset, 1446 int64_t offset,
1397 AddrMode addrmode) { 1447 AddrMode addrmode) {
1398 uint64_t address = xreg(addr_reg, Reg31IsStackPointer); 1448 const unsigned kSPRegCode = kSPRegInternalCode & kRegCodeMask;
1399 ASSERT((sizeof(uintptr_t) == kXRegSizeInBytes) || 1449 int64_t address = xreg(addr_reg, Reg31IsStackPointer);
1400 (address < 0x100000000UL)); 1450 if ((addr_reg == kSPRegCode) && ((address % 16) != 0)) {
1401 if ((addr_reg == 31) && ((address % 16) != 0)) {
1402 // When the base register is SP the stack pointer is required to be 1451 // When the base register is SP the stack pointer is required to be
1403 // quadword aligned prior to the address calculation and write-backs. 1452 // quadword aligned prior to the address calculation and write-backs.
1404 // Misalignment will cause a stack alignment fault. 1453 // Misalignment will cause a stack alignment fault.
1405 ALIGNMENT_EXCEPTION(); 1454 ALIGNMENT_EXCEPTION();
1406 } 1455 }
1407 if ((addrmode == PreIndex) || (addrmode == PostIndex)) {
1408 ASSERT(offset != 0);
1409 set_xreg(addr_reg, address + offset, Reg31IsStackPointer);
1410 }
1411 1456
1412 if ((addrmode == Offset) || (addrmode == PreIndex)) { 1457 if ((addrmode == Offset) || (addrmode == PreIndex)) {
1413 address += offset; 1458 address += offset;
1414 } 1459 }
1415 1460
1416 return reinterpret_cast<uint8_t*>(address); 1461 return reinterpret_cast<uint8_t*>(address);
1417 } 1462 }
1418 1463
1419 1464
1465 void Simulator::LoadStoreWriteBack(unsigned addr_reg,
1466 int64_t offset,
1467 AddrMode addrmode) {
1468 if ((addrmode == PreIndex) || (addrmode == PostIndex)) {
1469 ASSERT(offset != 0);
1470 uint64_t address = xreg(addr_reg, Reg31IsStackPointer);
1471 set_reg(addr_reg, address + offset, Reg31IsStackPointer);
1472 }
1473 }
1474
1475
1476 void Simulator::CheckMemoryAccess(uint8_t* address, uint8_t* stack) {
1477 if ((address >= stack_limit_) && (address < stack)) {
1478 fprintf(stream_, "ACCESS BELOW STACK POINTER:\n");
1479 fprintf(stream_, " sp is here: 0x%16p\n", stack);
1480 fprintf(stream_, " access was here: 0x%16p\n", address);
1481 fprintf(stream_, " stack limit is here: 0x%16p\n", stack_limit_);
1482 fprintf(stream_, "\n");
1483 ABORT();
1484 }
1485 }
1486
1487
1420 uint64_t Simulator::MemoryRead(uint8_t* address, unsigned num_bytes) { 1488 uint64_t Simulator::MemoryRead(uint8_t* address, unsigned num_bytes) {
1421 ASSERT(address != NULL); 1489 ASSERT(address != NULL);
1422 ASSERT((num_bytes > 0) && (num_bytes <= sizeof(uint64_t))); 1490 ASSERT((num_bytes > 0) && (num_bytes <= sizeof(uint64_t)));
1423 uint64_t read = 0; 1491 uint64_t read = 0;
1424 memcpy(&read, address, num_bytes); 1492 memcpy(&read, address, num_bytes);
1425 return read; 1493 return read;
1426 } 1494 }
1427 1495
1428 1496
1429 uint8_t Simulator::MemoryRead8(uint8_t* address) { 1497 uint8_t Simulator::MemoryRead8(uint8_t* address) {
(...skipping 1922 matching lines...) Expand 10 before | Expand all | Expand 10 after
3352 default: 3420 default:
3353 UNIMPLEMENTED(); 3421 UNIMPLEMENTED();
3354 } 3422 }
3355 } 3423 }
3356 3424
3357 #endif // USE_SIMULATOR 3425 #endif // USE_SIMULATOR
3358 3426
3359 } } // namespace v8::internal 3427 } } // namespace v8::internal
3360 3428
3361 #endif // V8_TARGET_ARCH_A64 3429 #endif // V8_TARGET_ARCH_A64
OLDNEW
« no previous file with comments | « src/a64/simulator-a64.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698