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

Side by Side Diff: runtime/vm/stub_code_arm.cc

Issue 436643002: Faster IC stubs by specializing them for Binary Smi operations (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 4 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
OLDNEW
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" 5 #include "vm/globals.h"
6 #if defined(TARGET_ARCH_ARM) 6 #if defined(TARGET_ARCH_ARM)
7 7
8 #include "vm/assembler.h" 8 #include "vm/assembler.h"
9 #include "vm/code_generator.h" 9 #include "vm/code_generator.h"
10 #include "vm/cpu.h" 10 #include "vm/cpu.h"
(...skipping 1202 matching lines...) Expand 10 before | Expand all | Expand 10 after
1213 Register ic_reg = R5; 1213 Register ic_reg = R5;
1214 Register func_reg = temp_reg; 1214 Register func_reg = temp_reg;
1215 ASSERT(temp_reg == R6); 1215 ASSERT(temp_reg == R6);
1216 __ ldr(func_reg, FieldAddress(ic_reg, ICData::owner_offset())); 1216 __ ldr(func_reg, FieldAddress(ic_reg, ICData::owner_offset()));
1217 __ ldr(R7, FieldAddress(func_reg, Function::usage_counter_offset())); 1217 __ ldr(R7, FieldAddress(func_reg, Function::usage_counter_offset()));
1218 __ add(R7, R7, Operand(1)); 1218 __ add(R7, R7, Operand(1));
1219 __ str(R7, FieldAddress(func_reg, Function::usage_counter_offset())); 1219 __ str(R7, FieldAddress(func_reg, Function::usage_counter_offset()));
1220 } 1220 }
1221 1221
1222 1222
1223 // Note: R5 must be preserved.
1224 // Attempt a quick Smi operation for known operations ('kind'). The ICData
1225 // must have been primed with a Smi/Smi check that will be used for counting
1226 // the invocations.
1227 static void EmitFastSmiOp(Assembler* assembler,
1228 Token::Kind kind,
1229 intptr_t num_args,
1230 Label* not_smi_or_overflow) {
1231 __ ldr(R0, Address(SP, 0 * kWordSize));
1232 __ ldr(R1, Address(SP, 1 * kWordSize));
1233 __ orr(TMP, R0, Operand(R1));
1234 __ tst(TMP, Operand(kSmiTagMask));
1235 __ b(not_smi_or_overflow, NE);
1236 switch (kind) {
1237 case Token::kADD: {
1238 __ adds(R0, R1, Operand(R0)); // Adds.
1239 __ b(not_smi_or_overflow, VS); // Branch if overflow.
1240 break;
1241 }
1242 case Token::kSUB: {
1243 __ subs(R0, R1, Operand(R0)); // Subtract.
1244 __ b(not_smi_or_overflow, VS); // Branch if overflow.
1245 break;
1246 }
1247 case Token::kEQ: {
1248 __ cmp(R0, Operand(R1));
1249 __ LoadObject(R0, Bool::True(), EQ);
1250 __ LoadObject(R0, Bool::False(), NE);
1251 break;
1252 }
1253 default: UNIMPLEMENTED();
1254 }
1255 // R5: IC data object (preserved).
1256 __ ldr(R6, FieldAddress(R5, ICData::ic_data_offset()));
1257 // R6: ic_data_array with check entries: classes and target functions.
1258 __ AddImmediate(R6, R6, Array::data_offset() - kHeapObjectTag);
1259 // R6: points directly to the first ic data array element.
1260 #if defined(DEBUG)
1261 // Check that first entry is for Smi/Smi.
1262 Label error, ok;
1263 const intptr_t imm_smi_cid = reinterpret_cast<intptr_t>(Smi::New(kSmiCid));
1264 __ ldr(R1, Address(R6, 0));
1265 __ CompareImmediate(R1, imm_smi_cid);
1266 __ b(&error, NE);
1267 __ ldr(R1, Address(R6, kWordSize));
1268 __ CompareImmediate(R1, imm_smi_cid);
1269 __ b(&ok, EQ);
1270 __ Bind(&error);
1271 __ Stop("Incorrect IC data");
1272 __ Bind(&ok);
1273 #endif
1274 // Update counter.
1275 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize;
1276 __ LoadFromOffset(kWord, R1, R6, count_offset);
1277 __ adds(R1, R1, Operand(Smi::RawValue(1)));
1278 __ LoadImmediate(R1, Smi::RawValue(Smi::kMaxValue), VS); // Overflow.
1279 __ StoreToOffset(kWord, R1, R6, count_offset);
1280 __ Ret();
1281 }
1282
1283
1223 // Generate inline cache check for 'num_args'. 1284 // Generate inline cache check for 'num_args'.
1224 // LR: return address. 1285 // LR: return address.
1225 // R5: inline cache data object. 1286 // R5: inline cache data object.
1226 // Control flow: 1287 // Control flow:
1227 // - If receiver is null -> jump to IC miss. 1288 // - If receiver is null -> jump to IC miss.
1228 // - If receiver is Smi -> load Smi class. 1289 // - If receiver is Smi -> load Smi class.
1229 // - If receiver is not-Smi -> load receiver's class. 1290 // - If receiver is not-Smi -> load receiver's class.
1230 // - Check if 'num_args' (including receiver) match any IC data group. 1291 // - Check if 'num_args' (including receiver) match any IC data group.
1231 // - Match found -> jump to target. 1292 // - Match found -> jump to target.
1232 // - Match not found -> jump to IC miss. 1293 // - Match not found -> jump to IC miss.
1233 void StubCode::GenerateNArgsCheckInlineCacheStub( 1294 void StubCode::GenerateNArgsCheckInlineCacheStub(
1234 Assembler* assembler, 1295 Assembler* assembler,
1235 intptr_t num_args, 1296 intptr_t num_args,
1236 const RuntimeEntry& handle_ic_miss) { 1297 const RuntimeEntry& handle_ic_miss,
1298 Token::Kind kind) {
1237 ASSERT(num_args > 0); 1299 ASSERT(num_args > 0);
1238 #if defined(DEBUG) 1300 #if defined(DEBUG)
1239 { Label ok; 1301 { Label ok;
1240 // Check that the IC data array has NumArgsTested() == num_args. 1302 // Check that the IC data array has NumArgsTested() == num_args.
1241 // 'NumArgsTested' is stored in the least significant bits of 'state_bits'. 1303 // 'NumArgsTested' is stored in the least significant bits of 'state_bits'.
1242 __ ldr(R6, FieldAddress(R5, ICData::state_bits_offset())); 1304 __ ldr(R6, FieldAddress(R5, ICData::state_bits_offset()));
1243 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. 1305 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed.
1244 __ and_(R6, R6, Operand(ICData::NumArgsTestedMask())); 1306 __ and_(R6, R6, Operand(ICData::NumArgsTestedMask()));
1245 __ CompareImmediate(R6, num_args); 1307 __ CompareImmediate(R6, num_args);
1246 __ b(&ok, EQ); 1308 __ b(&ok, EQ);
1247 __ Stop("Incorrect stub for IC data"); 1309 __ Stop("Incorrect stub for IC data");
1248 __ Bind(&ok); 1310 __ Bind(&ok);
1249 } 1311 }
1250 #endif // DEBUG 1312 #endif // DEBUG
1251 1313
1252 Label stepping, done_stepping; 1314 Label stepping, done_stepping;
1253 1315
1254 // Check single stepping. 1316 // Check single stepping.
1255 __ ldr(R6, FieldAddress(CTX, Context::isolate_offset())); 1317 __ ldr(R6, FieldAddress(CTX, Context::isolate_offset()));
1256 __ ldrb(R6, Address(R6, Isolate::single_step_offset())); 1318 __ ldrb(R6, Address(R6, Isolate::single_step_offset()));
1257 __ CompareImmediate(R6, 0); 1319 __ CompareImmediate(R6, 0);
1258 __ b(&stepping, NE); 1320 __ b(&stepping, NE);
1259 __ Bind(&done_stepping); 1321 __ Bind(&done_stepping);
1260 1322
1323 if (kind != Token::kILLEGAL) {
1324 Label not_smi_or_overflow;
1325 EmitFastSmiOp(assembler, kind, num_args, &not_smi_or_overflow);
1326 __ Bind(&not_smi_or_overflow);
1327 }
1328
1261 // Load arguments descriptor into R4. 1329 // Load arguments descriptor into R4.
1262 __ ldr(R4, FieldAddress(R5, ICData::arguments_descriptor_offset())); 1330 __ ldr(R4, FieldAddress(R5, ICData::arguments_descriptor_offset()));
1263 // Loop that checks if there is an IC data match. 1331 // Loop that checks if there is an IC data match.
1264 Label loop, update, test, found; 1332 Label loop, update, test, found;
1265 // R5: IC data object (preserved). 1333 // R5: IC data object (preserved).
1266 __ ldr(R6, FieldAddress(R5, ICData::ic_data_offset())); 1334 __ ldr(R6, FieldAddress(R5, ICData::ic_data_offset()));
1267 // R6: ic_data_array with check entries: classes and target functions. 1335 // R6: ic_data_array with check entries: classes and target functions.
1268 __ AddImmediate(R6, R6, Array::data_offset() - kHeapObjectTag); 1336 __ AddImmediate(R6, R6, Array::data_offset() - kHeapObjectTag);
1269 // R6: points directly to the first ic data array element. 1337 // R6: points directly to the first ic data array element.
1270 1338
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
1375 // LR: return address. 1443 // LR: return address.
1376 // R5: inline cache data object. 1444 // R5: inline cache data object.
1377 // Inline cache data object structure: 1445 // Inline cache data object structure:
1378 // 0: function-name 1446 // 0: function-name
1379 // 1: N, number of arguments checked. 1447 // 1: N, number of arguments checked.
1380 // 2 .. (length - 1): group of checks, each check containing: 1448 // 2 .. (length - 1): group of checks, each check containing:
1381 // - N classes. 1449 // - N classes.
1382 // - 1 target function. 1450 // - 1 target function.
1383 void StubCode::GenerateOneArgCheckInlineCacheStub(Assembler* assembler) { 1451 void StubCode::GenerateOneArgCheckInlineCacheStub(Assembler* assembler) {
1384 GenerateUsageCounterIncrement(assembler, R6); 1452 GenerateUsageCounterIncrement(assembler, R6);
1385 GenerateNArgsCheckInlineCacheStub( 1453 GenerateNArgsCheckInlineCacheStub(assembler, 1,
1386 assembler, 1, kInlineCacheMissHandlerOneArgRuntimeEntry); 1454 kInlineCacheMissHandlerOneArgRuntimeEntry, Token::kILLEGAL);
1387 } 1455 }
1388 1456
1389 1457
1390 void StubCode::GenerateTwoArgsCheckInlineCacheStub(Assembler* assembler) { 1458 void StubCode::GenerateTwoArgsCheckInlineCacheStub(Assembler* assembler) {
1391 GenerateUsageCounterIncrement(assembler, R6); 1459 GenerateUsageCounterIncrement(assembler, R6);
1392 GenerateNArgsCheckInlineCacheStub( 1460 GenerateNArgsCheckInlineCacheStub(assembler, 2,
1393 assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry); 1461 kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL);
1394 } 1462 }
1395 1463
1396 1464
1397 void StubCode::GenerateThreeArgsCheckInlineCacheStub(Assembler* assembler) { 1465 void StubCode::GenerateThreeArgsCheckInlineCacheStub(Assembler* assembler) {
1398 GenerateUsageCounterIncrement(assembler, R6); 1466 GenerateUsageCounterIncrement(assembler, R6);
1399 GenerateNArgsCheckInlineCacheStub( 1467 GenerateNArgsCheckInlineCacheStub(assembler, 3,
1400 assembler, 3, kInlineCacheMissHandlerThreeArgsRuntimeEntry); 1468 kInlineCacheMissHandlerThreeArgsRuntimeEntry, Token::kILLEGAL);
1469 }
1470
1471
1472 void StubCode::GenerateSmiAddInlineCacheStub(Assembler* assembler) {
1473 GenerateUsageCounterIncrement(assembler, R6);
1474 GenerateNArgsCheckInlineCacheStub(assembler, 2,
1475 kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kADD);
1476 }
1477
1478
1479 void StubCode::GenerateSmiSubInlineCacheStub(Assembler* assembler) {
1480 GenerateUsageCounterIncrement(assembler, R6);
1481 GenerateNArgsCheckInlineCacheStub(assembler, 2,
1482 kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kSUB);
1483 }
1484
1485
1486 void StubCode::GenerateSmiEqualInlineCacheStub(Assembler* assembler) {
1487 GenerateUsageCounterIncrement(assembler, R6);
1488 GenerateNArgsCheckInlineCacheStub(assembler, 2,
1489 kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kEQ);
1401 } 1490 }
1402 1491
1403 1492
1404 void StubCode::GenerateOneArgOptimizedCheckInlineCacheStub( 1493 void StubCode::GenerateOneArgOptimizedCheckInlineCacheStub(
1405 Assembler* assembler) { 1494 Assembler* assembler) {
1406 GenerateOptimizedUsageCounterIncrement(assembler); 1495 GenerateOptimizedUsageCounterIncrement(assembler);
1407 GenerateNArgsCheckInlineCacheStub( 1496 GenerateNArgsCheckInlineCacheStub(assembler, 1,
1408 assembler, 1, kInlineCacheMissHandlerOneArgRuntimeEntry); 1497 kInlineCacheMissHandlerOneArgRuntimeEntry, Token::kILLEGAL);
1409 } 1498 }
1410 1499
1411 1500
1412 void StubCode::GenerateTwoArgsOptimizedCheckInlineCacheStub( 1501 void StubCode::GenerateTwoArgsOptimizedCheckInlineCacheStub(
1413 Assembler* assembler) { 1502 Assembler* assembler) {
1414 GenerateOptimizedUsageCounterIncrement(assembler); 1503 GenerateOptimizedUsageCounterIncrement(assembler);
1415 GenerateNArgsCheckInlineCacheStub( 1504 GenerateNArgsCheckInlineCacheStub(assembler, 2,
1416 assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry); 1505 kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL);
1417 } 1506 }
1418 1507
1419 1508
1420 void StubCode::GenerateThreeArgsOptimizedCheckInlineCacheStub( 1509 void StubCode::GenerateThreeArgsOptimizedCheckInlineCacheStub(
1421 Assembler* assembler) { 1510 Assembler* assembler) {
1422 GenerateOptimizedUsageCounterIncrement(assembler); 1511 GenerateOptimizedUsageCounterIncrement(assembler);
1423 GenerateNArgsCheckInlineCacheStub( 1512 GenerateNArgsCheckInlineCacheStub(assembler, 3,
1424 assembler, 3, kInlineCacheMissHandlerThreeArgsRuntimeEntry); 1513 kInlineCacheMissHandlerThreeArgsRuntimeEntry, Token::kILLEGAL);
1425 } 1514 }
1426 1515
1427 1516
1428 void StubCode::GenerateClosureCallInlineCacheStub(Assembler* assembler) { 1517 void StubCode::GenerateClosureCallInlineCacheStub(Assembler* assembler) {
1429 GenerateNArgsCheckInlineCacheStub( 1518 GenerateNArgsCheckInlineCacheStub(assembler, 1,
1430 assembler, 1, kInlineCacheMissHandlerOneArgRuntimeEntry); 1519 kInlineCacheMissHandlerOneArgRuntimeEntry, Token::kILLEGAL);
1431 } 1520 }
1432 1521
1433 1522
1434 // Intermediary stub between a static call and its target. ICData contains 1523 // Intermediary stub between a static call and its target. ICData contains
1435 // the target function and the call count. 1524 // the target function and the call count.
1436 // R5: ICData 1525 // R5: ICData
1437 void StubCode::GenerateZeroArgsUnoptimizedStaticCallStub(Assembler* assembler) { 1526 void StubCode::GenerateZeroArgsUnoptimizedStaticCallStub(Assembler* assembler) {
1438 GenerateUsageCounterIncrement(assembler, R6); 1527 GenerateUsageCounterIncrement(assembler, R6);
1439 #if defined(DEBUG) 1528 #if defined(DEBUG)
1440 { Label ok; 1529 { Label ok;
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
1490 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); 1579 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0);
1491 __ Pop(R5); 1580 __ Pop(R5);
1492 __ LeaveStubFrame(); 1581 __ LeaveStubFrame();
1493 __ b(&done_stepping); 1582 __ b(&done_stepping);
1494 } 1583 }
1495 1584
1496 1585
1497 void StubCode::GenerateOneArgUnoptimizedStaticCallStub(Assembler* assembler) { 1586 void StubCode::GenerateOneArgUnoptimizedStaticCallStub(Assembler* assembler) {
1498 GenerateUsageCounterIncrement(assembler, R6); 1587 GenerateUsageCounterIncrement(assembler, R6);
1499 GenerateNArgsCheckInlineCacheStub( 1588 GenerateNArgsCheckInlineCacheStub(
1500 assembler, 1, kStaticCallMissHandlerOneArgRuntimeEntry); 1589 assembler, 1, kStaticCallMissHandlerOneArgRuntimeEntry, Token::kILLEGAL);
1501 } 1590 }
1502 1591
1503 1592
1504 void StubCode::GenerateTwoArgsUnoptimizedStaticCallStub(Assembler* assembler) { 1593 void StubCode::GenerateTwoArgsUnoptimizedStaticCallStub(Assembler* assembler) {
1505 GenerateUsageCounterIncrement(assembler, R6); 1594 GenerateUsageCounterIncrement(assembler, R6);
1506 GenerateNArgsCheckInlineCacheStub( 1595 GenerateNArgsCheckInlineCacheStub(assembler, 2,
1507 assembler, 2, kStaticCallMissHandlerTwoArgsRuntimeEntry); 1596 kStaticCallMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL);
1508 } 1597 }
1509 1598
1510 1599
1511 // Stub for compiling a function and jumping to the compiled code. 1600 // Stub for compiling a function and jumping to the compiled code.
1512 // R5: IC-Data (for methods). 1601 // R5: IC-Data (for methods).
1513 // R4: Arguments descriptor. 1602 // R4: Arguments descriptor.
1514 // R0: Function. 1603 // R0: Function.
1515 void StubCode::GenerateLazyCompileStub(Assembler* assembler) { 1604 void StubCode::GenerateLazyCompileStub(Assembler* assembler) {
1516 // Preserve arg desc. and IC data object. 1605 // Preserve arg desc. and IC data object.
1517 __ EnterStubFrame(); 1606 __ EnterStubFrame();
(...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after
1867 const Register right = R0; 1956 const Register right = R0;
1868 __ ldr(left, Address(SP, 1 * kWordSize)); 1957 __ ldr(left, Address(SP, 1 * kWordSize));
1869 __ ldr(right, Address(SP, 0 * kWordSize)); 1958 __ ldr(right, Address(SP, 0 * kWordSize));
1870 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); 1959 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp);
1871 __ Ret(); 1960 __ Ret();
1872 } 1961 }
1873 1962
1874 } // namespace dart 1963 } // namespace dart
1875 1964
1876 #endif // defined TARGET_ARCH_ARM 1965 #endif // defined TARGET_ARCH_ARM
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698