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 |