| 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" | 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 1231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1242 | 1242 |
| 1243 | 1243 |
| 1244 // Note: R5 must be preserved. | 1244 // Note: R5 must be preserved. |
| 1245 // Attempt a quick Smi operation for known operations ('kind'). The ICData | 1245 // Attempt a quick Smi operation for known operations ('kind'). The ICData |
| 1246 // must have been primed with a Smi/Smi check that will be used for counting | 1246 // must have been primed with a Smi/Smi check that will be used for counting |
| 1247 // the invocations. | 1247 // the invocations. |
| 1248 static void EmitFastSmiOp(Assembler* assembler, | 1248 static void EmitFastSmiOp(Assembler* assembler, |
| 1249 Token::Kind kind, | 1249 Token::Kind kind, |
| 1250 intptr_t num_args, | 1250 intptr_t num_args, |
| 1251 Label* not_smi_or_overflow) { | 1251 Label* not_smi_or_overflow) { |
| 1252 __ Comment("Fast Smi op"); |
| 1252 __ ldr(R0, Address(SP, 0 * kWordSize)); | 1253 __ ldr(R0, Address(SP, 0 * kWordSize)); |
| 1253 __ ldr(R1, Address(SP, 1 * kWordSize)); | 1254 __ ldr(R1, Address(SP, 1 * kWordSize)); |
| 1254 __ orr(TMP, R0, Operand(R1)); | 1255 __ orr(TMP, R0, Operand(R1)); |
| 1255 __ tst(TMP, Operand(kSmiTagMask)); | 1256 __ tst(TMP, Operand(kSmiTagMask)); |
| 1256 __ b(not_smi_or_overflow, NE); | 1257 __ b(not_smi_or_overflow, NE); |
| 1257 switch (kind) { | 1258 switch (kind) { |
| 1258 case Token::kADD: { | 1259 case Token::kADD: { |
| 1259 __ adds(R0, R1, Operand(R0)); // Adds. | 1260 __ adds(R0, R1, Operand(R0)); // Adds. |
| 1260 __ b(not_smi_or_overflow, VS); // Branch if overflow. | 1261 __ b(not_smi_or_overflow, VS); // Branch if overflow. |
| 1261 break; | 1262 break; |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1327 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. | 1328 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. |
| 1328 __ and_(R6, R6, Operand(ICData::NumArgsTestedMask())); | 1329 __ and_(R6, R6, Operand(ICData::NumArgsTestedMask())); |
| 1329 __ CompareImmediate(R6, num_args); | 1330 __ CompareImmediate(R6, num_args); |
| 1330 __ b(&ok, EQ); | 1331 __ b(&ok, EQ); |
| 1331 __ Stop("Incorrect stub for IC data"); | 1332 __ Stop("Incorrect stub for IC data"); |
| 1332 __ Bind(&ok); | 1333 __ Bind(&ok); |
| 1333 } | 1334 } |
| 1334 #endif // DEBUG | 1335 #endif // DEBUG |
| 1335 | 1336 |
| 1336 | 1337 |
| 1337 // Check single stepping. | 1338 __ Comment("Check single stepping"); |
| 1338 Label stepping, done_stepping; | 1339 Label stepping, done_stepping; |
| 1339 __ LoadIsolate(R6); | 1340 __ LoadIsolate(R6); |
| 1340 __ ldrb(R6, Address(R6, Isolate::single_step_offset())); | 1341 __ ldrb(R6, Address(R6, Isolate::single_step_offset())); |
| 1341 __ CompareImmediate(R6, 0); | 1342 __ CompareImmediate(R6, 0); |
| 1342 __ b(&stepping, NE); | 1343 __ b(&stepping, NE); |
| 1343 __ Bind(&done_stepping); | 1344 __ Bind(&done_stepping); |
| 1344 | 1345 |
| 1346 __ Comment("Range feedback collection"); |
| 1345 Label not_smi_or_overflow; | 1347 Label not_smi_or_overflow; |
| 1346 if (range_collection_mode == kCollectRanges) { | 1348 if (range_collection_mode == kCollectRanges) { |
| 1347 ASSERT((num_args == 1) || (num_args == 2)); | 1349 ASSERT((num_args == 1) || (num_args == 2)); |
| 1348 if (num_args == 2) { | 1350 if (num_args == 2) { |
| 1349 __ ldr(R0, Address(SP, 1 * kWordSize)); | 1351 __ ldr(R0, Address(SP, 1 * kWordSize)); |
| 1350 __ UpdateRangeFeedback(R0, 0, R5, R1, R4, ¬_smi_or_overflow); | 1352 __ UpdateRangeFeedback(R0, 0, R5, R1, R4, ¬_smi_or_overflow); |
| 1351 } | 1353 } |
| 1352 | 1354 |
| 1353 __ ldr(R0, Address(SP, 0 * kWordSize)); | 1355 __ ldr(R0, Address(SP, 0 * kWordSize)); |
| 1354 __ UpdateRangeFeedback(R0, num_args - 1, R5, R1, R4, ¬_smi_or_overflow); | 1356 __ UpdateRangeFeedback(R0, num_args - 1, R5, R1, R4, ¬_smi_or_overflow); |
| 1355 } | 1357 } |
| 1356 if (kind != Token::kILLEGAL) { | 1358 if (kind != Token::kILLEGAL) { |
| 1357 EmitFastSmiOp(assembler, kind, num_args, ¬_smi_or_overflow); | 1359 EmitFastSmiOp(assembler, kind, num_args, ¬_smi_or_overflow); |
| 1358 } | 1360 } |
| 1359 __ Bind(¬_smi_or_overflow); | 1361 __ Bind(¬_smi_or_overflow); |
| 1360 | 1362 |
| 1363 __ Comment("Extract ICData initial values and receiver cid"); |
| 1361 // Load arguments descriptor into R4. | 1364 // Load arguments descriptor into R4. |
| 1362 __ ldr(R4, FieldAddress(R5, ICData::arguments_descriptor_offset())); | 1365 __ ldr(R4, FieldAddress(R5, ICData::arguments_descriptor_offset())); |
| 1363 // Loop that checks if there is an IC data match. | 1366 // Loop that checks if there is an IC data match. |
| 1364 Label loop, update, test, found; | 1367 Label loop, update, test, found; |
| 1365 // R5: IC data object (preserved). | 1368 // R5: IC data object (preserved). |
| 1366 __ ldr(R6, FieldAddress(R5, ICData::ic_data_offset())); | 1369 __ ldr(R6, FieldAddress(R5, ICData::ic_data_offset())); |
| 1367 // R6: ic_data_array with check entries: classes and target functions. | 1370 // R6: ic_data_array with check entries: classes and target functions. |
| 1368 __ AddImmediate(R6, R6, Array::data_offset() - kHeapObjectTag); | 1371 __ AddImmediate(R6, R6, Array::data_offset() - kHeapObjectTag); |
| 1369 // R6: points directly to the first ic data array element. | 1372 // R6: points directly to the first ic data array element. |
| 1370 | 1373 |
| 1371 // Get the receiver's class ID (first read number of arguments from | 1374 // Get the receiver's class ID (first read number of arguments from |
| 1372 // arguments descriptor array and then access the receiver from the stack). | 1375 // arguments descriptor array and then access the receiver from the stack). |
| 1373 __ ldr(R7, FieldAddress(R4, ArgumentsDescriptor::count_offset())); | 1376 __ ldr(R7, FieldAddress(R4, ArgumentsDescriptor::count_offset())); |
| 1374 __ sub(R7, R7, Operand(Smi::RawValue(1))); | 1377 __ sub(R7, R7, Operand(Smi::RawValue(1))); |
| 1375 __ ldr(R0, Address(SP, R7, LSL, 1)); // R7 (argument_count - 1) is smi. | 1378 __ ldr(R0, Address(SP, R7, LSL, 1)); // R7 (argument_count - 1) is smi. |
| 1376 __ LoadTaggedClassIdMayBeSmi(R0, R0); | 1379 __ LoadTaggedClassIdMayBeSmi(R0, R0); |
| 1377 // R7: argument_count - 1 (smi). | 1380 // R7: argument_count - 1 (smi). |
| 1378 // R0: receiver's class ID (smi). | 1381 // R0: receiver's class ID (smi). |
| 1379 __ ldr(R1, Address(R6, 0)); // First class id (smi) to check. | 1382 __ ldr(R1, Address(R6, 0)); // First class id (smi) to check. |
| 1380 __ b(&test); | 1383 __ b(&test); |
| 1381 | 1384 |
| 1385 __ Comment("ICData loop"); |
| 1382 __ Bind(&loop); | 1386 __ Bind(&loop); |
| 1383 for (int i = 0; i < num_args; i++) { | 1387 for (int i = 0; i < num_args; i++) { |
| 1384 if (i > 0) { | 1388 if (i > 0) { |
| 1385 // If not the first, load the next argument's class ID. | 1389 // If not the first, load the next argument's class ID. |
| 1386 __ AddImmediate(R0, R7, Smi::RawValue(-i)); | 1390 __ AddImmediate(R0, R7, Smi::RawValue(-i)); |
| 1387 __ ldr(R0, Address(SP, R0, LSL, 1)); | 1391 __ ldr(R0, Address(SP, R0, LSL, 1)); |
| 1388 __ LoadTaggedClassIdMayBeSmi(R0, R0); | 1392 __ LoadTaggedClassIdMayBeSmi(R0, R0); |
| 1389 // R0: next argument class ID (smi). | 1393 // R0: next argument class ID (smi). |
| 1390 __ LoadFromOffset(kWord, R1, R6, i * kWordSize); | 1394 __ LoadFromOffset(kWord, R1, R6, i * kWordSize); |
| 1391 // R1: next class ID to check (smi). | 1395 // R1: next class ID to check (smi). |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1406 } | 1410 } |
| 1407 | 1411 |
| 1408 const intptr_t entry_size = ICData::TestEntryLengthFor(num_args) * kWordSize; | 1412 const intptr_t entry_size = ICData::TestEntryLengthFor(num_args) * kWordSize; |
| 1409 __ AddImmediate(R6, entry_size); // Next entry. | 1413 __ AddImmediate(R6, entry_size); // Next entry. |
| 1410 __ ldr(R1, Address(R6, 0)); // Next class ID. | 1414 __ ldr(R1, Address(R6, 0)); // Next class ID. |
| 1411 | 1415 |
| 1412 __ Bind(&test); | 1416 __ Bind(&test); |
| 1413 __ CompareImmediate(R1, Smi::RawValue(kIllegalCid)); // Done? | 1417 __ CompareImmediate(R1, Smi::RawValue(kIllegalCid)); // Done? |
| 1414 __ b(&loop, NE); | 1418 __ b(&loop, NE); |
| 1415 | 1419 |
| 1416 // IC miss. | 1420 __ Comment("IC miss"); |
| 1417 // Compute address of arguments. | 1421 // Compute address of arguments. |
| 1418 // R7: argument_count - 1 (smi). | 1422 // R7: argument_count - 1 (smi). |
| 1419 __ add(R7, SP, Operand(R7, LSL, 1)); // R7 is Smi. | 1423 __ add(R7, SP, Operand(R7, LSL, 1)); // R7 is Smi. |
| 1420 // R7: address of receiver. | 1424 // R7: address of receiver. |
| 1421 // Create a stub frame as we are pushing some objects on the stack before | 1425 // Create a stub frame as we are pushing some objects on the stack before |
| 1422 // calling into the runtime. | 1426 // calling into the runtime. |
| 1423 __ EnterStubFrame(); | 1427 __ EnterStubFrame(); |
| 1424 __ LoadImmediate(R0, reinterpret_cast<intptr_t>(Object::null())); | 1428 __ LoadImmediate(R0, reinterpret_cast<intptr_t>(Object::null())); |
| 1425 // Preserve IC data object and arguments descriptor array and | 1429 // Preserve IC data object and arguments descriptor array and |
| 1426 // setup space on stack for result (target code object). | 1430 // setup space on stack for result (target code object). |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1441 __ LeaveStubFrame(); | 1445 __ LeaveStubFrame(); |
| 1442 Label call_target_function; | 1446 Label call_target_function; |
| 1443 __ b(&call_target_function); | 1447 __ b(&call_target_function); |
| 1444 | 1448 |
| 1445 __ Bind(&found); | 1449 __ Bind(&found); |
| 1446 // R6: pointer to an IC data check group. | 1450 // R6: pointer to an IC data check group. |
| 1447 const intptr_t target_offset = ICData::TargetIndexFor(num_args) * kWordSize; | 1451 const intptr_t target_offset = ICData::TargetIndexFor(num_args) * kWordSize; |
| 1448 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; | 1452 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; |
| 1449 __ LoadFromOffset(kWord, R0, R6, target_offset); | 1453 __ LoadFromOffset(kWord, R0, R6, target_offset); |
| 1450 | 1454 |
| 1451 // Update counter. | 1455 __ Comment("Update caller's counter"); |
| 1452 __ LoadFromOffset(kWord, R1, R6, count_offset); | 1456 __ LoadFromOffset(kWord, R1, R6, count_offset); |
| 1453 __ adds(R1, R1, Operand(Smi::RawValue(1))); | 1457 __ adds(R1, R1, Operand(Smi::RawValue(1))); |
| 1454 __ LoadImmediate(R1, Smi::RawValue(Smi::kMaxValue), VS); // Overflow. | 1458 __ LoadImmediate(R1, Smi::RawValue(Smi::kMaxValue), VS); // Overflow. |
| 1455 __ StoreIntoSmiField(Address(R6, count_offset), R1); | 1459 __ StoreIntoSmiField(Address(R6, count_offset), R1); |
| 1456 | 1460 |
| 1461 __ Comment("Call target"); |
| 1457 __ Bind(&call_target_function); | 1462 __ Bind(&call_target_function); |
| 1458 // R0: target function. | 1463 // R0: target function. |
| 1459 __ ldr(R2, FieldAddress(R0, Function::instructions_offset())); | 1464 __ ldr(R2, FieldAddress(R0, Function::instructions_offset())); |
| 1460 __ AddImmediate(R2, Instructions::HeaderSize() - kHeapObjectTag); | 1465 __ AddImmediate(R2, Instructions::HeaderSize() - kHeapObjectTag); |
| 1461 if (range_collection_mode == kCollectRanges) { | 1466 if (range_collection_mode == kCollectRanges) { |
| 1462 __ ldr(R1, Address(SP, 0 * kWordSize)); | 1467 __ ldr(R1, Address(SP, 0 * kWordSize)); |
| 1463 if (num_args == 2) { | 1468 if (num_args == 2) { |
| 1464 __ ldr(R3, Address(SP, 1 * kWordSize)); | 1469 __ ldr(R3, Address(SP, 1 * kWordSize)); |
| 1465 } | 1470 } |
| 1466 __ EnterStubFrame(); | 1471 __ EnterStubFrame(); |
| (...skipping 575 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2042 const Register right = R0; | 2047 const Register right = R0; |
| 2043 __ ldr(left, Address(SP, 1 * kWordSize)); | 2048 __ ldr(left, Address(SP, 1 * kWordSize)); |
| 2044 __ ldr(right, Address(SP, 0 * kWordSize)); | 2049 __ ldr(right, Address(SP, 0 * kWordSize)); |
| 2045 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); | 2050 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); |
| 2046 __ Ret(); | 2051 __ Ret(); |
| 2047 } | 2052 } |
| 2048 | 2053 |
| 2049 } // namespace dart | 2054 } // namespace dart |
| 2050 | 2055 |
| 2051 #endif // defined TARGET_ARCH_ARM | 2056 #endif // defined TARGET_ARCH_ARM |
| OLD | NEW |