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

Side by Side Diff: runtime/vm/flow_graph_compiler_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/disassembler_mips.cc ('k') | runtime/vm/intermediate_language_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/flow_graph_compiler.h" 8 #include "vm/flow_graph_compiler.h"
9 9
10 #include "lib/error.h" 10 #include "lib/error.h"
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
59 } 59 }
60 60
61 61
62 #define __ assembler()-> 62 #define __ assembler()->
63 63
64 64
65 // Fall through if bool_register contains null. 65 // Fall through if bool_register contains null.
66 void FlowGraphCompiler::GenerateBoolToJump(Register bool_register, 66 void FlowGraphCompiler::GenerateBoolToJump(Register bool_register,
67 Label* is_true, 67 Label* is_true,
68 Label* is_false) { 68 Label* is_false) {
69 __ TraceSimMsg("BoolToJump");
69 Label fall_through; 70 Label fall_through;
70 __ BranchEqual(bool_register, reinterpret_cast<intptr_t>(Object::null()), 71 __ BranchEqual(bool_register, reinterpret_cast<intptr_t>(Object::null()),
71 &fall_through); 72 &fall_through);
72 __ BranchEqual(bool_register, Bool::True(), is_true); 73 __ BranchEqual(bool_register, Bool::True(), is_true);
73 __ b(is_false); 74 __ b(is_false);
74 __ Bind(&fall_through); 75 __ Bind(&fall_through);
75 } 76 }
76 77
77 78
78 // A0: instance (must be preserved). 79 // A0: instance (must be preserved).
79 // A1: instantiator type arguments (if used). 80 // A1: instantiator type arguments (if used).
80 RawSubtypeTestCache* FlowGraphCompiler::GenerateCallSubtypeTestStub( 81 RawSubtypeTestCache* FlowGraphCompiler::GenerateCallSubtypeTestStub(
81 TypeTestStubKind test_kind, 82 TypeTestStubKind test_kind,
82 Register instance_reg, 83 Register instance_reg,
83 Register type_arguments_reg, 84 Register type_arguments_reg,
84 Register temp_reg, 85 Register temp_reg,
85 Label* is_instance_lbl, 86 Label* is_instance_lbl,
86 Label* is_not_instance_lbl) { 87 Label* is_not_instance_lbl) {
88 __ TraceSimMsg("CallSubtypeTestStub");
87 ASSERT(instance_reg == A0); 89 ASSERT(instance_reg == A0);
88 ASSERT(temp_reg == kNoRegister); // Unused on MIPS. 90 ASSERT(temp_reg == kNoRegister); // Unused on MIPS.
89 const SubtypeTestCache& type_test_cache = 91 const SubtypeTestCache& type_test_cache =
90 SubtypeTestCache::ZoneHandle(SubtypeTestCache::New()); 92 SubtypeTestCache::ZoneHandle(SubtypeTestCache::New());
91 __ LoadObject(A2, type_test_cache); 93 __ LoadObject(A2, type_test_cache);
92 if (test_kind == kTestTypeOneArg) { 94 if (test_kind == kTestTypeOneArg) {
93 ASSERT(type_arguments_reg == kNoRegister); 95 ASSERT(type_arguments_reg == kNoRegister);
94 __ LoadImmediate(A1, reinterpret_cast<intptr_t>(Object::null())); 96 __ LoadImmediate(A1, reinterpret_cast<intptr_t>(Object::null()));
95 __ BranchLink(&StubCode::Subtype1TestCacheLabel()); 97 __ BranchLink(&StubCode::Subtype1TestCacheLabel());
96 } else if (test_kind == kTestTypeTwoArgs) { 98 } else if (test_kind == kTestTypeTwoArgs) {
(...skipping 20 matching lines...) Expand all
117 Label* is_not_instance_lbl) { 119 Label* is_not_instance_lbl) {
118 UNIMPLEMENTED(); 120 UNIMPLEMENTED();
119 return NULL; 121 return NULL;
120 } 122 }
121 123
122 124
123 void FlowGraphCompiler::CheckClassIds(Register class_id_reg, 125 void FlowGraphCompiler::CheckClassIds(Register class_id_reg,
124 const GrowableArray<intptr_t>& class_ids, 126 const GrowableArray<intptr_t>& class_ids,
125 Label* is_equal_lbl, 127 Label* is_equal_lbl,
126 Label* is_not_equal_lbl) { 128 Label* is_not_equal_lbl) {
129 __ TraceSimMsg("CheckClassIds");
127 for (intptr_t i = 0; i < class_ids.length(); i++) { 130 for (intptr_t i = 0; i < class_ids.length(); i++) {
128 __ BranchEqual(class_id_reg, class_ids[i], is_equal_lbl); 131 __ BranchEqual(class_id_reg, class_ids[i], is_equal_lbl);
129 } 132 }
130 __ b(is_not_equal_lbl); 133 __ b(is_not_equal_lbl);
131 } 134 }
132 135
133 136
134 // Testing against an instantiated type with no arguments, without 137 // Testing against an instantiated type with no arguments, without
135 // SubtypeTestCache. 138 // SubtypeTestCache.
136 // A0: instance being type checked (preserved). 139 // A0: instance being type checked (preserved).
137 // Clobbers: T0, T1, T2 140 // Clobbers: T0, T1, T2
138 // Returns true if there is a fallthrough. 141 // Returns true if there is a fallthrough.
139 bool FlowGraphCompiler::GenerateInstantiatedTypeNoArgumentsTest( 142 bool FlowGraphCompiler::GenerateInstantiatedTypeNoArgumentsTest(
140 intptr_t token_pos, 143 intptr_t token_pos,
141 const AbstractType& type, 144 const AbstractType& type,
142 Label* is_instance_lbl, 145 Label* is_instance_lbl,
143 Label* is_not_instance_lbl) { 146 Label* is_not_instance_lbl) {
147 __ TraceSimMsg("InstantiatedTypeNoArgumentsTest");
144 __ Comment("InstantiatedTypeNoArgumentsTest"); 148 __ Comment("InstantiatedTypeNoArgumentsTest");
145 ASSERT(type.IsInstantiated()); 149 ASSERT(type.IsInstantiated());
146 const Class& type_class = Class::Handle(type.type_class()); 150 const Class& type_class = Class::Handle(type.type_class());
147 ASSERT(!type_class.HasTypeArguments()); 151 ASSERT(!type_class.HasTypeArguments());
148 152
149 const Register kInstanceReg = A0; 153 const Register kInstanceReg = A0;
150 __ andi(T0, A0, Immediate(kSmiTagMask)); 154 __ andi(T0, A0, Immediate(kSmiTagMask));
151 // If instance is Smi, check directly. 155 // If instance is Smi, check directly.
152 const Class& smi_class = Class::Handle(Smi::Class()); 156 const Class& smi_class = Class::Handle(Smi::Class());
153 if (smi_class.IsSubtypeOf(TypeArguments::Handle(), 157 if (smi_class.IsSubtypeOf(TypeArguments::Handle(),
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
199 // Clobbers A1, A2, T0-T3. 203 // Clobbers A1, A2, T0-T3.
200 // Immediate class test already done. 204 // Immediate class test already done.
201 // TODO(srdjan): Implement a quicker subtype check, as type test 205 // TODO(srdjan): Implement a quicker subtype check, as type test
202 // arrays can grow too high, but they may be useful when optimizing 206 // arrays can grow too high, but they may be useful when optimizing
203 // code (type-feedback). 207 // code (type-feedback).
204 RawSubtypeTestCache* FlowGraphCompiler::GenerateSubtype1TestCacheLookup( 208 RawSubtypeTestCache* FlowGraphCompiler::GenerateSubtype1TestCacheLookup(
205 intptr_t token_pos, 209 intptr_t token_pos,
206 const Class& type_class, 210 const Class& type_class,
207 Label* is_instance_lbl, 211 Label* is_instance_lbl,
208 Label* is_not_instance_lbl) { 212 Label* is_not_instance_lbl) {
213 __ TraceSimMsg("Subtype1TestCacheLookup");
209 __ Comment("Subtype1TestCacheLookup"); 214 __ Comment("Subtype1TestCacheLookup");
210 const Register kInstanceReg = A0; 215 const Register kInstanceReg = A0;
211 __ LoadClass(T0, kInstanceReg); 216 __ LoadClass(T0, kInstanceReg);
212 // T0: instance class. 217 // T0: instance class.
213 // Check immediate superclass equality. 218 // Check immediate superclass equality.
214 __ lw(T0, FieldAddress(T0, Class::super_type_offset())); 219 __ lw(T0, FieldAddress(T0, Class::super_type_offset()));
215 __ lw(T0, FieldAddress(T0, Type::type_class_offset())); 220 __ lw(T0, FieldAddress(T0, Type::type_class_offset()));
216 __ BranchEqual(T0, type_class, is_instance_lbl); 221 __ BranchEqual(T0, type_class, is_instance_lbl);
217 222
218 const Register kTypeArgumentsReg = kNoRegister; 223 const Register kTypeArgumentsReg = kNoRegister;
(...skipping 24 matching lines...) Expand all
243 // - preserved instance in A0 and optional instantiator type arguments in A1. 248 // - preserved instance in A0 and optional instantiator type arguments in A1.
244 // Clobbers: T0, T1, T2 249 // Clobbers: T0, T1, T2
245 // Note that this inlined code must be followed by the runtime_call code, as it 250 // Note that this inlined code must be followed by the runtime_call code, as it
246 // may fall through to it. Otherwise, this inline code will jump to the label 251 // may fall through to it. Otherwise, this inline code will jump to the label
247 // is_instance or to the label is_not_instance. 252 // is_instance or to the label is_not_instance.
248 RawSubtypeTestCache* FlowGraphCompiler::GenerateInlineInstanceof( 253 RawSubtypeTestCache* FlowGraphCompiler::GenerateInlineInstanceof(
249 intptr_t token_pos, 254 intptr_t token_pos,
250 const AbstractType& type, 255 const AbstractType& type,
251 Label* is_instance_lbl, 256 Label* is_instance_lbl,
252 Label* is_not_instance_lbl) { 257 Label* is_not_instance_lbl) {
258 __ TraceSimMsg("InlineInstanceof");
253 __ Comment("InlineInstanceof"); 259 __ Comment("InlineInstanceof");
254 if (type.IsVoidType()) { 260 if (type.IsVoidType()) {
255 // A non-null value is returned from a void function, which will result in a 261 // A non-null value is returned from a void function, which will result in a
256 // type error. A null value is handled prior to executing this inline code. 262 // type error. A null value is handled prior to executing this inline code.
257 return SubtypeTestCache::null(); 263 return SubtypeTestCache::null();
258 } 264 }
259 if (TypeCheckAsClassEquality(type)) { 265 if (TypeCheckAsClassEquality(type)) {
260 const intptr_t type_cid = Class::Handle(type.type_class()).id(); 266 const intptr_t type_cid = Class::Handle(type.type_class()).id();
261 const Register kInstanceReg = A0; 267 const Register kInstanceReg = A0;
262 __ andi(T0, kInstanceReg, Immediate(kSmiTagMask)); 268 __ andi(T0, kInstanceReg, Immediate(kSmiTagMask));
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
323 // Returns: 329 // Returns:
324 // - object in A0 for successful assignable check (or throws TypeError). 330 // - object in A0 for successful assignable check (or throws TypeError).
325 // Clobbers: T0, T1, T2 331 // Clobbers: T0, T1, T2
326 // Performance notes: positive checks must be quick, negative checks can be slow 332 // Performance notes: positive checks must be quick, negative checks can be slow
327 // as they throw an exception. 333 // as they throw an exception.
328 void FlowGraphCompiler::GenerateAssertAssignable(intptr_t token_pos, 334 void FlowGraphCompiler::GenerateAssertAssignable(intptr_t token_pos,
329 intptr_t deopt_id, 335 intptr_t deopt_id,
330 const AbstractType& dst_type, 336 const AbstractType& dst_type,
331 const String& dst_name, 337 const String& dst_name,
332 LocationSummary* locs) { 338 LocationSummary* locs) {
339 __ TraceSimMsg("AssertAssignable");
333 ASSERT(token_pos >= 0); 340 ASSERT(token_pos >= 0);
334 ASSERT(!dst_type.IsNull()); 341 ASSERT(!dst_type.IsNull());
335 ASSERT(dst_type.IsFinalized()); 342 ASSERT(dst_type.IsFinalized());
336 // Assignable check is skipped in FlowGraphBuilder, not here. 343 // Assignable check is skipped in FlowGraphBuilder, not here.
337 ASSERT(dst_type.IsMalformed() || 344 ASSERT(dst_type.IsMalformed() ||
338 (!dst_type.IsDynamicType() && !dst_type.IsObjectType())); 345 (!dst_type.IsDynamicType() && !dst_type.IsObjectType()));
339 // Preserve instantiator and its type arguments. 346 // Preserve instantiator and its type arguments.
340 __ addiu(SP, SP, Immediate(-2 * kWordSize)); 347 __ addiu(SP, SP, Immediate(-2 * kWordSize));
341 __ sw(A2, Address(SP, 1 * kWordSize)); 348 __ sw(A2, Address(SP, 1 * kWordSize));
342 __ sw(A1, Address(SP, 0 * kWordSize)); 349 __ sw(A1, Address(SP, 0 * kWordSize));
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
376 383
377 // Generate inline type check, linking to runtime call if not assignable. 384 // Generate inline type check, linking to runtime call if not assignable.
378 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle(); 385 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle();
379 test_cache = GenerateInlineInstanceof(token_pos, dst_type, 386 test_cache = GenerateInlineInstanceof(token_pos, dst_type,
380 &is_assignable, &runtime_call); 387 &is_assignable, &runtime_call);
381 388
382 __ Bind(&runtime_call); 389 __ Bind(&runtime_call);
383 // Load instantiator and its type arguments. 390 // Load instantiator and its type arguments.
384 __ lw(A1, Address(SP, 0 * kWordSize)); 391 __ lw(A1, Address(SP, 0 * kWordSize));
385 __ lw(A2, Address(SP, 1 * kWordSize)); 392 __ lw(A2, Address(SP, 1 * kWordSize));
386 __ addiu(SP, SP, Immediate(2 * kWordSize));
387 __ PushObject(Object::ZoneHandle()); // Make room for the result. 393 __ PushObject(Object::ZoneHandle()); // Make room for the result.
388 __ Push(A0); // Push the source object. 394 __ Push(A0); // Push the source object.
389 __ PushObject(dst_type); // Push the type of the destination. 395 __ PushObject(dst_type); // Push the type of the destination.
390 // Push instantiator and its type arguments. 396 // Push instantiator and its type arguments.
391 __ addiu(SP, SP, Immediate(-2 * kWordSize)); 397 __ addiu(SP, SP, Immediate(-2 * kWordSize));
392 __ sw(A2, Address(SP, 1 * kWordSize)); 398 __ sw(A2, Address(SP, 1 * kWordSize));
393 __ sw(A1, Address(SP, 0 * kWordSize)); 399 __ sw(A1, Address(SP, 0 * kWordSize));
394 __ PushObject(dst_name); // Push the name of the destination. 400 __ PushObject(dst_name); // Push the name of the destination.
395 __ LoadObject(T0, test_cache); 401 __ LoadObject(T0, test_cache);
396 __ Push(T0); 402 __ Push(T0);
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
435 Definition* defn = instr->AsDefinition(); 441 Definition* defn = instr->AsDefinition();
436 if ((defn != NULL) && defn->is_used()) { 442 if ((defn != NULL) && defn->is_used()) {
437 __ Push(defn->locs()->out().reg()); 443 __ Push(defn->locs()->out().reg());
438 } 444 }
439 } 445 }
440 446
441 447
442 // Input parameters: 448 // Input parameters:
443 // S4: arguments descriptor array. 449 // S4: arguments descriptor array.
444 void FlowGraphCompiler::CopyParameters() { 450 void FlowGraphCompiler::CopyParameters() {
451 __ TraceSimMsg("CopyParameters");
445 __ Comment("Copy parameters"); 452 __ Comment("Copy parameters");
446 const Function& function = parsed_function().function(); 453 const Function& function = parsed_function().function();
447 LocalScope* scope = parsed_function().node_sequence()->scope(); 454 LocalScope* scope = parsed_function().node_sequence()->scope();
448 const int num_fixed_params = function.num_fixed_parameters(); 455 const int num_fixed_params = function.num_fixed_parameters();
449 const int num_opt_pos_params = function.NumOptionalPositionalParameters(); 456 const int num_opt_pos_params = function.NumOptionalPositionalParameters();
450 const int num_opt_named_params = function.NumOptionalNamedParameters(); 457 const int num_opt_named_params = function.NumOptionalNamedParameters();
451 const int num_params = 458 const int num_params =
452 num_fixed_params + num_opt_pos_params + num_opt_named_params; 459 num_fixed_params + num_opt_pos_params + num_opt_named_params;
453 ASSERT(function.NumParameters() == num_params); 460 ASSERT(function.NumParameters() == num_params);
454 ASSERT(parsed_function().first_parameter_index() == kFirstLocalSlotIndex); 461 ASSERT(parsed_function().first_parameter_index() == kFirstLocalSlotIndex);
(...skipping 20 matching lines...) Expand all
475 // Let T1 point to the last passed positional argument, i.e. to 482 // Let T1 point to the last passed positional argument, i.e. to
476 // fp[kLastParamSlotIndex + num_args - 1 - (num_pos_args - 1)]. 483 // fp[kLastParamSlotIndex + num_args - 1 - (num_pos_args - 1)].
477 __ subu(T1, T1, T2); 484 __ subu(T1, T1, T2);
478 __ sll(T1, T1, 1); 485 __ sll(T1, T1, 1);
479 __ addu(T1, FP, T1); 486 __ addu(T1, FP, T1);
480 __ AddImmediate(T1, kLastParamSlotIndex * kWordSize); 487 __ AddImmediate(T1, kLastParamSlotIndex * kWordSize);
481 488
482 // Let T0 point to the last copied positional argument, i.e. to 489 // Let T0 point to the last copied positional argument, i.e. to
483 // fp[kFirstLocalSlotIndex - (num_pos_args - 1)]. 490 // fp[kFirstLocalSlotIndex - (num_pos_args - 1)].
484 __ AddImmediate(T0, FP, (kFirstLocalSlotIndex + 1) * kWordSize); 491 __ AddImmediate(T0, FP, (kFirstLocalSlotIndex + 1) * kWordSize);
485 __ sll(T3, T2, 1); // T2 is a Smi. 492 __ sll(T2, T2, 1); // T2 is a Smi.
486 __ subu(T0, T0, T3);
487 493
488 Label loop, loop_condition; 494 Label loop, loop_condition;
489 __ b(&loop_condition); 495 __ b(&loop_condition);
490 __ delay_slot()->SmiUntag(T2); 496 __ delay_slot()->subu(T0, T0, T2);
491 // We do not use the final allocation index of the variable here, i.e. 497 // We do not use the final allocation index of the variable here, i.e.
492 // scope->VariableAt(i)->index(), because captured variables still need 498 // scope->VariableAt(i)->index(), because captured variables still need
493 // to be copied to the context that is not yet allocated. 499 // to be copied to the context that is not yet allocated.
494 __ Bind(&loop); 500 __ Bind(&loop);
495 __ addu(T4, T1, T2); 501 __ addu(T4, T1, T2);
496 __ addu(T5, T0, T2); 502 __ addu(T5, T0, T2);
497 __ lw(T3, Address(T4)); 503 __ lw(T3, Address(T4));
498 __ sw(T3, Address(T5)); 504 __ sw(T3, Address(T5));
499 __ Bind(&loop_condition); 505 __ Bind(&loop_condition);
500 __ addiu(T2, T2, Immediate(-kWordSize)); 506 __ addiu(T2, T2, Immediate(-kWordSize));
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
566 // scope->VariableAt(i)->index(), because captured variables still need 572 // scope->VariableAt(i)->index(), because captured variables still need
567 // to be copied to the context that is not yet allocated. 573 // to be copied to the context that is not yet allocated.
568 const intptr_t computed_param_pos = kFirstLocalSlotIndex - param_pos; 574 const intptr_t computed_param_pos = kFirstLocalSlotIndex - param_pos;
569 __ sw(T3, Address(FP, computed_param_pos * kWordSize)); 575 __ sw(T3, Address(FP, computed_param_pos * kWordSize));
570 } 576 }
571 delete[] opt_param; 577 delete[] opt_param;
572 delete[] opt_param_position; 578 delete[] opt_param_position;
573 // Check that T0 now points to the null terminator in the array descriptor. 579 // Check that T0 now points to the null terminator in the array descriptor.
574 __ lw(T3, Address(T0)); 580 __ lw(T3, Address(T0));
575 __ BranchEqual(T3, reinterpret_cast<int32_t>(Object::null()), 581 __ BranchEqual(T3, reinterpret_cast<int32_t>(Object::null()),
576 &all_arguments_processed); 582 &all_arguments_processed);
577 } else { 583 } else {
578 ASSERT(num_opt_pos_params > 0); 584 ASSERT(num_opt_pos_params > 0);
579 __ lw(T2, 585 __ lw(T2,
580 FieldAddress(S4, ArgumentsDescriptor::positional_count_offset())); 586 FieldAddress(S4, ArgumentsDescriptor::positional_count_offset()));
581 __ SmiUntag(T2); 587 __ SmiUntag(T2);
582 for (int i = 0; i < num_opt_pos_params; i++) { 588 for (int i = 0; i < num_opt_pos_params; i++) {
583 Label next_parameter; 589 Label next_parameter;
584 // Handle this optional positional parameter only if k or fewer positional 590 // Handle this optional positional parameter only if k or fewer positional
585 // arguments have been passed, where k is param_pos, the position of this 591 // arguments have been passed, where k is param_pos, the position of this
586 // optional parameter in the formal parameter list. 592 // optional parameter in the formal parameter list.
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
644 650
645 __ Bind(&all_arguments_processed); 651 __ Bind(&all_arguments_processed);
646 // Nullify originally passed arguments only after they have been copied and 652 // Nullify originally passed arguments only after they have been copied and
647 // checked, otherwise noSuchMethod would not see their original values. 653 // checked, otherwise noSuchMethod would not see their original values.
648 // This step can be skipped in case we decide that formal parameters are 654 // This step can be skipped in case we decide that formal parameters are
649 // implicitly final, since garbage collecting the unmodified value is not 655 // implicitly final, since garbage collecting the unmodified value is not
650 // an issue anymore. 656 // an issue anymore.
651 657
652 // S4 : arguments descriptor array. 658 // S4 : arguments descriptor array.
653 __ lw(T2, FieldAddress(S4, ArgumentsDescriptor::count_offset())); 659 __ lw(T2, FieldAddress(S4, ArgumentsDescriptor::count_offset()));
654 __ SmiUntag(T2); 660 __ sll(T2, T2, 1); // T2 is a Smi.
655 661
656 __ LoadImmediate(T0, reinterpret_cast<intptr_t>(Object::null())); 662 __ LoadImmediate(T0, reinterpret_cast<intptr_t>(Object::null()));
657 Label null_args_loop, null_args_loop_condition; 663 Label null_args_loop, null_args_loop_condition;
664
658 __ b(&null_args_loop_condition); 665 __ b(&null_args_loop_condition);
659 __ delay_slot()->addiu(T1, FP, Immediate(kLastParamSlotIndex * kWordSize)); 666 __ delay_slot()->addiu(T1, FP, Immediate(kLastParamSlotIndex * kWordSize));
667
660 __ Bind(&null_args_loop); 668 __ Bind(&null_args_loop);
661 __ addu(T3, T1, T2); 669 __ addu(T3, T1, T2);
662 __ sw(T0, Address(T3)); 670 __ sw(T0, Address(T3));
671
663 __ Bind(&null_args_loop_condition); 672 __ Bind(&null_args_loop_condition);
664 __ addiu(T2, T2, Immediate(-kWordSize)); 673 __ addiu(T2, T2, Immediate(-kWordSize));
665 __ bgez(T2, &null_args_loop); 674 __ bgez(T2, &null_args_loop);
666 } 675 }
667 676
668 677
669 void FlowGraphCompiler::GenerateInlinedGetter(intptr_t offset) { 678 void FlowGraphCompiler::GenerateInlinedGetter(intptr_t offset) {
670 UNIMPLEMENTED(); 679 // RA: return address.
680 // SP: receiver.
681 // Sequence node has one return node, its input is load field node.
682 __ lw(V0, Address(SP, 0 * kWordSize));
683 __ lw(V0, Address(V0, offset - kHeapObjectTag));
684 __ Ret();
671 } 685 }
672 686
673 687
674 void FlowGraphCompiler::GenerateInlinedSetter(intptr_t offset) { 688 void FlowGraphCompiler::GenerateInlinedSetter(intptr_t offset) {
675 UNIMPLEMENTED(); 689 // RA: return address.
690 // SP+1: receiver.
691 // SP+0: value.
692 // Sequence node has one store node and one return NULL node.
693 __ lw(T0, Address(SP, 1 * kWordSize)); // Receiver.
694 __ lw(T1, Address(SP, 0 * kWordSize)); // Value.
695 __ StoreIntoObject(T0, FieldAddress(T0, offset), T1);
696 __ LoadImmediate(V0, reinterpret_cast<intptr_t>(Object::null()));
697 __ Ret();
676 } 698 }
677 699
678 700
679 void FlowGraphCompiler::EmitFrameEntry() { 701 void FlowGraphCompiler::EmitFrameEntry() {
702 __ TraceSimMsg("FrameEntry");
680 const Function& function = parsed_function().function(); 703 const Function& function = parsed_function().function();
681 if (CanOptimizeFunction() && function.is_optimizable()) { 704 if (CanOptimizeFunction() && function.is_optimizable()) {
682 const bool can_optimize = !is_optimizing() || may_reoptimize(); 705 const bool can_optimize = !is_optimizing() || may_reoptimize();
683 const Register function_reg = T0; 706 const Register function_reg = T0;
684 if (can_optimize) { 707 if (can_optimize) {
685 Label next; 708 Label next;
686 // The pool pointer is not setup before entering the Dart frame. 709 // The pool pointer is not setup before entering the Dart frame.
687 710
688 __ mov(TMP1, RA); // Save RA. 711 __ mov(TMP1, RA); // Save RA.
689 __ bal(&next); // Branch and link to next instruction to get PC in RA. 712 __ bal(&next); // Branch and link to next instruction to get PC in RA.
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
779 LocalVariable* saved_args_desc_var = 802 LocalVariable* saved_args_desc_var =
780 parsed_function().GetSavedArgumentsDescriptorVar(); 803 parsed_function().GetSavedArgumentsDescriptorVar();
781 if (num_copied_params == 0) { 804 if (num_copied_params == 0) {
782 #ifdef DEBUG 805 #ifdef DEBUG
783 ASSERT(!parsed_function().function().HasOptionalParameters()); 806 ASSERT(!parsed_function().function().HasOptionalParameters());
784 const bool check_arguments = true; 807 const bool check_arguments = true;
785 #else 808 #else
786 const bool check_arguments = function.IsClosureFunction(); 809 const bool check_arguments = function.IsClosureFunction();
787 #endif 810 #endif
788 if (check_arguments) { 811 if (check_arguments) {
812 __ TraceSimMsg("Check argument count");
789 __ Comment("Check argument count"); 813 __ Comment("Check argument count");
790 // Check that exactly num_fixed arguments are passed in. 814 // Check that exactly num_fixed arguments are passed in.
791 Label correct_num_arguments, wrong_num_arguments; 815 Label correct_num_arguments, wrong_num_arguments;
792 __ lw(T0, FieldAddress(S4, ArgumentsDescriptor::count_offset())); 816 __ lw(T0, FieldAddress(S4, ArgumentsDescriptor::count_offset()));
793 __ BranchNotEqual(T0, Smi::RawValue(num_fixed_params), 817 __ BranchNotEqual(T0, Smi::RawValue(num_fixed_params),
794 &wrong_num_arguments); 818 &wrong_num_arguments);
795 819
796 __ lw(T1, FieldAddress(S4, 820 __ lw(T1, FieldAddress(S4,
797 ArgumentsDescriptor::positional_count_offset())); 821 ArgumentsDescriptor::positional_count_offset()));
798 __ beq(T0, T1, &correct_num_arguments); 822 __ beq(T0, T1, &correct_num_arguments);
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
851 ASSERT(saved_args_desc_var->is_captured() || 875 ASSERT(saved_args_desc_var->is_captured() ||
852 (saved_args_desc_var->index() == slot)); 876 (saved_args_desc_var->index() == slot));
853 __ sw(kArgumentsDescriptorReg, Address(FP, slot * kWordSize)); 877 __ sw(kArgumentsDescriptorReg, Address(FP, slot * kWordSize));
854 } 878 }
855 CopyParameters(); 879 CopyParameters();
856 } 880 }
857 881
858 // In unoptimized code, initialize (non-argument) stack allocated slots to 882 // In unoptimized code, initialize (non-argument) stack allocated slots to
859 // null. This does not cover the saved_args_desc_var slot. 883 // null. This does not cover the saved_args_desc_var slot.
860 if (!is_optimizing() && (num_locals > 0)) { 884 if (!is_optimizing() && (num_locals > 0)) {
885 __ TraceSimMsg("Initialize spill slots");
861 __ Comment("Initialize spill slots"); 886 __ Comment("Initialize spill slots");
862 const intptr_t slot_base = parsed_function().first_stack_local_index(); 887 const intptr_t slot_base = parsed_function().first_stack_local_index();
863 __ LoadImmediate(T0, reinterpret_cast<intptr_t>(Object::null())); 888 __ LoadImmediate(T0, reinterpret_cast<intptr_t>(Object::null()));
864 for (intptr_t i = 0; i < num_locals; ++i) { 889 for (intptr_t i = 0; i < num_locals; ++i) {
865 // Subtract index i (locals lie at lower addresses than FP). 890 // Subtract index i (locals lie at lower addresses than FP).
866 __ sw(T0, Address(FP, (slot_base - i) * kWordSize)); 891 __ sw(T0, Address(FP, (slot_base - i) * kWordSize));
867 } 892 }
868 } 893 }
869 894
870 if (FLAG_print_scopes) { 895 if (FLAG_print_scopes) {
(...skipping 20 matching lines...) Expand all
891 Isolate::kNoDeoptId, 916 Isolate::kNoDeoptId,
892 0); // No token position. 917 0); // No token position.
893 __ Branch(&StubCode::DeoptimizeLazyLabel()); 918 __ Branch(&StubCode::DeoptimizeLazyLabel());
894 } 919 }
895 920
896 921
897 void FlowGraphCompiler::GenerateCall(intptr_t token_pos, 922 void FlowGraphCompiler::GenerateCall(intptr_t token_pos,
898 const ExternalLabel* label, 923 const ExternalLabel* label,
899 PcDescriptors::Kind kind, 924 PcDescriptors::Kind kind,
900 LocationSummary* locs) { 925 LocationSummary* locs) {
926 __ TraceSimMsg("Call");
901 __ BranchLinkPatchable(label); 927 __ BranchLinkPatchable(label);
902 AddCurrentDescriptor(kind, Isolate::kNoDeoptId, token_pos); 928 AddCurrentDescriptor(kind, Isolate::kNoDeoptId, token_pos);
903 RecordSafepoint(locs); 929 RecordSafepoint(locs);
904 } 930 }
905 931
906 932
907 void FlowGraphCompiler::GenerateDartCall(intptr_t deopt_id, 933 void FlowGraphCompiler::GenerateDartCall(intptr_t deopt_id,
908 intptr_t token_pos, 934 intptr_t token_pos,
909 const ExternalLabel* label, 935 const ExternalLabel* label,
910 PcDescriptors::Kind kind, 936 PcDescriptors::Kind kind,
911 LocationSummary* locs) { 937 LocationSummary* locs) {
938 __ TraceSimMsg("DartCall");
912 __ BranchLinkPatchable(label); 939 __ BranchLinkPatchable(label);
913 AddCurrentDescriptor(kind, deopt_id, token_pos); 940 AddCurrentDescriptor(kind, deopt_id, token_pos);
914 RecordSafepoint(locs); 941 RecordSafepoint(locs);
915 // Marks either the continuation point in unoptimized code or the 942 // Marks either the continuation point in unoptimized code or the
916 // deoptimization point in optimized code, after call. 943 // deoptimization point in optimized code, after call.
917 const intptr_t deopt_id_after = Isolate::ToDeoptAfter(deopt_id); 944 const intptr_t deopt_id_after = Isolate::ToDeoptAfter(deopt_id);
918 if (is_optimizing()) { 945 if (is_optimizing()) {
919 AddDeoptIndexAtCall(deopt_id_after, token_pos); 946 AddDeoptIndexAtCall(deopt_id_after, token_pos);
920 } else { 947 } else {
921 // Add deoptimization continuation point after the call and before the 948 // Add deoptimization continuation point after the call and before the
922 // arguments are removed. 949 // arguments are removed.
923 AddCurrentDescriptor(PcDescriptors::kDeopt, 950 AddCurrentDescriptor(PcDescriptors::kDeopt,
924 deopt_id_after, 951 deopt_id_after,
925 token_pos); 952 token_pos);
926 } 953 }
927 } 954 }
928 955
929 956
930 void FlowGraphCompiler::GenerateCallRuntime(intptr_t token_pos, 957 void FlowGraphCompiler::GenerateCallRuntime(intptr_t token_pos,
931 intptr_t deopt_id, 958 intptr_t deopt_id,
932 const RuntimeEntry& entry, 959 const RuntimeEntry& entry,
933 LocationSummary* locs) { 960 LocationSummary* locs) {
961 __ TraceSimMsg("CallRuntime");
934 __ CallRuntime(entry); 962 __ CallRuntime(entry);
935 AddCurrentDescriptor(PcDescriptors::kOther, deopt_id, token_pos); 963 AddCurrentDescriptor(PcDescriptors::kOther, deopt_id, token_pos);
936 RecordSafepoint(locs); 964 RecordSafepoint(locs);
937 if (deopt_id != Isolate::kNoDeoptId) { 965 if (deopt_id != Isolate::kNoDeoptId) {
938 // Marks either the continuation point in unoptimized code or the 966 // Marks either the continuation point in unoptimized code or the
939 // deoptimization point in optimized code, after call. 967 // deoptimization point in optimized code, after call.
940 const intptr_t deopt_id_after = Isolate::ToDeoptAfter(deopt_id); 968 const intptr_t deopt_id_after = Isolate::ToDeoptAfter(deopt_id);
941 if (is_optimizing()) { 969 if (is_optimizing()) {
942 AddDeoptIndexAtCall(deopt_id_after, token_pos); 970 AddDeoptIndexAtCall(deopt_id_after, token_pos);
943 } else { 971 } else {
944 // Add deoptimization continuation point after the call and before the 972 // Add deoptimization continuation point after the call and before the
945 // arguments are removed. 973 // arguments are removed.
946 AddCurrentDescriptor(PcDescriptors::kDeopt, 974 AddCurrentDescriptor(PcDescriptors::kDeopt,
947 deopt_id_after, 975 deopt_id_after,
948 token_pos); 976 token_pos);
949 } 977 }
950 } 978 }
979 __ TraceSimMsg("CallRuntime return");
951 } 980 }
952 981
953 982
954 void FlowGraphCompiler::EmitOptimizedInstanceCall( 983 void FlowGraphCompiler::EmitOptimizedInstanceCall(
955 ExternalLabel* target_label, 984 ExternalLabel* target_label,
956 const ICData& ic_data, 985 const ICData& ic_data,
957 const Array& arguments_descriptor, 986 const Array& arguments_descriptor,
958 intptr_t argument_count, 987 intptr_t argument_count,
959 intptr_t deopt_id, 988 intptr_t deopt_id,
960 intptr_t token_pos, 989 intptr_t token_pos,
961 LocationSummary* locs) { 990 LocationSummary* locs) {
962 UNIMPLEMENTED(); 991 UNIMPLEMENTED();
963 } 992 }
964 993
965 994
966 void FlowGraphCompiler::EmitInstanceCall(ExternalLabel* target_label, 995 void FlowGraphCompiler::EmitInstanceCall(ExternalLabel* target_label,
967 const ICData& ic_data, 996 const ICData& ic_data,
968 const Array& arguments_descriptor, 997 const Array& arguments_descriptor,
969 intptr_t argument_count, 998 intptr_t argument_count,
970 intptr_t deopt_id, 999 intptr_t deopt_id,
971 intptr_t token_pos, 1000 intptr_t token_pos,
972 LocationSummary* locs) { 1001 LocationSummary* locs) {
1002 __ TraceSimMsg("InstanceCall");
973 __ LoadObject(S4, arguments_descriptor); 1003 __ LoadObject(S4, arguments_descriptor);
974 __ LoadObject(S5, ic_data); 1004 __ LoadObject(S5, ic_data);
975 GenerateDartCall(deopt_id, 1005 GenerateDartCall(deopt_id,
976 token_pos, 1006 token_pos,
977 target_label, 1007 target_label,
978 PcDescriptors::kIcCall, 1008 PcDescriptors::kIcCall,
979 locs); 1009 locs);
1010 __ TraceSimMsg("InstanceCall return");
980 __ Drop(argument_count); 1011 __ Drop(argument_count);
981 } 1012 }
982 1013
983 1014
984 void FlowGraphCompiler::EmitMegamorphicInstanceCall( 1015 void FlowGraphCompiler::EmitMegamorphicInstanceCall(
985 const ICData& ic_data, 1016 const ICData& ic_data,
986 const Array& arguments_descriptor, 1017 const Array& arguments_descriptor,
987 intptr_t argument_count, 1018 intptr_t argument_count,
988 intptr_t deopt_id, 1019 intptr_t deopt_id,
989 intptr_t token_pos, 1020 intptr_t token_pos,
990 LocationSummary* locs) { 1021 LocationSummary* locs) {
991 UNIMPLEMENTED(); 1022 UNIMPLEMENTED();
992 } 1023 }
993 1024
994 1025
995 void FlowGraphCompiler::EmitStaticCall(const Function& function, 1026 void FlowGraphCompiler::EmitStaticCall(const Function& function,
996 const Array& arguments_descriptor, 1027 const Array& arguments_descriptor,
997 intptr_t argument_count, 1028 intptr_t argument_count,
998 intptr_t deopt_id, 1029 intptr_t deopt_id,
999 intptr_t token_pos, 1030 intptr_t token_pos,
1000 LocationSummary* locs) { 1031 LocationSummary* locs) {
1032 __ TraceSimMsg("StaticCall");
1001 __ LoadObject(S4, arguments_descriptor); 1033 __ LoadObject(S4, arguments_descriptor);
1002 // Do not use the code from the function, but let the code be patched so that 1034 // Do not use the code from the function, but let the code be patched so that
1003 // we can record the outgoing edges to other code. 1035 // we can record the outgoing edges to other code.
1004 GenerateDartCall(deopt_id, 1036 GenerateDartCall(deopt_id,
1005 token_pos, 1037 token_pos,
1006 &StubCode::CallStaticFunctionLabel(), 1038 &StubCode::CallStaticFunctionLabel(),
1007 PcDescriptors::kFuncCall, 1039 PcDescriptors::kFuncCall,
1008 locs); 1040 locs);
1009 AddStaticCallTarget(function); 1041 AddStaticCallTarget(function);
1010 __ Drop(argument_count); 1042 __ Drop(argument_count);
1011 } 1043 }
1012 1044
1013 1045
1014 void FlowGraphCompiler::EmitEqualityRegConstCompare(Register reg, 1046 void FlowGraphCompiler::EmitEqualityRegConstCompare(Register reg,
1015 const Object& obj, 1047 const Object& obj,
1016 bool needs_number_check) { 1048 bool needs_number_check) {
1017 UNIMPLEMENTED(); 1049 UNIMPLEMENTED();
1018 } 1050 }
1019 1051
1020 1052
1021 void FlowGraphCompiler::EmitEqualityRegRegCompare(Register left, 1053 void FlowGraphCompiler::EmitEqualityRegRegCompare(Register left,
1022 Register right, 1054 Register right,
1023 bool needs_number_check) { 1055 bool needs_number_check) {
1056 __ TraceSimMsg("EqualityRegRegCompare");
1024 if (needs_number_check) { 1057 if (needs_number_check) {
1025 __ Push(left); 1058 __ Push(left);
1026 __ Push(right); 1059 __ Push(right);
1027 __ BranchLink(&StubCode::IdenticalWithNumberCheckLabel()); 1060 __ BranchLink(&StubCode::IdenticalWithNumberCheckLabel());
1028 // Stub returns result in CMPRES. If it is 0, then left and right are equal. 1061 // Stub returns result in CMPRES. If it is 0, then left and right are equal.
1029 __ Pop(right); 1062 __ Pop(right);
1030 __ Pop(left); 1063 __ Pop(left);
1031 } else { 1064 } else {
1032 __ subu(CMPRES, left, right); 1065 __ subu(CMPRES, left, right);
1033 } 1066 }
1034 } 1067 }
1035 1068
1036 1069
1037 void FlowGraphCompiler::EmitSuperEqualityCallPrologue(Register result, 1070 void FlowGraphCompiler::EmitSuperEqualityCallPrologue(Register result,
1038 Label* skip_call) { 1071 Label* skip_call) {
1039 UNIMPLEMENTED(); 1072 UNIMPLEMENTED();
1040 } 1073 }
1041 1074
1042 1075
1043 void FlowGraphCompiler::SaveLiveRegisters(LocationSummary* locs) { 1076 void FlowGraphCompiler::SaveLiveRegisters(LocationSummary* locs) {
1077 __ TraceSimMsg("SaveLiveRegisters");
1044 // TODO(vegorov): consider saving only caller save (volatile) registers. 1078 // TODO(vegorov): consider saving only caller save (volatile) registers.
1045 const intptr_t fpu_registers = locs->live_registers()->fpu_registers(); 1079 const intptr_t fpu_registers = locs->live_registers()->fpu_registers();
1046 if (fpu_registers > 0) { 1080 if (fpu_registers > 0) {
1047 UNIMPLEMENTED(); 1081 UNIMPLEMENTED();
1048 } 1082 }
1049 1083
1050 // Store general purpose registers with the lowest register number at the 1084 // Store general purpose registers with the lowest register number at the
1051 // lowest address. 1085 // lowest address.
1052 const intptr_t cpu_registers = locs->live_registers()->cpu_registers(); 1086 const intptr_t cpu_registers = locs->live_registers()->cpu_registers();
1053 ASSERT((cpu_registers & ~kAllCpuRegistersList) == 0); 1087 ASSERT((cpu_registers & ~kAllCpuRegistersList) == 0);
1054 const int register_count = Utils::CountOneBits(cpu_registers); 1088 const int register_count = Utils::CountOneBits(cpu_registers);
1055 int registers_pushed = 0; 1089 int registers_pushed = 0;
1056 1090
1057 __ addiu(SP, SP, Immediate(-register_count * kWordSize)); 1091 __ addiu(SP, SP, Immediate(-register_count * kWordSize));
1058 for (int i = 0; i < kNumberOfCpuRegisters; i++) { 1092 for (int i = 0; i < kNumberOfCpuRegisters; i++) {
1059 Register r = static_cast<Register>(i); 1093 Register r = static_cast<Register>(i);
1060 if (locs->live_registers()->ContainsRegister(r)) { 1094 if (locs->live_registers()->ContainsRegister(r)) {
1061 __ sw(r, Address(SP, registers_pushed * kWordSize)); 1095 __ sw(r, Address(SP, registers_pushed * kWordSize));
1062 registers_pushed++; 1096 registers_pushed++;
1063 } 1097 }
1064 } 1098 }
1065 } 1099 }
1066 1100
1067 1101
1068 void FlowGraphCompiler::RestoreLiveRegisters(LocationSummary* locs) { 1102 void FlowGraphCompiler::RestoreLiveRegisters(LocationSummary* locs) {
1069 // General purpose registers have the lowest register number at the 1103 // General purpose registers have the lowest register number at the
1070 // lowest address. 1104 // lowest address.
1105 __ TraceSimMsg("RestoreLiveRegisters");
1071 const intptr_t cpu_registers = locs->live_registers()->cpu_registers(); 1106 const intptr_t cpu_registers = locs->live_registers()->cpu_registers();
1072 ASSERT((cpu_registers & ~kAllCpuRegistersList) == 0); 1107 ASSERT((cpu_registers & ~kAllCpuRegistersList) == 0);
1073 const int register_count = Utils::CountOneBits(cpu_registers); 1108 const int register_count = Utils::CountOneBits(cpu_registers);
1074 int registers_popped = 0; 1109 int registers_popped = 0;
1075 1110
1076 for (int i = 0; i < kNumberOfCpuRegisters; i++) { 1111 for (int i = 0; i < kNumberOfCpuRegisters; i++) {
1077 Register r = static_cast<Register>(i); 1112 Register r = static_cast<Register>(i);
1078 if (locs->live_registers()->ContainsRegister(r)) { 1113 if (locs->live_registers()->ContainsRegister(r)) {
1079 __ lw(r, Address(SP, registers_popped * kWordSize)); 1114 __ lw(r, Address(SP, registers_popped * kWordSize));
1080 registers_popped++; 1115 registers_popped++;
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
1165 UNIMPLEMENTED(); 1200 UNIMPLEMENTED();
1166 return FieldAddress(array, index); 1201 return FieldAddress(array, index);
1167 } 1202 }
1168 1203
1169 1204
1170 #undef __ 1205 #undef __
1171 #define __ compiler_->assembler()-> 1206 #define __ compiler_->assembler()->
1172 1207
1173 1208
1174 void ParallelMoveResolver::EmitMove(int index) { 1209 void ParallelMoveResolver::EmitMove(int index) {
1210 __ TraceSimMsg("ParallelMoveResolver::EmitMove");
1175 MoveOperands* move = moves_[index]; 1211 MoveOperands* move = moves_[index];
1176 const Location source = move->src(); 1212 const Location source = move->src();
1177 const Location destination = move->dest(); 1213 const Location destination = move->dest();
1178 1214
1179 if (source.IsRegister()) { 1215 if (source.IsRegister()) {
1180 if (destination.IsRegister()) { 1216 if (destination.IsRegister()) {
1181 __ mov(destination.reg(), source.reg()); 1217 __ mov(destination.reg(), source.reg());
1182 } else { 1218 } else {
1183 ASSERT(destination.IsStackSlot()); 1219 ASSERT(destination.IsStackSlot());
1184 __ sw(source.reg(), destination.ToStackSlotAddress()); 1220 __ sw(source.reg(), destination.ToStackSlotAddress());
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
1221 ASSERT(destination.IsStackSlot()); 1257 ASSERT(destination.IsStackSlot());
1222 StoreObject(destination.ToStackSlotAddress(), source.constant()); 1258 StoreObject(destination.ToStackSlotAddress(), source.constant());
1223 } 1259 }
1224 } 1260 }
1225 1261
1226 move->Eliminate(); 1262 move->Eliminate();
1227 } 1263 }
1228 1264
1229 1265
1230 void ParallelMoveResolver::EmitSwap(int index) { 1266 void ParallelMoveResolver::EmitSwap(int index) {
1267 __ TraceSimMsg("ParallelMoveResolver::EmitSwap");
1231 MoveOperands* move = moves_[index]; 1268 MoveOperands* move = moves_[index];
1232 const Location source = move->src(); 1269 const Location source = move->src();
1233 const Location destination = move->dest(); 1270 const Location destination = move->dest();
1234 1271
1235 if (source.IsRegister() && destination.IsRegister()) { 1272 if (source.IsRegister() && destination.IsRegister()) {
1236 ASSERT(source.reg() != TMP1); 1273 ASSERT(source.reg() != TMP1);
1237 ASSERT(destination.reg() != TMP1); 1274 ASSERT(destination.reg() != TMP1);
1238 __ mov(TMP1, source.reg()); 1275 __ mov(TMP1, source.reg());
1239 __ mov(source.reg(), destination.reg()); 1276 __ mov(source.reg(), destination.reg());
1240 __ mov(destination.reg(), TMP1); 1277 __ mov(destination.reg(), TMP1);
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
1296 moves_[i]->set_src(destination); 1333 moves_[i]->set_src(destination);
1297 } else if (other_move.Blocks(destination)) { 1334 } else if (other_move.Blocks(destination)) {
1298 moves_[i]->set_src(source); 1335 moves_[i]->set_src(source);
1299 } 1336 }
1300 } 1337 }
1301 } 1338 }
1302 1339
1303 1340
1304 void ParallelMoveResolver::MoveMemoryToMemory(const Address& dst, 1341 void ParallelMoveResolver::MoveMemoryToMemory(const Address& dst,
1305 const Address& src) { 1342 const Address& src) {
1343 __ TraceSimMsg("ParallelMoveResolver::MoveMemoryToMemory");
1306 __ lw(TMP1, src); 1344 __ lw(TMP1, src);
1307 __ sw(TMP1, dst); 1345 __ sw(TMP1, dst);
1308 } 1346 }
1309 1347
1310 1348
1311 void ParallelMoveResolver::StoreObject(const Address& dst, const Object& obj) { 1349 void ParallelMoveResolver::StoreObject(const Address& dst, const Object& obj) {
1350 __ TraceSimMsg("ParallelMoveResolver::StoreObject");
1312 __ LoadObject(TMP1, obj); 1351 __ LoadObject(TMP1, obj);
1313 __ sw(TMP1, dst); 1352 __ sw(TMP1, dst);
1314 } 1353 }
1315 1354
1316 1355
1317 void ParallelMoveResolver::Exchange(Register reg, const Address& mem) { 1356 void ParallelMoveResolver::Exchange(Register reg, const Address& mem) {
1357 __ TraceSimMsg("ParallelMoveResolver::Exchange ra");
1318 ASSERT(reg != TMP1); 1358 ASSERT(reg != TMP1);
1319 __ mov(TMP1, reg); 1359 __ mov(TMP1, reg);
1320 __ lw(reg, mem); 1360 __ lw(reg, mem);
1321 __ sw(TMP1, mem); 1361 __ sw(TMP1, mem);
1322 } 1362 }
1323 1363
1324 1364
1325 void ParallelMoveResolver::Exchange(const Address& mem1, const Address& mem2) { 1365 void ParallelMoveResolver::Exchange(const Address& mem1, const Address& mem2) {
1366 __ TraceSimMsg("ParallelMoveResolver::Exchange aa");
1326 ScratchRegisterScope ensure_scratch(this, TMP1); 1367 ScratchRegisterScope ensure_scratch(this, TMP1);
1327 __ lw(ensure_scratch.reg(), mem1); 1368 __ lw(ensure_scratch.reg(), mem1);
1328 __ lw(TMP1, mem2); 1369 __ lw(TMP1, mem2);
1329 __ sw(ensure_scratch.reg(), mem2); 1370 __ sw(ensure_scratch.reg(), mem2);
1330 __ sw(TMP1, mem1); 1371 __ sw(TMP1, mem1);
1331 } 1372 }
1332 1373
1333 1374
1334 void ParallelMoveResolver::SpillScratch(Register reg) { 1375 void ParallelMoveResolver::SpillScratch(Register reg) {
1376 __ TraceSimMsg("ParallelMoveResolver::SpillScratch");
1335 __ Push(reg); 1377 __ Push(reg);
1336 } 1378 }
1337 1379
1338 1380
1339 void ParallelMoveResolver::RestoreScratch(Register reg) { 1381 void ParallelMoveResolver::RestoreScratch(Register reg) {
1382 __ TraceSimMsg("ParallelMoveResolver::RestoreScratch");
1340 __ Pop(reg); 1383 __ Pop(reg);
1341 } 1384 }
1342 1385
1343 1386
1344 void ParallelMoveResolver::SpillFpuScratch(FpuRegister reg) { 1387 void ParallelMoveResolver::SpillFpuScratch(FpuRegister reg) {
1388 __ TraceSimMsg("ParallelMoveResolver::SpillFpuScratch");
1345 __ AddImmediate(SP, -kDoubleSize); 1389 __ AddImmediate(SP, -kDoubleSize);
1346 __ sdc1(reg, Address(SP)); 1390 __ sdc1(reg, Address(SP));
1347 } 1391 }
1348 1392
1349 1393
1350 void ParallelMoveResolver::RestoreFpuScratch(FpuRegister reg) { 1394 void ParallelMoveResolver::RestoreFpuScratch(FpuRegister reg) {
1395 __ TraceSimMsg("ParallelMoveResolver::RestoreFpuScratch");
1351 __ ldc1(reg, Address(SP)); 1396 __ ldc1(reg, Address(SP));
1352 __ AddImmediate(SP, kDoubleSize); 1397 __ AddImmediate(SP, kDoubleSize);
1353 } 1398 }
1354 1399
1355 1400
1356 #undef __ 1401 #undef __
1357 1402
1358 1403
1359 } // namespace dart 1404 } // namespace dart
1360 1405
1361 #endif // defined TARGET_ARCH_MIPS 1406 #endif // defined TARGET_ARCH_MIPS
OLDNEW
« no previous file with comments | « runtime/vm/disassembler_mips.cc ('k') | runtime/vm/intermediate_language_mips.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698