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

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