| OLD | NEW |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, 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_IA32. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. |
| 6 #if defined(TARGET_ARCH_IA32) | 6 #if defined(TARGET_ARCH_IA32) |
| 7 | 7 |
| 8 #include "vm/opt_code_generator.h" | 8 #include "vm/opt_code_generator.h" |
| 9 | 9 |
| 10 #include "vm/assembler_macros.h" | 10 #include "vm/assembler_macros.h" |
| (...skipping 1337 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1348 node->left(), | 1348 node->left(), |
| 1349 node->id(), | 1349 node->id(), |
| 1350 node->token_index(), | 1350 node->token_index(), |
| 1351 number_of_arguments, | 1351 number_of_arguments, |
| 1352 no_optional_argument_names); | 1352 no_optional_argument_names); |
| 1353 HandleResult(node, EAX); | 1353 HandleResult(node, EAX); |
| 1354 return; | 1354 return; |
| 1355 } | 1355 } |
| 1356 | 1356 |
| 1357 | 1357 |
| 1358 // Debugging helper method, used in assert only. | |
| 1359 static bool HaveSameClassesInICData(const ICData& a, const ICData& b) { | |
| 1360 if (a.NumberOfChecks() != b.NumberOfChecks()) { | |
| 1361 return false; | |
| 1362 } | |
| 1363 if (a.NumberOfChecks() == 0) { | |
| 1364 return true; | |
| 1365 } | |
| 1366 if (a.num_args_tested() != b.num_args_tested()) { | |
| 1367 return false; | |
| 1368 } | |
| 1369 // Only one-argument checks implemented. | |
| 1370 ASSERT(a.num_args_tested() == 1); | |
| 1371 Function& a_target = Function::Handle(); | |
| 1372 Function& b_target = Function::Handle(); | |
| 1373 Class& a_class = Class::Handle(); | |
| 1374 Class& b_class = Class::Handle(); | |
| 1375 for (intptr_t i = 0; i < a.NumberOfChecks(); i++) { | |
| 1376 a.GetOneClassCheckAt(i, &a_class, &a_target); | |
| 1377 bool found = false; | |
| 1378 for (intptr_t n = 0; n < b.NumberOfChecks(); n++) { | |
| 1379 b.GetOneClassCheckAt(n, &b_class, &b_target); | |
| 1380 if ((a_class.raw() == b_class.raw())) { | |
| 1381 found = true; | |
| 1382 break; | |
| 1383 } | |
| 1384 } | |
| 1385 if (!found) { | |
| 1386 return false; | |
| 1387 } | |
| 1388 } | |
| 1389 return true; | |
| 1390 } | |
| 1391 | |
| 1392 | |
| 1393 void OptimizingCodeGenerator::VisitIncrOpInstanceFieldNode( | |
| 1394 IncrOpInstanceFieldNode* node) { | |
| 1395 ASSERT((node->kind() == Token::kINCR) || (node->kind() == Token::kDECR)); | |
| 1396 VisitLoadOne(node->receiver(), EBX); | |
| 1397 __ pushl(EBX); // Duplicate receiver (preserve for setter). | |
| 1398 const ICData& ic_data = node->ICDataAtId(node->id()); | |
| 1399 // Deoptimize if either this node has never been visited before or | |
| 1400 // if the classes collected at getter and setter do not match (can happen | |
| 1401 // if the increment is 'interrupted' by an exception). | |
| 1402 if ((ic_data.NumberOfChecks() == 0) || | |
| 1403 !HaveSameClassesInICData(node->ICDataAtId(node->getter_id()), | |
| 1404 node->ICDataAtId(node->setter_id()))) { | |
| 1405 // Deoptimization point for this node is after receiver has been | |
| 1406 // pushed twice on stack and before the getter (above) was executed. | |
| 1407 DeoptimizationBlob* deopt_blob = | |
| 1408 AddDeoptimizationBlob(node, EBX, kDeoptIncrInstance); | |
| 1409 __ jmp(deopt_blob->label()); | |
| 1410 return; | |
| 1411 } | |
| 1412 InlineInstanceGetter(node, | |
| 1413 node->getter_id(), | |
| 1414 node->receiver(), | |
| 1415 node->field_name(), | |
| 1416 EBX); | |
| 1417 // result is in EAX. | |
| 1418 __ popl(EDX); // Get receiver. | |
| 1419 const bool return_original_value = !node->prefix() && IsResultNeeded(node); | |
| 1420 const Immediate one_value = Immediate(Smi::RawValue(1)); | |
| 1421 // EAX: Value. | |
| 1422 // EDX: Receiver. | |
| 1423 if (AtIdNodeHasClassAt(node, node->operator_id(), smi_class_, 0)) { | |
| 1424 // Deoptimization point for this node is after receiver has been | |
| 1425 // pushed twice on stack and before the getter (above) was executed. | |
| 1426 DeoptimizationBlob* deopt_blob = | |
| 1427 AddDeoptimizationBlob(node, EDX, EDX, kDeoptIncrInstanceOneClass); | |
| 1428 if (return_original_value) { | |
| 1429 // Preserve pre increment result. | |
| 1430 __ movl(ECX, EAX); | |
| 1431 } | |
| 1432 __ testl(EAX, Immediate(kSmiTagMask)); | |
| 1433 __ j(NOT_ZERO, deopt_blob->label()); | |
| 1434 if (node->kind() == Token::kINCR) { | |
| 1435 __ addl(EAX, one_value); | |
| 1436 } else { | |
| 1437 __ subl(EAX, one_value); | |
| 1438 } | |
| 1439 __ j(OVERFLOW, deopt_blob->label()); | |
| 1440 if (return_original_value) { | |
| 1441 // Preserve as result. | |
| 1442 __ pushl(ECX); // Preserve pre-increment value as result. | |
| 1443 } | |
| 1444 } else { | |
| 1445 if (return_original_value) { | |
| 1446 // Preserve as result. | |
| 1447 __ pushl(EAX); // Preserve value as result. | |
| 1448 } | |
| 1449 __ pushl(EDX); // Preserve receiver. | |
| 1450 __ pushl(EAX); // Left operand. | |
| 1451 __ pushl(one_value); // Right operand. | |
| 1452 const char* operator_name = (node->kind() == Token::kINCR) ? "+" : "-"; | |
| 1453 GenerateBinaryOperatorCall(node->operator_id(), | |
| 1454 node->token_index(), | |
| 1455 operator_name); | |
| 1456 __ popl(EDX); // Restore receiver. | |
| 1457 } | |
| 1458 // EAX: Result of binary operation. | |
| 1459 // EDX: receiver | |
| 1460 if (IsResultNeeded(node) && node->prefix()) { | |
| 1461 // Value stored into field is the result. | |
| 1462 __ pushl(EAX); | |
| 1463 } | |
| 1464 | |
| 1465 // This can never deoptimize since the checks are the same as in getter. | |
| 1466 ASSERT(HaveSameClassesInICData(node->ICDataAtId(node->getter_id()), | |
| 1467 node->ICDataAtId(node->setter_id()))); | |
| 1468 InlineInstanceSetter(node, | |
| 1469 node->setter_id(), | |
| 1470 node->receiver(), | |
| 1471 node->field_name(), | |
| 1472 EDX, // receiver | |
| 1473 EAX); // value. | |
| 1474 } | |
| 1475 | |
| 1476 | |
| 1477 | |
| 1478 | |
| 1479 | |
| 1480 // Return offset of a field or -1 if field is not found. | 1358 // Return offset of a field or -1 if field is not found. |
| 1481 static intptr_t GetFieldOffset(const Class& field_class, | 1359 static intptr_t GetFieldOffset(const Class& field_class, |
| 1482 const String& field_name) { | 1360 const String& field_name) { |
| 1483 Class& cls = Class::Handle(field_class.raw()); | 1361 Class& cls = Class::Handle(field_class.raw()); |
| 1484 Field& field = Field::Handle(); | 1362 Field& field = Field::Handle(); |
| 1485 while (!cls.IsNull()) { | 1363 while (!cls.IsNull()) { |
| 1486 field = cls.LookupInstanceField(field_name); | 1364 field = cls.LookupInstanceField(field_name); |
| 1487 if (!field.IsNull()) { | 1365 if (!field.IsNull()) { |
| 1488 return field.Offset(); | 1366 return field.Offset(); |
| 1489 } | 1367 } |
| (...skipping 1545 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3035 } | 2913 } |
| 3036 } | 2914 } |
| 3037 // TODO(srdjan): Implement unary kSUB (negate) Mint. | 2915 // TODO(srdjan): Implement unary kSUB (negate) Mint. |
| 3038 CodeGenerator::VisitUnaryOpNode(node); | 2916 CodeGenerator::VisitUnaryOpNode(node); |
| 3039 } | 2917 } |
| 3040 | 2918 |
| 3041 | 2919 |
| 3042 } // namespace dart | 2920 } // namespace dart |
| 3043 | 2921 |
| 3044 #endif // defined TARGET_ARCH_IA32 | 2922 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |