Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(103)

Side by Side Diff: runtime/vm/intermediate_language_x64.cc

Issue 10855208: Implement new equality spec. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/intermediate_language_ia32.cc ('k') | tests/language/equality_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « runtime/vm/intermediate_language_ia32.cc ('k') | tests/language/equality_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698