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

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

Issue 13502002: Support FrameLookup vm test on ARM, requiring among other things: (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_arm.cc ('k') | runtime/vm/intermediate_language_ia32.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 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
160 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); 160 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
161 summary->set_in(0, Location::RegisterLocation(R0)); // Value. 161 summary->set_in(0, Location::RegisterLocation(R0)); // Value.
162 summary->set_in(1, Location::RegisterLocation(R1)); // Instantiator. 162 summary->set_in(1, Location::RegisterLocation(R1)); // Instantiator.
163 summary->set_in(2, Location::RegisterLocation(R2)); // Type arguments. 163 summary->set_in(2, Location::RegisterLocation(R2)); // Type arguments.
164 summary->set_out(Location::RegisterLocation(R0)); 164 summary->set_out(Location::RegisterLocation(R0));
165 return summary; 165 return summary;
166 } 166 }
167 167
168 168
169 LocationSummary* AssertBooleanInstr::MakeLocationSummary() const { 169 LocationSummary* AssertBooleanInstr::MakeLocationSummary() const {
170 UNIMPLEMENTED(); 170 const intptr_t kNumInputs = 1;
171 return NULL; 171 const intptr_t kNumTemps = 0;
172 LocationSummary* locs =
173 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
174 locs->set_in(0, Location::RegisterLocation(R0));
175 locs->set_out(Location::RegisterLocation(R0));
176 return locs;
177 }
178
179
180 static void EmitAssertBoolean(Register reg,
181 intptr_t token_pos,
182 intptr_t deopt_id,
183 LocationSummary* locs,
184 FlowGraphCompiler* compiler) {
185 // Check that the type of the value is allowed in conditional context.
186 // Call the runtime if the object is not bool::true or bool::false.
187 ASSERT(locs->always_calls());
188 Label done;
189 __ CompareObject(reg, Bool::True());
190 __ b(&done, EQ);
191 __ CompareObject(reg, Bool::False());
192 __ b(&done, EQ);
193
194 __ Push(reg); // Push the source object.
195 compiler->GenerateCallRuntime(token_pos,
196 deopt_id,
197 kConditionTypeErrorRuntimeEntry,
198 locs);
199 // We should never return here.
200 __ bkpt(0);
201 __ Bind(&done);
172 } 202 }
173 203
174 204
175 void AssertBooleanInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 205 void AssertBooleanInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
176 UNIMPLEMENTED(); 206 Register obj = locs()->in(0).reg();
207 Register result = locs()->out().reg();
208
209 EmitAssertBoolean(obj, token_pos(), deopt_id(), locs(), compiler);
210 ASSERT(obj == result);
177 } 211 }
178 212
179 213
180 LocationSummary* ArgumentDefinitionTestInstr::MakeLocationSummary() const { 214 LocationSummary* ArgumentDefinitionTestInstr::MakeLocationSummary() const {
181 UNIMPLEMENTED(); 215 UNIMPLEMENTED();
182 return NULL; 216 return NULL;
183 } 217 }
184 218
185 219
186 void ArgumentDefinitionTestInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 220 void ArgumentDefinitionTestInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
187 UNIMPLEMENTED(); 221 UNIMPLEMENTED();
188 } 222 }
189 223
190 224
191 LocationSummary* EqualityCompareInstr::MakeLocationSummary() const { 225 LocationSummary* EqualityCompareInstr::MakeLocationSummary() const {
192 UNIMPLEMENTED(); 226 const intptr_t kNumInputs = 2;
193 return NULL; 227 const bool is_checked_strict_equal =
228 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid);
229 if (receiver_class_id() == kMintCid) {
230 const intptr_t kNumTemps = 1;
231 LocationSummary* locs =
232 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
233 locs->set_in(0, Location::RequiresFpuRegister());
234 locs->set_in(1, Location::RequiresFpuRegister());
235 locs->set_temp(0, Location::RequiresRegister());
236 locs->set_out(Location::RequiresRegister());
237 return locs;
238 }
239 if (receiver_class_id() == kDoubleCid) {
240 const intptr_t kNumTemps = 0;
241 LocationSummary* locs =
242 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
243 locs->set_in(0, Location::RequiresFpuRegister());
244 locs->set_in(1, Location::RequiresFpuRegister());
245 locs->set_out(Location::RequiresRegister());
246 return locs;
247 }
248 if (receiver_class_id() == kSmiCid) {
249 const intptr_t kNumTemps = 0;
250 LocationSummary* locs =
251 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
252 locs->set_in(0, Location::RegisterOrConstant(left()));
253 // Only one input can be a constant operand. The case of two constant
254 // operands should be handled by constant propagation.
255 locs->set_in(1, locs->in(0).IsConstant()
256 ? Location::RequiresRegister()
257 : Location::RegisterOrConstant(right()));
258 locs->set_out(Location::RequiresRegister());
259 return locs;
260 }
261 if (is_checked_strict_equal) {
262 const intptr_t kNumTemps = 1;
263 LocationSummary* locs =
264 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
265 locs->set_in(0, Location::RequiresRegister());
266 locs->set_in(1, Location::RequiresRegister());
267 locs->set_temp(0, Location::RequiresRegister());
268 locs->set_out(Location::RequiresRegister());
269 return locs;
270 }
271 if (IsPolymorphic()) {
272 const intptr_t kNumTemps = 1;
273 LocationSummary* locs =
274 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
275 UNIMPLEMENTED(); // TODO(regis): Verify register allocation.
276 return locs;
277 }
278 const intptr_t kNumTemps = 1;
279 LocationSummary* locs =
280 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
281 locs->set_in(0, Location::RegisterLocation(R1));
282 locs->set_in(1, Location::RegisterLocation(R0));
283 locs->set_temp(0, Location::RegisterLocation(R6));
284 locs->set_out(Location::RegisterLocation(R0));
285 return locs;
286 }
287
288
289 // R1: left.
290 // R0: right.
291 // Uses R6 to load ic_call_data.
292 static void EmitEqualityAsInstanceCall(FlowGraphCompiler* compiler,
293 intptr_t deopt_id,
294 intptr_t token_pos,
295 Token::Kind kind,
296 LocationSummary* locs,
297 const ICData& original_ic_data) {
298 if (!compiler->is_optimizing()) {
299 compiler->AddCurrentDescriptor(PcDescriptors::kDeoptBefore,
300 deopt_id,
301 token_pos);
302 }
303 const int kNumberOfArguments = 2;
304 const Array& kNoArgumentNames = Array::Handle();
305 const int kNumArgumentsChecked = 2;
306
307 Label check_identity;
308 __ LoadImmediate(IP, reinterpret_cast<intptr_t>(Object::null()));
309 __ cmp(R1, ShifterOperand(IP));
310 __ b(&check_identity, EQ);
311 __ cmp(R0, ShifterOperand(IP));
312 __ b(&check_identity, EQ);
313
314 ICData& equality_ic_data = ICData::ZoneHandle();
315 if (compiler->is_optimizing() && FLAG_propagate_ic_data) {
316 ASSERT(!original_ic_data.IsNull());
317 if (original_ic_data.NumberOfChecks() == 0) {
318 // IC call for reoptimization populates original ICData.
319 equality_ic_data = original_ic_data.raw();
320 } else {
321 // Megamorphic call.
322 equality_ic_data = original_ic_data.AsUnaryClassChecks();
323 }
324 } else {
325 equality_ic_data = ICData::New(compiler->parsed_function().function(),
326 Symbols::EqualOperator(),
327 deopt_id,
328 kNumArgumentsChecked);
329 }
330 __ PushList((1 << R0) | (1 << R1));
331 compiler->GenerateInstanceCall(deopt_id,
332 token_pos,
333 kNumberOfArguments,
334 kNoArgumentNames,
335 locs,
336 equality_ic_data);
337 Label check_ne;
338 __ b(&check_ne);
339
340 __ Bind(&check_identity);
341 Label equality_done;
342 if (compiler->is_optimizing()) {
343 // No need to update IC data.
344 Label is_true;
345 __ cmp(R0, ShifterOperand(R1));
346 __ b(&is_true, EQ);
347 __ LoadObject(R0, (kind == Token::kEQ) ? Bool::False() : Bool::True());
348 __ b(&equality_done);
349 __ Bind(&is_true);
350 __ LoadObject(R0, (kind == Token::kEQ) ? Bool::True() : Bool::False());
351 if (kind == Token::kNE) {
352 // Skip not-equal result conversion.
353 __ b(&equality_done);
354 }
355 } else {
356 // Call stub, load IC data in register. The stub will update ICData if
357 // necessary.
358 Register ic_data_reg = locs->temp(0).reg();
359 ASSERT(ic_data_reg == R6); // Stub depends on it.
360 __ LoadObject(ic_data_reg, equality_ic_data);
361 // Pass left in R1 and right in R0.
362 compiler->GenerateCall(token_pos,
363 &StubCode::EqualityWithNullArgLabel(),
364 PcDescriptors::kOther,
365 locs);
366 }
367 __ Bind(&check_ne);
368 if (kind == Token::kNE) {
369 Label true_label, done;
370 // Negate the condition: true label returns false and vice versa.
371 __ CompareObject(R0, Bool::True());
372 __ b(&true_label, EQ);
373 __ LoadObject(R0, Bool::True());
374 __ b(&done);
375 __ Bind(&true_label);
376 __ LoadObject(R0, Bool::False());
377 __ Bind(&done);
378 }
379 __ Bind(&equality_done);
380 }
381
382
383 // Emit code when ICData's targets are all Object == (which is ===).
384 static void EmitCheckedStrictEqual(FlowGraphCompiler* compiler,
385 const ICData& ic_data,
386 const LocationSummary& locs,
387 Token::Kind kind,
388 BranchInstr* branch,
389 intptr_t deopt_id) {
390 UNIMPLEMENTED();
391 }
392
393
394 // First test if receiver is NULL, in which case === is applied.
395 // If type feedback was provided (lists of <class-id, target>), do a
396 // type by type check (either === or static call to the operator.
397 static void EmitGenericEqualityCompare(FlowGraphCompiler* compiler,
398 LocationSummary* locs,
399 Token::Kind kind,
400 BranchInstr* branch,
401 const ICData& ic_data,
402 intptr_t deopt_id,
403 intptr_t token_pos) {
404 UNIMPLEMENTED();
405 }
406
407
408 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler,
409 const LocationSummary& locs,
410 Token::Kind kind,
411 BranchInstr* branch) {
412 UNIMPLEMENTED();
413 }
414
415
416 static void EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler,
417 const LocationSummary& locs,
418 Token::Kind kind,
419 BranchInstr* branch) {
420 UNIMPLEMENTED();
421 }
422
423
424 static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler,
425 const LocationSummary& locs,
426 Token::Kind kind,
427 BranchInstr* branch) {
428 UNIMPLEMENTED();
194 } 429 }
195 430
196 431
197 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 432 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
198 UNIMPLEMENTED(); 433 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ));
434 BranchInstr* kNoBranch = NULL;
435 if (receiver_class_id() == kSmiCid) {
436 EmitSmiComparisonOp(compiler, *locs(), kind(), kNoBranch);
437 return;
438 }
439 if (receiver_class_id() == kMintCid) {
440 EmitUnboxedMintEqualityOp(compiler, *locs(), kind(), kNoBranch);
441 return;
442 }
443 if (receiver_class_id() == kDoubleCid) {
444 EmitDoubleComparisonOp(compiler, *locs(), kind(), kNoBranch);
445 return;
446 }
447 const bool is_checked_strict_equal =
448 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid);
449 if (is_checked_strict_equal) {
450 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), kNoBranch,
451 deopt_id());
452 return;
453 }
454 if (IsPolymorphic()) {
455 EmitGenericEqualityCompare(compiler, locs(), kind(), kNoBranch, *ic_data(),
456 deopt_id(), token_pos());
457 return;
458 }
459 Register left = locs()->in(0).reg();
460 Register right = locs()->in(1).reg();
461 ASSERT(left == R1);
462 ASSERT(right == R0);
463 EmitEqualityAsInstanceCall(compiler,
464 deopt_id(),
465 token_pos(),
466 kind(),
467 locs(),
468 *ic_data());
469 ASSERT(locs()->out().reg() == R0);
199 } 470 }
200 471
201 472
202 void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, 473 void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler,
203 BranchInstr* branch) { 474 BranchInstr* branch) {
204 UNIMPLEMENTED(); 475 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ));
205 } 476 if (receiver_class_id() == kSmiCid) {
206 477 // Deoptimizes if both arguments not Smi.
207 478 EmitSmiComparisonOp(compiler, *locs(), kind(), branch);
479 return;
480 }
481 if (receiver_class_id() == kMintCid) {
482 EmitUnboxedMintEqualityOp(compiler, *locs(), kind(), branch);
483 return;
484 }
485 if (receiver_class_id() == kDoubleCid) {
486 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch);
487 return;
488 }
489 const bool is_checked_strict_equal =
490 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid);
491 if (is_checked_strict_equal) {
492 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), branch,
493 deopt_id());
494 return;
495 }
496 if (IsPolymorphic()) {
497 EmitGenericEqualityCompare(compiler, locs(), kind(), branch, *ic_data(),
498 deopt_id(), token_pos());
499 return;
500 }
501 Register left = locs()->in(0).reg();
502 Register right = locs()->in(1).reg();
503 ASSERT(left == R1);
504 ASSERT(right == R0);
505 EmitEqualityAsInstanceCall(compiler,
506 deopt_id(),
507 token_pos(),
508 Token::kEQ, // kNE reverse occurs at branch.
509 locs(),
510 *ic_data());
511 if (branch->is_checked()) {
512 EmitAssertBoolean(R0, token_pos(), deopt_id(), locs(), compiler);
513 }
514 Condition branch_condition = (kind() == Token::kNE) ? NE : EQ;
515 __ CompareObject(R0, Bool::True());
516 branch->EmitBranchOnCondition(compiler, branch_condition);
517 }
518
519
208 LocationSummary* RelationalOpInstr::MakeLocationSummary() const { 520 LocationSummary* RelationalOpInstr::MakeLocationSummary() const {
209 UNIMPLEMENTED(); 521 UNIMPLEMENTED();
210 return NULL; 522 return NULL;
211 } 523 }
212 524
213 525
214 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 526 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
215 UNIMPLEMENTED(); 527 UNIMPLEMENTED();
216 } 528 }
217 529
(...skipping 466 matching lines...) Expand 10 before | Expand all | Expand 10 after
684 } 996 }
685 997
686 998
687 LocationSummary* BranchInstr::MakeLocationSummary() const { 999 LocationSummary* BranchInstr::MakeLocationSummary() const {
688 UNREACHABLE(); 1000 UNREACHABLE();
689 return NULL; 1001 return NULL;
690 } 1002 }
691 1003
692 1004
693 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1005 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
694 UNIMPLEMENTED(); 1006 comparison()->EmitBranchCode(compiler, this);
695 } 1007 }
696 1008
697 1009
698 LocationSummary* CheckClassInstr::MakeLocationSummary() const { 1010 LocationSummary* CheckClassInstr::MakeLocationSummary() const {
699 UNIMPLEMENTED(); 1011 UNIMPLEMENTED();
700 return NULL; 1012 return NULL;
701 } 1013 }
702 1014
703 1015
704 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1016 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
800 return NULL; 1112 return NULL;
801 } 1113 }
802 1114
803 1115
804 void ReThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1116 void ReThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
805 UNIMPLEMENTED(); 1117 UNIMPLEMENTED();
806 } 1118 }
807 1119
808 1120
809 LocationSummary* GotoInstr::MakeLocationSummary() const { 1121 LocationSummary* GotoInstr::MakeLocationSummary() const {
810 UNIMPLEMENTED(); 1122 return new LocationSummary(0, 0, LocationSummary::kNoCall);
811 return NULL;
812 } 1123 }
813 1124
814 1125
815 void GotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1126 void GotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
816 UNIMPLEMENTED(); 1127 // Add deoptimization descriptor for deoptimizing instructions
1128 // that may be inserted before this instruction.
1129 if (!compiler->is_optimizing()) {
1130 compiler->AddCurrentDescriptor(PcDescriptors::kDeoptBefore,
1131 GetDeoptId(),
1132 0); // No token position.
1133 }
1134
1135 if (HasParallelMove()) {
1136 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move());
1137 }
1138
1139 // We can fall through if the successor is the next block in the list.
1140 // Otherwise, we need a jump.
1141 if (!compiler->CanFallThroughTo(successor())) {
1142 __ b(compiler->GetJumpLabel(successor()));
1143 }
1144 }
1145
1146
1147 static Condition NegateCondition(Condition condition) {
1148 switch (condition) {
1149 case EQ: return NE;
1150 case NE: return EQ;
1151 case LT: return GE;
1152 case LE: return GT;
1153 case GT: return LE;
1154 case GE: return LT;
1155 case CC: return CS;
1156 case LS: return HI;
1157 case HI: return LS;
1158 case CS: return CC;
1159 default:
1160 OS::Print("Error %d\n", condition);
1161 UNIMPLEMENTED();
1162 return EQ;
1163 }
817 } 1164 }
818 1165
819 1166
820 void ControlInstruction::EmitBranchOnValue(FlowGraphCompiler* compiler, 1167 void ControlInstruction::EmitBranchOnValue(FlowGraphCompiler* compiler,
821 bool value) { 1168 bool value) {
822 UNIMPLEMENTED(); 1169 if (value && !compiler->CanFallThroughTo(true_successor())) {
1170 __ b(compiler->GetJumpLabel(true_successor()));
1171 } else if (!value && !compiler->CanFallThroughTo(false_successor())) {
1172 __ b(compiler->GetJumpLabel(false_successor()));
1173 }
823 } 1174 }
824 1175
825 1176
826 void ControlInstruction::EmitBranchOnCondition(FlowGraphCompiler* compiler, 1177 void ControlInstruction::EmitBranchOnCondition(FlowGraphCompiler* compiler,
827 Condition true_condition) { 1178 Condition true_condition) {
828 UNIMPLEMENTED(); 1179 if (compiler->CanFallThroughTo(false_successor())) {
1180 // If the next block is the false successor we will fall through to it.
1181 __ b(compiler->GetJumpLabel(true_successor()), true_condition);
1182 } else {
1183 // If the next block is the true successor we negate comparison and fall
1184 // through to it.
1185 Condition false_condition = NegateCondition(true_condition);
1186 __ b(compiler->GetJumpLabel(false_successor()), false_condition);
1187
1188 // Fall through or jump to the true successor.
1189 if (!compiler->CanFallThroughTo(true_successor())) {
1190 __ b(compiler->GetJumpLabel(true_successor()));
1191 }
1192 }
829 } 1193 }
830 1194
831 1195
832 LocationSummary* CurrentContextInstr::MakeLocationSummary() const { 1196 LocationSummary* CurrentContextInstr::MakeLocationSummary() const {
833 UNIMPLEMENTED(); 1197 UNIMPLEMENTED();
834 return NULL; 1198 return NULL;
835 } 1199 }
836 1200
837 1201
838 void CurrentContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1202 void CurrentContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
839 UNIMPLEMENTED(); 1203 UNIMPLEMENTED();
840 } 1204 }
841 1205
842 1206
843 LocationSummary* StrictCompareInstr::MakeLocationSummary() const { 1207 LocationSummary* StrictCompareInstr::MakeLocationSummary() const {
844 UNIMPLEMENTED(); 1208 const intptr_t kNumInputs = 2;
845 return NULL; 1209 const intptr_t kNumTemps = 0;
1210 LocationSummary* locs =
1211 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
1212 locs->set_in(0, Location::RegisterOrConstant(left()));
1213 locs->set_in(1, Location::RegisterOrConstant(right()));
1214 locs->set_out(Location::RequiresRegister());
1215 return locs;
846 } 1216 }
847 1217
848 1218
1219 // Special code for numbers (compare values instead of references.)
849 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1220 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
850 UNIMPLEMENTED(); 1221 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT);
1222 Location left = locs()->in(0);
1223 Location right = locs()->in(1);
1224 if (left.IsConstant() && right.IsConstant()) {
1225 // TODO(vegorov): should be eliminated earlier by constant propagation.
1226 const bool result = (kind() == Token::kEQ_STRICT) ?
1227 left.constant().raw() == right.constant().raw() :
1228 left.constant().raw() != right.constant().raw();
1229 __ LoadObject(locs()->out().reg(), result ? Bool::True() : Bool::False());
1230 return;
1231 }
1232 if (left.IsConstant()) {
1233 compiler->EmitEqualityRegConstCompare(right.reg(),
1234 left.constant(),
1235 needs_number_check());
1236 } else if (right.IsConstant()) {
1237 compiler->EmitEqualityRegConstCompare(left.reg(),
1238 right.constant(),
1239 needs_number_check());
1240 } else {
1241 compiler->EmitEqualityRegRegCompare(left.reg(),
1242 right.reg(),
1243 needs_number_check());
1244 }
1245
1246 Register result = locs()->out().reg();
1247 Label load_true, done;
1248 Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQ : NE;
1249 __ b(&load_true, true_condition);
1250 __ LoadObject(result, Bool::False());
1251 __ b(&done);
1252 __ Bind(&load_true);
1253 __ LoadObject(result, Bool::True());
1254 __ Bind(&done);
851 } 1255 }
852 1256
853 1257
854 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, 1258 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler,
855 BranchInstr* branch) { 1259 BranchInstr* branch) {
856 UNIMPLEMENTED(); 1260 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT);
1261 Location left = locs()->in(0);
1262 Location right = locs()->in(1);
1263 if (left.IsConstant() && right.IsConstant()) {
1264 // TODO(vegorov): should be eliminated earlier by constant propagation.
1265 const bool result = (kind() == Token::kEQ_STRICT) ?
1266 left.constant().raw() == right.constant().raw() :
1267 left.constant().raw() != right.constant().raw();
1268 branch->EmitBranchOnValue(compiler, result);
1269 return;
1270 }
1271 if (left.IsConstant()) {
1272 compiler->EmitEqualityRegConstCompare(right.reg(),
1273 left.constant(),
1274 needs_number_check());
1275 } else if (right.IsConstant()) {
1276 compiler->EmitEqualityRegConstCompare(left.reg(),
1277 right.constant(),
1278 needs_number_check());
1279 } else {
1280 compiler->EmitEqualityRegRegCompare(left.reg(),
1281 right.reg(),
1282 needs_number_check());
1283 }
1284
1285 Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQ : NE;
1286 branch->EmitBranchOnCondition(compiler, true_condition);
857 } 1287 }
858 1288
859 1289
860 void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1290 void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
861 UNIMPLEMENTED(); 1291 UNIMPLEMENTED();
862 } 1292 }
863 1293
864 1294
865 LocationSummary* BooleanNegateInstr::MakeLocationSummary() const { 1295 LocationSummary* BooleanNegateInstr::MakeLocationSummary() const {
866 UNIMPLEMENTED(); 1296 UNIMPLEMENTED();
(...skipping 22 matching lines...) Expand all
889 return NULL; 1319 return NULL;
890 } 1320 }
891 1321
892 1322
893 void StoreVMFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1323 void StoreVMFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
894 UNIMPLEMENTED(); 1324 UNIMPLEMENTED();
895 } 1325 }
896 1326
897 1327
898 LocationSummary* AllocateObjectInstr::MakeLocationSummary() const { 1328 LocationSummary* AllocateObjectInstr::MakeLocationSummary() const {
899 UNIMPLEMENTED(); 1329 return MakeCallSummary();
900 return NULL;
901 } 1330 }
902 1331
903 1332
904 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1333 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
905 UNIMPLEMENTED(); 1334 const Class& cls = Class::ZoneHandle(constructor().Owner());
1335 const Code& stub = Code::Handle(StubCode::GetAllocationStubForClass(cls));
1336 const ExternalLabel label(cls.ToCString(), stub.EntryPoint());
1337 compiler->GenerateCall(token_pos(),
1338 &label,
1339 PcDescriptors::kOther,
1340 locs());
1341 __ Drop(ArgumentCount()); // Discard arguments.
906 } 1342 }
907 1343
908 1344
909 LocationSummary* CreateClosureInstr::MakeLocationSummary() const { 1345 LocationSummary* CreateClosureInstr::MakeLocationSummary() const {
910 UNIMPLEMENTED(); 1346 UNIMPLEMENTED();
911 return NULL; 1347 return NULL;
912 } 1348 }
913 1349
914 1350
915 void CreateClosureInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1351 void CreateClosureInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
916 UNIMPLEMENTED(); 1352 UNIMPLEMENTED();
917 } 1353 }
918 1354
919 } // namespace dart 1355 } // namespace dart
920 1356
921 #endif // defined TARGET_ARCH_ARM 1357 #endif // defined TARGET_ARCH_ARM
922 1358
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_compiler_arm.cc ('k') | runtime/vm/intermediate_language_ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698