Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(140)

Side by Side Diff: runtime/vm/intermediate_language_arm.cc

Issue 15697009: Enable code optimization on ARM. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/flow_graph_compiler_x64.cc ('k') | runtime/vm/stub_code_arm.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_compiler_x64.cc ('k') | runtime/vm/stub_code_arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698