| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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_X64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. |
| 6 #if defined(TARGET_ARCH_X64) | 6 #if defined(TARGET_ARCH_X64) |
| 7 | 7 |
| 8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
| 9 | 9 |
| 10 #include "lib/error.h" | 10 #include "lib/error.h" |
| (...skipping 429 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 440 __ jmp(&done); | 440 __ jmp(&done); |
| 441 __ Bind(&non_null_compare); // Receiver is not null. | 441 __ Bind(&non_null_compare); // Receiver is not null. |
| 442 __ pushq(left); | 442 __ pushq(left); |
| 443 __ pushq(right); | 443 __ pushq(right); |
| 444 EmitEqualityAsPolymorphicCall(compiler, ic_data, locs, branch, kind, | 444 EmitEqualityAsPolymorphicCall(compiler, ic_data, locs, branch, kind, |
| 445 deopt_id, token_pos, try_index); | 445 deopt_id, token_pos, try_index); |
| 446 __ Bind(&done); | 446 __ Bind(&done); |
| 447 } | 447 } |
| 448 | 448 |
| 449 | 449 |
| 450 static intptr_t GetCid(const Value& v) { |
| 451 const AbstractType& type = AbstractType::Handle(v.CompileType()); |
| 452 return Class::Handle(type.type_class()).id(); |
| 453 } |
| 454 |
| 455 |
| 450 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, | 456 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, |
| 451 const LocationSummary& locs, | 457 const LocationSummary& locs, |
| 452 Token::Kind kind, | 458 Token::Kind kind, |
| 453 BranchInstr* branch, | 459 BranchInstr* branch, |
| 454 intptr_t deopt_id, | 460 intptr_t deopt_id, |
| 455 intptr_t token_pos, | 461 intptr_t token_pos, |
| 456 intptr_t try_index) { | 462 intptr_t try_index) { |
| 457 Register left = locs.in(0).reg(); | 463 Register left = locs.in(0).reg(); |
| 458 Register right = locs.in(1).reg(); | 464 Register right = locs.in(1).reg(); |
| 459 Register temp = locs.temp(0).reg(); | 465 const bool left_is_smi = (branch == NULL) ? |
| 460 Label* deopt = compiler->AddDeoptStub(deopt_id, | 466 false : (GetCid(*branch->left()) == kSmiCid); |
| 461 try_index, | 467 const bool right_is_smi = (branch == NULL) ? |
| 462 kDeoptSmiCompareSmi, | 468 false : (GetCid(*branch->right()) == kSmiCid); |
| 463 left, | 469 if (!left_is_smi || !right_is_smi) { |
| 464 right); | 470 Register temp = locs.temp(0).reg(); |
| 465 __ movq(temp, left); | 471 Label* deopt = compiler->AddDeoptStub(deopt_id, |
| 466 __ orq(temp, right); | 472 try_index, |
| 467 __ testq(temp, Immediate(kSmiTagMask)); | 473 kDeoptSmiCompareSmi, |
| 468 __ j(NOT_ZERO, deopt); | 474 left, |
| 475 right); |
| 476 __ movq(temp, left); |
| 477 __ orq(temp, right); |
| 478 __ testq(temp, Immediate(kSmiTagMask)); |
| 479 __ j(NOT_ZERO, deopt); |
| 480 } |
| 469 | 481 |
| 470 Condition true_condition = TokenKindToSmiCondition(kind); | 482 Condition true_condition = TokenKindToSmiCondition(kind); |
| 471 __ cmpq(left, right); | 483 __ cmpq(left, right); |
| 472 | 484 |
| 473 if (branch != NULL) { | 485 if (branch != NULL) { |
| 474 branch->EmitBranchOnCondition(compiler, true_condition); | 486 branch->EmitBranchOnCondition(compiler, true_condition); |
| 475 } else { | 487 } else { |
| 476 Register result = locs.out().reg(); | 488 Register result = locs.out().reg(); |
| 477 Label done, is_true; | 489 Label done, is_true; |
| 478 __ j(true_condition, &is_true); | 490 __ j(true_condition, &is_true); |
| (...skipping 954 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1433 } | 1445 } |
| 1434 } | 1446 } |
| 1435 | 1447 |
| 1436 | 1448 |
| 1437 static void EmitSmiBinaryOp(FlowGraphCompiler* compiler, BinaryOpComp* comp) { | 1449 static void EmitSmiBinaryOp(FlowGraphCompiler* compiler, BinaryOpComp* comp) { |
| 1438 Register left = comp->locs()->in(0).reg(); | 1450 Register left = comp->locs()->in(0).reg(); |
| 1439 Register right = comp->locs()->in(1).reg(); | 1451 Register right = comp->locs()->in(1).reg(); |
| 1440 Register result = comp->locs()->out().reg(); | 1452 Register result = comp->locs()->out().reg(); |
| 1441 Register temp = comp->locs()->temp(0).reg(); | 1453 Register temp = comp->locs()->temp(0).reg(); |
| 1442 ASSERT(left == result); | 1454 ASSERT(left == result); |
| 1443 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->deopt_id(), | 1455 const bool left_is_smi = (GetCid(*comp->left()) == kSmiCid); |
| 1444 comp->instance_call()->try_index(), | 1456 const bool right_is_smi = (GetCid(*comp->right()) == kSmiCid); |
| 1445 kDeoptSmiBinaryOp, | 1457 bool can_deopt; |
| 1446 temp, | 1458 switch (comp->op_kind()) { |
| 1447 right); | 1459 case Token::kBIT_AND: |
| 1448 // TODO(vegorov): for many binary operations this pattern can be rearranged | 1460 case Token::kBIT_OR: |
| 1449 // to save one move. | 1461 case Token::kBIT_XOR: |
| 1450 __ movq(temp, left); | 1462 can_deopt = !(right_is_smi && left_is_smi); |
| 1451 __ orq(left, right); | 1463 break; |
| 1452 __ testq(left, Immediate(kSmiTagMask)); | 1464 default: |
| 1453 __ j(NOT_ZERO, deopt); | 1465 can_deopt = true; |
| 1454 __ movq(left, temp); | 1466 } |
| 1467 Label* deopt = NULL; |
| 1468 if (can_deopt) { |
| 1469 deopt = compiler->AddDeoptStub(comp->instance_call()->deopt_id(), |
| 1470 comp->instance_call()->try_index(), |
| 1471 kDeoptSmiBinaryOp, |
| 1472 temp, |
| 1473 right); |
| 1474 } |
| 1475 if (left_is_smi && right_is_smi) { |
| 1476 if (can_deopt) { |
| 1477 // Preserve left for deopt. |
| 1478 __ movq(temp, left); |
| 1479 } |
| 1480 } else { |
| 1481 // TODO(vegorov): for many binary operations this pattern can be rearranged |
| 1482 // to save one move. |
| 1483 __ movq(temp, left); |
| 1484 __ orq(left, right); |
| 1485 __ testq(left, Immediate(kSmiTagMask)); |
| 1486 __ j(NOT_ZERO, deopt); |
| 1487 __ movq(left, temp); |
| 1488 } |
| 1455 switch (comp->op_kind()) { | 1489 switch (comp->op_kind()) { |
| 1456 case Token::kADD: { | 1490 case Token::kADD: { |
| 1457 __ addq(left, right); | 1491 __ addq(left, right); |
| 1458 __ j(OVERFLOW, deopt); | 1492 __ j(OVERFLOW, deopt); |
| 1459 break; | 1493 break; |
| 1460 } | 1494 } |
| 1461 case Token::kSUB: { | 1495 case Token::kSUB: { |
| 1462 __ subq(left, right); | 1496 __ subq(left, right); |
| 1463 __ j(OVERFLOW, deopt); | 1497 __ j(OVERFLOW, deopt); |
| 1464 break; | 1498 break; |
| (...skipping 604 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2069 kNumArgsChecked); | 2103 kNumArgsChecked); |
| 2070 __ CompareObject(RAX, compiler->bool_true()); | 2104 __ CompareObject(RAX, compiler->bool_true()); |
| 2071 EmitBranchOnCondition(compiler, branch_condition); | 2105 EmitBranchOnCondition(compiler, branch_condition); |
| 2072 } | 2106 } |
| 2073 | 2107 |
| 2074 } // namespace dart | 2108 } // namespace dart |
| 2075 | 2109 |
| 2076 #undef __ | 2110 #undef __ |
| 2077 | 2111 |
| 2078 #endif // defined TARGET_ARCH_X64 | 2112 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |