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 |