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

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

Issue 2974233002: VM: Re-format to use at most one newline between functions (Closed)
Patch Set: Rebase and merge Created 3 years, 5 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
« no previous file with comments | « runtime/vm/flow_graph_compiler_arm.cc ('k') | runtime/vm/flow_graph_compiler_dbc.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) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, 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_ARM64. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM64.
6 #if defined(TARGET_ARCH_ARM64) 6 #if defined(TARGET_ARCH_ARM64)
7 7
8 #include "vm/flow_graph_compiler.h" 8 #include "vm/flow_graph_compiler.h"
9 9
10 #include "vm/ast_printer.h" 10 #include "vm/ast_printer.h"
11 #include "vm/compiler.h" 11 #include "vm/compiler.h"
12 #include "vm/cpu.h" 12 #include "vm/cpu.h"
13 #include "vm/dart_entry.h" 13 #include "vm/dart_entry.h"
14 #include "vm/deopt_instructions.h" 14 #include "vm/deopt_instructions.h"
15 #include "vm/il_printer.h" 15 #include "vm/il_printer.h"
16 #include "vm/instructions.h" 16 #include "vm/instructions.h"
17 #include "vm/locations.h" 17 #include "vm/locations.h"
18 #include "vm/object_store.h" 18 #include "vm/object_store.h"
19 #include "vm/parser.h" 19 #include "vm/parser.h"
20 #include "vm/stack_frame.h" 20 #include "vm/stack_frame.h"
21 #include "vm/stub_code.h" 21 #include "vm/stub_code.h"
22 #include "vm/symbols.h" 22 #include "vm/symbols.h"
23 23
24 namespace dart { 24 namespace dart {
25 25
26 DEFINE_FLAG(bool, trap_on_deoptimization, false, "Trap on deoptimization."); 26 DEFINE_FLAG(bool, trap_on_deoptimization, false, "Trap on deoptimization.");
27 DECLARE_FLAG(bool, enable_simd_inline); 27 DECLARE_FLAG(bool, enable_simd_inline);
28 28
29
30 FlowGraphCompiler::~FlowGraphCompiler() { 29 FlowGraphCompiler::~FlowGraphCompiler() {
31 // BlockInfos are zone-allocated, so their destructors are not called. 30 // BlockInfos are zone-allocated, so their destructors are not called.
32 // Verify the labels explicitly here. 31 // Verify the labels explicitly here.
33 for (int i = 0; i < block_info_.length(); ++i) { 32 for (int i = 0; i < block_info_.length(); ++i) {
34 ASSERT(!block_info_[i]->jump_label()->IsLinked()); 33 ASSERT(!block_info_[i]->jump_label()->IsLinked());
35 } 34 }
36 } 35 }
37 36
38
39 bool FlowGraphCompiler::SupportsUnboxedDoubles() { 37 bool FlowGraphCompiler::SupportsUnboxedDoubles() {
40 return true; 38 return true;
41 } 39 }
42 40
43
44 bool FlowGraphCompiler::SupportsUnboxedMints() { 41 bool FlowGraphCompiler::SupportsUnboxedMints() {
45 return false; 42 return false;
46 } 43 }
47 44
48
49 bool FlowGraphCompiler::SupportsUnboxedSimd128() { 45 bool FlowGraphCompiler::SupportsUnboxedSimd128() {
50 return FLAG_enable_simd_inline; 46 return FLAG_enable_simd_inline;
51 } 47 }
52 48
53
54 bool FlowGraphCompiler::CanConvertUnboxedMintToDouble() { 49 bool FlowGraphCompiler::CanConvertUnboxedMintToDouble() {
55 // ARM does not have a short instruction sequence for converting int64 to 50 // ARM does not have a short instruction sequence for converting int64 to
56 // double. 51 // double.
57 return false; 52 return false;
58 } 53 }
59 54
60
61 bool FlowGraphCompiler::SupportsHardwareDivision() { 55 bool FlowGraphCompiler::SupportsHardwareDivision() {
62 return true; 56 return true;
63 } 57 }
64 58
65
66 void FlowGraphCompiler::EnterIntrinsicMode() { 59 void FlowGraphCompiler::EnterIntrinsicMode() {
67 ASSERT(!intrinsic_mode()); 60 ASSERT(!intrinsic_mode());
68 intrinsic_mode_ = true; 61 intrinsic_mode_ = true;
69 ASSERT(!assembler()->constant_pool_allowed()); 62 ASSERT(!assembler()->constant_pool_allowed());
70 } 63 }
71 64
72
73 void FlowGraphCompiler::ExitIntrinsicMode() { 65 void FlowGraphCompiler::ExitIntrinsicMode() {
74 ASSERT(intrinsic_mode()); 66 ASSERT(intrinsic_mode());
75 intrinsic_mode_ = false; 67 intrinsic_mode_ = false;
76 } 68 }
77 69
78
79 RawTypedData* CompilerDeoptInfo::CreateDeoptInfo(FlowGraphCompiler* compiler, 70 RawTypedData* CompilerDeoptInfo::CreateDeoptInfo(FlowGraphCompiler* compiler,
80 DeoptInfoBuilder* builder, 71 DeoptInfoBuilder* builder,
81 const Array& deopt_table) { 72 const Array& deopt_table) {
82 if (deopt_env_ == NULL) { 73 if (deopt_env_ == NULL) {
83 ++builder->current_info_number_; 74 ++builder->current_info_number_;
84 return TypedData::null(); 75 return TypedData::null();
85 } 76 }
86 77
87 intptr_t stack_height = compiler->StackSize(); 78 intptr_t stack_height = compiler->StackSize();
88 AllocateIncomingParametersRecursive(deopt_env_, &stack_height); 79 AllocateIncomingParametersRecursive(deopt_env_, &stack_height);
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
155 builder->AddCallerPc(slot_ix++); 146 builder->AddCallerPc(slot_ix++);
156 147
157 // For the outermost environment, set the incoming arguments. 148 // For the outermost environment, set the incoming arguments.
158 for (intptr_t i = previous->fixed_parameter_count() - 1; i >= 0; i--) { 149 for (intptr_t i = previous->fixed_parameter_count() - 1; i >= 0; i--) {
159 builder->AddCopy(previous->ValueAt(i), previous->LocationAt(i), slot_ix++); 150 builder->AddCopy(previous->ValueAt(i), previous->LocationAt(i), slot_ix++);
160 } 151 }
161 152
162 return builder->CreateDeoptInfo(deopt_table); 153 return builder->CreateDeoptInfo(deopt_table);
163 } 154 }
164 155
165
166 void CompilerDeoptInfoWithStub::GenerateCode(FlowGraphCompiler* compiler, 156 void CompilerDeoptInfoWithStub::GenerateCode(FlowGraphCompiler* compiler,
167 intptr_t stub_ix) { 157 intptr_t stub_ix) {
168 // Calls do not need stubs, they share a deoptimization trampoline. 158 // Calls do not need stubs, they share a deoptimization trampoline.
169 ASSERT(reason() != ICData::kDeoptAtCall); 159 ASSERT(reason() != ICData::kDeoptAtCall);
170 Assembler* assembler = compiler->assembler(); 160 Assembler* assembler = compiler->assembler();
171 #define __ assembler-> 161 #define __ assembler->
172 __ Comment("%s", Name()); 162 __ Comment("%s", Name());
173 __ Bind(entry_label()); 163 __ Bind(entry_label());
174 if (FLAG_trap_on_deoptimization) { 164 if (FLAG_trap_on_deoptimization) {
175 __ brk(0); 165 __ brk(0);
176 } 166 }
177 167
178 ASSERT(deopt_env() != NULL); 168 ASSERT(deopt_env() != NULL);
179 __ Push(CODE_REG); 169 __ Push(CODE_REG);
180 __ BranchLink(*StubCode::Deoptimize_entry()); 170 __ BranchLink(*StubCode::Deoptimize_entry());
181 set_pc_offset(assembler->CodeSize()); 171 set_pc_offset(assembler->CodeSize());
182 #undef __ 172 #undef __
183 } 173 }
184 174
185
186 #define __ assembler()-> 175 #define __ assembler()->
187 176
188
189 // Fall through if bool_register contains null. 177 // Fall through if bool_register contains null.
190 void FlowGraphCompiler::GenerateBoolToJump(Register bool_register, 178 void FlowGraphCompiler::GenerateBoolToJump(Register bool_register,
191 Label* is_true, 179 Label* is_true,
192 Label* is_false) { 180 Label* is_false) {
193 Label fall_through; 181 Label fall_through;
194 __ CompareObject(bool_register, Object::null_object()); 182 __ CompareObject(bool_register, Object::null_object());
195 __ b(&fall_through, EQ); 183 __ b(&fall_through, EQ);
196 __ CompareObject(bool_register, Bool::True()); 184 __ CompareObject(bool_register, Bool::True());
197 __ b(is_true, EQ); 185 __ b(is_true, EQ);
198 __ b(is_false); 186 __ b(is_false);
199 __ Bind(&fall_through); 187 __ Bind(&fall_through);
200 } 188 }
201 189
202
203 // R0: instance (must be preserved). 190 // R0: instance (must be preserved).
204 // R1: instantiator type arguments (if used). 191 // R1: instantiator type arguments (if used).
205 // R2: function type arguments (if used). 192 // R2: function type arguments (if used).
206 RawSubtypeTestCache* FlowGraphCompiler::GenerateCallSubtypeTestStub( 193 RawSubtypeTestCache* FlowGraphCompiler::GenerateCallSubtypeTestStub(
207 TypeTestStubKind test_kind, 194 TypeTestStubKind test_kind,
208 Register instance_reg, 195 Register instance_reg,
209 Register instantiator_type_arguments_reg, 196 Register instantiator_type_arguments_reg,
210 Register function_type_arguments_reg, 197 Register function_type_arguments_reg,
211 Register temp_reg, 198 Register temp_reg,
212 Label* is_instance_lbl, 199 Label* is_instance_lbl,
(...skipping 16 matching lines...) Expand all
229 ASSERT(function_type_arguments_reg == R2); 216 ASSERT(function_type_arguments_reg == R2);
230 __ BranchLink(*StubCode::Subtype4TestCache_entry()); 217 __ BranchLink(*StubCode::Subtype4TestCache_entry());
231 } else { 218 } else {
232 UNREACHABLE(); 219 UNREACHABLE();
233 } 220 }
234 // Result is in R1: null -> not found, otherwise Bool::True or Bool::False. 221 // Result is in R1: null -> not found, otherwise Bool::True or Bool::False.
235 GenerateBoolToJump(R1, is_instance_lbl, is_not_instance_lbl); 222 GenerateBoolToJump(R1, is_instance_lbl, is_not_instance_lbl);
236 return type_test_cache.raw(); 223 return type_test_cache.raw();
237 } 224 }
238 225
239
240 // Jumps to labels 'is_instance' or 'is_not_instance' respectively, if 226 // Jumps to labels 'is_instance' or 'is_not_instance' respectively, if
241 // type test is conclusive, otherwise fallthrough if a type test could not 227 // type test is conclusive, otherwise fallthrough if a type test could not
242 // be completed. 228 // be completed.
243 // R0: instance being type checked (preserved). 229 // R0: instance being type checked (preserved).
244 // Clobbers R1, R2. 230 // Clobbers R1, R2.
245 RawSubtypeTestCache* 231 RawSubtypeTestCache*
246 FlowGraphCompiler::GenerateInstantiatedTypeWithArgumentsTest( 232 FlowGraphCompiler::GenerateInstantiatedTypeWithArgumentsTest(
247 TokenPosition token_pos, 233 TokenPosition token_pos,
248 const AbstractType& type, 234 const AbstractType& type,
249 Label* is_instance_lbl, 235 Label* is_instance_lbl,
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
308 const Register kInstantiatorTypeArgumentsReg = kNoRegister; 294 const Register kInstantiatorTypeArgumentsReg = kNoRegister;
309 const Register kFunctionTypeArgumentsReg = kNoRegister; 295 const Register kFunctionTypeArgumentsReg = kNoRegister;
310 const Register kTempReg = kNoRegister; 296 const Register kTempReg = kNoRegister;
311 // R0: instance (must be preserved). 297 // R0: instance (must be preserved).
312 return GenerateCallSubtypeTestStub(kTestTypeTwoArgs, kInstanceReg, 298 return GenerateCallSubtypeTestStub(kTestTypeTwoArgs, kInstanceReg,
313 kInstantiatorTypeArgumentsReg, 299 kInstantiatorTypeArgumentsReg,
314 kFunctionTypeArgumentsReg, kTempReg, 300 kFunctionTypeArgumentsReg, kTempReg,
315 is_instance_lbl, is_not_instance_lbl); 301 is_instance_lbl, is_not_instance_lbl);
316 } 302 }
317 303
318
319 void FlowGraphCompiler::CheckClassIds(Register class_id_reg, 304 void FlowGraphCompiler::CheckClassIds(Register class_id_reg,
320 const GrowableArray<intptr_t>& class_ids, 305 const GrowableArray<intptr_t>& class_ids,
321 Label* is_equal_lbl, 306 Label* is_equal_lbl,
322 Label* is_not_equal_lbl) { 307 Label* is_not_equal_lbl) {
323 for (intptr_t i = 0; i < class_ids.length(); i++) { 308 for (intptr_t i = 0; i < class_ids.length(); i++) {
324 __ CompareImmediate(class_id_reg, class_ids[i]); 309 __ CompareImmediate(class_id_reg, class_ids[i]);
325 __ b(is_equal_lbl, EQ); 310 __ b(is_equal_lbl, EQ);
326 } 311 }
327 __ b(is_not_equal_lbl); 312 __ b(is_not_equal_lbl);
328 } 313 }
329 314
330
331 // Testing against an instantiated type with no arguments, without 315 // Testing against an instantiated type with no arguments, without
332 // SubtypeTestCache. 316 // SubtypeTestCache.
333 // R0: instance being type checked (preserved). 317 // R0: instance being type checked (preserved).
334 // Clobbers R2, R3. 318 // Clobbers R2, R3.
335 // Returns true if there is a fallthrough. 319 // Returns true if there is a fallthrough.
336 bool FlowGraphCompiler::GenerateInstantiatedTypeNoArgumentsTest( 320 bool FlowGraphCompiler::GenerateInstantiatedTypeNoArgumentsTest(
337 TokenPosition token_pos, 321 TokenPosition token_pos,
338 const AbstractType& type, 322 const AbstractType& type,
339 Label* is_instance_lbl, 323 Label* is_instance_lbl,
340 Label* is_not_instance_lbl) { 324 Label* is_not_instance_lbl) {
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
388 } 372 }
389 // Compare if the classes are equal. 373 // Compare if the classes are equal.
390 if (!type_class.is_abstract()) { 374 if (!type_class.is_abstract()) {
391 __ CompareImmediate(kClassIdReg, type_class.id()); 375 __ CompareImmediate(kClassIdReg, type_class.id());
392 __ b(is_instance_lbl, EQ); 376 __ b(is_instance_lbl, EQ);
393 } 377 }
394 // Otherwise fallthrough. 378 // Otherwise fallthrough.
395 return true; 379 return true;
396 } 380 }
397 381
398
399 // Uses SubtypeTestCache to store instance class and result. 382 // Uses SubtypeTestCache to store instance class and result.
400 // R0: instance to test. 383 // R0: instance to test.
401 // Clobbers R1-R5. 384 // Clobbers R1-R5.
402 // Immediate class test already done. 385 // Immediate class test already done.
403 // TODO(srdjan): Implement a quicker subtype check, as type test 386 // TODO(srdjan): Implement a quicker subtype check, as type test
404 // arrays can grow too high, but they may be useful when optimizing 387 // arrays can grow too high, but they may be useful when optimizing
405 // code (type-feedback). 388 // code (type-feedback).
406 RawSubtypeTestCache* FlowGraphCompiler::GenerateSubtype1TestCacheLookup( 389 RawSubtypeTestCache* FlowGraphCompiler::GenerateSubtype1TestCacheLookup(
407 TokenPosition token_pos, 390 TokenPosition token_pos,
408 const Class& type_class, 391 const Class& type_class,
(...skipping 11 matching lines...) Expand all
420 403
421 const Register kInstantiatorTypeArgumentsReg = kNoRegister; 404 const Register kInstantiatorTypeArgumentsReg = kNoRegister;
422 const Register kFunctionTypeArgumentsReg = kNoRegister; 405 const Register kFunctionTypeArgumentsReg = kNoRegister;
423 const Register kTempReg = kNoRegister; 406 const Register kTempReg = kNoRegister;
424 return GenerateCallSubtypeTestStub(kTestTypeOneArg, kInstanceReg, 407 return GenerateCallSubtypeTestStub(kTestTypeOneArg, kInstanceReg,
425 kInstantiatorTypeArgumentsReg, 408 kInstantiatorTypeArgumentsReg,
426 kFunctionTypeArgumentsReg, kTempReg, 409 kFunctionTypeArgumentsReg, kTempReg,
427 is_instance_lbl, is_not_instance_lbl); 410 is_instance_lbl, is_not_instance_lbl);
428 } 411 }
429 412
430
431 // Generates inlined check if 'type' is a type parameter or type itself 413 // Generates inlined check if 'type' is a type parameter or type itself
432 // R0: instance (preserved). 414 // R0: instance (preserved).
433 RawSubtypeTestCache* FlowGraphCompiler::GenerateUninstantiatedTypeTest( 415 RawSubtypeTestCache* FlowGraphCompiler::GenerateUninstantiatedTypeTest(
434 TokenPosition token_pos, 416 TokenPosition token_pos,
435 const AbstractType& type, 417 const AbstractType& type,
436 Label* is_instance_lbl, 418 Label* is_instance_lbl,
437 Label* is_not_instance_lbl) { 419 Label* is_not_instance_lbl) {
438 __ Comment("UninstantiatedTypeTest"); 420 __ Comment("UninstantiatedTypeTest");
439 ASSERT(!type.IsInstantiated()); 421 ASSERT(!type.IsInstantiated());
440 // Skip check if destination is a dynamic type. 422 // Skip check if destination is a dynamic type.
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
499 // arguments are determined at runtime by the instantiator. 481 // arguments are determined at runtime by the instantiator.
500 const Register kTempReg = kNoRegister; 482 const Register kTempReg = kNoRegister;
501 return GenerateCallSubtypeTestStub(kTestTypeFourArgs, kInstanceReg, 483 return GenerateCallSubtypeTestStub(kTestTypeFourArgs, kInstanceReg,
502 kInstantiatorTypeArgumentsReg, 484 kInstantiatorTypeArgumentsReg,
503 kFunctionTypeArgumentsReg, kTempReg, 485 kFunctionTypeArgumentsReg, kTempReg,
504 is_instance_lbl, is_not_instance_lbl); 486 is_instance_lbl, is_not_instance_lbl);
505 } 487 }
506 return SubtypeTestCache::null(); 488 return SubtypeTestCache::null();
507 } 489 }
508 490
509
510 // Inputs: 491 // Inputs:
511 // - R0: instance being type checked (preserved). 492 // - R0: instance being type checked (preserved).
512 // - R1: optional instantiator type arguments (preserved). 493 // - R1: optional instantiator type arguments (preserved).
513 // - R2: optional function type arguments (preserved). 494 // - R2: optional function type arguments (preserved).
514 // Clobbers R3, R4, R8, R9. 495 // Clobbers R3, R4, R8, R9.
515 // Returns: 496 // Returns:
516 // - preserved instance in R0, optional instantiator type arguments in R1, and 497 // - preserved instance in R0, optional instantiator type arguments in R1, and
517 // optional function type arguments in R2. 498 // optional function type arguments in R2.
518 // Note that this inlined code must be followed by the runtime_call code, as it 499 // Note that this inlined code must be followed by the runtime_call code, as it
519 // may fall through to it. Otherwise, this inline code will jump to the label 500 // may fall through to it. Otherwise, this inline code will jump to the label
(...skipping 22 matching lines...) Expand all
542 return GenerateSubtype1TestCacheLookup( 523 return GenerateSubtype1TestCacheLookup(
543 token_pos, type_class, is_instance_lbl, is_not_instance_lbl); 524 token_pos, type_class, is_instance_lbl, is_not_instance_lbl);
544 } else { 525 } else {
545 return SubtypeTestCache::null(); 526 return SubtypeTestCache::null();
546 } 527 }
547 } 528 }
548 return GenerateUninstantiatedTypeTest(token_pos, type, is_instance_lbl, 529 return GenerateUninstantiatedTypeTest(token_pos, type, is_instance_lbl,
549 is_not_instance_lbl); 530 is_not_instance_lbl);
550 } 531 }
551 532
552
553 // If instanceof type test cannot be performed successfully at compile time and 533 // If instanceof type test cannot be performed successfully at compile time and
554 // therefore eliminated, optimize it by adding inlined tests for: 534 // therefore eliminated, optimize it by adding inlined tests for:
555 // - NULL -> return type == Null (type is not Object or dynamic). 535 // - NULL -> return type == Null (type is not Object or dynamic).
556 // - Smi -> compile time subtype check (only if dst class is not parameterized). 536 // - Smi -> compile time subtype check (only if dst class is not parameterized).
557 // - Class equality (only if class is not parameterized). 537 // - Class equality (only if class is not parameterized).
558 // Inputs: 538 // Inputs:
559 // - R0: object. 539 // - R0: object.
560 // - R1: instantiator type arguments or raw_null. 540 // - R1: instantiator type arguments or raw_null.
561 // - R2: function type arguments or raw_null. 541 // - R2: function type arguments or raw_null.
562 // Returns: 542 // Returns:
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
615 __ LoadObject(R0, Bool::Get(false)); 595 __ LoadObject(R0, Bool::Get(false));
616 __ b(&done); 596 __ b(&done);
617 597
618 __ Bind(&is_instance); 598 __ Bind(&is_instance);
619 __ LoadObject(R0, Bool::Get(true)); 599 __ LoadObject(R0, Bool::Get(true));
620 __ Bind(&done); 600 __ Bind(&done);
621 // Remove instantiator type arguments and function type arguments. 601 // Remove instantiator type arguments and function type arguments.
622 __ Drop(2); 602 __ Drop(2);
623 } 603 }
624 604
625
626 // Optimize assignable type check by adding inlined tests for: 605 // Optimize assignable type check by adding inlined tests for:
627 // - NULL -> return NULL. 606 // - NULL -> return NULL.
628 // - Smi -> compile time subtype check (only if dst class is not parameterized). 607 // - Smi -> compile time subtype check (only if dst class is not parameterized).
629 // - Class equality (only if class is not parameterized). 608 // - Class equality (only if class is not parameterized).
630 // Inputs: 609 // Inputs:
631 // - R0: instance being type checked. 610 // - R0: instance being type checked.
632 // - R1: instantiator type arguments or raw_null. 611 // - R1: instantiator type arguments or raw_null.
633 // - R2: function type arguments or raw_null. 612 // - R2: function type arguments or raw_null.
634 // Returns: 613 // Returns:
635 // - object in R0 for successful assignable check (or throws TypeError). 614 // - object in R0 for successful assignable check (or throws TypeError).
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
689 GenerateRuntimeCall(token_pos, deopt_id, kTypeCheckRuntimeEntry, 6, locs); 668 GenerateRuntimeCall(token_pos, deopt_id, kTypeCheckRuntimeEntry, 6, locs);
690 // Pop the parameters supplied to the runtime entry. The result of the 669 // Pop the parameters supplied to the runtime entry. The result of the
691 // type check runtime call is the checked value. 670 // type check runtime call is the checked value.
692 __ Drop(6); 671 __ Drop(6);
693 __ Pop(R0); 672 __ Pop(R0);
694 673
695 __ Bind(&is_assignable); 674 __ Bind(&is_assignable);
696 __ PopPair(kFunctionTypeArgumentsReg, kInstantiatorTypeArgumentsReg); 675 __ PopPair(kFunctionTypeArgumentsReg, kInstantiatorTypeArgumentsReg);
697 } 676 }
698 677
699
700 void FlowGraphCompiler::EmitInstructionEpilogue(Instruction* instr) { 678 void FlowGraphCompiler::EmitInstructionEpilogue(Instruction* instr) {
701 if (is_optimizing()) { 679 if (is_optimizing()) {
702 return; 680 return;
703 } 681 }
704 Definition* defn = instr->AsDefinition(); 682 Definition* defn = instr->AsDefinition();
705 if ((defn != NULL) && defn->HasTemp()) { 683 if ((defn != NULL) && defn->HasTemp()) {
706 __ Push(defn->locs()->out(0).reg()); 684 __ Push(defn->locs()->out(0).reg());
707 } 685 }
708 } 686 }
709 687
710
711 // Input parameters: 688 // Input parameters:
712 // R4: arguments descriptor array. 689 // R4: arguments descriptor array.
713 void FlowGraphCompiler::CopyParameters() { 690 void FlowGraphCompiler::CopyParameters() {
714 __ Comment("Copy parameters"); 691 __ Comment("Copy parameters");
715 const Function& function = parsed_function().function(); 692 const Function& function = parsed_function().function();
716 LocalScope* scope = parsed_function().node_sequence()->scope(); 693 LocalScope* scope = parsed_function().node_sequence()->scope();
717 const int num_fixed_params = function.num_fixed_parameters(); 694 const int num_fixed_params = function.num_fixed_parameters();
718 const int num_opt_pos_params = function.NumOptionalPositionalParameters(); 695 const int num_opt_pos_params = function.NumOptionalPositionalParameters();
719 const int num_opt_named_params = function.NumOptionalNamedParameters(); 696 const int num_opt_named_params = function.NumOptionalNamedParameters();
720 const int num_params = 697 const int num_params =
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
794 opt_param[i + 1] = parameter; 771 opt_param[i + 1] = parameter;
795 opt_param_position[i + 1] = pos; 772 opt_param_position[i + 1] = pos;
796 } 773 }
797 // Generate code handling each optional parameter in alphabetical order. 774 // Generate code handling each optional parameter in alphabetical order.
798 __ LoadFieldFromOffset(R7, R4, ArgumentsDescriptor::count_offset()); 775 __ LoadFieldFromOffset(R7, R4, ArgumentsDescriptor::count_offset());
799 // Let R7 point to the first passed argument, i.e. to 776 // Let R7 point to the first passed argument, i.e. to
800 // fp[kParamEndSlotFromFp + num_args - 0]; num_args (R7) is Smi. 777 // fp[kParamEndSlotFromFp + num_args - 0]; num_args (R7) is Smi.
801 __ add(R7, FP, Operand(R7, LSL, 2)); 778 __ add(R7, FP, Operand(R7, LSL, 2));
802 __ AddImmediate(R7, kParamEndSlotFromFp * kWordSize); 779 __ AddImmediate(R7, kParamEndSlotFromFp * kWordSize);
803 // Let R6 point to the entry of the first named argument. 780 // Let R6 point to the entry of the first named argument.
804 __ add(R6, R4, Operand(ArgumentsDescriptor::first_named_entry_offset() - 781 __ add(R6, R4,
805 kHeapObjectTag)); 782 Operand(ArgumentsDescriptor::first_named_entry_offset() -
783 kHeapObjectTag));
806 for (int i = 0; i < num_opt_named_params; i++) { 784 for (int i = 0; i < num_opt_named_params; i++) {
807 Label load_default_value, assign_optional_parameter; 785 Label load_default_value, assign_optional_parameter;
808 const int param_pos = opt_param_position[i]; 786 const int param_pos = opt_param_position[i];
809 // Check if this named parameter was passed in. 787 // Check if this named parameter was passed in.
810 // Load R5 with the name of the argument. 788 // Load R5 with the name of the argument.
811 __ LoadFromOffset(R5, R6, ArgumentsDescriptor::name_offset()); 789 __ LoadFromOffset(R5, R6, ArgumentsDescriptor::name_offset());
812 ASSERT(opt_param[i]->name().IsSymbol()); 790 ASSERT(opt_param[i]->name().IsSymbol());
813 __ CompareObject(R5, opt_param[i]->name()); 791 __ CompareObject(R5, opt_param[i]->name());
814 __ b(&load_default_value, NE); 792 __ b(&load_default_value, NE);
815 // Load R5 with passed-in argument at provided arg_pos, i.e. at 793 // Load R5 with passed-in argument at provided arg_pos, i.e. at
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
902 __ LoadObject(TMP, Object::null_object()); 880 __ LoadObject(TMP, Object::null_object());
903 Label null_args_loop, null_args_loop_condition; 881 Label null_args_loop, null_args_loop_condition;
904 __ b(&null_args_loop_condition); 882 __ b(&null_args_loop_condition);
905 __ Bind(&null_args_loop); 883 __ Bind(&null_args_loop);
906 __ str(TMP, original_argument_addr); 884 __ str(TMP, original_argument_addr);
907 __ Bind(&null_args_loop_condition); 885 __ Bind(&null_args_loop_condition);
908 __ subs(R8, R8, Operand(1)); 886 __ subs(R8, R8, Operand(1));
909 __ b(&null_args_loop, PL); 887 __ b(&null_args_loop, PL);
910 } 888 }
911 889
912
913 void FlowGraphCompiler::GenerateInlinedGetter(intptr_t offset) { 890 void FlowGraphCompiler::GenerateInlinedGetter(intptr_t offset) {
914 // LR: return address. 891 // LR: return address.
915 // SP: receiver. 892 // SP: receiver.
916 // Sequence node has one return node, its input is load field node. 893 // Sequence node has one return node, its input is load field node.
917 __ Comment("Inlined Getter"); 894 __ Comment("Inlined Getter");
918 __ LoadFromOffset(R0, SP, 0 * kWordSize); 895 __ LoadFromOffset(R0, SP, 0 * kWordSize);
919 __ LoadFieldFromOffset(R0, R0, offset); 896 __ LoadFieldFromOffset(R0, R0, offset);
920 __ ret(); 897 __ ret();
921 } 898 }
922 899
923
924 void FlowGraphCompiler::GenerateInlinedSetter(intptr_t offset) { 900 void FlowGraphCompiler::GenerateInlinedSetter(intptr_t offset) {
925 // LR: return address. 901 // LR: return address.
926 // SP+1: receiver. 902 // SP+1: receiver.
927 // SP+0: value. 903 // SP+0: value.
928 // Sequence node has one store node and one return NULL node. 904 // Sequence node has one store node and one return NULL node.
929 __ Comment("Inlined Setter"); 905 __ Comment("Inlined Setter");
930 __ LoadFromOffset(R0, SP, 1 * kWordSize); // Receiver. 906 __ LoadFromOffset(R0, SP, 1 * kWordSize); // Receiver.
931 __ LoadFromOffset(R1, SP, 0 * kWordSize); // Value. 907 __ LoadFromOffset(R1, SP, 0 * kWordSize); // Value.
932 __ StoreIntoObjectOffset(R0, offset, R1); 908 __ StoreIntoObjectOffset(R0, offset, R1);
933 __ LoadObject(R0, Object::null_object()); 909 __ LoadObject(R0, Object::null_object());
934 __ ret(); 910 __ ret();
935 } 911 }
936 912
937
938 void FlowGraphCompiler::EmitFrameEntry() { 913 void FlowGraphCompiler::EmitFrameEntry() {
939 const Function& function = parsed_function().function(); 914 const Function& function = parsed_function().function();
940 Register new_pp = kNoRegister; 915 Register new_pp = kNoRegister;
941 if (CanOptimizeFunction() && function.IsOptimizable() && 916 if (CanOptimizeFunction() && function.IsOptimizable() &&
942 (!is_optimizing() || may_reoptimize())) { 917 (!is_optimizing() || may_reoptimize())) {
943 __ Comment("Invocation Count Check"); 918 __ Comment("Invocation Count Check");
944 const Register function_reg = R6; 919 const Register function_reg = R6;
945 new_pp = R13; 920 new_pp = R13;
946 // The pool pointer is not setup before entering the Dart frame. 921 // The pool pointer is not setup before entering the Dart frame.
947 // Temporarily setup pool pointer for this dart function. 922 // Temporarily setup pool pointer for this dart function.
(...skipping 23 matching lines...) Expand all
971 intptr_t extra_slots = StackSize() - flow_graph().num_stack_locals() - 946 intptr_t extra_slots = StackSize() - flow_graph().num_stack_locals() -
972 flow_graph().num_copied_params(); 947 flow_graph().num_copied_params();
973 ASSERT(extra_slots >= 0); 948 ASSERT(extra_slots >= 0);
974 __ EnterOsrFrame(extra_slots * kWordSize, new_pp); 949 __ EnterOsrFrame(extra_slots * kWordSize, new_pp);
975 } else { 950 } else {
976 ASSERT(StackSize() >= 0); 951 ASSERT(StackSize() >= 0);
977 __ EnterDartFrame(StackSize() * kWordSize, new_pp); 952 __ EnterDartFrame(StackSize() * kWordSize, new_pp);
978 } 953 }
979 } 954 }
980 955
981
982 // Input parameters: 956 // Input parameters:
983 // LR: return address. 957 // LR: return address.
984 // SP: address of last argument. 958 // SP: address of last argument.
985 // FP: caller's frame pointer. 959 // FP: caller's frame pointer.
986 // PP: caller's pool pointer. 960 // PP: caller's pool pointer.
987 // R5: ic-data. 961 // R5: ic-data.
988 // R4: arguments descriptor array. 962 // R4: arguments descriptor array.
989 void FlowGraphCompiler::CompileGraph() { 963 void FlowGraphCompiler::CompileGraph() {
990 InitCompiler(); 964 InitCompiler();
991 const Function& function = parsed_function().function(); 965 const Function& function = parsed_function().function();
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
1105 // checked during resolution. 1079 // checked during resolution.
1106 1080
1107 EndCodeSourceRange(TokenPosition::kDartCodePrologue); 1081 EndCodeSourceRange(TokenPosition::kDartCodePrologue);
1108 VisitBlocks(); 1082 VisitBlocks();
1109 1083
1110 __ brk(0); 1084 __ brk(0);
1111 ASSERT(assembler()->constant_pool_allowed()); 1085 ASSERT(assembler()->constant_pool_allowed());
1112 GenerateDeferredCode(); 1086 GenerateDeferredCode();
1113 } 1087 }
1114 1088
1115
1116 void FlowGraphCompiler::GenerateCall(TokenPosition token_pos, 1089 void FlowGraphCompiler::GenerateCall(TokenPosition token_pos,
1117 const StubEntry& stub_entry, 1090 const StubEntry& stub_entry,
1118 RawPcDescriptors::Kind kind, 1091 RawPcDescriptors::Kind kind,
1119 LocationSummary* locs) { 1092 LocationSummary* locs) {
1120 __ BranchLink(stub_entry); 1093 __ BranchLink(stub_entry);
1121 EmitCallsiteMetaData(token_pos, Thread::kNoDeoptId, kind, locs); 1094 EmitCallsiteMetaData(token_pos, Thread::kNoDeoptId, kind, locs);
1122 } 1095 }
1123 1096
1124
1125 void FlowGraphCompiler::GeneratePatchableCall(TokenPosition token_pos, 1097 void FlowGraphCompiler::GeneratePatchableCall(TokenPosition token_pos,
1126 const StubEntry& stub_entry, 1098 const StubEntry& stub_entry,
1127 RawPcDescriptors::Kind kind, 1099 RawPcDescriptors::Kind kind,
1128 LocationSummary* locs) { 1100 LocationSummary* locs) {
1129 __ BranchLinkPatchable(stub_entry); 1101 __ BranchLinkPatchable(stub_entry);
1130 EmitCallsiteMetaData(token_pos, Thread::kNoDeoptId, kind, locs); 1102 EmitCallsiteMetaData(token_pos, Thread::kNoDeoptId, kind, locs);
1131 } 1103 }
1132 1104
1133
1134 void FlowGraphCompiler::GenerateDartCall(intptr_t deopt_id, 1105 void FlowGraphCompiler::GenerateDartCall(intptr_t deopt_id,
1135 TokenPosition token_pos, 1106 TokenPosition token_pos,
1136 const StubEntry& stub_entry, 1107 const StubEntry& stub_entry,
1137 RawPcDescriptors::Kind kind, 1108 RawPcDescriptors::Kind kind,
1138 LocationSummary* locs) { 1109 LocationSummary* locs) {
1139 __ BranchLinkPatchable(stub_entry); 1110 __ BranchLinkPatchable(stub_entry);
1140 EmitCallsiteMetaData(token_pos, deopt_id, kind, locs); 1111 EmitCallsiteMetaData(token_pos, deopt_id, kind, locs);
1141 // Marks either the continuation point in unoptimized code or the 1112 // Marks either the continuation point in unoptimized code or the
1142 // deoptimization point in optimized code, after call. 1113 // deoptimization point in optimized code, after call.
1143 const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id); 1114 const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id);
1144 if (is_optimizing()) { 1115 if (is_optimizing()) {
1145 AddDeoptIndexAtCall(deopt_id_after); 1116 AddDeoptIndexAtCall(deopt_id_after);
1146 } else { 1117 } else {
1147 // Add deoptimization continuation point after the call and before the 1118 // Add deoptimization continuation point after the call and before the
1148 // arguments are removed. 1119 // arguments are removed.
1149 AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id_after, token_pos); 1120 AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id_after, token_pos);
1150 } 1121 }
1151 } 1122 }
1152 1123
1153
1154 void FlowGraphCompiler::GenerateStaticDartCall(intptr_t deopt_id, 1124 void FlowGraphCompiler::GenerateStaticDartCall(intptr_t deopt_id,
1155 TokenPosition token_pos, 1125 TokenPosition token_pos,
1156 const StubEntry& stub_entry, 1126 const StubEntry& stub_entry,
1157 RawPcDescriptors::Kind kind, 1127 RawPcDescriptors::Kind kind,
1158 LocationSummary* locs, 1128 LocationSummary* locs,
1159 const Function& target) { 1129 const Function& target) {
1160 // Call sites to the same target can share object pool entries. These 1130 // Call sites to the same target can share object pool entries. These
1161 // call sites are never patched for breakpoints: the function is deoptimized 1131 // call sites are never patched for breakpoints: the function is deoptimized
1162 // and the unoptimized code with IC calls for static calls is patched instead. 1132 // and the unoptimized code with IC calls for static calls is patched instead.
1163 ASSERT(is_optimizing()); 1133 ASSERT(is_optimizing());
1164 __ BranchLinkWithEquivalence(stub_entry, target); 1134 __ BranchLinkWithEquivalence(stub_entry, target);
1165 1135
1166 EmitCallsiteMetaData(token_pos, deopt_id, kind, locs); 1136 EmitCallsiteMetaData(token_pos, deopt_id, kind, locs);
1167 // Marks either the continuation point in unoptimized code or the 1137 // Marks either the continuation point in unoptimized code or the
1168 // deoptimization point in optimized code, after call. 1138 // deoptimization point in optimized code, after call.
1169 const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id); 1139 const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id);
1170 if (is_optimizing()) { 1140 if (is_optimizing()) {
1171 AddDeoptIndexAtCall(deopt_id_after); 1141 AddDeoptIndexAtCall(deopt_id_after);
1172 } else { 1142 } else {
1173 // Add deoptimization continuation point after the call and before the 1143 // Add deoptimization continuation point after the call and before the
1174 // arguments are removed. 1144 // arguments are removed.
1175 AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id_after, token_pos); 1145 AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id_after, token_pos);
1176 } 1146 }
1177 AddStaticCallTarget(target); 1147 AddStaticCallTarget(target);
1178 } 1148 }
1179 1149
1180
1181 void FlowGraphCompiler::GenerateRuntimeCall(TokenPosition token_pos, 1150 void FlowGraphCompiler::GenerateRuntimeCall(TokenPosition token_pos,
1182 intptr_t deopt_id, 1151 intptr_t deopt_id,
1183 const RuntimeEntry& entry, 1152 const RuntimeEntry& entry,
1184 intptr_t argument_count, 1153 intptr_t argument_count,
1185 LocationSummary* locs) { 1154 LocationSummary* locs) {
1186 __ CallRuntime(entry, argument_count); 1155 __ CallRuntime(entry, argument_count);
1187 EmitCallsiteMetaData(token_pos, deopt_id, RawPcDescriptors::kOther, locs); 1156 EmitCallsiteMetaData(token_pos, deopt_id, RawPcDescriptors::kOther, locs);
1188 if (deopt_id != Thread::kNoDeoptId) { 1157 if (deopt_id != Thread::kNoDeoptId) {
1189 // Marks either the continuation point in unoptimized code or the 1158 // Marks either the continuation point in unoptimized code or the
1190 // deoptimization point in optimized code, after call. 1159 // deoptimization point in optimized code, after call.
1191 const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id); 1160 const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id);
1192 if (is_optimizing()) { 1161 if (is_optimizing()) {
1193 AddDeoptIndexAtCall(deopt_id_after); 1162 AddDeoptIndexAtCall(deopt_id_after);
1194 } else { 1163 } else {
1195 // Add deoptimization continuation point after the call and before the 1164 // Add deoptimization continuation point after the call and before the
1196 // arguments are removed. 1165 // arguments are removed.
1197 AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id_after, token_pos); 1166 AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id_after, token_pos);
1198 } 1167 }
1199 } 1168 }
1200 } 1169 }
1201 1170
1202
1203 void FlowGraphCompiler::EmitEdgeCounter(intptr_t edge_id) { 1171 void FlowGraphCompiler::EmitEdgeCounter(intptr_t edge_id) {
1204 // We do not check for overflow when incrementing the edge counter. The 1172 // We do not check for overflow when incrementing the edge counter. The
1205 // function should normally be optimized long before the counter can 1173 // function should normally be optimized long before the counter can
1206 // overflow; and though we do not reset the counters when we optimize or 1174 // overflow; and though we do not reset the counters when we optimize or
1207 // deoptimize, there is a bound on the number of 1175 // deoptimize, there is a bound on the number of
1208 // optimization/deoptimization cycles we will attempt. 1176 // optimization/deoptimization cycles we will attempt.
1209 ASSERT(!edge_counters_array_.IsNull()); 1177 ASSERT(!edge_counters_array_.IsNull());
1210 ASSERT(assembler_->constant_pool_allowed()); 1178 ASSERT(assembler_->constant_pool_allowed());
1211 __ Comment("Edge counter"); 1179 __ Comment("Edge counter");
1212 __ LoadObject(R0, edge_counters_array_); 1180 __ LoadObject(R0, edge_counters_array_);
1213 __ LoadFieldFromOffset(TMP, R0, Array::element_offset(edge_id)); 1181 __ LoadFieldFromOffset(TMP, R0, Array::element_offset(edge_id));
1214 __ add(TMP, TMP, Operand(Smi::RawValue(1))); 1182 __ add(TMP, TMP, Operand(Smi::RawValue(1)));
1215 __ StoreFieldToOffset(TMP, R0, Array::element_offset(edge_id)); 1183 __ StoreFieldToOffset(TMP, R0, Array::element_offset(edge_id));
1216 } 1184 }
1217 1185
1218
1219 void FlowGraphCompiler::EmitOptimizedInstanceCall(const StubEntry& stub_entry, 1186 void FlowGraphCompiler::EmitOptimizedInstanceCall(const StubEntry& stub_entry,
1220 const ICData& ic_data, 1187 const ICData& ic_data,
1221 intptr_t argument_count, 1188 intptr_t argument_count,
1222 intptr_t deopt_id, 1189 intptr_t deopt_id,
1223 TokenPosition token_pos, 1190 TokenPosition token_pos,
1224 LocationSummary* locs) { 1191 LocationSummary* locs) {
1225 ASSERT(Array::Handle(zone(), ic_data.arguments_descriptor()).Length() > 0); 1192 ASSERT(Array::Handle(zone(), ic_data.arguments_descriptor()).Length() > 0);
1226 // Each ICData propagated from unoptimized to optimized code contains the 1193 // Each ICData propagated from unoptimized to optimized code contains the
1227 // function that corresponds to the Dart function of that IC call. Due 1194 // function that corresponds to the Dart function of that IC call. Due
1228 // to inlining in optimized code, that function may not correspond to the 1195 // to inlining in optimized code, that function may not correspond to the
1229 // top-level function (parsed_function().function()) which could be 1196 // top-level function (parsed_function().function()) which could be
1230 // reoptimized and which counter needs to be incremented. 1197 // reoptimized and which counter needs to be incremented.
1231 // Pass the function explicitly, it is used in IC stub. 1198 // Pass the function explicitly, it is used in IC stub.
1232 1199
1233 __ LoadObject(R6, parsed_function().function()); 1200 __ LoadObject(R6, parsed_function().function());
1234 __ LoadUniqueObject(R5, ic_data); 1201 __ LoadUniqueObject(R5, ic_data);
1235 GenerateDartCall(deopt_id, token_pos, stub_entry, RawPcDescriptors::kIcCall, 1202 GenerateDartCall(deopt_id, token_pos, stub_entry, RawPcDescriptors::kIcCall,
1236 locs); 1203 locs);
1237 __ Drop(argument_count); 1204 __ Drop(argument_count);
1238 } 1205 }
1239 1206
1240
1241 void FlowGraphCompiler::EmitInstanceCall(const StubEntry& stub_entry, 1207 void FlowGraphCompiler::EmitInstanceCall(const StubEntry& stub_entry,
1242 const ICData& ic_data, 1208 const ICData& ic_data,
1243 intptr_t argument_count, 1209 intptr_t argument_count,
1244 intptr_t deopt_id, 1210 intptr_t deopt_id,
1245 TokenPosition token_pos, 1211 TokenPosition token_pos,
1246 LocationSummary* locs) { 1212 LocationSummary* locs) {
1247 ASSERT(Array::Handle(zone(), ic_data.arguments_descriptor()).Length() > 0); 1213 ASSERT(Array::Handle(zone(), ic_data.arguments_descriptor()).Length() > 0);
1248 __ LoadUniqueObject(R5, ic_data); 1214 __ LoadUniqueObject(R5, ic_data);
1249 GenerateDartCall(deopt_id, token_pos, stub_entry, RawPcDescriptors::kIcCall, 1215 GenerateDartCall(deopt_id, token_pos, stub_entry, RawPcDescriptors::kIcCall,
1250 locs); 1216 locs);
1251 __ Drop(argument_count); 1217 __ Drop(argument_count);
1252 } 1218 }
1253 1219
1254
1255 void FlowGraphCompiler::EmitMegamorphicInstanceCall( 1220 void FlowGraphCompiler::EmitMegamorphicInstanceCall(
1256 const String& name, 1221 const String& name,
1257 const Array& arguments_descriptor, 1222 const Array& arguments_descriptor,
1258 intptr_t argument_count, 1223 intptr_t argument_count,
1259 intptr_t deopt_id, 1224 intptr_t deopt_id,
1260 TokenPosition token_pos, 1225 TokenPosition token_pos,
1261 LocationSummary* locs, 1226 LocationSummary* locs,
1262 intptr_t try_index, 1227 intptr_t try_index,
1263 intptr_t slow_path_argument_count) { 1228 intptr_t slow_path_argument_count) {
1264 ASSERT(!arguments_descriptor.IsNull() && (arguments_descriptor.Length() > 0)); 1229 ASSERT(!arguments_descriptor.IsNull() && (arguments_descriptor.Length() > 0));
(...skipping 27 matching lines...) Expand all
1292 AddCurrentDescriptor(RawPcDescriptors::kOther, Thread::kNoDeoptId, 1257 AddCurrentDescriptor(RawPcDescriptors::kOther, Thread::kNoDeoptId,
1293 token_pos); 1258 token_pos);
1294 // Add deoptimization continuation point after the call and before the 1259 // Add deoptimization continuation point after the call and before the
1295 // arguments are removed. 1260 // arguments are removed.
1296 AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id_after, token_pos); 1261 AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id_after, token_pos);
1297 } 1262 }
1298 EmitCatchEntryState(pending_deoptimization_env_, try_index); 1263 EmitCatchEntryState(pending_deoptimization_env_, try_index);
1299 __ Drop(argument_count); 1264 __ Drop(argument_count);
1300 } 1265 }
1301 1266
1302
1303 void FlowGraphCompiler::EmitSwitchableInstanceCall(const ICData& ic_data, 1267 void FlowGraphCompiler::EmitSwitchableInstanceCall(const ICData& ic_data,
1304 intptr_t argument_count, 1268 intptr_t argument_count,
1305 intptr_t deopt_id, 1269 intptr_t deopt_id,
1306 TokenPosition token_pos, 1270 TokenPosition token_pos,
1307 LocationSummary* locs) { 1271 LocationSummary* locs) {
1308 ASSERT(ic_data.NumArgsTested() == 1); 1272 ASSERT(ic_data.NumArgsTested() == 1);
1309 const Code& initial_stub = 1273 const Code& initial_stub =
1310 Code::ZoneHandle(StubCode::ICCallThroughFunction_entry()->code()); 1274 Code::ZoneHandle(StubCode::ICCallThroughFunction_entry()->code());
1311 __ Comment("SwitchableCall"); 1275 __ Comment("SwitchableCall");
1312 1276
1313 __ LoadFromOffset(R0, SP, (argument_count - 1) * kWordSize); 1277 __ LoadFromOffset(R0, SP, (argument_count - 1) * kWordSize);
1314 __ LoadUniqueObject(CODE_REG, initial_stub); 1278 __ LoadUniqueObject(CODE_REG, initial_stub);
1315 __ ldr(TMP, FieldAddress(CODE_REG, Code::checked_entry_point_offset())); 1279 __ ldr(TMP, FieldAddress(CODE_REG, Code::checked_entry_point_offset()));
1316 __ LoadUniqueObject(R5, ic_data); 1280 __ LoadUniqueObject(R5, ic_data);
1317 __ blr(TMP); 1281 __ blr(TMP);
1318 1282
1319 EmitCallsiteMetaData(token_pos, Thread::kNoDeoptId, RawPcDescriptors::kOther, 1283 EmitCallsiteMetaData(token_pos, Thread::kNoDeoptId, RawPcDescriptors::kOther,
1320 locs); 1284 locs);
1321 const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id); 1285 const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id);
1322 if (is_optimizing()) { 1286 if (is_optimizing()) {
1323 AddDeoptIndexAtCall(deopt_id_after); 1287 AddDeoptIndexAtCall(deopt_id_after);
1324 } else { 1288 } else {
1325 // Add deoptimization continuation point after the call and before the 1289 // Add deoptimization continuation point after the call and before the
1326 // arguments are removed. 1290 // arguments are removed.
1327 AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id_after, token_pos); 1291 AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id_after, token_pos);
1328 } 1292 }
1329 __ Drop(argument_count); 1293 __ Drop(argument_count);
1330 } 1294 }
1331 1295
1332
1333 void FlowGraphCompiler::EmitUnoptimizedStaticCall(intptr_t argument_count, 1296 void FlowGraphCompiler::EmitUnoptimizedStaticCall(intptr_t argument_count,
1334 intptr_t deopt_id, 1297 intptr_t deopt_id,
1335 TokenPosition token_pos, 1298 TokenPosition token_pos,
1336 LocationSummary* locs, 1299 LocationSummary* locs,
1337 const ICData& ic_data) { 1300 const ICData& ic_data) {
1338 const StubEntry* stub_entry = 1301 const StubEntry* stub_entry =
1339 StubCode::UnoptimizedStaticCallEntry(ic_data.NumArgsTested()); 1302 StubCode::UnoptimizedStaticCallEntry(ic_data.NumArgsTested());
1340 __ LoadObject(R5, ic_data); 1303 __ LoadObject(R5, ic_data);
1341 GenerateDartCall(deopt_id, token_pos, *stub_entry, 1304 GenerateDartCall(deopt_id, token_pos, *stub_entry,
1342 RawPcDescriptors::kUnoptStaticCall, locs); 1305 RawPcDescriptors::kUnoptStaticCall, locs);
1343 __ Drop(argument_count); 1306 __ Drop(argument_count);
1344 } 1307 }
1345 1308
1346
1347 void FlowGraphCompiler::EmitOptimizedStaticCall( 1309 void FlowGraphCompiler::EmitOptimizedStaticCall(
1348 const Function& function, 1310 const Function& function,
1349 const Array& arguments_descriptor, 1311 const Array& arguments_descriptor,
1350 intptr_t argument_count, 1312 intptr_t argument_count,
1351 intptr_t deopt_id, 1313 intptr_t deopt_id,
1352 TokenPosition token_pos, 1314 TokenPosition token_pos,
1353 LocationSummary* locs) { 1315 LocationSummary* locs) {
1354 ASSERT(!function.IsClosureFunction()); 1316 ASSERT(!function.IsClosureFunction());
1355 if (function.HasOptionalParameters() || 1317 if (function.HasOptionalParameters() ||
1356 (FLAG_reify_generic_functions && function.IsGeneric())) { 1318 (FLAG_reify_generic_functions && function.IsGeneric())) {
1357 __ LoadObject(R4, arguments_descriptor); 1319 __ LoadObject(R4, arguments_descriptor);
1358 } else { 1320 } else {
1359 __ LoadImmediate(R4, 0); // GC safe smi zero because of stub. 1321 __ LoadImmediate(R4, 0); // GC safe smi zero because of stub.
1360 } 1322 }
1361 // Do not use the code from the function, but let the code be patched so that 1323 // Do not use the code from the function, but let the code be patched so that
1362 // we can record the outgoing edges to other code. 1324 // we can record the outgoing edges to other code.
1363 GenerateStaticDartCall(deopt_id, token_pos, 1325 GenerateStaticDartCall(deopt_id, token_pos,
1364 *StubCode::CallStaticFunction_entry(), 1326 *StubCode::CallStaticFunction_entry(),
1365 RawPcDescriptors::kOther, locs, function); 1327 RawPcDescriptors::kOther, locs, function);
1366 __ Drop(argument_count); 1328 __ Drop(argument_count);
1367 } 1329 }
1368 1330
1369
1370 Condition FlowGraphCompiler::EmitEqualityRegConstCompare( 1331 Condition FlowGraphCompiler::EmitEqualityRegConstCompare(
1371 Register reg, 1332 Register reg,
1372 const Object& obj, 1333 const Object& obj,
1373 bool needs_number_check, 1334 bool needs_number_check,
1374 TokenPosition token_pos, 1335 TokenPosition token_pos,
1375 intptr_t deopt_id) { 1336 intptr_t deopt_id) {
1376 if (needs_number_check) { 1337 if (needs_number_check) {
1377 ASSERT(!obj.IsMint() && !obj.IsDouble() && !obj.IsBigint()); 1338 ASSERT(!obj.IsMint() && !obj.IsDouble() && !obj.IsBigint());
1378 __ Push(reg); 1339 __ Push(reg);
1379 __ PushObject(obj); 1340 __ PushObject(obj);
1380 if (is_optimizing()) { 1341 if (is_optimizing()) {
1381 __ BranchLinkPatchable( 1342 __ BranchLinkPatchable(
1382 *StubCode::OptimizedIdenticalWithNumberCheck_entry()); 1343 *StubCode::OptimizedIdenticalWithNumberCheck_entry());
1383 } else { 1344 } else {
1384 __ BranchLinkPatchable( 1345 __ BranchLinkPatchable(
1385 *StubCode::UnoptimizedIdenticalWithNumberCheck_entry()); 1346 *StubCode::UnoptimizedIdenticalWithNumberCheck_entry());
1386 } 1347 }
1387 AddCurrentDescriptor(RawPcDescriptors::kRuntimeCall, deopt_id, token_pos); 1348 AddCurrentDescriptor(RawPcDescriptors::kRuntimeCall, deopt_id, token_pos);
1388 // Stub returns result in flags (result of a cmp, we need Z computed). 1349 // Stub returns result in flags (result of a cmp, we need Z computed).
1389 __ Drop(1); // Discard constant. 1350 __ Drop(1); // Discard constant.
1390 __ Pop(reg); // Restore 'reg'. 1351 __ Pop(reg); // Restore 'reg'.
1391 } else { 1352 } else {
1392 __ CompareObject(reg, obj); 1353 __ CompareObject(reg, obj);
1393 } 1354 }
1394 return EQ; 1355 return EQ;
1395 } 1356 }
1396 1357
1397
1398 Condition FlowGraphCompiler::EmitEqualityRegRegCompare(Register left, 1358 Condition FlowGraphCompiler::EmitEqualityRegRegCompare(Register left,
1399 Register right, 1359 Register right,
1400 bool needs_number_check, 1360 bool needs_number_check,
1401 TokenPosition token_pos, 1361 TokenPosition token_pos,
1402 intptr_t deopt_id) { 1362 intptr_t deopt_id) {
1403 if (needs_number_check) { 1363 if (needs_number_check) {
1404 __ Push(left); 1364 __ Push(left);
1405 __ Push(right); 1365 __ Push(right);
1406 if (is_optimizing()) { 1366 if (is_optimizing()) {
1407 __ BranchLinkPatchable( 1367 __ BranchLinkPatchable(
1408 *StubCode::OptimizedIdenticalWithNumberCheck_entry()); 1368 *StubCode::OptimizedIdenticalWithNumberCheck_entry());
1409 } else { 1369 } else {
1410 __ BranchLinkPatchable( 1370 __ BranchLinkPatchable(
1411 *StubCode::UnoptimizedIdenticalWithNumberCheck_entry()); 1371 *StubCode::UnoptimizedIdenticalWithNumberCheck_entry());
1412 } 1372 }
1413 AddCurrentDescriptor(RawPcDescriptors::kRuntimeCall, deopt_id, token_pos); 1373 AddCurrentDescriptor(RawPcDescriptors::kRuntimeCall, deopt_id, token_pos);
1414 // Stub returns result in flags (result of a cmp, we need Z computed). 1374 // Stub returns result in flags (result of a cmp, we need Z computed).
1415 __ Pop(right); 1375 __ Pop(right);
1416 __ Pop(left); 1376 __ Pop(left);
1417 } else { 1377 } else {
1418 __ CompareRegisters(left, right); 1378 __ CompareRegisters(left, right);
1419 } 1379 }
1420 return EQ; 1380 return EQ;
1421 } 1381 }
1422 1382
1423
1424 // This function must be in sync with FlowGraphCompiler::RecordSafepoint and 1383 // This function must be in sync with FlowGraphCompiler::RecordSafepoint and
1425 // FlowGraphCompiler::SlowPathEnvironmentFor. 1384 // FlowGraphCompiler::SlowPathEnvironmentFor.
1426 void FlowGraphCompiler::SaveLiveRegisters(LocationSummary* locs) { 1385 void FlowGraphCompiler::SaveLiveRegisters(LocationSummary* locs) {
1427 #if defined(DEBUG) 1386 #if defined(DEBUG)
1428 locs->CheckWritableInputs(); 1387 locs->CheckWritableInputs();
1429 ClobberDeadTempRegisters(locs); 1388 ClobberDeadTempRegisters(locs);
1430 #endif 1389 #endif
1431 1390
1432 // TODO(vegorov): consider saving only caller save (volatile) registers. 1391 // TODO(vegorov): consider saving only caller save (volatile) registers.
1433 const intptr_t fpu_regs_count = locs->live_registers()->FpuRegisterCount(); 1392 const intptr_t fpu_regs_count = locs->live_registers()->FpuRegisterCount();
(...skipping 11 matching lines...) Expand all
1445 // The order in which the registers are pushed must match the order 1404 // The order in which the registers are pushed must match the order
1446 // in which the registers are encoded in the safe point's stack map. 1405 // in which the registers are encoded in the safe point's stack map.
1447 for (intptr_t i = kNumberOfCpuRegisters - 1; i >= 0; --i) { 1406 for (intptr_t i = kNumberOfCpuRegisters - 1; i >= 0; --i) {
1448 Register reg = static_cast<Register>(i); 1407 Register reg = static_cast<Register>(i);
1449 if (locs->live_registers()->ContainsRegister(reg)) { 1408 if (locs->live_registers()->ContainsRegister(reg)) {
1450 __ Push(reg); 1409 __ Push(reg);
1451 } 1410 }
1452 } 1411 }
1453 } 1412 }
1454 1413
1455
1456 void FlowGraphCompiler::RestoreLiveRegisters(LocationSummary* locs) { 1414 void FlowGraphCompiler::RestoreLiveRegisters(LocationSummary* locs) {
1457 for (intptr_t i = 0; i < kNumberOfCpuRegisters; ++i) { 1415 for (intptr_t i = 0; i < kNumberOfCpuRegisters; ++i) {
1458 Register reg = static_cast<Register>(i); 1416 Register reg = static_cast<Register>(i);
1459 if (locs->live_registers()->ContainsRegister(reg)) { 1417 if (locs->live_registers()->ContainsRegister(reg)) {
1460 __ Pop(reg); 1418 __ Pop(reg);
1461 } 1419 }
1462 } 1420 }
1463 1421
1464 const intptr_t fpu_regs_count = locs->live_registers()->FpuRegisterCount(); 1422 const intptr_t fpu_regs_count = locs->live_registers()->FpuRegisterCount();
1465 if (fpu_regs_count > 0) { 1423 if (fpu_regs_count > 0) {
1466 // Fpu registers have the lowest register number at the lowest address. 1424 // Fpu registers have the lowest register number at the lowest address.
1467 for (intptr_t i = 0; i < kNumberOfVRegisters; ++i) { 1425 for (intptr_t i = 0; i < kNumberOfVRegisters; ++i) {
1468 VRegister fpu_reg = static_cast<VRegister>(i); 1426 VRegister fpu_reg = static_cast<VRegister>(i);
1469 if (locs->live_registers()->ContainsFpuRegister(fpu_reg)) { 1427 if (locs->live_registers()->ContainsFpuRegister(fpu_reg)) {
1470 __ PopQuad(fpu_reg); 1428 __ PopQuad(fpu_reg);
1471 } 1429 }
1472 } 1430 }
1473 } 1431 }
1474 } 1432 }
1475 1433
1476
1477 #if defined(DEBUG) 1434 #if defined(DEBUG)
1478 void FlowGraphCompiler::ClobberDeadTempRegisters(LocationSummary* locs) { 1435 void FlowGraphCompiler::ClobberDeadTempRegisters(LocationSummary* locs) {
1479 // Clobber temporaries that have not been manually preserved. 1436 // Clobber temporaries that have not been manually preserved.
1480 for (intptr_t i = 0; i < locs->temp_count(); ++i) { 1437 for (intptr_t i = 0; i < locs->temp_count(); ++i) {
1481 Location tmp = locs->temp(i); 1438 Location tmp = locs->temp(i);
1482 // TODO(zerny): clobber non-live temporary FPU registers. 1439 // TODO(zerny): clobber non-live temporary FPU registers.
1483 if (tmp.IsRegister() && 1440 if (tmp.IsRegister() &&
1484 !locs->live_registers()->ContainsRegister(tmp.reg())) { 1441 !locs->live_registers()->ContainsRegister(tmp.reg())) {
1485 __ movz(tmp.reg(), Immediate(0xf7), 0); 1442 __ movz(tmp.reg(), Immediate(0xf7), 0);
1486 } 1443 }
1487 } 1444 }
1488 } 1445 }
1489 #endif 1446 #endif
1490 1447
1491
1492 void FlowGraphCompiler::EmitTestAndCallLoadReceiver( 1448 void FlowGraphCompiler::EmitTestAndCallLoadReceiver(
1493 intptr_t argument_count, 1449 intptr_t argument_count,
1494 const Array& arguments_descriptor) { 1450 const Array& arguments_descriptor) {
1495 __ Comment("EmitTestAndCall"); 1451 __ Comment("EmitTestAndCall");
1496 // Load receiver into R0. 1452 // Load receiver into R0.
1497 __ LoadFromOffset(R0, SP, (argument_count - 1) * kWordSize); 1453 __ LoadFromOffset(R0, SP, (argument_count - 1) * kWordSize);
1498 __ LoadObject(R4, arguments_descriptor); 1454 __ LoadObject(R4, arguments_descriptor);
1499 } 1455 }
1500 1456
1501
1502 void FlowGraphCompiler::EmitTestAndCallSmiBranch(Label* label, bool if_smi) { 1457 void FlowGraphCompiler::EmitTestAndCallSmiBranch(Label* label, bool if_smi) {
1503 __ tsti(R0, Immediate(kSmiTagMask)); 1458 __ tsti(R0, Immediate(kSmiTagMask));
1504 // Jump if receiver is not Smi. 1459 // Jump if receiver is not Smi.
1505 __ b(label, if_smi ? EQ : NE); 1460 __ b(label, if_smi ? EQ : NE);
1506 } 1461 }
1507 1462
1508
1509 void FlowGraphCompiler::EmitTestAndCallLoadCid() { 1463 void FlowGraphCompiler::EmitTestAndCallLoadCid() {
1510 __ LoadClassId(R2, R0); 1464 __ LoadClassId(R2, R0);
1511 } 1465 }
1512 1466
1513
1514 int FlowGraphCompiler::EmitTestAndCallCheckCid(Label* next_label, 1467 int FlowGraphCompiler::EmitTestAndCallCheckCid(Label* next_label,
1515 const CidRange& range, 1468 const CidRange& range,
1516 int bias) { 1469 int bias) {
1517 intptr_t cid_start = range.cid_start; 1470 intptr_t cid_start = range.cid_start;
1518 if (range.IsSingleCid()) { 1471 if (range.IsSingleCid()) {
1519 __ CompareImmediate(R2, cid_start - bias); 1472 __ CompareImmediate(R2, cid_start - bias);
1520 __ b(next_label, NE); 1473 __ b(next_label, NE);
1521 } else { 1474 } else {
1522 __ AddImmediate(R2, bias - cid_start); 1475 __ AddImmediate(R2, bias - cid_start);
1523 bias = cid_start; 1476 bias = cid_start;
1524 __ CompareImmediate(R2, range.Extent()); 1477 __ CompareImmediate(R2, range.Extent());
1525 __ b(next_label, HI); // Unsigned higher. 1478 __ b(next_label, HI); // Unsigned higher.
1526 } 1479 }
1527 return bias; 1480 return bias;
1528 } 1481 }
1529 1482
1530
1531 #undef __ 1483 #undef __
1532 #define __ compiler_->assembler()-> 1484 #define __ compiler_->assembler()->
1533 1485
1534
1535 void ParallelMoveResolver::EmitMove(int index) { 1486 void ParallelMoveResolver::EmitMove(int index) {
1536 MoveOperands* move = moves_[index]; 1487 MoveOperands* move = moves_[index];
1537 const Location source = move->src(); 1488 const Location source = move->src();
1538 const Location destination = move->dest(); 1489 const Location destination = move->dest();
1539 1490
1540 if (source.IsRegister()) { 1491 if (source.IsRegister()) {
1541 if (destination.IsRegister()) { 1492 if (destination.IsRegister()) {
1542 __ mov(destination.reg(), source.reg()); 1493 __ mov(destination.reg(), source.reg());
1543 } else { 1494 } else {
1544 ASSERT(destination.IsStackSlot()); 1495 ASSERT(destination.IsStackSlot());
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
1637 } else { 1588 } else {
1638 __ LoadObject(tmp.reg(), constant); 1589 __ LoadObject(tmp.reg(), constant);
1639 } 1590 }
1640 __ StoreToOffset(tmp.reg(), destination.base_reg(), dest_offset); 1591 __ StoreToOffset(tmp.reg(), destination.base_reg(), dest_offset);
1641 } 1592 }
1642 } 1593 }
1643 1594
1644 move->Eliminate(); 1595 move->Eliminate();
1645 } 1596 }
1646 1597
1647
1648 void ParallelMoveResolver::EmitSwap(int index) { 1598 void ParallelMoveResolver::EmitSwap(int index) {
1649 MoveOperands* move = moves_[index]; 1599 MoveOperands* move = moves_[index];
1650 const Location source = move->src(); 1600 const Location source = move->src();
1651 const Location destination = move->dest(); 1601 const Location destination = move->dest();
1652 1602
1653 if (source.IsRegister() && destination.IsRegister()) { 1603 if (source.IsRegister() && destination.IsRegister()) {
1654 ASSERT(source.reg() != TMP); 1604 ASSERT(source.reg() != TMP);
1655 ASSERT(destination.reg() != TMP); 1605 ASSERT(destination.reg() != TMP);
1656 __ mov(TMP, source.reg()); 1606 __ mov(TMP, source.reg());
1657 __ mov(source.reg(), destination.reg()); 1607 __ mov(source.reg(), destination.reg());
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
1726 for (int i = 0; i < moves_.length(); ++i) { 1676 for (int i = 0; i < moves_.length(); ++i) {
1727 const MoveOperands& other_move = *moves_[i]; 1677 const MoveOperands& other_move = *moves_[i];
1728 if (other_move.Blocks(source)) { 1678 if (other_move.Blocks(source)) {
1729 moves_[i]->set_src(destination); 1679 moves_[i]->set_src(destination);
1730 } else if (other_move.Blocks(destination)) { 1680 } else if (other_move.Blocks(destination)) {
1731 moves_[i]->set_src(source); 1681 moves_[i]->set_src(source);
1732 } 1682 }
1733 } 1683 }
1734 } 1684 }
1735 1685
1736
1737 void ParallelMoveResolver::MoveMemoryToMemory(const Address& dst, 1686 void ParallelMoveResolver::MoveMemoryToMemory(const Address& dst,
1738 const Address& src) { 1687 const Address& src) {
1739 UNREACHABLE(); 1688 UNREACHABLE();
1740 } 1689 }
1741 1690
1742
1743 void ParallelMoveResolver::StoreObject(const Address& dst, const Object& obj) { 1691 void ParallelMoveResolver::StoreObject(const Address& dst, const Object& obj) {
1744 UNREACHABLE(); 1692 UNREACHABLE();
1745 } 1693 }
1746 1694
1747
1748 // Do not call or implement this function. Instead, use the form below that 1695 // Do not call or implement this function. Instead, use the form below that
1749 // uses an offset from the frame pointer instead of an Address. 1696 // uses an offset from the frame pointer instead of an Address.
1750 void ParallelMoveResolver::Exchange(Register reg, const Address& mem) { 1697 void ParallelMoveResolver::Exchange(Register reg, const Address& mem) {
1751 UNREACHABLE(); 1698 UNREACHABLE();
1752 } 1699 }
1753 1700
1754
1755 // Do not call or implement this function. Instead, use the form below that 1701 // Do not call or implement this function. Instead, use the form below that
1756 // uses offsets from the frame pointer instead of Addresses. 1702 // uses offsets from the frame pointer instead of Addresses.
1757 void ParallelMoveResolver::Exchange(const Address& mem1, const Address& mem2) { 1703 void ParallelMoveResolver::Exchange(const Address& mem1, const Address& mem2) {
1758 UNREACHABLE(); 1704 UNREACHABLE();
1759 } 1705 }
1760 1706
1761
1762 void ParallelMoveResolver::Exchange(Register reg, 1707 void ParallelMoveResolver::Exchange(Register reg,
1763 Register base_reg, 1708 Register base_reg,
1764 intptr_t stack_offset) { 1709 intptr_t stack_offset) {
1765 ScratchRegisterScope tmp(this, reg); 1710 ScratchRegisterScope tmp(this, reg);
1766 __ mov(tmp.reg(), reg); 1711 __ mov(tmp.reg(), reg);
1767 __ LoadFromOffset(reg, base_reg, stack_offset); 1712 __ LoadFromOffset(reg, base_reg, stack_offset);
1768 __ StoreToOffset(tmp.reg(), base_reg, stack_offset); 1713 __ StoreToOffset(tmp.reg(), base_reg, stack_offset);
1769 } 1714 }
1770 1715
1771
1772 void ParallelMoveResolver::Exchange(Register base_reg1, 1716 void ParallelMoveResolver::Exchange(Register base_reg1,
1773 intptr_t stack_offset1, 1717 intptr_t stack_offset1,
1774 Register base_reg2, 1718 Register base_reg2,
1775 intptr_t stack_offset2) { 1719 intptr_t stack_offset2) {
1776 ScratchRegisterScope tmp1(this, kNoRegister); 1720 ScratchRegisterScope tmp1(this, kNoRegister);
1777 ScratchRegisterScope tmp2(this, tmp1.reg()); 1721 ScratchRegisterScope tmp2(this, tmp1.reg());
1778 __ LoadFromOffset(tmp1.reg(), base_reg1, stack_offset1); 1722 __ LoadFromOffset(tmp1.reg(), base_reg1, stack_offset1);
1779 __ LoadFromOffset(tmp2.reg(), base_reg2, stack_offset2); 1723 __ LoadFromOffset(tmp2.reg(), base_reg2, stack_offset2);
1780 __ StoreToOffset(tmp1.reg(), base_reg2, stack_offset2); 1724 __ StoreToOffset(tmp1.reg(), base_reg2, stack_offset2);
1781 __ StoreToOffset(tmp2.reg(), base_reg1, stack_offset1); 1725 __ StoreToOffset(tmp2.reg(), base_reg1, stack_offset1);
1782 } 1726 }
1783 1727
1784
1785 void ParallelMoveResolver::SpillScratch(Register reg) { 1728 void ParallelMoveResolver::SpillScratch(Register reg) {
1786 __ Push(reg); 1729 __ Push(reg);
1787 } 1730 }
1788 1731
1789
1790 void ParallelMoveResolver::RestoreScratch(Register reg) { 1732 void ParallelMoveResolver::RestoreScratch(Register reg) {
1791 __ Pop(reg); 1733 __ Pop(reg);
1792 } 1734 }
1793 1735
1794
1795 void ParallelMoveResolver::SpillFpuScratch(FpuRegister reg) { 1736 void ParallelMoveResolver::SpillFpuScratch(FpuRegister reg) {
1796 __ PushDouble(reg); 1737 __ PushDouble(reg);
1797 } 1738 }
1798 1739
1799
1800 void ParallelMoveResolver::RestoreFpuScratch(FpuRegister reg) { 1740 void ParallelMoveResolver::RestoreFpuScratch(FpuRegister reg) {
1801 __ PopDouble(reg); 1741 __ PopDouble(reg);
1802 } 1742 }
1803 1743
1804
1805 #undef __ 1744 #undef __
1806 1745
1807 } // namespace dart 1746 } // namespace dart
1808 1747
1809 #endif // defined TARGET_ARCH_ARM64 1748 #endif // defined TARGET_ARCH_ARM64
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_compiler_arm.cc ('k') | runtime/vm/flow_graph_compiler_dbc.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698