| 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 "lib/error.h" | 10 #include "lib/error.h" |
| (...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 332 locs->set_in(0, Location::RequiresRegister()); | 332 locs->set_in(0, Location::RequiresRegister()); |
| 333 locs->set_in(1, Location::RequiresRegister()); | 333 locs->set_in(1, Location::RequiresRegister()); |
| 334 locs->set_temp(0, Location::RequiresRegister()); | 334 locs->set_temp(0, Location::RequiresRegister()); |
| 335 locs->set_out(Location::RequiresRegister()); | 335 locs->set_out(Location::RequiresRegister()); |
| 336 return locs; | 336 return locs; |
| 337 } | 337 } |
| 338 if (IsPolymorphic()) { | 338 if (IsPolymorphic()) { |
| 339 const intptr_t kNumTemps = 1; | 339 const intptr_t kNumTemps = 1; |
| 340 LocationSummary* locs = | 340 LocationSummary* locs = |
| 341 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 341 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 342 UNIMPLEMENTED(); // TODO(regis): Verify register allocation. | 342 locs->set_in(0, Location::RegisterLocation(R1)); |
| 343 locs->set_in(1, Location::RegisterLocation(R0)); |
| 344 locs->set_temp(0, Location::RegisterLocation(R5)); |
| 345 locs->set_out(Location::RegisterLocation(R0)); |
| 343 return locs; | 346 return locs; |
| 344 } | 347 } |
| 345 const intptr_t kNumTemps = 1; | 348 const intptr_t kNumTemps = 1; |
| 346 LocationSummary* locs = | 349 LocationSummary* locs = |
| 347 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 350 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 348 locs->set_in(0, Location::RegisterLocation(R1)); | 351 locs->set_in(0, Location::RegisterLocation(R1)); |
| 349 locs->set_in(1, Location::RegisterLocation(R0)); | 352 locs->set_in(1, Location::RegisterLocation(R0)); |
| 350 locs->set_temp(0, Location::RegisterLocation(R5)); | 353 locs->set_temp(0, Location::RegisterLocation(R5)); |
| 351 locs->set_out(Location::RegisterLocation(R0)); | 354 locs->set_out(Location::RegisterLocation(R0)); |
| 352 return locs; | 355 return locs; |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 450 if (value_is_smi == NULL) { | 453 if (value_is_smi == NULL) { |
| 451 __ b(&done, EQ); | 454 __ b(&done, EQ); |
| 452 } else { | 455 } else { |
| 453 __ b(value_is_smi, EQ); | 456 __ b(value_is_smi, EQ); |
| 454 } | 457 } |
| 455 __ LoadClassId(value_cid_reg, value_reg); | 458 __ LoadClassId(value_cid_reg, value_reg); |
| 456 __ Bind(&done); | 459 __ Bind(&done); |
| 457 } | 460 } |
| 458 | 461 |
| 459 | 462 |
| 463 static Condition NegateCondition(Condition condition) { |
| 464 switch (condition) { |
| 465 case EQ: return NE; |
| 466 case NE: return EQ; |
| 467 case LT: return GE; |
| 468 case LE: return GT; |
| 469 case GT: return LE; |
| 470 case GE: return LT; |
| 471 case CC: return CS; |
| 472 case LS: return HI; |
| 473 case HI: return LS; |
| 474 case CS: return CC; |
| 475 default: |
| 476 UNIMPLEMENTED(); |
| 477 return EQ; |
| 478 } |
| 479 } |
| 480 |
| 481 |
| 482 // R1: left. |
| 483 // R0: right. |
| 484 static void EmitEqualityAsPolymorphicCall(FlowGraphCompiler* compiler, |
| 485 const ICData& orig_ic_data, |
| 486 LocationSummary* locs, |
| 487 BranchInstr* branch, |
| 488 Token::Kind kind, |
| 489 intptr_t deopt_id, |
| 490 intptr_t token_pos) { |
| 491 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); |
| 492 const ICData& ic_data = ICData::Handle(orig_ic_data.AsUnaryClassChecks()); |
| 493 ASSERT(ic_data.NumberOfChecks() > 0); |
| 494 ASSERT(ic_data.num_args_tested() == 1); |
| 495 Label* deopt = compiler->AddDeoptStub(deopt_id, kDeoptEquality); |
| 496 Register left = locs->in(0).reg(); |
| 497 Register right = locs->in(1).reg(); |
| 498 ASSERT(left == R1); |
| 499 ASSERT(right == R0); |
| 500 Register temp = locs->temp(0).reg(); |
| 501 LoadValueCid(compiler, temp, left, |
| 502 (ic_data.GetReceiverClassIdAt(0) == kSmiCid) ? NULL : deopt); |
| 503 // 'temp' contains class-id of the left argument. |
| 504 ObjectStore* object_store = Isolate::Current()->object_store(); |
| 505 Condition cond = TokenKindToSmiCondition(kind); |
| 506 Label done; |
| 507 const intptr_t len = ic_data.NumberOfChecks(); |
| 508 for (intptr_t i = 0; i < len; i++) { |
| 509 // Assert that the Smi is at position 0, if at all. |
| 510 ASSERT((ic_data.GetReceiverClassIdAt(i) != kSmiCid) || (i == 0)); |
| 511 Label next_test; |
| 512 __ CompareImmediate(temp, ic_data.GetReceiverClassIdAt(i)); |
| 513 if (i < len - 1) { |
| 514 __ b(&next_test, NE); |
| 515 } else { |
| 516 __ b(deopt, NE); |
| 517 } |
| 518 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(i)); |
| 519 if (target.Owner() == object_store->object_class()) { |
| 520 // Object.== is same as ===. |
| 521 __ cmp(left, ShifterOperand(right)); |
| 522 if (branch != NULL) { |
| 523 branch->EmitBranchOnCondition(compiler, cond); |
| 524 } else { |
| 525 Register result = locs->out().reg(); |
| 526 __ LoadObject(result, Bool::True(), cond); |
| 527 __ LoadObject(result, Bool::False(), NegateCondition(cond)); |
| 528 } |
| 529 } else { |
| 530 const int kNumberOfArguments = 2; |
| 531 const Array& kNoArgumentNames = Array::Handle(); |
| 532 compiler->GenerateStaticCall(deopt_id, |
| 533 token_pos, |
| 534 target, |
| 535 kNumberOfArguments, |
| 536 kNoArgumentNames, |
| 537 locs); |
| 538 if (branch == NULL) { |
| 539 if (kind == Token::kNE) { |
| 540 __ CompareObject(R0, Bool::True()); |
| 541 __ LoadObject(R0, Bool::True(), NE); |
| 542 __ LoadObject(R0, Bool::False(), EQ); |
| 543 } |
| 544 } else { |
| 545 if (branch->is_checked()) { |
| 546 EmitAssertBoolean(R0, token_pos, deopt_id, locs, compiler); |
| 547 } |
| 548 __ CompareObject(R0, Bool::True()); |
| 549 branch->EmitBranchOnCondition(compiler, cond); |
| 550 } |
| 551 } |
| 552 if (i < len - 1) { |
| 553 __ b(&done); |
| 554 __ Bind(&next_test); |
| 555 } |
| 556 } |
| 557 __ Bind(&done); |
| 558 } |
| 559 |
| 560 |
| 460 // Emit code when ICData's targets are all Object == (which is ===). | 561 // Emit code when ICData's targets are all Object == (which is ===). |
| 461 static void EmitCheckedStrictEqual(FlowGraphCompiler* compiler, | 562 static void EmitCheckedStrictEqual(FlowGraphCompiler* compiler, |
| 462 const ICData& ic_data, | 563 const ICData& ic_data, |
| 463 const LocationSummary& locs, | 564 const LocationSummary& locs, |
| 464 Token::Kind kind, | 565 Token::Kind kind, |
| 465 BranchInstr* branch, | 566 BranchInstr* branch, |
| 466 intptr_t deopt_id) { | 567 intptr_t deopt_id) { |
| 467 UNIMPLEMENTED(); | 568 UNIMPLEMENTED(); |
| 468 } | 569 } |
| 469 | 570 |
| 470 | 571 |
| 471 // First test if receiver is NULL, in which case === is applied. | 572 // First test if receiver is NULL, in which case === is applied. |
| 472 // If type feedback was provided (lists of <class-id, target>), do a | 573 // If type feedback was provided (lists of <class-id, target>), do a |
| 473 // type by type check (either === or static call to the operator. | 574 // type by type check (either === or static call to the operator. |
| 474 static void EmitGenericEqualityCompare(FlowGraphCompiler* compiler, | 575 static void EmitGenericEqualityCompare(FlowGraphCompiler* compiler, |
| 475 LocationSummary* locs, | 576 LocationSummary* locs, |
| 476 Token::Kind kind, | 577 Token::Kind kind, |
| 477 BranchInstr* branch, | 578 BranchInstr* branch, |
| 478 const ICData& ic_data, | 579 const ICData& ic_data, |
| 479 intptr_t deopt_id, | 580 intptr_t deopt_id, |
| 480 intptr_t token_pos) { | 581 intptr_t token_pos) { |
| 481 UNIMPLEMENTED(); | 582 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); |
| 583 ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0)); |
| 584 Register left = locs->in(0).reg(); |
| 585 Register right = locs->in(1).reg(); |
| 586 Label done, identity_compare, non_null_compare; |
| 587 __ LoadImmediate(IP, reinterpret_cast<intptr_t>(Object::null())); |
| 588 __ cmp(right, ShifterOperand(IP)); |
| 589 __ b(&identity_compare, EQ); |
| 590 __ cmp(left, ShifterOperand(IP)); |
| 591 __ b(&non_null_compare, NE); |
| 592 // Comparison with NULL is "===". |
| 593 __ Bind(&identity_compare); |
| 594 __ cmp(left, ShifterOperand(right)); |
| 595 Condition cond = TokenKindToSmiCondition(kind); |
| 596 if (branch != NULL) { |
| 597 branch->EmitBranchOnCondition(compiler, cond); |
| 598 } else { |
| 599 Register result = locs->out().reg(); |
| 600 Label load_true; |
| 601 __ b(&load_true, cond); |
| 602 __ LoadObject(result, Bool::False()); |
| 603 __ b(&done); |
| 604 __ Bind(&load_true); |
| 605 __ LoadObject(result, Bool::True()); |
| 606 } |
| 607 __ b(&done); |
| 608 __ Bind(&non_null_compare); // Receiver is not null. |
| 609 ASSERT(left == R1); |
| 610 ASSERT(right == R0); |
| 611 EmitEqualityAsPolymorphicCall(compiler, ic_data, locs, branch, kind, |
| 612 deopt_id, token_pos); |
| 613 __ Bind(&done); |
| 482 } | 614 } |
| 483 | 615 |
| 484 | 616 |
| 485 static Condition NegateCondition(Condition condition) { | |
| 486 switch (condition) { | |
| 487 case EQ: return NE; | |
| 488 case NE: return EQ; | |
| 489 case LT: return GE; | |
| 490 case LE: return GT; | |
| 491 case GT: return LE; | |
| 492 case GE: return LT; | |
| 493 case CC: return CS; | |
| 494 case LS: return HI; | |
| 495 case HI: return LS; | |
| 496 case CS: return CC; | |
| 497 default: | |
| 498 UNIMPLEMENTED(); | |
| 499 return EQ; | |
| 500 } | |
| 501 } | |
| 502 | |
| 503 | |
| 504 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, | 617 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, |
| 505 const LocationSummary& locs, | 618 const LocationSummary& locs, |
| 506 Token::Kind kind, | 619 Token::Kind kind, |
| 507 BranchInstr* branch) { | 620 BranchInstr* branch) { |
| 508 Location left = locs.in(0); | 621 Location left = locs.in(0); |
| 509 Location right = locs.in(1); | 622 Location right = locs.in(1); |
| 510 ASSERT(!left.IsConstant() || !right.IsConstant()); | 623 ASSERT(!left.IsConstant() || !right.IsConstant()); |
| 511 | 624 |
| 512 Condition true_condition = TokenKindToSmiCondition(kind); | 625 Condition true_condition = TokenKindToSmiCondition(kind); |
| 513 | 626 |
| (...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 838 return NULL; | 951 return NULL; |
| 839 } | 952 } |
| 840 | 953 |
| 841 | 954 |
| 842 void LoadUntaggedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 955 void LoadUntaggedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 843 UNIMPLEMENTED(); | 956 UNIMPLEMENTED(); |
| 844 } | 957 } |
| 845 | 958 |
| 846 | 959 |
| 847 LocationSummary* LoadClassIdInstr::MakeLocationSummary() const { | 960 LocationSummary* LoadClassIdInstr::MakeLocationSummary() const { |
| 848 UNIMPLEMENTED(); | 961 const intptr_t kNumInputs = 1; |
| 849 return NULL; | 962 return LocationSummary::Make(kNumInputs, |
| 963 Location::RequiresRegister(), |
| 964 LocationSummary::kNoCall); |
| 850 } | 965 } |
| 851 | 966 |
| 852 | 967 |
| 853 void LoadClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 968 void LoadClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 854 UNIMPLEMENTED(); | 969 Register object = locs()->in(0).reg(); |
| 970 Register result = locs()->out().reg(); |
| 971 Label load, done; |
| 972 __ tst(object, ShifterOperand(kSmiTagMask)); |
| 973 __ b(&load, NE); |
| 974 __ LoadImmediate(result, Smi::RawValue(kSmiCid)); |
| 975 __ b(&done); |
| 976 __ Bind(&load); |
| 977 __ LoadClassId(result, object); |
| 978 __ SmiTag(result); |
| 979 __ Bind(&done); |
| 855 } | 980 } |
| 856 | 981 |
| 857 | 982 |
| 858 CompileType LoadIndexedInstr::ComputeType() const { | 983 CompileType LoadIndexedInstr::ComputeType() const { |
| 859 switch (class_id_) { | 984 switch (class_id_) { |
| 860 case kArrayCid: | 985 case kArrayCid: |
| 861 case kImmutableArrayCid: | 986 case kImmutableArrayCid: |
| 862 return CompileType::Dynamic(); | 987 return CompileType::Dynamic(); |
| 863 | 988 |
| 864 case kTypedDataFloat32ArrayCid: | 989 case kTypedDataFloat32ArrayCid: |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 985 element_address = Address(array, index.reg(), LSL, 0); | 1110 element_address = Address(array, index.reg(), LSL, 0); |
| 986 } | 1111 } |
| 987 | 1112 |
| 988 if ((representation() == kUnboxedDouble) || | 1113 if ((representation() == kUnboxedDouble) || |
| 989 (representation() == kUnboxedMint) || | 1114 (representation() == kUnboxedMint) || |
| 990 (representation() == kUnboxedFloat32x4)) { | 1115 (representation() == kUnboxedFloat32x4)) { |
| 991 UNIMPLEMENTED(); | 1116 UNIMPLEMENTED(); |
| 992 } | 1117 } |
| 993 | 1118 |
| 994 Register result = locs()->out().reg(); | 1119 Register result = locs()->out().reg(); |
| 995 if ((index_scale() == 1) && index.IsRegister()) { | |
| 996 __ SmiUntag(index.reg()); | |
| 997 } | |
| 998 switch (class_id()) { | 1120 switch (class_id()) { |
| 999 case kTypedDataInt8ArrayCid: | 1121 case kTypedDataInt8ArrayCid: |
| 1000 ASSERT(index_scale() == 1); | 1122 ASSERT(index_scale() == 1); |
| 1001 __ ldrsb(result, element_address); | 1123 __ ldrsb(result, element_address); |
| 1002 __ SmiTag(result); | 1124 __ SmiTag(result); |
| 1003 break; | 1125 break; |
| 1004 case kTypedDataUint8ArrayCid: | 1126 case kTypedDataUint8ArrayCid: |
| 1005 case kTypedDataUint8ClampedArrayCid: | 1127 case kTypedDataUint8ClampedArrayCid: |
| 1006 case kExternalTypedDataUint8ArrayCid: | 1128 case kExternalTypedDataUint8ArrayCid: |
| 1007 case kExternalTypedDataUint8ClampedArrayCid: | 1129 case kExternalTypedDataUint8ClampedArrayCid: |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1098 case kTypedDataInt8ArrayCid: | 1220 case kTypedDataInt8ArrayCid: |
| 1099 case kTypedDataUint8ArrayCid: | 1221 case kTypedDataUint8ArrayCid: |
| 1100 case kTypedDataUint8ClampedArrayCid: | 1222 case kTypedDataUint8ClampedArrayCid: |
| 1101 case kOneByteStringCid: | 1223 case kOneByteStringCid: |
| 1102 locs->set_in(2, Location::RegisterOrSmiConstant(value())); | 1224 locs->set_in(2, Location::RegisterOrSmiConstant(value())); |
| 1103 break; | 1225 break; |
| 1104 case kTypedDataInt16ArrayCid: | 1226 case kTypedDataInt16ArrayCid: |
| 1105 case kTypedDataUint16ArrayCid: | 1227 case kTypedDataUint16ArrayCid: |
| 1106 case kTypedDataInt32ArrayCid: | 1228 case kTypedDataInt32ArrayCid: |
| 1107 case kTypedDataUint32ArrayCid: | 1229 case kTypedDataUint32ArrayCid: |
| 1108 locs->set_in(2, Location::RequiresRegister()); | 1230 locs->set_in(2, Location::WritableRegister()); |
| 1109 break; | 1231 break; |
| 1110 case kTypedDataFloat32ArrayCid: | 1232 case kTypedDataFloat32ArrayCid: |
| 1111 // TODO(regis): Verify. | 1233 // TODO(regis): Verify. |
| 1112 // Need temp register for float-to-double conversion. | 1234 // Need temp register for float-to-double conversion. |
| 1113 locs->AddTemp(Location::RequiresFpuRegister()); | 1235 locs->AddTemp(Location::RequiresFpuRegister()); |
| 1114 // Fall through. | 1236 // Fall through. |
| 1115 case kTypedDataFloat64ArrayCid: // TODO(srdjan): Support Float64 constants. | 1237 case kTypedDataFloat64ArrayCid: // TODO(srdjan): Support Float64 constants. |
| 1116 case kTypedDataFloat32x4ArrayCid: | 1238 case kTypedDataFloat32x4ArrayCid: |
| 1117 locs->set_in(2, Location::RequiresFpuRegister()); | 1239 locs->set_in(2, Location::RequiresFpuRegister()); |
| 1118 break; | 1240 break; |
| (...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1472 __ StoreIntoObject(temp, | 1594 __ StoreIntoObject(temp, |
| 1473 FieldAddress(temp, Field::value_offset()), value, CanValueBeSmi()); | 1595 FieldAddress(temp, Field::value_offset()), value, CanValueBeSmi()); |
| 1474 } else { | 1596 } else { |
| 1475 __ StoreIntoObjectNoBarrier( | 1597 __ StoreIntoObjectNoBarrier( |
| 1476 temp, FieldAddress(temp, Field::value_offset()), value); | 1598 temp, FieldAddress(temp, Field::value_offset()), value); |
| 1477 } | 1599 } |
| 1478 } | 1600 } |
| 1479 | 1601 |
| 1480 | 1602 |
| 1481 LocationSummary* InstanceOfInstr::MakeLocationSummary() const { | 1603 LocationSummary* InstanceOfInstr::MakeLocationSummary() const { |
| 1482 UNIMPLEMENTED(); | 1604 const intptr_t kNumInputs = 3; |
| 1483 return NULL; | 1605 const intptr_t kNumTemps = 0; |
| 1606 LocationSummary* summary = |
| 1607 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 1608 summary->set_in(0, Location::RegisterLocation(R0)); |
| 1609 summary->set_in(1, Location::RegisterLocation(R2)); |
| 1610 summary->set_in(2, Location::RegisterLocation(R1)); |
| 1611 summary->set_out(Location::RegisterLocation(R0)); |
| 1612 return summary; |
| 1484 } | 1613 } |
| 1485 | 1614 |
| 1486 | 1615 |
| 1487 void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1616 void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1488 UNIMPLEMENTED(); | 1617 ASSERT(locs()->in(0).reg() == R0); // Value. |
| 1618 ASSERT(locs()->in(1).reg() == R2); // Instantiator. |
| 1619 ASSERT(locs()->in(2).reg() == R1); // Instantiator type arguments. |
| 1620 |
| 1621 compiler->GenerateInstanceOf(token_pos(), |
| 1622 deopt_id(), |
| 1623 type(), |
| 1624 negate_result(), |
| 1625 locs()); |
| 1626 ASSERT(locs()->out().reg() == R0); |
| 1489 } | 1627 } |
| 1490 | 1628 |
| 1491 | 1629 |
| 1492 LocationSummary* CreateArrayInstr::MakeLocationSummary() const { | 1630 LocationSummary* CreateArrayInstr::MakeLocationSummary() const { |
| 1493 const intptr_t kNumInputs = 1; | 1631 const intptr_t kNumInputs = 1; |
| 1494 const intptr_t kNumTemps = 0; | 1632 const intptr_t kNumTemps = 0; |
| 1495 LocationSummary* locs = | 1633 LocationSummary* locs = |
| 1496 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 1634 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 1497 locs->set_in(0, Location::RegisterLocation(R1)); | 1635 locs->set_in(0, Location::RegisterLocation(R1)); |
| 1498 locs->set_out(Location::RegisterLocation(R0)); | 1636 locs->set_out(Location::RegisterLocation(R0)); |
| (...skipping 429 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1928 if (deopt == NULL) { | 2066 if (deopt == NULL) { |
| 1929 __ sub(result, left, ShifterOperand(right)); | 2067 __ sub(result, left, ShifterOperand(right)); |
| 1930 } else { | 2068 } else { |
| 1931 __ subs(result, left, ShifterOperand(right)); | 2069 __ subs(result, left, ShifterOperand(right)); |
| 1932 __ b(deopt, VS); | 2070 __ b(deopt, VS); |
| 1933 } | 2071 } |
| 1934 break; | 2072 break; |
| 1935 } | 2073 } |
| 1936 case Token::kMUL: { | 2074 case Token::kMUL: { |
| 1937 __ SmiUntag(left); | 2075 __ SmiUntag(left); |
| 1938 __ mul(result, left, right); | 2076 if (deopt == NULL) { |
| 1939 if (deopt != NULL) { | 2077 __ mul(result, left, right); |
| 1940 UNIMPLEMENTED(); | 2078 } else { |
| 2079 __ smull(result, IP, left, right); |
| 2080 // IP: result bits 32..63. |
| 2081 __ cmp(IP, ShifterOperand(result, ASR, 31)); |
| 2082 __ b(deopt, NE); |
| 1941 } | 2083 } |
| 1942 break; | 2084 break; |
| 1943 } | 2085 } |
| 1944 case Token::kBIT_AND: { | 2086 case Token::kBIT_AND: { |
| 1945 // No overflow check. | 2087 // No overflow check. |
| 1946 __ and_(result, left, ShifterOperand(right)); | 2088 __ and_(result, left, ShifterOperand(right)); |
| 1947 break; | 2089 break; |
| 1948 } | 2090 } |
| 1949 case Token::kBIT_OR: { | 2091 case Token::kBIT_OR: { |
| 1950 // No overflow check. | 2092 // No overflow check. |
| (...skipping 911 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2862 compiler->GenerateCall(token_pos(), | 3004 compiler->GenerateCall(token_pos(), |
| 2863 &label, | 3005 &label, |
| 2864 PcDescriptors::kOther, | 3006 PcDescriptors::kOther, |
| 2865 locs()); | 3007 locs()); |
| 2866 __ Drop(2); // Discard type arguments and receiver. | 3008 __ Drop(2); // Discard type arguments and receiver. |
| 2867 } | 3009 } |
| 2868 | 3010 |
| 2869 } // namespace dart | 3011 } // namespace dart |
| 2870 | 3012 |
| 2871 #endif // defined TARGET_ARCH_ARM | 3013 #endif // defined TARGET_ARCH_ARM |
| OLD | NEW |