| 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_ARM. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM. |
| 6 #if defined(TARGET_ARCH_ARM) | 6 #if defined(TARGET_ARCH_ARM) |
| 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 343 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 354 const ICData& original_ic_data) { | 354 const ICData& original_ic_data) { |
| 355 if (!compiler->is_optimizing()) { | 355 if (!compiler->is_optimizing()) { |
| 356 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 356 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
| 357 deopt_id, | 357 deopt_id, |
| 358 token_pos); | 358 token_pos); |
| 359 } | 359 } |
| 360 const int kNumberOfArguments = 2; | 360 const int kNumberOfArguments = 2; |
| 361 const Array& kNoArgumentNames = Object::null_array(); | 361 const Array& kNoArgumentNames = Object::null_array(); |
| 362 const int kNumArgumentsChecked = 2; | 362 const int kNumArgumentsChecked = 2; |
| 363 | 363 |
| 364 Label check_identity; | |
| 365 __ LoadImmediate(IP, reinterpret_cast<intptr_t>(Object::null())); | |
| 366 __ ldm(IA, SP, (1 << R0) | (1 << R1)); | |
| 367 __ cmp(R1, ShifterOperand(IP)); | |
| 368 __ b(&check_identity, EQ); | |
| 369 __ cmp(R0, ShifterOperand(IP)); | |
| 370 __ b(&check_identity, EQ); | |
| 371 | |
| 372 ICData& equality_ic_data = ICData::ZoneHandle(); | 364 ICData& equality_ic_data = ICData::ZoneHandle(); |
| 373 if (compiler->is_optimizing() && FLAG_propagate_ic_data) { | 365 if (compiler->is_optimizing() && FLAG_propagate_ic_data) { |
| 374 ASSERT(!original_ic_data.IsNull()); | 366 ASSERT(!original_ic_data.IsNull()); |
| 375 if (original_ic_data.NumberOfChecks() == 0) { | 367 if (original_ic_data.NumberOfChecks() == 0) { |
| 376 // IC call for reoptimization populates original ICData. | 368 // IC call for reoptimization populates original ICData. |
| 377 equality_ic_data = original_ic_data.raw(); | 369 equality_ic_data = original_ic_data.raw(); |
| 378 } else { | 370 } else { |
| 379 // Megamorphic call. | 371 // Megamorphic call. |
| 380 equality_ic_data = original_ic_data.AsUnaryClassChecks(); | 372 equality_ic_data = original_ic_data.AsUnaryClassChecks(); |
| 381 } | 373 } |
| 382 } else { | 374 } else { |
| 383 const Array& arguments_descriptor = | 375 const Array& arguments_descriptor = |
| 384 Array::Handle(ArgumentsDescriptor::New(kNumberOfArguments, | 376 Array::Handle(ArgumentsDescriptor::New(kNumberOfArguments, |
| 385 kNoArgumentNames)); | 377 kNoArgumentNames)); |
| 386 equality_ic_data = ICData::New(compiler->parsed_function().function(), | 378 equality_ic_data = ICData::New(compiler->parsed_function().function(), |
| 387 Symbols::EqualOperator(), | 379 Symbols::EqualOperator(), |
| 388 arguments_descriptor, | 380 arguments_descriptor, |
| 389 deopt_id, | 381 deopt_id, |
| 390 kNumArgumentsChecked); | 382 kNumArgumentsChecked); |
| 391 } | 383 } |
| 392 compiler->GenerateInstanceCall(deopt_id, | 384 compiler->GenerateInstanceCall(deopt_id, |
| 393 token_pos, | 385 token_pos, |
| 394 kNumberOfArguments, | 386 kNumberOfArguments, |
| 395 kNoArgumentNames, | 387 kNoArgumentNames, |
| 396 locs, | 388 locs, |
| 397 equality_ic_data); | 389 equality_ic_data); |
| 398 Label check_ne; | |
| 399 __ b(&check_ne); | |
| 400 | |
| 401 __ Bind(&check_identity); | |
| 402 Label equality_done; | |
| 403 if (compiler->is_optimizing()) { | |
| 404 // No need to update IC data. | |
| 405 __ PopList((1 << R0) | (1 << R1)); | |
| 406 __ cmp(R0, ShifterOperand(R1)); | |
| 407 __ LoadObject(R0, Bool::Get(kind != Token::kEQ), NE); | |
| 408 __ LoadObject(R0, Bool::Get(kind == Token::kEQ), EQ); | |
| 409 if (kind == Token::kNE) { | |
| 410 // Skip not-equal result conversion. | |
| 411 __ b(&equality_done); | |
| 412 } | |
| 413 } else { | |
| 414 // Call stub, load IC data in register. The stub will update ICData if | |
| 415 // necessary. | |
| 416 Register ic_data_reg = locs->temp(0).reg(); | |
| 417 ASSERT(ic_data_reg == R5); // Stub depends on it. | |
| 418 __ LoadObject(ic_data_reg, equality_ic_data); | |
| 419 // Pass left in R1 and right in R0. | |
| 420 compiler->GenerateCall(token_pos, | |
| 421 &StubCode::EqualityWithNullArgLabel(), | |
| 422 PcDescriptors::kRuntimeCall, | |
| 423 locs); | |
| 424 __ Drop(2); | |
| 425 } | |
| 426 __ Bind(&check_ne); | |
| 427 if (kind == Token::kNE) { | 390 if (kind == Token::kNE) { |
| 428 // Negate the condition: true label returns false and vice versa. | 391 // Negate the condition: true label returns false and vice versa. |
| 429 __ CompareObject(R0, Bool::True()); | 392 __ CompareObject(R0, Bool::True()); |
| 430 __ LoadObject(R0, Bool::True(), NE); | 393 __ LoadObject(R0, Bool::True(), NE); |
| 431 __ LoadObject(R0, Bool::False(), EQ); | 394 __ LoadObject(R0, Bool::False(), EQ); |
| 432 } | 395 } |
| 433 __ Bind(&equality_done); | |
| 434 } | 396 } |
| 435 | 397 |
| 436 | 398 |
| 437 static void LoadValueCid(FlowGraphCompiler* compiler, | 399 static void LoadValueCid(FlowGraphCompiler* compiler, |
| 438 Register value_cid_reg, | 400 Register value_cid_reg, |
| 439 Register value_reg, | 401 Register value_reg, |
| 440 Label* value_is_smi = NULL) { | 402 Label* value_is_smi = NULL) { |
| 441 Label done; | 403 Label done; |
| 442 if (value_is_smi == NULL) { | 404 if (value_is_smi == NULL) { |
| 443 __ mov(value_cid_reg, ShifterOperand(kSmiCid)); | 405 __ mov(value_cid_reg, ShifterOperand(kSmiCid)); |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 605 LocationSummary* locs, | 567 LocationSummary* locs, |
| 606 Token::Kind kind, | 568 Token::Kind kind, |
| 607 BranchInstr* branch, | 569 BranchInstr* branch, |
| 608 const ICData& ic_data, | 570 const ICData& ic_data, |
| 609 intptr_t deopt_id, | 571 intptr_t deopt_id, |
| 610 intptr_t token_pos) { | 572 intptr_t token_pos) { |
| 611 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); | 573 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); |
| 612 ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0)); | 574 ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0)); |
| 613 Register left = locs->in(0).reg(); | 575 Register left = locs->in(0).reg(); |
| 614 Register right = locs->in(1).reg(); | 576 Register right = locs->in(1).reg(); |
| 615 Label done, identity_compare, non_null_compare; | |
| 616 __ LoadImmediate(IP, reinterpret_cast<intptr_t>(Object::null())); | |
| 617 __ cmp(right, ShifterOperand(IP)); | |
| 618 __ b(&identity_compare, EQ); | |
| 619 __ cmp(left, ShifterOperand(IP)); | |
| 620 __ b(&non_null_compare, NE); | |
| 621 // Comparison with NULL is "===". | |
| 622 __ Bind(&identity_compare); | |
| 623 __ cmp(left, ShifterOperand(right)); | |
| 624 Condition cond = TokenKindToSmiCondition(kind); | |
| 625 if (branch != NULL) { | |
| 626 branch->EmitBranchOnCondition(compiler, cond); | |
| 627 } else { | |
| 628 Register result = locs->out().reg(); | |
| 629 Label load_true; | |
| 630 __ b(&load_true, cond); | |
| 631 __ LoadObject(result, Bool::False()); | |
| 632 __ b(&done); | |
| 633 __ Bind(&load_true); | |
| 634 __ LoadObject(result, Bool::True()); | |
| 635 } | |
| 636 __ b(&done); | |
| 637 __ Bind(&non_null_compare); // Receiver is not null. | |
| 638 ASSERT(left == R1); | 577 ASSERT(left == R1); |
| 639 ASSERT(right == R0); | 578 ASSERT(right == R0); |
| 640 __ PushList((1 << R0) | (1 << R1)); | 579 __ PushList((1 << R0) | (1 << R1)); |
| 641 EmitEqualityAsPolymorphicCall(compiler, ic_data, locs, branch, kind, | 580 EmitEqualityAsPolymorphicCall(compiler, ic_data, locs, branch, kind, |
| 642 deopt_id, token_pos); | 581 deopt_id, token_pos); |
| 643 __ Bind(&done); | |
| 644 } | 582 } |
| 645 | 583 |
| 646 | 584 |
| 647 static Condition FlipCondition(Condition condition) { | 585 static Condition FlipCondition(Condition condition) { |
| 648 switch (condition) { | 586 switch (condition) { |
| 649 case EQ: return EQ; | 587 case EQ: return EQ; |
| 650 case NE: return NE; | 588 case NE: return NE; |
| 651 case LT: return GT; | 589 case LT: return GT; |
| 652 case LE: return GE; | 590 case LE: return GE; |
| 653 case GT: return LT; | 591 case GT: return LT; |
| (...skipping 4024 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4678 compiler->GenerateCall(token_pos(), | 4616 compiler->GenerateCall(token_pos(), |
| 4679 &label, | 4617 &label, |
| 4680 PcDescriptors::kOther, | 4618 PcDescriptors::kOther, |
| 4681 locs()); | 4619 locs()); |
| 4682 __ Drop(2); // Discard type arguments and receiver. | 4620 __ Drop(2); // Discard type arguments and receiver. |
| 4683 } | 4621 } |
| 4684 | 4622 |
| 4685 } // namespace dart | 4623 } // namespace dart |
| 4686 | 4624 |
| 4687 #endif // defined TARGET_ARCH_ARM | 4625 #endif // defined TARGET_ARCH_ARM |
| OLD | NEW |