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

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

Issue 14246039: Implements features to run "Hello, world!" on simulated MIPS. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 8 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_mips.cc ('k') | runtime/vm/simulator_mips.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_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 "lib/error.h" 10 #include "lib/error.h"
(...skipping 28 matching lines...) Expand all
39 LocationSummary* locs = 39 LocationSummary* locs =
40 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 40 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
41 locs->set_in(0, Location::AnyOrConstant(value())); 41 locs->set_in(0, Location::AnyOrConstant(value()));
42 return locs; 42 return locs;
43 } 43 }
44 44
45 45
46 void PushArgumentInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 46 void PushArgumentInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
47 // In SSA mode, we need an explicit push. Nothing to do in non-SSA mode 47 // In SSA mode, we need an explicit push. Nothing to do in non-SSA mode
48 // where PushArgument is handled by BindInstr::EmitNativeCode. 48 // where PushArgument is handled by BindInstr::EmitNativeCode.
49 __ TraceSimMsg("PushArgumentInstr");
49 if (compiler->is_optimizing()) { 50 if (compiler->is_optimizing()) {
50 Location value = locs()->in(0); 51 Location value = locs()->in(0);
51 if (value.IsRegister()) { 52 if (value.IsRegister()) {
52 __ Push(value.reg()); 53 __ Push(value.reg());
53 } else if (value.IsConstant()) { 54 } else if (value.IsConstant()) {
54 __ PushObject(value.constant()); 55 __ PushObject(value.constant());
55 } else { 56 } else {
56 ASSERT(value.IsStackSlot()); 57 ASSERT(value.IsStackSlot());
57 __ lw(TMP, value.ToStackSlotAddress()); 58 __ lw(TMP, value.ToStackSlotAddress());
58 __ Push(TMP); 59 __ Push(TMP);
59 } 60 }
60 } 61 }
61 } 62 }
62 63
63 64
64 LocationSummary* ReturnInstr::MakeLocationSummary() const { 65 LocationSummary* ReturnInstr::MakeLocationSummary() const {
65 const intptr_t kNumInputs = 1; 66 const intptr_t kNumInputs = 1;
66 const intptr_t kNumTemps = 0; 67 const intptr_t kNumTemps = 0;
67 LocationSummary* locs = 68 LocationSummary* locs =
68 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 69 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
69 locs->set_in(0, Location::RegisterLocation(V0)); 70 locs->set_in(0, Location::RegisterLocation(V0));
70 return locs; 71 return locs;
71 } 72 }
72 73
73 74
74 // Attempt optimized compilation at return instruction instead of at the entry. 75 // Attempt optimized compilation at return instruction instead of at the entry.
75 // The entry needs to be patchable, no inlined objects are allowed in the area 76 // The entry needs to be patchable, no inlined objects are allowed in the area
76 // that will be overwritten by the patch instructions: a branch macro sequence. 77 // that will be overwritten by the patch instructions: a branch macro sequence.
77 void ReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 78 void ReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
79 __ TraceSimMsg("ReturnInstr");
78 Register result = locs()->in(0).reg(); 80 Register result = locs()->in(0).reg();
79 ASSERT(result == V0); 81 ASSERT(result == V0);
80 #if defined(DEBUG) 82 #if defined(DEBUG)
81 // TODO(srdjan): Fix for functions with finally clause. 83 // TODO(srdjan): Fix for functions with finally clause.
82 // A finally clause may leave a previously pushed return value if it 84 // A finally clause may leave a previously pushed return value if it
83 // has its own return instruction. Method that have finally are currently 85 // has its own return instruction. Method that have finally are currently
84 // not optimized. 86 // not optimized.
85 if (!compiler->HasFinally()) { 87 if (!compiler->HasFinally()) {
86 Label stack_ok; 88 Label stack_ok;
87 __ Comment("Stack Check"); 89 __ Comment("Stack Check");
90 __ TraceSimMsg("Stack Check");
88 const intptr_t fp_sp_dist = 91 const intptr_t fp_sp_dist =
89 (kFirstLocalSlotIndex + 1 - compiler->StackSize()) * kWordSize; 92 (kFirstLocalSlotIndex + 1 - compiler->StackSize()) * kWordSize;
90 ASSERT(fp_sp_dist <= 0); 93 ASSERT(fp_sp_dist <= 0);
91 __ subu(T2, SP, FP); 94 __ subu(T2, SP, FP);
92 95
93 __ BranchEqual(T2, fp_sp_dist, &stack_ok); 96 __ BranchEqual(T2, fp_sp_dist, &stack_ok);
94 __ break_(0); 97 __ break_(0);
95 98
96 __ Bind(&stack_ok); 99 __ Bind(&stack_ok);
97 } 100 }
(...skipping 29 matching lines...) Expand all
127 return NULL; 130 return NULL;
128 } 131 }
129 132
130 133
131 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 134 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
132 UNREACHABLE(); 135 UNREACHABLE();
133 } 136 }
134 137
135 138
136 LocationSummary* ClosureCallInstr::MakeLocationSummary() const { 139 LocationSummary* ClosureCallInstr::MakeLocationSummary() const {
137 UNIMPLEMENTED(); 140 const intptr_t kNumInputs = 0;
138 return NULL; 141 const intptr_t kNumTemps = 1;
142 LocationSummary* result =
143 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
144 result->set_out(Location::RegisterLocation(V0));
145 result->set_temp(0, Location::RegisterLocation(S4)); // Arg. descriptor.
146 return result;
147 }
148
149
150 void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
151 // The arguments to the stub include the closure, as does the arguments
152 // descriptor.
153 Register temp_reg = locs()->temp(0).reg();
154 int argument_count = ArgumentCount();
155 const Array& arguments_descriptor =
156 Array::ZoneHandle(ArgumentsDescriptor::New(argument_count,
157 argument_names()));
158 __ LoadObject(temp_reg, arguments_descriptor);
159 compiler->GenerateDartCall(deopt_id(),
160 token_pos(),
161 &StubCode::CallClosureFunctionLabel(),
162 PcDescriptors::kOther,
163 locs());
164 __ Drop(argument_count);
139 } 165 }
140 166
141 167
142 LocationSummary* LoadLocalInstr::MakeLocationSummary() const { 168 LocationSummary* LoadLocalInstr::MakeLocationSummary() const {
143 return LocationSummary::Make(0, 169 return LocationSummary::Make(0,
144 Location::RequiresRegister(), 170 Location::RequiresRegister(),
145 LocationSummary::kNoCall); 171 LocationSummary::kNoCall);
146 } 172 }
147 173
148 174
149 void LoadLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 175 void LoadLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
176 __ TraceSimMsg("LoadLocalInstr");
150 Register result = locs()->out().reg(); 177 Register result = locs()->out().reg();
151 __ lw(result, Address(FP, local().index() * kWordSize)); 178 __ lw(result, Address(FP, local().index() * kWordSize));
152 } 179 }
153 180
154 181
155 LocationSummary* StoreLocalInstr::MakeLocationSummary() const { 182 LocationSummary* StoreLocalInstr::MakeLocationSummary() const {
156 return LocationSummary::Make(1, 183 return LocationSummary::Make(1,
157 Location::SameAsFirstInput(), 184 Location::SameAsFirstInput(),
158 LocationSummary::kNoCall); 185 LocationSummary::kNoCall);
159 } 186 }
160 187
161 188
162 void StoreLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 189 void StoreLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
190 __ TraceSimMsg("StoreLocalInstr");
163 Register value = locs()->in(0).reg(); 191 Register value = locs()->in(0).reg();
164 Register result = locs()->out().reg(); 192 Register result = locs()->out().reg();
165 ASSERT(result == value); // Assert that register assignment is correct. 193 ASSERT(result == value); // Assert that register assignment is correct.
166 __ sw(value, Address(FP, local().index() * kWordSize)); 194 __ sw(value, Address(FP, local().index() * kWordSize));
167 } 195 }
168 196
169 197
170 LocationSummary* ConstantInstr::MakeLocationSummary() const { 198 LocationSummary* ConstantInstr::MakeLocationSummary() const {
171 return LocationSummary::Make(0, 199 return LocationSummary::Make(0,
172 Location::RequiresRegister(), 200 Location::RequiresRegister(),
173 LocationSummary::kNoCall); 201 LocationSummary::kNoCall);
174 } 202 }
175 203
176 204
177 void ConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 205 void ConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
178 // The register allocator drops constant definitions that have no uses. 206 // The register allocator drops constant definitions that have no uses.
179 if (!locs()->out().IsInvalid()) { 207 if (!locs()->out().IsInvalid()) {
208 __ TraceSimMsg("ConstantInstr");
180 Register result = locs()->out().reg(); 209 Register result = locs()->out().reg();
181 __ LoadObject(result, value()); 210 __ LoadObject(result, value());
182 } 211 }
183 } 212 }
184 213
185 214
186 LocationSummary* AssertAssignableInstr::MakeLocationSummary() const { 215 LocationSummary* AssertAssignableInstr::MakeLocationSummary() const {
187 const intptr_t kNumInputs = 3; 216 const intptr_t kNumInputs = 3;
188 const intptr_t kNumTemps = 0; 217 const intptr_t kNumTemps = 0;
189 LocationSummary* summary = 218 LocationSummary* summary =
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
227 // We should never return here. 256 // We should never return here.
228 __ break_(0); 257 __ break_(0);
229 __ Bind(&done); 258 __ Bind(&done);
230 } 259 }
231 260
232 261
233 void AssertBooleanInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 262 void AssertBooleanInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
234 Register obj = locs()->in(0).reg(); 263 Register obj = locs()->in(0).reg();
235 Register result = locs()->out().reg(); 264 Register result = locs()->out().reg();
236 265
266 __ TraceSimMsg("AssertBooleanInstr");
237 EmitAssertBoolean(obj, token_pos(), deopt_id(), locs(), compiler); 267 EmitAssertBoolean(obj, token_pos(), deopt_id(), locs(), compiler);
238 ASSERT(obj == result); 268 ASSERT(obj == result);
239 } 269 }
240 270
241 271
242 LocationSummary* ArgumentDefinitionTestInstr::MakeLocationSummary() const { 272 LocationSummary* ArgumentDefinitionTestInstr::MakeLocationSummary() const {
243 UNIMPLEMENTED(); 273 UNIMPLEMENTED();
244 return NULL; 274 return NULL;
245 } 275 }
246 276
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
317 // A1: left. 347 // A1: left.
318 // A0: right. 348 // A0: right.
319 // Uses T0 to load ic_call_data. 349 // Uses T0 to load ic_call_data.
320 // Result in V0. 350 // Result in V0.
321 static void EmitEqualityAsInstanceCall(FlowGraphCompiler* compiler, 351 static void EmitEqualityAsInstanceCall(FlowGraphCompiler* compiler,
322 intptr_t deopt_id, 352 intptr_t deopt_id,
323 intptr_t token_pos, 353 intptr_t token_pos,
324 Token::Kind kind, 354 Token::Kind kind,
325 LocationSummary* locs, 355 LocationSummary* locs,
326 const ICData& original_ic_data) { 356 const ICData& original_ic_data) {
357 __ TraceSimMsg("EmitEqualityAsInstanceCall");
327 if (!compiler->is_optimizing()) { 358 if (!compiler->is_optimizing()) {
328 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, 359 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt,
329 deopt_id, 360 deopt_id,
330 token_pos); 361 token_pos);
331 } 362 }
332 const int kNumberOfArguments = 2; 363 const int kNumberOfArguments = 2;
333 const Array& kNoArgumentNames = Array::Handle(); 364 const Array& kNoArgumentNames = Array::Handle();
334 const int kNumArgumentsChecked = 2; 365 const int kNumArgumentsChecked = 2;
335 366
336 Label check_identity; 367 Label check_identity;
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
404 __ Bind(&done); 435 __ Bind(&done);
405 } 436 }
406 __ Bind(&equality_done); 437 __ Bind(&equality_done);
407 } 438 }
408 439
409 440
410 static void LoadValueCid(FlowGraphCompiler* compiler, 441 static void LoadValueCid(FlowGraphCompiler* compiler,
411 Register value_cid_reg, 442 Register value_cid_reg,
412 Register value_reg, 443 Register value_reg,
413 Label* value_is_smi = NULL) { 444 Label* value_is_smi = NULL) {
445 __ TraceSimMsg("LoadValueCid");
414 Label done; 446 Label done;
415 if (value_is_smi == NULL) { 447 if (value_is_smi == NULL) {
416 __ LoadImmediate(value_cid_reg, kSmiCid); 448 __ LoadImmediate(value_cid_reg, kSmiCid);
417 } 449 }
418 __ andi(TMP1, value_reg, Immediate(kSmiTagMask)); 450 __ andi(TMP1, value_reg, Immediate(kSmiTagMask));
419 if (value_is_smi == NULL) { 451 if (value_is_smi == NULL) {
420 __ beq(TMP1, ZR, &done); 452 __ beq(TMP1, ZR, &done);
421 } else { 453 } else {
422 __ beq(TMP1, ZR, value_is_smi); 454 __ beq(TMP1, ZR, value_is_smi);
423 } 455 }
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
463 UNREACHABLE(); 495 UNREACHABLE();
464 return VS; 496 return VS;
465 } 497 }
466 } 498 }
467 499
468 500
469 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, 501 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler,
470 const LocationSummary& locs, 502 const LocationSummary& locs,
471 Token::Kind kind, 503 Token::Kind kind,
472 BranchInstr* branch) { 504 BranchInstr* branch) {
505 __ TraceSimMsg("EmitSmiComparisonOp");
473 Location left = locs.in(0); 506 Location left = locs.in(0);
474 Location right = locs.in(1); 507 Location right = locs.in(1);
475 ASSERT(!left.IsConstant() || !right.IsConstant()); 508 ASSERT(!left.IsConstant() || !right.IsConstant());
476 509
477 Condition true_condition = TokenKindToSmiCondition(kind); 510 Condition true_condition = TokenKindToSmiCondition(kind);
478 511
479 if (left.IsConstant()) { 512 if (left.IsConstant()) {
480 __ CompareObject(CMPRES, right.reg(), left.constant()); 513 __ CompareObject(CMPRES, right.reg(), left.constant());
481 true_condition = FlowGraphCompiler::FlipCondition(true_condition); 514 true_condition = FlowGraphCompiler::FlipCondition(true_condition);
482 } else if (right.IsConstant()) { 515 } else if (right.IsConstant()) {
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
570 token_pos(), 603 token_pos(),
571 kind(), 604 kind(),
572 locs(), 605 locs(),
573 *ic_data()); 606 *ic_data());
574 ASSERT(locs()->out().reg() == V0); 607 ASSERT(locs()->out().reg() == V0);
575 } 608 }
576 609
577 610
578 void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, 611 void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler,
579 BranchInstr* branch) { 612 BranchInstr* branch) {
613 __ TraceSimMsg("EqualityCompareInstr");
580 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); 614 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ));
581 if (receiver_class_id() == kSmiCid) { 615 if (receiver_class_id() == kSmiCid) {
582 // Deoptimizes if both arguments not Smi. 616 // Deoptimizes if both arguments not Smi.
583 EmitSmiComparisonOp(compiler, *locs(), kind(), branch); 617 EmitSmiComparisonOp(compiler, *locs(), kind(), branch);
584 return; 618 return;
585 } 619 }
586 if (receiver_class_id() == kMintCid) { 620 if (receiver_class_id() == kMintCid) {
587 EmitUnboxedMintEqualityOp(compiler, *locs(), kind(), branch); 621 EmitUnboxedMintEqualityOp(compiler, *locs(), kind(), branch);
588 return; 622 return;
589 } 623 }
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
659 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); 693 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
660 // Pick arbitrary fixed input registers because this is a call. 694 // Pick arbitrary fixed input registers because this is a call.
661 locs->set_in(0, Location::RegisterLocation(A0)); 695 locs->set_in(0, Location::RegisterLocation(A0));
662 locs->set_in(1, Location::RegisterLocation(A1)); 696 locs->set_in(1, Location::RegisterLocation(A1));
663 locs->set_out(Location::RegisterLocation(V0)); 697 locs->set_out(Location::RegisterLocation(V0));
664 return locs; 698 return locs;
665 } 699 }
666 700
667 701
668 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 702 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
703 __ TraceSimMsg("RelationalOpInstr");
669 if (operands_class_id() == kSmiCid) { 704 if (operands_class_id() == kSmiCid) {
670 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL); 705 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL);
671 return; 706 return;
672 } 707 }
673 if (operands_class_id() == kMintCid) { 708 if (operands_class_id() == kMintCid) {
674 EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), NULL); 709 EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), NULL);
675 return; 710 return;
676 } 711 }
677 if (operands_class_id() == kDoubleCid) { 712 if (operands_class_id() == kDoubleCid) {
678 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL); 713 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL);
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
730 token_pos(), 765 token_pos(),
731 kNumArguments, 766 kNumArguments,
732 Array::ZoneHandle(), // No optional arguments. 767 Array::ZoneHandle(), // No optional arguments.
733 locs(), 768 locs(),
734 relational_ic_data); 769 relational_ic_data);
735 } 770 }
736 771
737 772
738 void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler, 773 void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler,
739 BranchInstr* branch) { 774 BranchInstr* branch) {
775 __ TraceSimMsg("RelationalOpInstr");
740 if (operands_class_id() == kSmiCid) { 776 if (operands_class_id() == kSmiCid) {
741 EmitSmiComparisonOp(compiler, *locs(), kind(), branch); 777 EmitSmiComparisonOp(compiler, *locs(), kind(), branch);
742 return; 778 return;
743 } 779 }
744 if (operands_class_id() == kMintCid) { 780 if (operands_class_id() == kMintCid) {
745 EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), branch); 781 EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), branch);
746 return; 782 return;
747 } 783 }
748 if (operands_class_id() == kDoubleCid) { 784 if (operands_class_id() == kDoubleCid) {
749 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch); 785 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch);
(...skipping 12 matching lines...) Expand all
762 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); 798 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
763 locs->set_temp(0, Location::RegisterLocation(A1)); 799 locs->set_temp(0, Location::RegisterLocation(A1));
764 locs->set_temp(1, Location::RegisterLocation(A2)); 800 locs->set_temp(1, Location::RegisterLocation(A2));
765 locs->set_temp(2, Location::RegisterLocation(T5)); 801 locs->set_temp(2, Location::RegisterLocation(T5));
766 locs->set_out(Location::RegisterLocation(V0)); 802 locs->set_out(Location::RegisterLocation(V0));
767 return locs; 803 return locs;
768 } 804 }
769 805
770 806
771 void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 807 void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
808 __ TraceSimMsg("NativeCallInstr");
772 ASSERT(locs()->temp(0).reg() == A1); 809 ASSERT(locs()->temp(0).reg() == A1);
773 ASSERT(locs()->temp(1).reg() == A2); 810 ASSERT(locs()->temp(1).reg() == A2);
774 ASSERT(locs()->temp(2).reg() == T5); 811 ASSERT(locs()->temp(2).reg() == T5);
775 Register result = locs()->out().reg(); 812 Register result = locs()->out().reg();
776 813
777 // Push the result place holder initialized to NULL. 814 // Push the result place holder initialized to NULL.
778 __ PushObject(Object::ZoneHandle()); 815 __ PushObject(Object::ZoneHandle());
779 // Pass a pointer to the first argument in A2. 816 // Pass a pointer to the first argument in A2.
780 if (!function().HasOptionalParameters()) { 817 if (!function().HasOptionalParameters()) {
781 __ AddImmediate(A2, FP, (kLastParamSlotIndex + 818 __ AddImmediate(A2, FP, (kLastParamSlotIndex +
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
846 883
847 884
848 Representation StoreIndexedInstr::RequiredInputRepresentation( 885 Representation StoreIndexedInstr::RequiredInputRepresentation(
849 intptr_t idx) const { 886 intptr_t idx) const {
850 UNIMPLEMENTED(); 887 UNIMPLEMENTED();
851 return kTagged; 888 return kTagged;
852 } 889 }
853 890
854 891
855 LocationSummary* StoreIndexedInstr::MakeLocationSummary() const { 892 LocationSummary* StoreIndexedInstr::MakeLocationSummary() const {
856 UNIMPLEMENTED(); 893 const intptr_t kNumInputs = 3;
857 return NULL; 894 const intptr_t kNumTemps = 0;
895 LocationSummary* locs =
896 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
897 locs->set_in(0, Location::RequiresRegister());
898 // The smi index is either untagged (element size == 1), or it is left smi
899 // tagged (for all element sizes > 1).
900 // TODO(regis): Revisit and see if the index can be immediate.
901 locs->set_in(1, Location::WritableRegister());
902 switch (class_id()) {
903 case kArrayCid:
904 locs->set_in(2, ShouldEmitStoreBarrier()
905 ? Location::WritableRegister()
906 : Location::RegisterOrConstant(value()));
907 break;
908 case kExternalTypedDataUint8ArrayCid:
909 case kExternalTypedDataUint8ClampedArrayCid:
910 case kTypedDataInt8ArrayCid:
911 case kTypedDataUint8ArrayCid:
912 case kTypedDataUint8ClampedArrayCid:
913 case kTypedDataInt16ArrayCid:
914 case kTypedDataUint16ArrayCid:
915 case kTypedDataInt32ArrayCid:
916 case kTypedDataUint32ArrayCid:
917 case kTypedDataFloat32ArrayCid:
918 case kTypedDataFloat64ArrayCid:
919 case kTypedDataFloat32x4ArrayCid:
920 UNIMPLEMENTED();
921 break;
922 default:
923 UNREACHABLE();
924 return NULL;
925 }
926 return locs;
858 } 927 }
859 928
860 929
861 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 930 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
862 UNIMPLEMENTED(); 931 __ TraceSimMsg("StoreIndexedInstr");
932 Register array = locs()->in(0).reg();
933 Location index = locs()->in(1);
934
935 Address element_address(kNoRegister, 0);
936 if (IsExternal()) {
937 UNIMPLEMENTED();
938 } else {
939 ASSERT(this->array()->definition()->representation() == kTagged);
940 ASSERT(index.IsRegister()); // TODO(regis): Revisit.
941 // Note that index is expected smi-tagged, (i.e, times 2) for all arrays
942 // with index scale factor > 1. E.g., for Uint8Array and OneByteString the
943 // index is expected to be untagged before accessing.
944 ASSERT(kSmiTagShift == 1);
945 switch (index_scale()) {
946 case 1: {
947 __ SmiUntag(index.reg());
948 break;
949 }
950 case 2: {
951 break;
952 }
953 case 4: {
954 __ sll(index.reg(), index.reg(), 1);
955 break;
956 }
957 case 8: {
958 __ sll(index.reg(), index.reg(), 2);
959 break;
960 }
961 case 16: {
962 __ sll(index.reg(), index.reg(), 3);
963 break;
964 }
965 default:
966 UNREACHABLE();
967 }
968 __ AddImmediate(index.reg(),
969 FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag);
970 __ addu(TMP1, array, index.reg());
971 element_address = Address(TMP1);
972 }
973
974 switch (class_id()) {
975 case kArrayCid:
976 if (ShouldEmitStoreBarrier()) {
977 Register value = locs()->in(2).reg();
978 __ StoreIntoObject(array, element_address, value);
979 } else if (locs()->in(2).IsConstant()) {
980 const Object& constant = locs()->in(2).constant();
981 __ StoreIntoObjectNoBarrier(array, element_address, constant);
982 } else {
983 Register value = locs()->in(2).reg();
984 __ StoreIntoObjectNoBarrier(array, element_address, value);
985 }
986 break;
987 case kTypedDataInt8ArrayCid:
988 case kTypedDataUint8ArrayCid:
989 case kExternalTypedDataUint8ArrayCid:
990 case kTypedDataUint8ClampedArrayCid:
991 case kExternalTypedDataUint8ClampedArrayCid:
992 case kTypedDataInt16ArrayCid:
993 case kTypedDataUint16ArrayCid:
994 case kTypedDataInt32ArrayCid:
995 case kTypedDataUint32ArrayCid:
996 case kTypedDataFloat32ArrayCid:
997 case kTypedDataFloat64ArrayCid:
998 case kTypedDataFloat32x4ArrayCid:
999 UNIMPLEMENTED();
1000 break;
1001 default:
1002 UNREACHABLE();
1003 }
863 } 1004 }
864 1005
865 1006
866 LocationSummary* GuardFieldInstr::MakeLocationSummary() const { 1007 LocationSummary* GuardFieldInstr::MakeLocationSummary() const {
867 UNIMPLEMENTED(); 1008 const intptr_t kNumInputs = 1;
868 return NULL; 1009 LocationSummary* summary =
1010 new LocationSummary(kNumInputs, 0, LocationSummary::kNoCall);
1011 summary->set_in(0, Location::RequiresRegister());
1012 if ((value()->Type()->ToCid() == kDynamicCid) &&
1013 (field().guarded_cid() != kSmiCid)) {
1014 summary->AddTemp(Location::RequiresRegister());
1015 }
1016 if (field().guarded_cid() == kIllegalCid) {
1017 summary->AddTemp(Location::RequiresRegister());
1018 }
1019 return summary;
869 } 1020 }
870 1021
871 1022
872 void GuardFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1023 void GuardFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
873 UNIMPLEMENTED(); 1024 __ TraceSimMsg("GuardFieldInstr");
1025 const intptr_t field_cid = field().guarded_cid();
1026 const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid;
1027
1028 if (field_cid == kDynamicCid) {
1029 ASSERT(!compiler->is_optimizing());
1030 return; // Nothing to emit.
1031 }
1032
1033 const intptr_t value_cid = value()->Type()->ToCid();
1034
1035 Register value_reg = locs()->in(0).reg();
1036
1037 Register value_cid_reg = ((value_cid == kDynamicCid) &&
1038 (field_cid != kSmiCid)) ? locs()->temp(0).reg() : kNoRegister;
1039
1040 Register field_reg = (field_cid == kIllegalCid) ?
1041 locs()->temp(locs()->temp_count() - 1).reg() : kNoRegister;
1042
1043 Label ok, fail_label;
1044
1045 Label* deopt = compiler->is_optimizing() ?
1046 compiler->AddDeoptStub(deopt_id(), kDeoptGuardField) : NULL;
1047
1048 Label* fail = (deopt != NULL) ? deopt : &fail_label;
1049
1050 const bool ok_is_fall_through = (deopt != NULL);
1051
1052 if (!compiler->is_optimizing() || (field_cid == kIllegalCid)) {
1053 if (!compiler->is_optimizing()) {
1054 // Currently we can't have different location summaries for optimized
1055 // and non-optimized code. So instead we manually pick up a register
1056 // that is known to be free because we know how non-optimizing compiler
1057 // allocates registers.
1058 field_reg = A0;
1059 ASSERT((field_reg != value_reg) && (field_reg != value_cid_reg));
1060 }
1061
1062 __ LoadObject(field_reg, Field::ZoneHandle(field().raw()));
1063
1064 FieldAddress field_cid_operand(field_reg, Field::guarded_cid_offset());
1065 FieldAddress field_nullability_operand(
1066 field_reg, Field::is_nullable_offset());
1067
1068 if (value_cid == kDynamicCid) {
1069 if (value_cid_reg == kNoRegister) {
1070 ASSERT(!compiler->is_optimizing());
1071 value_cid_reg = A1;
1072 ASSERT((value_cid_reg != value_reg) && (field_reg != value_cid_reg));
1073 }
1074
1075 LoadValueCid(compiler, value_cid_reg, value_reg);
1076
1077 __ lw(TMP1, field_cid_operand);
1078 __ beq(value_cid_reg, TMP1, &ok);
1079 __ lw(TMP1, field_nullability_operand);
1080 __ subu(CMPRES, value_cid_reg, TMP1);
1081 } else if (value_cid == kNullCid) {
1082 // TODO(regis): TMP1 may conflict. Revisit.
1083 __ lw(TMP1, field_nullability_operand);
1084 __ LoadImmediate(TMP2, value_cid);
1085 __ subu(CMPRES, TMP1, TMP2);
1086 } else {
1087 // TODO(regis): TMP1 may conflict. Revisit.
1088 __ lw(TMP1, field_cid_operand);
1089 __ LoadImmediate(TMP2, value_cid);
1090 __ subu(CMPRES, TMP1, TMP2);
1091 }
1092 __ beq(CMPRES, ZR, &ok);
1093
1094 __ lw(TMP1, field_cid_operand);
1095 __ BranchNotEqual(TMP1, kIllegalCid, fail);
1096
1097 if (value_cid == kDynamicCid) {
1098 __ sw(value_cid_reg, field_cid_operand);
1099 __ sw(value_cid_reg, field_nullability_operand);
1100 } else {
1101 __ LoadImmediate(TMP1, value_cid);
1102 __ sw(TMP1, field_cid_operand);
1103 __ sw(TMP1, field_nullability_operand);
1104 }
1105
1106 if (!ok_is_fall_through) {
1107 __ b(&ok);
1108 }
1109 } else {
1110 if (value_cid == kDynamicCid) {
1111 // Field's guarded class id is fixed by value's class id is not known.
1112 __ andi(CMPRES, value_reg, Immediate(kSmiTagMask));
1113
1114 if (field_cid != kSmiCid) {
1115 __ beq(CMPRES, ZR, fail);
1116 __ LoadClassId(value_cid_reg, value_reg);
1117 __ LoadImmediate(TMP1, field_cid);
1118 __ subu(CMPRES, value_cid_reg, TMP1);
1119 }
1120
1121 if (field().is_nullable() && (field_cid != kNullCid)) {
1122 __ beq(CMPRES, ZR, &ok);
1123 __ LoadImmediate(TMP1, reinterpret_cast<intptr_t>(Object::null()));
1124 __ subu(CMPRES, value_reg, TMP1);
1125 }
1126
1127 if (ok_is_fall_through) {
1128 __ bne(CMPRES, ZR, fail);
1129 } else {
1130 __ beq(CMPRES, ZR, &ok);
1131 }
1132 } else {
1133 // Both value's and field's class id is known.
1134 if ((value_cid != field_cid) && (value_cid != nullability)) {
1135 if (ok_is_fall_through) {
1136 __ b(fail);
1137 }
1138 } else {
1139 // Nothing to emit.
1140 ASSERT(!compiler->is_optimizing());
1141 return;
1142 }
1143 }
1144 }
1145
1146 if (deopt == NULL) {
1147 ASSERT(!compiler->is_optimizing());
1148 __ Bind(fail);
1149
1150 __ lw(TMP1, FieldAddress(field_reg, Field::guarded_cid_offset()));
1151 __ BranchEqual(TMP1, kDynamicCid, &ok);
1152
1153 __ Push(field_reg);
1154 __ Push(value_reg);
1155 __ CallRuntime(kUpdateFieldCidRuntimeEntry);
1156 __ Drop(2); // Drop the field and the value.
1157 }
1158
1159 __ Bind(&ok);
874 } 1160 }
875 1161
876 1162
877 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary() const { 1163 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary() const {
878 UNIMPLEMENTED(); 1164 const intptr_t kNumInputs = 2;
879 return NULL; 1165 const intptr_t num_temps = 0;
1166 LocationSummary* summary =
1167 new LocationSummary(kNumInputs, num_temps, LocationSummary::kNoCall);
1168 summary->set_in(0, Location::RequiresRegister());
1169 summary->set_in(1, ShouldEmitStoreBarrier()
1170 ? Location::WritableRegister()
1171 : Location::RegisterOrConstant(value()));
1172 return summary;
880 } 1173 }
881 1174
882 1175
883 void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1176 void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
884 UNIMPLEMENTED(); 1177 Register instance_reg = locs()->in(0).reg();
1178 if (ShouldEmitStoreBarrier()) {
1179 Register value_reg = locs()->in(1).reg();
1180 __ StoreIntoObject(instance_reg,
1181 FieldAddress(instance_reg, field().Offset()),
1182 value_reg,
1183 CanValueBeSmi());
1184 } else {
1185 if (locs()->in(1).IsConstant()) {
1186 __ StoreIntoObjectNoBarrier(
1187 instance_reg,
1188 FieldAddress(instance_reg, field().Offset()),
1189 locs()->in(1).constant());
1190 } else {
1191 Register value_reg = locs()->in(1).reg();
1192 __ StoreIntoObjectNoBarrier(instance_reg,
1193 FieldAddress(instance_reg, field().Offset()), value_reg);
1194 }
1195 }
885 } 1196 }
886 1197
887 1198
888 LocationSummary* LoadStaticFieldInstr::MakeLocationSummary() const { 1199 LocationSummary* LoadStaticFieldInstr::MakeLocationSummary() const {
889 UNIMPLEMENTED(); 1200 return LocationSummary::Make(0,
890 return NULL; 1201 Location::RequiresRegister(),
1202 LocationSummary::kNoCall);
891 } 1203 }
892 1204
893 1205
894 void LoadStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1206 void LoadStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
895 UNIMPLEMENTED(); 1207 __ TraceSimMsg("LoadStaticFieldInstr");
1208 Register result = locs()->out().reg();
1209 __ LoadObject(result, field());
1210 __ lw(result, Address(result, Field::value_offset() - kHeapObjectTag));
896 } 1211 }
897 1212
898 1213
899 LocationSummary* StoreStaticFieldInstr::MakeLocationSummary() const { 1214 LocationSummary* StoreStaticFieldInstr::MakeLocationSummary() const {
900 UNIMPLEMENTED(); 1215 LocationSummary* locs = new LocationSummary(1, 1, LocationSummary::kNoCall);
901 return NULL; 1216 locs->set_in(0, value()->NeedsStoreBuffer() ? Location::WritableRegister()
1217 : Location::RequiresRegister());
1218 locs->set_temp(0, Location::RequiresRegister());
1219 return locs;
902 } 1220 }
903 1221
904 1222
905 void StoreStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1223 void StoreStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
906 UNIMPLEMENTED(); 1224 __ TraceSimMsg("StoreStaticFieldInstr");
907 } 1225 Register value = locs()->in(0).reg();
908 1226 Register temp = locs()->temp(0).reg();
909 1227
1228 __ LoadObject(temp, field());
1229 if (this->value()->NeedsStoreBuffer()) {
1230 __ StoreIntoObject(temp,
1231 FieldAddress(temp, Field::value_offset()), value, CanValueBeSmi());
1232 } else {
1233 __ StoreIntoObjectNoBarrier(
1234 temp, FieldAddress(temp, Field::value_offset()), value);
1235 }
1236 }
1237
1238
910 LocationSummary* InstanceOfInstr::MakeLocationSummary() const { 1239 LocationSummary* InstanceOfInstr::MakeLocationSummary() const {
911 UNIMPLEMENTED(); 1240 UNIMPLEMENTED();
912 return NULL; 1241 return NULL;
913 } 1242 }
914 1243
915 1244
916 void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1245 void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
917 UNIMPLEMENTED(); 1246 UNIMPLEMENTED();
918 } 1247 }
919 1248
920 1249
921 LocationSummary* CreateArrayInstr::MakeLocationSummary() const { 1250 LocationSummary* CreateArrayInstr::MakeLocationSummary() const {
922 UNIMPLEMENTED(); 1251 const intptr_t kNumInputs = 1;
923 return NULL; 1252 const intptr_t kNumTemps = 0;
1253 LocationSummary* locs =
1254 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
1255 locs->set_in(0, Location::RegisterLocation(A0));
1256 locs->set_out(Location::RegisterLocation(V0));
1257 return locs;
924 } 1258 }
925 1259
926 1260
927 void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1261 void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
928 UNIMPLEMENTED(); 1262 __ TraceSimMsg("CreateArrayInstr");
1263 // Allocate the array. A1 = length, A0 = element type.
1264 ASSERT(locs()->in(0).reg() == A0);
1265 __ LoadImmediate(A1, Smi::RawValue(num_elements()));
1266 compiler->GenerateCall(token_pos(),
1267 &StubCode::AllocateArrayLabel(),
1268 PcDescriptors::kOther,
1269 locs());
1270 ASSERT(locs()->out().reg() == V0);
929 } 1271 }
930 1272
931 1273
932 LocationSummary* 1274 LocationSummary*
933 AllocateObjectWithBoundsCheckInstr::MakeLocationSummary() const { 1275 AllocateObjectWithBoundsCheckInstr::MakeLocationSummary() const {
934 UNIMPLEMENTED(); 1276 UNIMPLEMENTED();
935 return NULL; 1277 return NULL;
936 } 1278 }
937 1279
938 1280
939 void AllocateObjectWithBoundsCheckInstr::EmitNativeCode( 1281 void AllocateObjectWithBoundsCheckInstr::EmitNativeCode(
940 FlowGraphCompiler* compiler) { 1282 FlowGraphCompiler* compiler) {
941 UNIMPLEMENTED(); 1283 UNIMPLEMENTED();
942 } 1284 }
943 1285
944 1286
945 LocationSummary* LoadFieldInstr::MakeLocationSummary() const { 1287 LocationSummary* LoadFieldInstr::MakeLocationSummary() const {
946 UNIMPLEMENTED(); 1288 return LocationSummary::Make(1,
947 return NULL; 1289 Location::RequiresRegister(),
1290 LocationSummary::kNoCall);
948 } 1291 }
949 1292
950 1293
951 void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1294 void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
952 UNIMPLEMENTED(); 1295 Register instance_reg = locs()->in(0).reg();
1296 Register result_reg = locs()->out().reg();
1297
1298 __ lw(result_reg, Address(instance_reg, offset_in_bytes() - kHeapObjectTag));
953 } 1299 }
954 1300
955 1301
956 LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary() const { 1302 LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary() const {
957 UNIMPLEMENTED(); 1303 const intptr_t kNumInputs = 1;
958 return NULL; 1304 const intptr_t kNumTemps = 1;
1305 LocationSummary* locs =
1306 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
1307 locs->set_in(0, Location::RegisterLocation(T0));
1308 locs->set_temp(0, Location::RegisterLocation(T1));
1309 locs->set_out(Location::RegisterLocation(T0));
1310 return locs;
959 } 1311 }
960 1312
961 1313
962 void InstantiateTypeArgumentsInstr::EmitNativeCode( 1314 void InstantiateTypeArgumentsInstr::EmitNativeCode(
963 FlowGraphCompiler* compiler) { 1315 FlowGraphCompiler* compiler) {
964 UNIMPLEMENTED(); 1316 __ TraceSimMsg("InstantiateTypeArgumentsInstr");
1317 Register instantiator_reg = locs()->in(0).reg();
1318 Register temp = locs()->temp(0).reg();
1319 Register result_reg = locs()->out().reg();
1320
1321 // 'instantiator_reg' is the instantiator AbstractTypeArguments object
1322 // (or null).
1323 // If the instantiator is null and if the type argument vector
1324 // instantiated from null becomes a vector of dynamic, then use null as
1325 // the type arguments.
1326 Label type_arguments_instantiated;
1327 const intptr_t len = type_arguments().Length();
1328 if (type_arguments().IsRawInstantiatedRaw(len)) {
1329 __ BranchEqual(instantiator_reg, reinterpret_cast<intptr_t>(Object::null()),
1330 &type_arguments_instantiated);
1331 }
1332 // Instantiate non-null type arguments.
1333 if (type_arguments().IsUninstantiatedIdentity()) {
1334 // Check if the instantiator type argument vector is a TypeArguments of a
1335 // matching length and, if so, use it as the instantiated type_arguments.
1336 // No need to check the instantiator ('instantiator_reg') for null here,
1337 // because a null instantiator will have the wrong class (Null instead of
1338 // TypeArguments).
1339 Label type_arguments_uninstantiated;
1340 __ LoadClassId(temp, instantiator_reg);
1341 __ BranchNotEqual(temp, kTypeArgumentsCid, &type_arguments_uninstantiated);
1342 __ lw(temp, FieldAddress(instantiator_reg, TypeArguments::length_offset()));
1343 __ BranchEqual(temp, Smi::RawValue(len), &type_arguments_instantiated);
1344 __ Bind(&type_arguments_uninstantiated);
1345 }
1346 // A runtime call to instantiate the type arguments is required.
1347 __ PushObject(Object::ZoneHandle()); // Make room for the result.
1348 __ PushObject(type_arguments());
1349 __ Push(instantiator_reg); // Push instantiator type arguments.
1350 compiler->GenerateCallRuntime(token_pos(),
1351 deopt_id(),
1352 kInstantiateTypeArgumentsRuntimeEntry,
1353 locs());
1354 __ Drop(2); // Drop instantiator and uninstantiated type arguments.
1355 __ Pop(result_reg); // Pop instantiated type arguments.
1356 __ Bind(&type_arguments_instantiated);
1357 ASSERT(instantiator_reg == result_reg);
1358 // 'result_reg': Instantiated type arguments.
965 } 1359 }
966 1360
967 1361
968 LocationSummary* 1362 LocationSummary*
969 ExtractConstructorTypeArgumentsInstr::MakeLocationSummary() const { 1363 ExtractConstructorTypeArgumentsInstr::MakeLocationSummary() const {
970 UNIMPLEMENTED(); 1364 const intptr_t kNumInputs = 1;
971 return NULL; 1365 const intptr_t kNumTemps = 1;
1366 LocationSummary* locs =
1367 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
1368 locs->set_in(0, Location::RequiresRegister());
1369 locs->set_out(Location::SameAsFirstInput());
1370 locs->set_temp(0, Location::RequiresRegister());
1371 return locs;
972 } 1372 }
973 1373
974 1374
975 void ExtractConstructorTypeArgumentsInstr::EmitNativeCode( 1375 void ExtractConstructorTypeArgumentsInstr::EmitNativeCode(
976 FlowGraphCompiler* compiler) { 1376 FlowGraphCompiler* compiler) {
977 UNIMPLEMENTED(); 1377 Register instantiator_reg = locs()->in(0).reg();
1378 Register result_reg = locs()->out().reg();
1379 ASSERT(instantiator_reg == result_reg);
1380 Register temp_reg = locs()->temp(0).reg();
1381
1382 // instantiator_reg is the instantiator type argument vector, i.e. an
1383 // AbstractTypeArguments object (or null).
1384 // If the instantiator is null and if the type argument vector
1385 // instantiated from null becomes a vector of dynamic, then use null as
1386 // the type arguments.
1387 Label type_arguments_instantiated;
1388 const intptr_t len = type_arguments().Length();
1389 if (type_arguments().IsRawInstantiatedRaw(len)) {
1390 __ BranchEqual(instantiator_reg, reinterpret_cast<intptr_t>(Object::null()),
1391 &type_arguments_instantiated);
1392 }
1393 // Instantiate non-null type arguments.
1394 if (type_arguments().IsUninstantiatedIdentity()) {
1395 // Check if the instantiator type argument vector is a TypeArguments of a
1396 // matching length and, if so, use it as the instantiated type_arguments.
1397 // No need to check instantiator_reg for null here, because a null
1398 // instantiator will have the wrong class (Null instead of TypeArguments).
1399 Label type_arguments_uninstantiated;
1400 __ LoadClassId(temp_reg, instantiator_reg);
1401 __ BranchNotEqual(temp_reg, kTypeArgumentsCid,
1402 &type_arguments_uninstantiated);
1403 __ lw(temp_reg,
1404 FieldAddress(instantiator_reg, TypeArguments::length_offset()));
1405 __ BranchEqual(temp_reg, Smi::RawValue(type_arguments().Length()),
1406 &type_arguments_instantiated);
1407 __ Bind(&type_arguments_uninstantiated);
1408 }
1409 // In the non-factory case, we rely on the allocation stub to
1410 // instantiate the type arguments.
1411 __ LoadObject(result_reg, type_arguments());
1412 // result_reg: uninstantiated type arguments.
1413 __ Bind(&type_arguments_instantiated);
1414 // result_reg: uninstantiated or instantiated type arguments.
978 } 1415 }
979 1416
980 1417
981 LocationSummary* 1418 LocationSummary*
982 ExtractConstructorInstantiatorInstr::MakeLocationSummary() const { 1419 ExtractConstructorInstantiatorInstr::MakeLocationSummary() const {
983 UNIMPLEMENTED(); 1420 const intptr_t kNumInputs = 1;
984 return NULL; 1421 const intptr_t kNumTemps = 1;
1422 LocationSummary* locs =
1423 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
1424 locs->set_in(0, Location::RequiresRegister());
1425 locs->set_out(Location::SameAsFirstInput());
1426 locs->set_temp(0, Location::RequiresRegister());
1427 return locs;
985 } 1428 }
986 1429
987 1430
988 void ExtractConstructorInstantiatorInstr::EmitNativeCode( 1431 void ExtractConstructorInstantiatorInstr::EmitNativeCode(
989 FlowGraphCompiler* compiler) { 1432 FlowGraphCompiler* compiler) {
990 UNIMPLEMENTED(); 1433 Register instantiator_reg = locs()->in(0).reg();
1434 ASSERT(locs()->out().reg() == instantiator_reg);
1435 Register temp_reg = locs()->temp(0).reg();
1436
1437 // instantiator_reg is the instantiator AbstractTypeArguments object
1438 // (or null). If the instantiator is null and if the type argument vector
1439 // instantiated from null becomes a vector of dynamic, then use null as
1440 // the type arguments and do not pass the instantiator.
1441 Label done;
1442 const intptr_t len = type_arguments().Length();
1443 if (type_arguments().IsRawInstantiatedRaw(len)) {
1444 Label instantiator_not_null;
1445 __ BranchNotEqual(instantiator_reg,
1446 reinterpret_cast<intptr_t>(Object::null()), &instantiator_not_null);
1447 // Null was used in VisitExtractConstructorTypeArguments as the
1448 // instantiated type arguments, no proper instantiator needed.
1449 __ LoadImmediate(instantiator_reg,
1450 Smi::RawValue(StubCode::kNoInstantiator));
1451 __ b(&done);
1452 __ Bind(&instantiator_not_null);
1453 }
1454 // Instantiate non-null type arguments.
1455 if (type_arguments().IsUninstantiatedIdentity()) {
1456 // TODO(regis): The following emitted code is duplicated in
1457 // VisitExtractConstructorTypeArguments above. The reason is that the code
1458 // is split between two computations, so that each one produces a
1459 // single value, rather than producing a pair of values.
1460 // If this becomes an issue, we should expose these tests at the IL level.
1461
1462 // Check if the instantiator type argument vector is a TypeArguments of a
1463 // matching length and, if so, use it as the instantiated type_arguments.
1464 // No need to check the instantiator ('instantiator_reg') for null here,
1465 // because a null instantiator will have the wrong class (Null instead of
1466 // TypeArguments).
1467 __ LoadClassId(temp_reg, instantiator_reg);
1468 __ BranchNotEqual(temp_reg, kTypeArgumentsCid, &done);
1469 __ lw(temp_reg,
1470 FieldAddress(instantiator_reg, TypeArguments::length_offset()));
1471 __ BranchNotEqual(temp_reg, Smi::RawValue(type_arguments().Length()),
1472 &done);
1473 // The instantiator was used in VisitExtractConstructorTypeArguments as the
1474 // instantiated type arguments, no proper instantiator needed.
1475 __ LoadImmediate(instantiator_reg,
1476 Smi::RawValue(StubCode::kNoInstantiator));
1477 }
1478 __ Bind(&done);
1479 // instantiator_reg: instantiator or kNoInstantiator.
991 } 1480 }
992 1481
993 1482
994 LocationSummary* AllocateContextInstr::MakeLocationSummary() const { 1483 LocationSummary* AllocateContextInstr::MakeLocationSummary() const {
995 UNIMPLEMENTED(); 1484 UNIMPLEMENTED();
996 return NULL; 1485 return NULL;
997 } 1486 }
998 1487
999 1488
1000 void AllocateContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1489 void AllocateContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
1034 return summary; 1523 return summary;
1035 } 1524 }
1036 1525
1037 1526
1038 class CheckStackOverflowSlowPath : public SlowPathCode { 1527 class CheckStackOverflowSlowPath : public SlowPathCode {
1039 public: 1528 public:
1040 explicit CheckStackOverflowSlowPath(CheckStackOverflowInstr* instruction) 1529 explicit CheckStackOverflowSlowPath(CheckStackOverflowInstr* instruction)
1041 : instruction_(instruction) { } 1530 : instruction_(instruction) { }
1042 1531
1043 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { 1532 virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
1533 __ TraceSimMsg("CheckStackOverflowSlowPath");
1044 __ Comment("CheckStackOverflowSlowPath"); 1534 __ Comment("CheckStackOverflowSlowPath");
1045 __ Bind(entry_label()); 1535 __ Bind(entry_label());
1046 compiler->SaveLiveRegisters(instruction_->locs()); 1536 compiler->SaveLiveRegisters(instruction_->locs());
1047 // pending_deoptimization_env_ is needed to generate a runtime call that 1537 // pending_deoptimization_env_ is needed to generate a runtime call that
1048 // may throw an exception. 1538 // may throw an exception.
1049 ASSERT(compiler->pending_deoptimization_env_ == NULL); 1539 ASSERT(compiler->pending_deoptimization_env_ == NULL);
1050 compiler->pending_deoptimization_env_ = instruction_->env(); 1540 compiler->pending_deoptimization_env_ = instruction_->env();
1051 compiler->GenerateCallRuntime(instruction_->token_pos(), 1541 compiler->GenerateCallRuntime(instruction_->token_pos(),
1052 instruction_->deopt_id(), 1542 instruction_->deopt_id(),
1053 kStackOverflowRuntimeEntry, 1543 kStackOverflowRuntimeEntry,
1054 instruction_->locs()); 1544 instruction_->locs());
1055 compiler->pending_deoptimization_env_ = NULL; 1545 compiler->pending_deoptimization_env_ = NULL;
1056 compiler->RestoreLiveRegisters(instruction_->locs()); 1546 compiler->RestoreLiveRegisters(instruction_->locs());
1057 __ b(exit_label()); 1547 __ b(exit_label());
1058 } 1548 }
1059 1549
1060 private: 1550 private:
1061 CheckStackOverflowInstr* instruction_; 1551 CheckStackOverflowInstr* instruction_;
1062 }; 1552 };
1063 1553
1064 1554
1065 void CheckStackOverflowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1555 void CheckStackOverflowInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1556 __ TraceSimMsg("CheckStackOverflowInstr");
1066 CheckStackOverflowSlowPath* slow_path = new CheckStackOverflowSlowPath(this); 1557 CheckStackOverflowSlowPath* slow_path = new CheckStackOverflowSlowPath(this);
1067 compiler->AddSlowPathCode(slow_path); 1558 compiler->AddSlowPathCode(slow_path);
1068 1559
1069 __ LoadImmediate(TMP1, Isolate::Current()->stack_limit_address()); 1560 __ LoadImmediate(TMP1, Isolate::Current()->stack_limit_address());
1070 1561
1071 __ lw(TMP1, Address(TMP1)); 1562 __ lw(TMP1, Address(TMP1));
1072 __ BranchLessEqual(SP, TMP1, slow_path->entry_label()); 1563 __ BranchLessEqual(SP, TMP1, slow_path->entry_label());
1073 1564
1074 __ Bind(slow_path->exit_label()); 1565 __ Bind(slow_path->exit_label());
1075 } 1566 }
(...skipping 12 matching lines...) Expand all
1088 summary->set_in(1, Location::RegisterOrSmiConstant(right())); 1579 summary->set_in(1, Location::RegisterOrSmiConstant(right()));
1089 // We make use of 3-operand instructions by not requiring result register 1580 // We make use of 3-operand instructions by not requiring result register
1090 // to be identical to first input register as on Intel. 1581 // to be identical to first input register as on Intel.
1091 summary->set_out(Location::RequiresRegister()); 1582 summary->set_out(Location::RequiresRegister());
1092 return summary; 1583 return summary;
1093 } 1584 }
1094 } 1585 }
1095 1586
1096 1587
1097 void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1588 void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1589 __ TraceSimMsg("BinarySmiOpInstr");
1098 if (op_kind() == Token::kSHL) { 1590 if (op_kind() == Token::kSHL) {
1099 UNIMPLEMENTED(); 1591 UNIMPLEMENTED();
1100 return; 1592 return;
1101 } 1593 }
1102 1594
1103 ASSERT(!is_truncating()); 1595 ASSERT(!is_truncating());
1104 Register left = locs()->in(0).reg(); 1596 Register left = locs()->in(0).reg();
1105 Register result = locs()->out().reg(); 1597 Register result = locs()->out().reg();
1106 Label* deopt = NULL; 1598 Label* deopt = NULL;
1107 if (CanDeoptimize()) { 1599 if (CanDeoptimize()) {
(...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after
1422 UNIMPLEMENTED(); 1914 UNIMPLEMENTED();
1423 } 1915 }
1424 1916
1425 1917
1426 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary() const { 1918 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary() const {
1427 return MakeCallSummary(); 1919 return MakeCallSummary();
1428 } 1920 }
1429 1921
1430 1922
1431 void PolymorphicInstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1923 void PolymorphicInstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1924 __ TraceSimMsg("PolymorphicInstanceCallInstr");
1432 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), 1925 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(),
1433 kDeoptPolymorphicInstanceCallTestFail); 1926 kDeoptPolymorphicInstanceCallTestFail);
1434 if (ic_data().NumberOfChecks() == 0) { 1927 if (ic_data().NumberOfChecks() == 0) {
1435 __ b(deopt); 1928 __ b(deopt);
1436 return; 1929 return;
1437 } 1930 }
1438 ASSERT(ic_data().num_args_tested() == 1); 1931 ASSERT(ic_data().num_args_tested() == 1);
1439 if (!with_checks()) { 1932 if (!with_checks()) {
1440 ASSERT(ic_data().HasOneTarget()); 1933 ASSERT(ic_data().HasOneTarget());
1441 const Function& target = Function::ZoneHandle(ic_data().GetTargetAt(0)); 1934 const Function& target = Function::ZoneHandle(ic_data().GetTargetAt(0));
1442 compiler->GenerateStaticCall(instance_call()->deopt_id(), 1935 compiler->GenerateStaticCall(instance_call()->deopt_id(),
1443 instance_call()->token_pos(), 1936 instance_call()->token_pos(),
1444 target, 1937 target,
1445 instance_call()->ArgumentCount(), 1938 instance_call()->ArgumentCount(),
1446 instance_call()->argument_names(), 1939 instance_call()->argument_names(),
1447 locs()); 1940 locs());
1448 return; 1941 return;
1449 } 1942 }
1450 1943
1451 // Load receiver into R0. 1944 // Load receiver into T0.
1452 __ lw(T0, Address(SP, (instance_call()->ArgumentCount() - 1) * kWordSize)); 1945 __ lw(T0, Address(SP, (instance_call()->ArgumentCount() - 1) * kWordSize));
1453 1946
1454 LoadValueCid(compiler, T2, T0, 1947 LoadValueCid(compiler, T2, T0,
1455 (ic_data().GetReceiverClassIdAt(0) == kSmiCid) ? NULL : deopt); 1948 (ic_data().GetReceiverClassIdAt(0) == kSmiCid) ? NULL : deopt);
1456 1949
1457 compiler->EmitTestAndCall(ic_data(), 1950 compiler->EmitTestAndCall(ic_data(),
1458 T2, // Class id register. 1951 T2, // Class id register.
1459 instance_call()->ArgumentCount(), 1952 instance_call()->ArgumentCount(),
1460 instance_call()->argument_names(), 1953 instance_call()->argument_names(),
1461 deopt, 1954 deopt,
1462 instance_call()->deopt_id(), 1955 instance_call()->deopt_id(),
1463 instance_call()->token_pos(), 1956 instance_call()->token_pos(),
1464 locs()); 1957 locs());
1465 } 1958 }
1466 1959
1467 1960
1468 LocationSummary* BranchInstr::MakeLocationSummary() const { 1961 LocationSummary* BranchInstr::MakeLocationSummary() const {
1469 UNREACHABLE(); 1962 UNREACHABLE();
1470 return NULL; 1963 return NULL;
1471 } 1964 }
1472 1965
1473 1966
1474 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1967 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1968 __ TraceSimMsg("BranchInstr");
1475 comparison()->EmitBranchCode(compiler, this); 1969 comparison()->EmitBranchCode(compiler, this);
1476 } 1970 }
1477 1971
1478 1972
1479 LocationSummary* CheckClassInstr::MakeLocationSummary() const { 1973 LocationSummary* CheckClassInstr::MakeLocationSummary() const {
1480 UNIMPLEMENTED(); 1974 UNIMPLEMENTED();
1481 return NULL; 1975 return NULL;
1482 } 1976 }
1483 1977
1484 1978
1485 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1979 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1486 UNIMPLEMENTED(); 1980 UNIMPLEMENTED();
1487 } 1981 }
1488 1982
1489 1983
1490 LocationSummary* CheckSmiInstr::MakeLocationSummary() const { 1984 LocationSummary* CheckSmiInstr::MakeLocationSummary() const {
1491 const intptr_t kNumInputs = 1; 1985 const intptr_t kNumInputs = 1;
1492 const intptr_t kNumTemps = 0; 1986 const intptr_t kNumTemps = 0;
1493 LocationSummary* summary = 1987 LocationSummary* summary =
1494 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 1988 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
1495 summary->set_in(0, Location::RequiresRegister()); 1989 summary->set_in(0, Location::RequiresRegister());
1496 return summary; 1990 return summary;
1497 } 1991 }
1498 1992
1499 1993
1500 void CheckSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1994 void CheckSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1995 __ TraceSimMsg("CheckSmiInstr");
1501 Register value = locs()->in(0).reg(); 1996 Register value = locs()->in(0).reg();
1502 Label* deopt = compiler->AddDeoptStub(deopt_id(), 1997 Label* deopt = compiler->AddDeoptStub(deopt_id(),
1503 kDeoptCheckSmi); 1998 kDeoptCheckSmi);
1504 __ andi(TMP1, value, Immediate(kSmiTagMask)); 1999 __ andi(TMP1, value, Immediate(kSmiTagMask));
1505 __ bne(TMP1, ZR, deopt); 2000 __ bne(TMP1, ZR, deopt);
1506 } 2001 }
1507 2002
1508 2003
1509 LocationSummary* CheckArrayBoundInstr::MakeLocationSummary() const { 2004 LocationSummary* CheckArrayBoundInstr::MakeLocationSummary() const {
1510 UNIMPLEMENTED(); 2005 UNIMPLEMENTED();
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
1566 return NULL; 2061 return NULL;
1567 } 2062 }
1568 2063
1569 2064
1570 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2065 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1571 UNIMPLEMENTED(); 2066 UNIMPLEMENTED();
1572 } 2067 }
1573 2068
1574 2069
1575 LocationSummary* ThrowInstr::MakeLocationSummary() const { 2070 LocationSummary* ThrowInstr::MakeLocationSummary() const {
1576 UNIMPLEMENTED(); 2071 return new LocationSummary(0, 0, LocationSummary::kCall);
1577 return NULL;
1578 } 2072 }
1579 2073
1580 2074
1581 2075
1582 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2076 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1583 UNIMPLEMENTED(); 2077 compiler->GenerateCallRuntime(token_pos(),
2078 deopt_id(),
2079 kThrowRuntimeEntry,
2080 locs());
2081 __ break_(0);
1584 } 2082 }
1585 2083
1586 2084
1587 LocationSummary* ReThrowInstr::MakeLocationSummary() const { 2085 LocationSummary* ReThrowInstr::MakeLocationSummary() const {
1588 UNIMPLEMENTED(); 2086 UNIMPLEMENTED();
1589 return NULL; 2087 return NULL;
1590 } 2088 }
1591 2089
1592 2090
1593 void ReThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2091 void ReThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1594 UNIMPLEMENTED(); 2092 UNIMPLEMENTED();
1595 } 2093 }
1596 2094
1597 2095
1598 LocationSummary* GotoInstr::MakeLocationSummary() const { 2096 LocationSummary* GotoInstr::MakeLocationSummary() const {
1599 return new LocationSummary(0, 0, LocationSummary::kNoCall); 2097 return new LocationSummary(0, 0, LocationSummary::kNoCall);
1600 } 2098 }
1601 2099
1602 2100
1603 void GotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2101 void GotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2102 __ TraceSimMsg("GotoInstr");
1604 // Add deoptimization descriptor for deoptimizing instructions 2103 // Add deoptimization descriptor for deoptimizing instructions
1605 // that may be inserted before this instruction. 2104 // that may be inserted before this instruction.
1606 if (!compiler->is_optimizing()) { 2105 if (!compiler->is_optimizing()) {
1607 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, 2106 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt,
1608 GetDeoptId(), 2107 GetDeoptId(),
1609 0); // No token position. 2108 0); // No token position.
1610 } 2109 }
1611 2110
1612 if (HasParallelMove()) { 2111 if (HasParallelMove()) {
1613 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); 2112 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move());
(...skipping 18 matching lines...) Expand all
1632 default: 2131 default:
1633 OS::Print("Error: Condition not recognized: %d\n", condition); 2132 OS::Print("Error: Condition not recognized: %d\n", condition);
1634 UNIMPLEMENTED(); 2133 UNIMPLEMENTED();
1635 return EQ; 2134 return EQ;
1636 } 2135 }
1637 } 2136 }
1638 2137
1639 2138
1640 void ControlInstruction::EmitBranchOnValue(FlowGraphCompiler* compiler, 2139 void ControlInstruction::EmitBranchOnValue(FlowGraphCompiler* compiler,
1641 bool value) { 2140 bool value) {
2141 __ TraceSimMsg("ControlInstruction::EmitBranchOnValue");
1642 if (value && !compiler->CanFallThroughTo(true_successor())) { 2142 if (value && !compiler->CanFallThroughTo(true_successor())) {
1643 __ b(compiler->GetJumpLabel(true_successor())); 2143 __ b(compiler->GetJumpLabel(true_successor()));
1644 } else if (!value && !compiler->CanFallThroughTo(false_successor())) { 2144 } else if (!value && !compiler->CanFallThroughTo(false_successor())) {
1645 __ b(compiler->GetJumpLabel(false_successor())); 2145 __ b(compiler->GetJumpLabel(false_successor()));
1646 } 2146 }
1647 } 2147 }
1648 2148
1649 2149
1650 // The comparison result is in CMPRES. 2150 // The comparison result is in CMPRES.
1651 void ControlInstruction::EmitBranchOnCondition(FlowGraphCompiler* compiler, 2151 void ControlInstruction::EmitBranchOnCondition(FlowGraphCompiler* compiler,
1652 Condition true_condition) { 2152 Condition true_condition) {
2153 __ TraceSimMsg("ControlInstruction::EmitBranchOnCondition");
1653 if (compiler->CanFallThroughTo(false_successor())) { 2154 if (compiler->CanFallThroughTo(false_successor())) {
1654 // If the next block is the false successor we will fall through to it. 2155 // If the next block is the false successor we will fall through to it.
1655 Label* label = compiler->GetJumpLabel(true_successor()); 2156 Label* label = compiler->GetJumpLabel(true_successor());
1656 switch (true_condition) { 2157 switch (true_condition) {
1657 case EQ: __ beq(CMPRES, ZR, label); break; 2158 case EQ: __ beq(CMPRES, ZR, label); break;
1658 case NE: __ bne(CMPRES, ZR, label); break; 2159 case NE: __ bne(CMPRES, ZR, label); break;
1659 case GT: __ bgtz(CMPRES, label); break; 2160 case GT: __ bgtz(CMPRES, label); break;
1660 case GE: __ bgez(CMPRES, label); break; 2161 case GE: __ bgez(CMPRES, label); break;
1661 case LT: __ bltz(CMPRES, label); break; 2162 case LT: __ bltz(CMPRES, label); break;
1662 case LE: __ blez(CMPRES, label); break; 2163 case LE: __ blez(CMPRES, label); break;
(...skipping 19 matching lines...) Expand all
1682 } 2183 }
1683 // Fall through or jump to the true successor. 2184 // Fall through or jump to the true successor.
1684 if (!compiler->CanFallThroughTo(true_successor())) { 2185 if (!compiler->CanFallThroughTo(true_successor())) {
1685 __ b(compiler->GetJumpLabel(true_successor())); 2186 __ b(compiler->GetJumpLabel(true_successor()));
1686 } 2187 }
1687 } 2188 }
1688 } 2189 }
1689 2190
1690 2191
1691 LocationSummary* CurrentContextInstr::MakeLocationSummary() const { 2192 LocationSummary* CurrentContextInstr::MakeLocationSummary() const {
1692 UNIMPLEMENTED(); 2193 return LocationSummary::Make(0,
1693 return NULL; 2194 Location::RequiresRegister(),
2195 LocationSummary::kNoCall);
1694 } 2196 }
1695 2197
1696 2198
1697 void CurrentContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2199 void CurrentContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1698 UNIMPLEMENTED(); 2200 __ mov(locs()->out().reg(), CTX);
1699 } 2201 }
1700 2202
1701 2203
1702 LocationSummary* StrictCompareInstr::MakeLocationSummary() const { 2204 LocationSummary* StrictCompareInstr::MakeLocationSummary() const {
1703 const intptr_t kNumInputs = 2; 2205 const intptr_t kNumInputs = 2;
1704 const intptr_t kNumTemps = 0; 2206 const intptr_t kNumTemps = 0;
1705 LocationSummary* locs = 2207 LocationSummary* locs =
1706 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 2208 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
1707 locs->set_in(0, Location::RegisterOrConstant(left())); 2209 locs->set_in(0, Location::RegisterOrConstant(left()));
1708 locs->set_in(1, Location::RegisterOrConstant(right())); 2210 locs->set_in(1, Location::RegisterOrConstant(right()));
1709 locs->set_out(Location::RequiresRegister()); 2211 locs->set_out(Location::RequiresRegister());
1710 return locs; 2212 return locs;
1711 } 2213 }
1712 2214
1713 2215
1714 // Special code for numbers (compare values instead of references.) 2216 // Special code for numbers (compare values instead of references.)
1715 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2217 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2218 __ TraceSimMsg("StrictCompareInstr");
1716 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); 2219 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT);
1717 Location left = locs()->in(0); 2220 Location left = locs()->in(0);
1718 Location right = locs()->in(1); 2221 Location right = locs()->in(1);
1719 if (left.IsConstant() && right.IsConstant()) { 2222 if (left.IsConstant() && right.IsConstant()) {
1720 // TODO(vegorov): should be eliminated earlier by constant propagation. 2223 // TODO(vegorov): should be eliminated earlier by constant propagation.
1721 const bool result = (kind() == Token::kEQ_STRICT) ? 2224 const bool result = (kind() == Token::kEQ_STRICT) ?
1722 left.constant().raw() == right.constant().raw() : 2225 left.constant().raw() == right.constant().raw() :
1723 left.constant().raw() != right.constant().raw(); 2226 left.constant().raw() != right.constant().raw();
1724 __ LoadObject(locs()->out().reg(), result ? Bool::True() : Bool::False()); 2227 __ LoadObject(locs()->out().reg(), result ? Bool::True() : Bool::False());
1725 return; 2228 return;
(...skipping 23 matching lines...) Expand all
1749 __ LoadObject(result, Bool::False()); 2252 __ LoadObject(result, Bool::False());
1750 __ b(&done); 2253 __ b(&done);
1751 __ Bind(&load_true); 2254 __ Bind(&load_true);
1752 __ LoadObject(result, Bool::True()); 2255 __ LoadObject(result, Bool::True());
1753 __ Bind(&done); 2256 __ Bind(&done);
1754 } 2257 }
1755 2258
1756 2259
1757 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, 2260 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler,
1758 BranchInstr* branch) { 2261 BranchInstr* branch) {
2262 __ TraceSimMsg("StrictCompareInstr::EmitBranchCode");
1759 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); 2263 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT);
1760 Location left = locs()->in(0); 2264 Location left = locs()->in(0);
1761 Location right = locs()->in(1); 2265 Location right = locs()->in(1);
1762 if (left.IsConstant() && right.IsConstant()) { 2266 if (left.IsConstant() && right.IsConstant()) {
1763 // TODO(vegorov): should be eliminated earlier by constant propagation. 2267 // TODO(vegorov): should be eliminated earlier by constant propagation.
1764 const bool result = (kind() == Token::kEQ_STRICT) ? 2268 const bool result = (kind() == Token::kEQ_STRICT) ?
1765 left.constant().raw() == right.constant().raw() : 2269 left.constant().raw() == right.constant().raw() :
1766 left.constant().raw() != right.constant().raw(); 2270 left.constant().raw() != right.constant().raw();
1767 branch->EmitBranchOnValue(compiler, result); 2271 branch->EmitBranchOnValue(compiler, result);
1768 return; 2272 return;
(...skipping 10 matching lines...) Expand all
1779 compiler->EmitEqualityRegRegCompare(left.reg(), 2283 compiler->EmitEqualityRegRegCompare(left.reg(),
1780 right.reg(), 2284 right.reg(),
1781 needs_number_check()); 2285 needs_number_check());
1782 } 2286 }
1783 2287
1784 Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQ : NE; 2288 Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQ : NE;
1785 branch->EmitBranchOnCondition(compiler, true_condition); 2289 branch->EmitBranchOnCondition(compiler, true_condition);
1786 } 2290 }
1787 2291
1788 2292
1789 void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1790 UNIMPLEMENTED();
1791 }
1792
1793
1794 LocationSummary* BooleanNegateInstr::MakeLocationSummary() const { 2293 LocationSummary* BooleanNegateInstr::MakeLocationSummary() const {
1795 UNIMPLEMENTED(); 2294 UNIMPLEMENTED();
1796 return NULL; 2295 return NULL;
1797 } 2296 }
1798 2297
1799 2298
1800 void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2299 void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1801 UNIMPLEMENTED(); 2300 UNIMPLEMENTED();
1802 } 2301 }
1803 2302
(...skipping 19 matching lines...) Expand all
1823 UNIMPLEMENTED(); 2322 UNIMPLEMENTED();
1824 } 2323 }
1825 2324
1826 2325
1827 LocationSummary* AllocateObjectInstr::MakeLocationSummary() const { 2326 LocationSummary* AllocateObjectInstr::MakeLocationSummary() const {
1828 return MakeCallSummary(); 2327 return MakeCallSummary();
1829 } 2328 }
1830 2329
1831 2330
1832 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2331 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2332 __ TraceSimMsg("AllocateObjectInstr");
1833 const Class& cls = Class::ZoneHandle(constructor().Owner()); 2333 const Class& cls = Class::ZoneHandle(constructor().Owner());
1834 const Code& stub = Code::Handle(StubCode::GetAllocationStubForClass(cls)); 2334 const Code& stub = Code::Handle(StubCode::GetAllocationStubForClass(cls));
1835 const ExternalLabel label(cls.ToCString(), stub.EntryPoint()); 2335 const ExternalLabel label(cls.ToCString(), stub.EntryPoint());
1836 compiler->GenerateCall(token_pos(), 2336 compiler->GenerateCall(token_pos(),
1837 &label, 2337 &label,
1838 PcDescriptors::kOther, 2338 PcDescriptors::kOther,
1839 locs()); 2339 locs());
1840 __ Drop(ArgumentCount()); // Discard arguments. 2340 __ Drop(ArgumentCount()); // Discard arguments.
1841 } 2341 }
1842 2342
1843 2343
1844 LocationSummary* CreateClosureInstr::MakeLocationSummary() const { 2344 LocationSummary* CreateClosureInstr::MakeLocationSummary() const {
1845 UNIMPLEMENTED(); 2345 return MakeCallSummary();
1846 return NULL;
1847 } 2346 }
1848 2347
1849 2348
1850 void CreateClosureInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2349 void CreateClosureInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1851 UNIMPLEMENTED(); 2350 const Function& closure_function = function();
2351 ASSERT(!closure_function.IsImplicitStaticClosureFunction());
2352 const Code& stub = Code::Handle(
2353 StubCode::GetAllocationStubForClosure(closure_function));
2354 const ExternalLabel label(closure_function.ToCString(), stub.EntryPoint());
2355 compiler->GenerateCall(token_pos(),
2356 &label,
2357 PcDescriptors::kOther,
2358 locs());
2359 __ Drop(2); // Discard type arguments and receiver.
1852 } 2360 }
1853 2361
1854 } // namespace dart 2362 } // namespace dart
1855 2363
1856 #endif // defined TARGET_ARCH_MIPS 2364 #endif // defined TARGET_ARCH_MIPS
1857 2365
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_compiler_mips.cc ('k') | runtime/vm/simulator_mips.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698