| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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_MIPS. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_MIPS. |
| 6 #if defined(TARGET_ARCH_MIPS) | 6 #if defined(TARGET_ARCH_MIPS) |
| 7 | 7 |
| 8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
| 9 | 9 |
| 10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
| (...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 349 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 349 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
| 350 deopt_id, | 350 deopt_id, |
| 351 token_pos); | 351 token_pos); |
| 352 } | 352 } |
| 353 const int kNumberOfArguments = 2; | 353 const int kNumberOfArguments = 2; |
| 354 const Array& kNoArgumentNames = Object::null_array(); | 354 const Array& kNoArgumentNames = Object::null_array(); |
| 355 const int kNumArgumentsChecked = 2; | 355 const int kNumArgumentsChecked = 2; |
| 356 | 356 |
| 357 __ TraceSimMsg("EmitEqualityAsInstanceCall"); | 357 __ TraceSimMsg("EmitEqualityAsInstanceCall"); |
| 358 __ Comment("EmitEqualityAsInstanceCall"); | 358 __ Comment("EmitEqualityAsInstanceCall"); |
| 359 Label check_identity; | |
| 360 __ lw(A1, Address(SP, 1 * kWordSize)); | |
| 361 __ lw(A0, Address(SP, 0 * kWordSize)); | |
| 362 __ LoadImmediate(CMPRES1, reinterpret_cast<int32_t>(Object::null())); | |
| 363 __ beq(A1, CMPRES1, &check_identity); | |
| 364 __ beq(A0, CMPRES1, &check_identity); | |
| 365 | 359 |
| 366 ICData& equality_ic_data = ICData::ZoneHandle(); | 360 ICData& equality_ic_data = ICData::ZoneHandle(); |
| 367 if (compiler->is_optimizing() && FLAG_propagate_ic_data) { | 361 if (compiler->is_optimizing() && FLAG_propagate_ic_data) { |
| 368 ASSERT(!original_ic_data.IsNull()); | 362 ASSERT(!original_ic_data.IsNull()); |
| 369 if (original_ic_data.NumberOfChecks() == 0) { | 363 if (original_ic_data.NumberOfChecks() == 0) { |
| 370 // IC call for reoptimization populates original ICData. | 364 // IC call for reoptimization populates original ICData. |
| 371 equality_ic_data = original_ic_data.raw(); | 365 equality_ic_data = original_ic_data.raw(); |
| 372 } else { | 366 } else { |
| 373 // Megamorphic call. | 367 // Megamorphic call. |
| 374 equality_ic_data = original_ic_data.AsUnaryClassChecks(); | 368 equality_ic_data = original_ic_data.AsUnaryClassChecks(); |
| 375 } | 369 } |
| 376 } else { | 370 } else { |
| 377 const Array& arguments_descriptor = | 371 const Array& arguments_descriptor = |
| 378 Array::Handle(ArgumentsDescriptor::New(kNumberOfArguments, | 372 Array::Handle(ArgumentsDescriptor::New(kNumberOfArguments, |
| 379 kNoArgumentNames)); | 373 kNoArgumentNames)); |
| 380 equality_ic_data = ICData::New(compiler->parsed_function().function(), | 374 equality_ic_data = ICData::New(compiler->parsed_function().function(), |
| 381 Symbols::EqualOperator(), | 375 Symbols::EqualOperator(), |
| 382 arguments_descriptor, | 376 arguments_descriptor, |
| 383 deopt_id, | 377 deopt_id, |
| 384 kNumArgumentsChecked); | 378 kNumArgumentsChecked); |
| 385 } | 379 } |
| 386 compiler->GenerateInstanceCall(deopt_id, | 380 compiler->GenerateInstanceCall(deopt_id, |
| 387 token_pos, | 381 token_pos, |
| 388 kNumberOfArguments, | 382 kNumberOfArguments, |
| 389 kNoArgumentNames, | 383 kNoArgumentNames, |
| 390 locs, | 384 locs, |
| 391 equality_ic_data); | 385 equality_ic_data); |
| 392 Label check_ne; | |
| 393 __ b(&check_ne); | |
| 394 | |
| 395 __ Bind(&check_identity); | |
| 396 Label equality_done; | |
| 397 if (compiler->is_optimizing()) { | |
| 398 // No need to update IC data. | |
| 399 Label is_true; | |
| 400 __ lw(A1, Address(SP, 1 * kWordSize)); | |
| 401 __ lw(A0, Address(SP, 0 * kWordSize)); | |
| 402 __ addiu(SP, SP, Immediate(2 * kWordSize)); | |
| 403 __ beq(A1, A0, &is_true); | |
| 404 __ LoadObject(V0, Bool::Get(kind != Token::kEQ)); | |
| 405 __ b(&equality_done); | |
| 406 __ Bind(&is_true); | |
| 407 __ LoadObject(V0, Bool::Get(kind == Token::kEQ)); | |
| 408 if (kind == Token::kNE) { | |
| 409 // Skip not-equal result conversion. | |
| 410 __ b(&equality_done); | |
| 411 } | |
| 412 } else { | |
| 413 // Call stub, load IC data in register. The stub will update ICData if | |
| 414 // necessary. | |
| 415 Register ic_data_reg = locs->temp(0).reg(); | |
| 416 ASSERT(ic_data_reg == T0); // Stub depends on it. | |
| 417 __ LoadObject(ic_data_reg, equality_ic_data); | |
| 418 // Pass left in A1 and right in A0. | |
| 419 compiler->GenerateCall(token_pos, | |
| 420 &StubCode::EqualityWithNullArgLabel(), | |
| 421 PcDescriptors::kRuntimeCall, | |
| 422 locs); | |
| 423 __ Drop(2); | |
| 424 } | |
| 425 __ Bind(&check_ne); | |
| 426 if (kind == Token::kNE) { | 386 if (kind == Token::kNE) { |
| 427 Label true_label, done; | 387 Label true_label, done; |
| 428 // Negate the condition: true label returns false and vice versa. | 388 // Negate the condition: true label returns false and vice versa. |
| 429 __ BranchEqual(V0, Bool::True(), &true_label); | 389 __ BranchEqual(V0, Bool::True(), &true_label); |
| 430 __ LoadObject(V0, Bool::True()); | 390 __ LoadObject(V0, Bool::True()); |
| 431 __ b(&done); | 391 __ b(&done); |
| 432 __ Bind(&true_label); | 392 __ Bind(&true_label); |
| 433 __ LoadObject(V0, Bool::False()); | 393 __ LoadObject(V0, Bool::False()); |
| 434 __ Bind(&done); | 394 __ Bind(&done); |
| 435 } | 395 } |
| 436 __ Bind(&equality_done); | |
| 437 } | 396 } |
| 438 | 397 |
| 439 | 398 |
| 440 static void LoadValueCid(FlowGraphCompiler* compiler, | 399 static void LoadValueCid(FlowGraphCompiler* compiler, |
| 441 Register value_cid_reg, | 400 Register value_cid_reg, |
| 442 Register value_reg, | 401 Register value_reg, |
| 443 Label* value_is_smi = NULL) { | 402 Label* value_is_smi = NULL) { |
| 444 __ TraceSimMsg("LoadValueCid"); | 403 __ TraceSimMsg("LoadValueCid"); |
| 445 Label done; | 404 Label done; |
| 446 if (value_is_smi == NULL) { | 405 if (value_is_smi == NULL) { |
| (...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 642 LocationSummary* locs, | 601 LocationSummary* locs, |
| 643 Token::Kind kind, | 602 Token::Kind kind, |
| 644 BranchInstr* branch, | 603 BranchInstr* branch, |
| 645 const ICData& ic_data, | 604 const ICData& ic_data, |
| 646 intptr_t deopt_id, | 605 intptr_t deopt_id, |
| 647 intptr_t token_pos) { | 606 intptr_t token_pos) { |
| 648 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); | 607 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); |
| 649 ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0)); | 608 ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0)); |
| 650 Register left = locs->in(0).reg(); | 609 Register left = locs->in(0).reg(); |
| 651 Register right = locs->in(1).reg(); | 610 Register right = locs->in(1).reg(); |
| 652 Label done, identity_compare, non_null_compare; | |
| 653 __ TraceSimMsg("EmitGenericEqualityCompare"); | 611 __ TraceSimMsg("EmitGenericEqualityCompare"); |
| 654 __ Comment("EmitGenericEqualityCompare"); | 612 __ Comment("EmitGenericEqualityCompare"); |
| 655 __ LoadImmediate(CMPRES1, reinterpret_cast<int32_t>(Object::null())); | |
| 656 __ beq(right, CMPRES1, &identity_compare); | |
| 657 __ bne(left, CMPRES1, &non_null_compare); | |
| 658 | |
| 659 // Comparison with NULL is "===". | |
| 660 __ Bind(&identity_compare); | |
| 661 Condition cond = TokenKindToSmiCondition(kind); | |
| 662 __ slt(CMPRES1, left, right); | |
| 663 __ slt(CMPRES2, right, left); | |
| 664 if (branch != NULL) { | |
| 665 branch->EmitBranchOnCondition(compiler, cond); | |
| 666 } else { | |
| 667 Register result = locs->out().reg(); | |
| 668 Label load_true; | |
| 669 EmitBranchAfterCompare(compiler, cond, &load_true); | |
| 670 __ LoadObject(result, Bool::False()); | |
| 671 __ b(&done); | |
| 672 __ Bind(&load_true); | |
| 673 __ LoadObject(result, Bool::True()); | |
| 674 } | |
| 675 __ b(&done); | |
| 676 __ Bind(&non_null_compare); // Receiver is not null. | |
| 677 ASSERT(left == A1); | 613 ASSERT(left == A1); |
| 678 ASSERT(right == A0); | 614 ASSERT(right == A0); |
| 679 __ addiu(SP, SP, Immediate(-2 * kWordSize)); | 615 __ addiu(SP, SP, Immediate(-2 * kWordSize)); |
| 680 __ sw(A1, Address(SP, 1 * kWordSize)); | 616 __ sw(A1, Address(SP, 1 * kWordSize)); |
| 681 __ sw(A0, Address(SP, 0 * kWordSize)); | 617 __ sw(A0, Address(SP, 0 * kWordSize)); |
| 682 EmitEqualityAsPolymorphicCall(compiler, ic_data, locs, branch, kind, | 618 EmitEqualityAsPolymorphicCall(compiler, ic_data, locs, branch, kind, |
| 683 deopt_id, token_pos); | 619 deopt_id, token_pos); |
| 684 __ Bind(&done); | |
| 685 } | 620 } |
| 686 | 621 |
| 687 | 622 |
| 688 static Condition FlipCondition(Condition condition) { | 623 static Condition FlipCondition(Condition condition) { |
| 689 switch (condition) { | 624 switch (condition) { |
| 690 case EQ: return EQ; | 625 case EQ: return EQ; |
| 691 case NE: return NE; | 626 case NE: return NE; |
| 692 case LT: return GT; | 627 case LT: return GT; |
| 693 case LE: return GE; | 628 case LE: return GE; |
| 694 case GT: return LT; | 629 case GT: return LT; |
| (...skipping 3418 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4113 compiler->GenerateCall(token_pos(), | 4048 compiler->GenerateCall(token_pos(), |
| 4114 &label, | 4049 &label, |
| 4115 PcDescriptors::kOther, | 4050 PcDescriptors::kOther, |
| 4116 locs()); | 4051 locs()); |
| 4117 __ Drop(2); // Discard type arguments and receiver. | 4052 __ Drop(2); // Discard type arguments and receiver. |
| 4118 } | 4053 } |
| 4119 | 4054 |
| 4120 } // namespace dart | 4055 } // namespace dart |
| 4121 | 4056 |
| 4122 #endif // defined TARGET_ARCH_MIPS | 4057 #endif // defined TARGET_ARCH_MIPS |
| OLD | NEW |