| 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 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 292 EqualityCompareComp* comp) { | 292 EqualityCompareComp* comp) { |
| 293 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 293 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
| 294 comp->deopt_id(), | 294 comp->deopt_id(), |
| 295 comp->token_pos(), | 295 comp->token_pos(), |
| 296 comp->try_index()); | 296 comp->try_index()); |
| 297 const String& operator_name = String::ZoneHandle(Symbols::New("==")); | 297 const String& operator_name = String::ZoneHandle(Symbols::New("==")); |
| 298 const int kNumberOfArguments = 2; | 298 const int kNumberOfArguments = 2; |
| 299 const Array& kNoArgumentNames = Array::Handle(); | 299 const Array& kNoArgumentNames = Array::Handle(); |
| 300 const int kNumArgumentsChecked = 2; | 300 const int kNumArgumentsChecked = 2; |
| 301 | 301 |
| 302 Label done, false_label, true_label; |
| 303 Register left = comp->locs()->in(0).reg(); |
| 304 Register right = comp->locs()->in(1).reg(); |
| 305 __ popq(right); |
| 306 __ popq(left); |
| 307 const Immediate raw_null = |
| 308 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 309 Label check_identity, instance_call; |
| 310 __ cmpq(right, raw_null); |
| 311 __ j(EQUAL, &check_identity, Assembler::kNearJump); |
| 312 __ cmpq(left, raw_null); |
| 313 __ j(NOT_EQUAL, &instance_call, Assembler::kNearJump); |
| 314 |
| 315 __ Bind(&check_identity); |
| 316 __ cmpq(left, right); |
| 317 __ j(EQUAL, &true_label); |
| 318 if (comp->kind() == Token::kEQ) { |
| 319 __ LoadObject(RAX, compiler->bool_false()); |
| 320 __ jmp(&done); |
| 321 __ Bind(&true_label); |
| 322 __ LoadObject(RAX, compiler->bool_true()); |
| 323 __ jmp(&done); |
| 324 } else { |
| 325 ASSERT(comp->kind() == Token::kNE); |
| 326 __ jmp(&false_label); |
| 327 } |
| 328 |
| 329 __ Bind(&instance_call); |
| 330 __ pushq(left); |
| 331 __ pushq(right); |
| 302 compiler->GenerateInstanceCall(comp->deopt_id(), | 332 compiler->GenerateInstanceCall(comp->deopt_id(), |
| 303 comp->token_pos(), | 333 comp->token_pos(), |
| 304 comp->try_index(), | 334 comp->try_index(), |
| 305 operator_name, | 335 operator_name, |
| 306 kNumberOfArguments, | 336 kNumberOfArguments, |
| 307 kNoArgumentNames, | 337 kNoArgumentNames, |
| 308 kNumArgumentsChecked, | 338 kNumArgumentsChecked, |
| 309 comp->locs()->stack_bitmap()); | 339 comp->locs()->stack_bitmap()); |
| 310 ASSERT(comp->locs()->out().reg() == RAX); | 340 ASSERT(comp->locs()->out().reg() == RAX); |
| 311 if (comp->kind() == Token::kNE) { | 341 if (comp->kind() == Token::kNE) { |
| 312 Label done, false_label; | 342 // Negate the condition: true label returns false and vice versa. |
| 313 __ CompareObject(RAX, compiler->bool_true()); | 343 __ CompareObject(RAX, compiler->bool_true()); |
| 314 __ j(EQUAL, &false_label, Assembler::kNearJump); | 344 __ j(EQUAL, &true_label, Assembler::kNearJump); |
| 345 __ Bind(&false_label); |
| 315 __ LoadObject(RAX, compiler->bool_true()); | 346 __ LoadObject(RAX, compiler->bool_true()); |
| 316 __ jmp(&done, Assembler::kNearJump); | 347 __ jmp(&done, Assembler::kNearJump); |
| 317 __ Bind(&false_label); | 348 __ Bind(&true_label); |
| 318 __ LoadObject(RAX, compiler->bool_false()); | 349 __ LoadObject(RAX, compiler->bool_false()); |
| 319 __ Bind(&done); | |
| 320 } | 350 } |
| 351 __ Bind(&done); |
| 321 } | 352 } |
| 322 | 353 |
| 323 | 354 |
| 324 static void EmitEqualityAsPolymorphicCall(FlowGraphCompiler* compiler, | 355 static void EmitEqualityAsPolymorphicCall(FlowGraphCompiler* compiler, |
| 325 const ICData& orig_ic_data, | 356 const ICData& orig_ic_data, |
| 326 const LocationSummary& locs, | 357 const LocationSummary& locs, |
| 327 BranchInstr* branch, | 358 BranchInstr* branch, |
| 328 Token::Kind kind, | 359 Token::Kind kind, |
| 329 intptr_t deopt_id, | 360 intptr_t deopt_id, |
| 330 intptr_t token_pos, | 361 intptr_t token_pos, |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 426 Register left = locs.in(0).reg(); | 457 Register left = locs.in(0).reg(); |
| 427 Register right = locs.in(1).reg(); | 458 Register right = locs.in(1).reg(); |
| 428 Register temp = locs.temp(0).reg(); | 459 Register temp = locs.temp(0).reg(); |
| 429 Label* deopt = compiler->AddDeoptStub(deopt_id, | 460 Label* deopt = compiler->AddDeoptStub(deopt_id, |
| 430 try_index, | 461 try_index, |
| 431 kDeoptEquality, | 462 kDeoptEquality, |
| 432 left, | 463 left, |
| 433 right); | 464 right); |
| 434 __ testq(left, Immediate(kSmiTagMask)); | 465 __ testq(left, Immediate(kSmiTagMask)); |
| 435 __ j(ZERO, deopt); | 466 __ j(ZERO, deopt); |
| 467 // 'left' is not Smi. |
| 468 const Immediate raw_null = |
| 469 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 470 Label identity_compare; |
| 471 __ cmpq(right, raw_null); |
| 472 __ j(EQUAL, &identity_compare); |
| 473 __ cmpq(left, raw_null); |
| 474 __ j(EQUAL, &identity_compare); |
| 475 |
| 436 __ LoadClassId(temp, left); | 476 __ LoadClassId(temp, left); |
| 437 Label done; | |
| 438 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { | 477 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { |
| 439 __ cmpq(temp, Immediate(ic_data.GetReceiverClassIdAt(i))); | 478 __ cmpq(temp, Immediate(ic_data.GetReceiverClassIdAt(i))); |
| 440 if (i == (ic_data.NumberOfChecks() - 1)) { | 479 if (i == (ic_data.NumberOfChecks() - 1)) { |
| 441 __ j(NOT_EQUAL, deopt); | 480 __ j(NOT_EQUAL, deopt); |
| 442 } else { | 481 } else { |
| 443 __ j(EQUAL, &done); | 482 __ j(EQUAL, &identity_compare); |
| 444 } | 483 } |
| 445 } | 484 } |
| 446 __ Bind(&done); | 485 __ Bind(&identity_compare); |
| 447 __ cmpq(left, right); | 486 __ cmpq(left, right); |
| 448 if (branch == NULL) { | 487 if (branch == NULL) { |
| 449 Label done, is_equal; | 488 Label done, is_equal; |
| 450 Register result = locs.out().reg(); | 489 Register result = locs.out().reg(); |
| 451 __ j(EQUAL, &is_equal, Assembler::kNearJump); | 490 __ j(EQUAL, &is_equal, Assembler::kNearJump); |
| 452 // Not equal. | 491 // Not equal. |
| 453 __ LoadObject(result, (kind == Token::kEQ) ? compiler->bool_false() | 492 __ LoadObject(result, (kind == Token::kEQ) ? compiler->bool_false() |
| 454 : compiler->bool_true()); | 493 : compiler->bool_true()); |
| 455 __ jmp(&done, Assembler::kNearJump); | 494 __ jmp(&done, Assembler::kNearJump); |
| 456 __ Bind(&is_equal); | 495 __ Bind(&is_equal); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 474 const ICData& ic_data, | 513 const ICData& ic_data, |
| 475 intptr_t deopt_id, | 514 intptr_t deopt_id, |
| 476 intptr_t token_pos, | 515 intptr_t token_pos, |
| 477 intptr_t try_index) { | 516 intptr_t try_index) { |
| 478 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); | 517 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); |
| 479 ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0)); | 518 ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0)); |
| 480 Register left = locs.in(0).reg(); | 519 Register left = locs.in(0).reg(); |
| 481 Register right = locs.in(1).reg(); | 520 Register right = locs.in(1).reg(); |
| 482 const Immediate raw_null = | 521 const Immediate raw_null = |
| 483 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 522 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 484 Label done, non_null_compare; | 523 Label done, identity_compare, non_null_compare; |
| 524 __ cmpq(right, raw_null); |
| 525 __ j(EQUAL, &identity_compare, Assembler::kNearJump); |
| 485 __ cmpq(left, raw_null); | 526 __ cmpq(left, raw_null); |
| 486 __ j(NOT_EQUAL, &non_null_compare, Assembler::kNearJump); | 527 __ j(NOT_EQUAL, &non_null_compare, Assembler::kNearJump); |
| 487 // Comparison with NULL is "===". | 528 // Comparison with NULL is "===". |
| 529 __ Bind(&identity_compare); |
| 488 __ cmpq(left, right); | 530 __ cmpq(left, right); |
| 489 Condition cond = TokenKindToSmiCondition(kind); | 531 Condition cond = TokenKindToSmiCondition(kind); |
| 490 if (branch != NULL) { | 532 if (branch != NULL) { |
| 491 branch->EmitBranchOnCondition(compiler, cond); | 533 branch->EmitBranchOnCondition(compiler, cond); |
| 492 } else { | 534 } else { |
| 493 Register result = locs.out().reg(); | 535 Register result = locs.out().reg(); |
| 494 Label load_true; | 536 Label load_true; |
| 495 __ j(cond, &load_true, Assembler::kNearJump); | 537 __ j(cond, &load_true, Assembler::kNearJump); |
| 496 __ LoadObject(result, compiler->bool_false()); | 538 __ LoadObject(result, compiler->bool_false()); |
| 497 __ jmp(&done); | 539 __ jmp(&done); |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 593 true_condition, XMM0, XMM1, branch); | 635 true_condition, XMM0, XMM1, branch); |
| 594 } else { | 636 } else { |
| 595 compiler->EmitDoubleCompareBool( | 637 compiler->EmitDoubleCompareBool( |
| 596 true_condition, XMM0, XMM1, locs.out().reg()); | 638 true_condition, XMM0, XMM1, locs.out().reg()); |
| 597 } | 639 } |
| 598 } | 640 } |
| 599 | 641 |
| 600 | 642 |
| 601 void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 643 void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 602 if (receiver_class_id() == kSmiCid) { | 644 if (receiver_class_id() == kSmiCid) { |
| 645 // Deoptimizes if both arguments not Smi. |
| 603 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL, // No branch. | 646 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL, // No branch. |
| 604 deopt_id(), token_pos(), try_index()); | 647 deopt_id(), token_pos(), try_index()); |
| 605 return; | 648 return; |
| 606 } | 649 } |
| 607 if (receiver_class_id() == kDoubleCid) { | 650 if (receiver_class_id() == kDoubleCid) { |
| 651 // Deoptimizes if both arguments are Smi, or if none is Double or Smi. |
| 608 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL, // No branch. | 652 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL, // No branch. |
| 609 deopt_id(), token_pos(), try_index()); | 653 deopt_id(), token_pos(), try_index()); |
| 610 return; | 654 return; |
| 611 } | 655 } |
| 612 const bool is_checked_strict_equal = | 656 const bool is_checked_strict_equal = |
| 613 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid); | 657 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid); |
| 614 if (is_checked_strict_equal) { | 658 if (is_checked_strict_equal) { |
| 615 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), NULL, | 659 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), NULL, |
| 616 deopt_id(), token_pos(), try_index()); | 660 deopt_id(), token_pos(), try_index()); |
| 617 return; | 661 return; |
| (...skipping 1523 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2141 locs()->stack_bitmap()); | 2185 locs()->stack_bitmap()); |
| 2142 __ CompareObject(RAX, compiler->bool_true()); | 2186 __ CompareObject(RAX, compiler->bool_true()); |
| 2143 EmitBranchOnCondition(compiler, branch_condition); | 2187 EmitBranchOnCondition(compiler, branch_condition); |
| 2144 } | 2188 } |
| 2145 | 2189 |
| 2146 } // namespace dart | 2190 } // namespace dart |
| 2147 | 2191 |
| 2148 #undef __ | 2192 #undef __ |
| 2149 | 2193 |
| 2150 #endif // defined TARGET_ARCH_X64 | 2194 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |