| 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_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/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
| 9 | 9 |
| 10 #include "lib/error.h" | 10 #include "lib/error.h" |
| (...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 283 EqualityCompareComp* comp) { | 283 EqualityCompareComp* comp) { |
| 284 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 284 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
| 285 comp->deopt_id(), | 285 comp->deopt_id(), |
| 286 comp->token_pos(), | 286 comp->token_pos(), |
| 287 comp->try_index()); | 287 comp->try_index()); |
| 288 const String& operator_name = String::ZoneHandle(Symbols::New("==")); | 288 const String& operator_name = String::ZoneHandle(Symbols::New("==")); |
| 289 const int kNumberOfArguments = 2; | 289 const int kNumberOfArguments = 2; |
| 290 const Array& kNoArgumentNames = Array::Handle(); | 290 const Array& kNoArgumentNames = Array::Handle(); |
| 291 const int kNumArgumentsChecked = 2; | 291 const int kNumArgumentsChecked = 2; |
| 292 | 292 |
| 293 Label done, false_label, true_label; |
| 294 Register left = comp->locs()->in(0).reg(); |
| 295 Register right = comp->locs()->in(1).reg(); |
| 296 __ popl(right); |
| 297 __ popl(left); |
| 298 const Immediate raw_null = |
| 299 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 300 Label check_identity, instance_call; |
| 301 __ cmpl(right, raw_null); |
| 302 __ j(EQUAL, &check_identity, Assembler::kNearJump); |
| 303 __ cmpl(left, raw_null); |
| 304 __ j(NOT_EQUAL, &instance_call, Assembler::kNearJump); |
| 305 |
| 306 __ Bind(&check_identity); |
| 307 __ cmpl(left, right); |
| 308 __ j(EQUAL, &true_label); |
| 309 if (comp->kind() == Token::kEQ) { |
| 310 __ LoadObject(EAX, compiler->bool_false()); |
| 311 __ jmp(&done); |
| 312 __ Bind(&true_label); |
| 313 __ LoadObject(EAX, compiler->bool_true()); |
| 314 __ jmp(&done); |
| 315 } else { |
| 316 ASSERT(comp->kind() == Token::kNE); |
| 317 __ jmp(&false_label); |
| 318 } |
| 319 |
| 320 __ Bind(&instance_call); |
| 321 __ pushl(left); |
| 322 __ pushl(right); |
| 293 compiler->GenerateInstanceCall(comp->deopt_id(), | 323 compiler->GenerateInstanceCall(comp->deopt_id(), |
| 294 comp->token_pos(), | 324 comp->token_pos(), |
| 295 comp->try_index(), | 325 comp->try_index(), |
| 296 operator_name, | 326 operator_name, |
| 297 kNumberOfArguments, | 327 kNumberOfArguments, |
| 298 kNoArgumentNames, | 328 kNoArgumentNames, |
| 299 kNumArgumentsChecked, | 329 kNumArgumentsChecked, |
| 300 comp->locs()->stack_bitmap()); | 330 comp->locs()->stack_bitmap()); |
| 301 ASSERT(comp->locs()->out().reg() == EAX); | 331 ASSERT(comp->locs()->out().reg() == EAX); |
| 302 if (comp->kind() == Token::kNE) { | 332 if (comp->kind() == Token::kNE) { |
| 303 Label done, false_label; | 333 // Negate the condition: true label returns false and vice versa. |
| 304 __ CompareObject(EAX, compiler->bool_true()); | 334 __ CompareObject(EAX, compiler->bool_true()); |
| 305 __ j(EQUAL, &false_label, Assembler::kNearJump); | 335 __ j(EQUAL, &true_label, Assembler::kNearJump); |
| 336 __ Bind(&false_label); |
| 306 __ LoadObject(EAX, compiler->bool_true()); | 337 __ LoadObject(EAX, compiler->bool_true()); |
| 307 __ jmp(&done, Assembler::kNearJump); | 338 __ jmp(&done, Assembler::kNearJump); |
| 308 __ Bind(&false_label); | 339 __ Bind(&true_label); |
| 309 __ LoadObject(EAX, compiler->bool_false()); | 340 __ LoadObject(EAX, compiler->bool_false()); |
| 310 __ Bind(&done); | |
| 311 } | 341 } |
| 342 __ Bind(&done); |
| 312 } | 343 } |
| 313 | 344 |
| 314 | 345 |
| 315 static void EmitEqualityAsPolymorphicCall(FlowGraphCompiler* compiler, | 346 static void EmitEqualityAsPolymorphicCall(FlowGraphCompiler* compiler, |
| 316 const ICData& orig_ic_data, | 347 const ICData& orig_ic_data, |
| 317 const LocationSummary& locs, | 348 const LocationSummary& locs, |
| 318 BranchInstr* branch, | 349 BranchInstr* branch, |
| 319 Token::Kind kind, | 350 Token::Kind kind, |
| 320 intptr_t deopt_id, | 351 intptr_t deopt_id, |
| 321 intptr_t token_pos, | 352 intptr_t token_pos, |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 416 Register left = locs.in(0).reg(); | 447 Register left = locs.in(0).reg(); |
| 417 Register right = locs.in(1).reg(); | 448 Register right = locs.in(1).reg(); |
| 418 Register temp = locs.temp(0).reg(); | 449 Register temp = locs.temp(0).reg(); |
| 419 Label* deopt = compiler->AddDeoptStub(deopt_id, | 450 Label* deopt = compiler->AddDeoptStub(deopt_id, |
| 420 try_index, | 451 try_index, |
| 421 kDeoptEquality, | 452 kDeoptEquality, |
| 422 left, | 453 left, |
| 423 right); | 454 right); |
| 424 __ testl(left, Immediate(kSmiTagMask)); | 455 __ testl(left, Immediate(kSmiTagMask)); |
| 425 __ j(ZERO, deopt); | 456 __ j(ZERO, deopt); |
| 457 // 'left' is not Smi. |
| 458 const Immediate raw_null = |
| 459 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 460 Label identity_compare; |
| 461 __ cmpl(right, raw_null); |
| 462 __ j(EQUAL, &identity_compare); |
| 463 __ cmpl(left, raw_null); |
| 464 __ j(EQUAL, &identity_compare); |
| 465 |
| 426 __ LoadClassId(temp, left); | 466 __ LoadClassId(temp, left); |
| 427 Label done; | |
| 428 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { | 467 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { |
| 429 __ cmpl(temp, Immediate(ic_data.GetReceiverClassIdAt(i))); | 468 __ cmpl(temp, Immediate(ic_data.GetReceiverClassIdAt(i))); |
| 430 if (i == (ic_data.NumberOfChecks() - 1)) { | 469 if (i == (ic_data.NumberOfChecks() - 1)) { |
| 431 __ j(NOT_EQUAL, deopt); | 470 __ j(NOT_EQUAL, deopt); |
| 432 } else { | 471 } else { |
| 433 __ j(EQUAL, &done); | 472 __ j(EQUAL, &identity_compare); |
| 434 } | 473 } |
| 435 } | 474 } |
| 436 __ Bind(&done); | 475 __ Bind(&identity_compare); |
| 437 __ cmpl(left, right); | 476 __ cmpl(left, right); |
| 438 if (branch == NULL) { | 477 if (branch == NULL) { |
| 439 Label done, is_equal; | 478 Label done, is_equal; |
| 440 Register result = locs.out().reg(); | 479 Register result = locs.out().reg(); |
| 441 __ j(EQUAL, &is_equal, Assembler::kNearJump); | 480 __ j(EQUAL, &is_equal, Assembler::kNearJump); |
| 442 // Not equal. | 481 // Not equal. |
| 443 __ LoadObject(result, (kind == Token::kEQ) ? compiler->bool_false() | 482 __ LoadObject(result, (kind == Token::kEQ) ? compiler->bool_false() |
| 444 : compiler->bool_true()); | 483 : compiler->bool_true()); |
| 445 __ jmp(&done, Assembler::kNearJump); | 484 __ jmp(&done, Assembler::kNearJump); |
| 446 __ Bind(&is_equal); | 485 __ Bind(&is_equal); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 464 const ICData& ic_data, | 503 const ICData& ic_data, |
| 465 intptr_t deopt_id, | 504 intptr_t deopt_id, |
| 466 intptr_t token_pos, | 505 intptr_t token_pos, |
| 467 intptr_t try_index) { | 506 intptr_t try_index) { |
| 468 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); | 507 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); |
| 469 ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0)); | 508 ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0)); |
| 470 Register left = locs.in(0).reg(); | 509 Register left = locs.in(0).reg(); |
| 471 Register right = locs.in(1).reg(); | 510 Register right = locs.in(1).reg(); |
| 472 const Immediate raw_null = | 511 const Immediate raw_null = |
| 473 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 512 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 474 Label done, non_null_compare; | 513 Label done, identity_compare, non_null_compare; |
| 514 __ cmpl(right, raw_null); |
| 515 __ j(EQUAL, &identity_compare, Assembler::kNearJump); |
| 475 __ cmpl(left, raw_null); | 516 __ cmpl(left, raw_null); |
| 476 __ j(NOT_EQUAL, &non_null_compare, Assembler::kNearJump); | 517 __ j(NOT_EQUAL, &non_null_compare, Assembler::kNearJump); |
| 477 // Comparison with NULL is "===". | 518 // Comparison with NULL is "===". |
| 519 __ Bind(&identity_compare); |
| 478 __ cmpl(left, right); | 520 __ cmpl(left, right); |
| 479 Condition cond = TokenKindToSmiCondition(kind); | 521 Condition cond = TokenKindToSmiCondition(kind); |
| 480 if (branch != NULL) { | 522 if (branch != NULL) { |
| 481 branch->EmitBranchOnCondition(compiler, cond); | 523 branch->EmitBranchOnCondition(compiler, cond); |
| 482 } else { | 524 } else { |
| 483 Register result = locs.out().reg(); | 525 Register result = locs.out().reg(); |
| 484 Label load_true; | 526 Label load_true; |
| 485 __ j(cond, &load_true, Assembler::kNearJump); | 527 __ j(cond, &load_true, Assembler::kNearJump); |
| 486 __ LoadObject(result, compiler->bool_false()); | 528 __ LoadObject(result, compiler->bool_false()); |
| 487 __ jmp(&done); | 529 __ jmp(&done); |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 583 true_condition, XMM0, XMM1, branch); | 625 true_condition, XMM0, XMM1, branch); |
| 584 } else { | 626 } else { |
| 585 compiler->EmitDoubleCompareBool( | 627 compiler->EmitDoubleCompareBool( |
| 586 true_condition, XMM0, XMM1, locs.out().reg()); | 628 true_condition, XMM0, XMM1, locs.out().reg()); |
| 587 } | 629 } |
| 588 } | 630 } |
| 589 | 631 |
| 590 | 632 |
| 591 void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 633 void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 592 if (receiver_class_id() == kSmiCid) { | 634 if (receiver_class_id() == kSmiCid) { |
| 635 // Deoptimizes if both arguments not Smi. |
| 593 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL, // No branch. | 636 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL, // No branch. |
| 594 deopt_id(), token_pos(), try_index()); | 637 deopt_id(), token_pos(), try_index()); |
| 595 return; | 638 return; |
| 596 } | 639 } |
| 597 if (receiver_class_id() == kDoubleCid) { | 640 if (receiver_class_id() == kDoubleCid) { |
| 641 // Deoptimizes if both arguments are Smi, or if none is Double or Smi. |
| 598 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL, // No branch. | 642 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL, // No branch. |
| 599 deopt_id(), token_pos(), try_index()); | 643 deopt_id(), token_pos(), try_index()); |
| 600 return; | 644 return; |
| 601 } | 645 } |
| 602 const bool is_checked_strict_equal = | 646 const bool is_checked_strict_equal = |
| 603 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid); | 647 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid); |
| 604 if (is_checked_strict_equal) { | 648 if (is_checked_strict_equal) { |
| 605 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), NULL, | 649 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), NULL, |
| 606 deopt_id(), token_pos(), try_index()); | 650 deopt_id(), token_pos(), try_index()); |
| 607 return; | 651 return; |
| (...skipping 1520 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2128 locs()->stack_bitmap()); | 2172 locs()->stack_bitmap()); |
| 2129 __ CompareObject(EAX, compiler->bool_true()); | 2173 __ CompareObject(EAX, compiler->bool_true()); |
| 2130 EmitBranchOnCondition(compiler, branch_condition); | 2174 EmitBranchOnCondition(compiler, branch_condition); |
| 2131 } | 2175 } |
| 2132 | 2176 |
| 2133 } // namespace dart | 2177 } // namespace dart |
| 2134 | 2178 |
| 2135 #undef __ | 2179 #undef __ |
| 2136 | 2180 |
| 2137 #endif // defined TARGET_ARCH_X64 | 2181 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |