| 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_IA32) | 6 #if defined(TARGET_ARCH_IA32) |
| 7 | 7 |
| 8 #include "vm/assembler.h" | 8 #include "vm/assembler.h" |
| 9 #include "vm/compiler.h" | 9 #include "vm/compiler.h" |
| 10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
| (...skipping 1172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1183 | 1183 |
| 1184 | 1184 |
| 1185 // Note: ECX must be preserved. | 1185 // Note: ECX must be preserved. |
| 1186 // Attempt a quick Smi operation for known operations ('kind'). The ICData | 1186 // Attempt a quick Smi operation for known operations ('kind'). The ICData |
| 1187 // must have been primed with a Smi/Smi check that will be used for counting | 1187 // must have been primed with a Smi/Smi check that will be used for counting |
| 1188 // the invocations. | 1188 // the invocations. |
| 1189 static void EmitFastSmiOp(Assembler* assembler, | 1189 static void EmitFastSmiOp(Assembler* assembler, |
| 1190 Token::Kind kind, | 1190 Token::Kind kind, |
| 1191 intptr_t num_args, | 1191 intptr_t num_args, |
| 1192 Label* not_smi_or_overflow) { | 1192 Label* not_smi_or_overflow) { |
| 1193 __ Comment("Fast Smi op"); |
| 1193 ASSERT(num_args == 2); | 1194 ASSERT(num_args == 2); |
| 1194 __ movl(EDI, Address(ESP, + 1 * kWordSize)); // Right | 1195 __ movl(EDI, Address(ESP, + 1 * kWordSize)); // Right |
| 1195 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // Left | 1196 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // Left |
| 1196 __ movl(EBX, EDI); | 1197 __ movl(EBX, EDI); |
| 1197 __ orl(EBX, EAX); | 1198 __ orl(EBX, EAX); |
| 1198 __ testl(EBX, Immediate(kSmiTagMask)); | 1199 __ testl(EBX, Immediate(kSmiTagMask)); |
| 1199 __ j(NOT_ZERO, not_smi_or_overflow, Assembler::kNearJump); | 1200 __ j(NOT_ZERO, not_smi_or_overflow, Assembler::kNearJump); |
| 1200 switch (kind) { | 1201 switch (kind) { |
| 1201 case Token::kADD: { | 1202 case Token::kADD: { |
| 1202 __ addl(EAX, EDI); | 1203 __ addl(EAX, EDI); |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1281 __ movl(EBX, FieldAddress(ECX, ICData::state_bits_offset())); | 1282 __ movl(EBX, FieldAddress(ECX, ICData::state_bits_offset())); |
| 1282 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. | 1283 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. |
| 1283 __ andl(EBX, Immediate(ICData::NumArgsTestedMask())); | 1284 __ andl(EBX, Immediate(ICData::NumArgsTestedMask())); |
| 1284 __ cmpl(EBX, Immediate(num_args)); | 1285 __ cmpl(EBX, Immediate(num_args)); |
| 1285 __ j(EQUAL, &ok, Assembler::kNearJump); | 1286 __ j(EQUAL, &ok, Assembler::kNearJump); |
| 1286 __ Stop("Incorrect stub for IC data"); | 1287 __ Stop("Incorrect stub for IC data"); |
| 1287 __ Bind(&ok); | 1288 __ Bind(&ok); |
| 1288 } | 1289 } |
| 1289 #endif // DEBUG | 1290 #endif // DEBUG |
| 1290 | 1291 |
| 1291 // Check single stepping. | 1292 __ Comment("Check single stepping"); |
| 1292 Label stepping, done_stepping; | 1293 Label stepping, done_stepping; |
| 1293 uword single_step_address = reinterpret_cast<uword>(Isolate::Current()) + | 1294 uword single_step_address = reinterpret_cast<uword>(Isolate::Current()) + |
| 1294 Isolate::single_step_offset(); | 1295 Isolate::single_step_offset(); |
| 1295 __ cmpb(Address::Absolute(single_step_address), Immediate(0)); | 1296 __ cmpb(Address::Absolute(single_step_address), Immediate(0)); |
| 1296 __ j(NOT_EQUAL, &stepping); | 1297 __ j(NOT_EQUAL, &stepping); |
| 1297 __ Bind(&done_stepping); | 1298 __ Bind(&done_stepping); |
| 1298 | 1299 |
| 1300 __ Comment("Range feedback collection"); |
| 1299 Label not_smi_or_overflow; | 1301 Label not_smi_or_overflow; |
| 1300 if (range_collection_mode == kCollectRanges) { | 1302 if (range_collection_mode == kCollectRanges) { |
| 1301 ASSERT((num_args == 1) || (num_args == 2)); | 1303 ASSERT((num_args == 1) || (num_args == 2)); |
| 1302 if (num_args == 2) { | 1304 if (num_args == 2) { |
| 1303 __ movl(EAX, Address(ESP, + 2 * kWordSize)); | 1305 __ movl(EAX, Address(ESP, + 2 * kWordSize)); |
| 1304 __ UpdateRangeFeedback(EAX, 0, ECX, EBX, EDI, ESI, ¬_smi_or_overflow); | 1306 __ UpdateRangeFeedback(EAX, 0, ECX, EBX, EDI, ESI, ¬_smi_or_overflow); |
| 1305 } | 1307 } |
| 1306 | 1308 |
| 1307 __ movl(EAX, Address(ESP, + 1 * kWordSize)); | 1309 __ movl(EAX, Address(ESP, + 1 * kWordSize)); |
| 1308 __ UpdateRangeFeedback(EAX, (num_args - 1), ECX, EBX, EDI, ESI, | 1310 __ UpdateRangeFeedback(EAX, (num_args - 1), ECX, EBX, EDI, ESI, |
| 1309 ¬_smi_or_overflow); | 1311 ¬_smi_or_overflow); |
| 1310 } | 1312 } |
| 1311 if (kind != Token::kILLEGAL) { | 1313 if (kind != Token::kILLEGAL) { |
| 1312 EmitFastSmiOp(assembler, kind, num_args, ¬_smi_or_overflow); | 1314 EmitFastSmiOp(assembler, kind, num_args, ¬_smi_or_overflow); |
| 1313 } | 1315 } |
| 1314 __ Bind(¬_smi_or_overflow); | 1316 __ Bind(¬_smi_or_overflow); |
| 1315 | 1317 |
| 1318 __ Comment("Extract ICData initial values and receiver cid"); |
| 1316 // ECX: IC data object (preserved). | 1319 // ECX: IC data object (preserved). |
| 1317 // Load arguments descriptor into EDX. | 1320 // Load arguments descriptor into EDX. |
| 1318 __ movl(EDX, FieldAddress(ECX, ICData::arguments_descriptor_offset())); | 1321 __ movl(EDX, FieldAddress(ECX, ICData::arguments_descriptor_offset())); |
| 1319 // Loop that checks if there is an IC data match. | 1322 // Loop that checks if there is an IC data match. |
| 1320 Label loop, update, test, found; | |
| 1321 // ECX: IC data object (preserved). | 1323 // ECX: IC data object (preserved). |
| 1322 __ movl(EBX, FieldAddress(ECX, ICData::ic_data_offset())); | 1324 __ movl(EBX, FieldAddress(ECX, ICData::ic_data_offset())); |
| 1323 // EBX: ic_data_array with check entries: classes and target functions. | 1325 // EBX: ic_data_array with check entries: classes and target functions. |
| 1324 __ leal(EBX, FieldAddress(EBX, Array::data_offset())); | 1326 __ leal(EBX, FieldAddress(EBX, Array::data_offset())); |
| 1325 // EBX: points directly to the first ic data array element. | 1327 // EBX: points directly to the first ic data array element. |
| 1326 | 1328 |
| 1327 // Get the receiver's class ID (first read number of arguments from | 1329 // Get the receiver's class ID (first read number of arguments from |
| 1328 // arguments descriptor array and then access the receiver from the stack). | 1330 // arguments descriptor array and then access the receiver from the stack). |
| 1329 __ movl(EAX, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); | 1331 __ movl(EAX, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); |
| 1330 __ movl(EDI, Address(ESP, EAX, TIMES_2, 0)); // EAX (argument_count) is smi. | 1332 __ movl(EDI, Address(ESP, EAX, TIMES_2, 0)); // EAX (argument_count) is smi. |
| 1331 __ LoadTaggedClassIdMayBeSmi(EAX, EDI); | 1333 __ LoadTaggedClassIdMayBeSmi(EAX, EDI); |
| 1332 | 1334 |
| 1333 // EAX: receiver's class ID (smi). | 1335 // EAX: receiver's class ID (smi). |
| 1334 __ movl(EDI, Address(EBX, 0)); // First class id (smi) to check. | 1336 __ movl(EDI, Address(EBX, 0)); // First class id (smi) to check. |
| 1337 Label loop, update, test, found; |
| 1335 __ jmp(&test); | 1338 __ jmp(&test); |
| 1336 | 1339 |
| 1340 __ Comment("ICData loop"); |
| 1337 __ Bind(&loop); | 1341 __ Bind(&loop); |
| 1338 for (int i = 0; i < num_args; i++) { | 1342 for (int i = 0; i < num_args; i++) { |
| 1339 if (i > 0) { | 1343 if (i > 0) { |
| 1340 // If not the first, load the next argument's class ID. | 1344 // If not the first, load the next argument's class ID. |
| 1341 __ movl(EAX, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); | 1345 __ movl(EAX, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); |
| 1342 __ movl(EDI, Address(ESP, EAX, TIMES_2, - i * kWordSize)); | 1346 __ movl(EDI, Address(ESP, EAX, TIMES_2, - i * kWordSize)); |
| 1343 __ LoadTaggedClassIdMayBeSmi(EAX, EDI); | 1347 __ LoadTaggedClassIdMayBeSmi(EAX, EDI); |
| 1344 | 1348 |
| 1345 // EAX: next argument class ID (smi). | 1349 // EAX: next argument class ID (smi). |
| 1346 __ movl(EDI, Address(EBX, i * kWordSize)); | 1350 __ movl(EDI, Address(EBX, i * kWordSize)); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1363 } | 1367 } |
| 1364 | 1368 |
| 1365 const intptr_t entry_size = ICData::TestEntryLengthFor(num_args) * kWordSize; | 1369 const intptr_t entry_size = ICData::TestEntryLengthFor(num_args) * kWordSize; |
| 1366 __ addl(EBX, Immediate(entry_size)); // Next entry. | 1370 __ addl(EBX, Immediate(entry_size)); // Next entry. |
| 1367 __ movl(EDI, Address(EBX, 0)); // Next class ID. | 1371 __ movl(EDI, Address(EBX, 0)); // Next class ID. |
| 1368 | 1372 |
| 1369 __ Bind(&test); | 1373 __ Bind(&test); |
| 1370 __ cmpl(EDI, Immediate(Smi::RawValue(kIllegalCid))); // Done? | 1374 __ cmpl(EDI, Immediate(Smi::RawValue(kIllegalCid))); // Done? |
| 1371 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); | 1375 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); |
| 1372 | 1376 |
| 1373 // IC miss. | 1377 __ Comment("IC miss"); |
| 1374 const Immediate& raw_null = | 1378 const Immediate& raw_null = |
| 1375 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1379 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 1376 // Compute address of arguments (first read number of arguments from | 1380 // Compute address of arguments (first read number of arguments from |
| 1377 // arguments descriptor array and then compute address on the stack). | 1381 // arguments descriptor array and then compute address on the stack). |
| 1378 __ movl(EAX, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); | 1382 __ movl(EAX, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); |
| 1379 __ leal(EAX, Address(ESP, EAX, TIMES_2, 0)); // EAX is Smi. | 1383 __ leal(EAX, Address(ESP, EAX, TIMES_2, 0)); // EAX is Smi. |
| 1380 // Create a stub frame as we are pushing some objects on the stack before | 1384 // Create a stub frame as we are pushing some objects on the stack before |
| 1381 // calling into the runtime. | 1385 // calling into the runtime. |
| 1382 __ EnterStubFrame(); | 1386 __ EnterStubFrame(); |
| 1383 __ pushl(EDX); // Preserve arguments descriptor array. | 1387 __ pushl(EDX); // Preserve arguments descriptor array. |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1395 __ popl(EAX); | 1399 __ popl(EAX); |
| 1396 } | 1400 } |
| 1397 __ popl(EAX); // Pop returned function object into EAX. | 1401 __ popl(EAX); // Pop returned function object into EAX. |
| 1398 __ popl(ECX); // Restore IC data array. | 1402 __ popl(ECX); // Restore IC data array. |
| 1399 __ popl(EDX); // Restore arguments descriptor array. | 1403 __ popl(EDX); // Restore arguments descriptor array. |
| 1400 __ LeaveFrame(); | 1404 __ LeaveFrame(); |
| 1401 Label call_target_function; | 1405 Label call_target_function; |
| 1402 __ jmp(&call_target_function); | 1406 __ jmp(&call_target_function); |
| 1403 | 1407 |
| 1404 __ Bind(&found); | 1408 __ Bind(&found); |
| 1409 |
| 1405 // EBX: Pointer to an IC data check group. | 1410 // EBX: Pointer to an IC data check group. |
| 1406 const intptr_t target_offset = ICData::TargetIndexFor(num_args) * kWordSize; | 1411 const intptr_t target_offset = ICData::TargetIndexFor(num_args) * kWordSize; |
| 1407 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; | 1412 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; |
| 1408 | 1413 |
| 1409 // Update counter. | 1414 __ Comment("Update caller's counter"); |
| 1410 __ movl(EAX, Address(EBX, count_offset)); | 1415 __ movl(EAX, Address(EBX, count_offset)); |
| 1411 __ addl(EAX, Immediate(Smi::RawValue(1))); | 1416 __ addl(EAX, Immediate(Smi::RawValue(1))); |
| 1412 __ movl(EDI, Immediate(Smi::RawValue(Smi::kMaxValue))); | 1417 __ movl(EDI, Immediate(Smi::RawValue(Smi::kMaxValue))); |
| 1413 __ cmovno(EDI, EAX); | 1418 __ cmovno(EDI, EAX); |
| 1414 __ StoreIntoSmiField(Address(EBX, count_offset), EDI); | 1419 __ StoreIntoSmiField(Address(EBX, count_offset), EDI); |
| 1415 | 1420 |
| 1416 __ movl(EAX, Address(EBX, target_offset)); | 1421 __ movl(EAX, Address(EBX, target_offset)); |
| 1417 __ Bind(&call_target_function); | 1422 __ Bind(&call_target_function); |
| 1423 __ Comment("Call target"); |
| 1418 // EAX: Target function. | 1424 // EAX: Target function. |
| 1419 __ movl(EBX, FieldAddress(EAX, Function::instructions_offset())); | 1425 __ movl(EBX, FieldAddress(EAX, Function::instructions_offset())); |
| 1420 __ addl(EBX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 1426 __ addl(EBX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
| 1421 if (range_collection_mode == kCollectRanges) { | 1427 if (range_collection_mode == kCollectRanges) { |
| 1422 __ movl(EDI, Address(ESP, + 1 * kWordSize)); | 1428 __ movl(EDI, Address(ESP, + 1 * kWordSize)); |
| 1423 if (num_args == 2) { | 1429 if (num_args == 2) { |
| 1424 __ movl(ESI, Address(ESP, + 2 * kWordSize)); | 1430 __ movl(ESI, Address(ESP, + 2 * kWordSize)); |
| 1425 } | 1431 } |
| 1426 __ EnterStubFrame(); | 1432 __ EnterStubFrame(); |
| 1427 __ pushl(ECX); | 1433 __ pushl(ECX); |
| (...skipping 604 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2032 const Register temp = ECX; | 2038 const Register temp = ECX; |
| 2033 __ movl(left, Address(ESP, 2 * kWordSize)); | 2039 __ movl(left, Address(ESP, 2 * kWordSize)); |
| 2034 __ movl(right, Address(ESP, 1 * kWordSize)); | 2040 __ movl(right, Address(ESP, 1 * kWordSize)); |
| 2035 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); | 2041 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); |
| 2036 __ ret(); | 2042 __ ret(); |
| 2037 } | 2043 } |
| 2038 | 2044 |
| 2039 } // namespace dart | 2045 } // namespace dart |
| 2040 | 2046 |
| 2041 #endif // defined TARGET_ARCH_IA32 | 2047 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |