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

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

Issue 263243002: Enables many language tests for arm64. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/flow_graph_compiler_arm.cc ('k') | runtime/vm/flow_graph_compiler_ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 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/locations.h" 16 #include "vm/locations.h"
17 #include "vm/object_store.h" 17 #include "vm/object_store.h"
18 #include "vm/parser.h" 18 #include "vm/parser.h"
19 #include "vm/stack_frame.h" 19 #include "vm/stack_frame.h"
20 #include "vm/stub_code.h" 20 #include "vm/stub_code.h"
21 #include "vm/symbols.h" 21 #include "vm/symbols.h"
22 22
23 namespace dart { 23 namespace dart {
24 24
25 DEFINE_FLAG(bool, trap_on_deoptimization, false, "Trap on deoptimization.");
25 DECLARE_FLAG(int, optimization_counter_threshold); 26 DECLARE_FLAG(int, optimization_counter_threshold);
26 DECLARE_FLAG(int, reoptimization_counter_threshold); 27 DECLARE_FLAG(int, reoptimization_counter_threshold);
27 DECLARE_FLAG(bool, eliminate_type_checks); 28 DECLARE_FLAG(bool, eliminate_type_checks);
28 29
29 FlowGraphCompiler::~FlowGraphCompiler() { 30 FlowGraphCompiler::~FlowGraphCompiler() {
30 // BlockInfos are zone-allocated, so their destructors are not called. 31 // BlockInfos are zone-allocated, so their destructors are not called.
31 // Verify the labels explicitly here. 32 // Verify the labels explicitly here.
32 for (int i = 0; i < block_info_.length(); ++i) { 33 for (int i = 0; i < block_info_.length(); ++i) {
33 ASSERT(!block_info_[i]->jump_label()->IsLinked()); 34 ASSERT(!block_info_[i]->jump_label()->IsLinked());
34 } 35 }
(...skipping 11 matching lines...) Expand all
46 47
47 48
48 bool FlowGraphCompiler::SupportsSinCos() { 49 bool FlowGraphCompiler::SupportsSinCos() {
49 return false; 50 return false;
50 } 51 }
51 52
52 53
53 RawDeoptInfo* CompilerDeoptInfo::CreateDeoptInfo(FlowGraphCompiler* compiler, 54 RawDeoptInfo* CompilerDeoptInfo::CreateDeoptInfo(FlowGraphCompiler* compiler,
54 DeoptInfoBuilder* builder, 55 DeoptInfoBuilder* builder,
55 const Array& deopt_table) { 56 const Array& deopt_table) {
56 UNIMPLEMENTED(); 57 if (deopt_env_ == NULL) {
57 return NULL; 58 return DeoptInfo::null();
59 }
60
61 intptr_t stack_height = compiler->StackSize();
62 AllocateIncomingParametersRecursive(deopt_env_, &stack_height);
63
64 intptr_t slot_ix = 0;
65 Environment* current = deopt_env_;
66
67 // Emit all kMaterializeObject instructions describing objects to be
68 // materialized on the deoptimization as a prefix to the deoptimization info.
69 EmitMaterializations(deopt_env_, builder);
70
71 // The real frame starts here.
72 builder->MarkFrameStart();
73
74 // Current PP, FP, and PC.
75 builder->AddPp(current->code(), slot_ix++);
76 builder->AddPcMarker(Code::Handle(), slot_ix++);
77 builder->AddCallerFp(slot_ix++);
78 builder->AddReturnAddress(current->code(), deopt_id(), slot_ix++);
79
80 // Emit all values that are needed for materialization as a part of the
81 // expression stack for the bottom-most frame. This guarantees that GC
82 // will be able to find them during materialization.
83 slot_ix = builder->EmitMaterializationArguments(slot_ix);
84
85 // For the innermost environment, set outgoing arguments and the locals.
86 for (intptr_t i = current->Length() - 1;
87 i >= current->fixed_parameter_count();
88 i--) {
89 builder->AddCopy(current->ValueAt(i), current->LocationAt(i), slot_ix++);
90 }
91
92 Environment* previous = current;
93 current = current->outer();
94 while (current != NULL) {
95 // PP, FP, and PC.
96 builder->AddPp(current->code(), slot_ix++);
97 builder->AddPcMarker(previous->code(), slot_ix++);
98 builder->AddCallerFp(slot_ix++);
99
100 // For any outer environment the deopt id is that of the call instruction
101 // which is recorded in the outer environment.
102 builder->AddReturnAddress(current->code(),
103 Isolate::ToDeoptAfter(current->deopt_id()),
104 slot_ix++);
105
106 // The values of outgoing arguments can be changed from the inlined call so
107 // we must read them from the previous environment.
108 for (intptr_t i = previous->fixed_parameter_count() - 1; i >= 0; i--) {
109 builder->AddCopy(previous->ValueAt(i),
110 previous->LocationAt(i),
111 slot_ix++);
112 }
113
114 // Set the locals, note that outgoing arguments are not in the environment.
115 for (intptr_t i = current->Length() - 1;
116 i >= current->fixed_parameter_count();
117 i--) {
118 builder->AddCopy(current->ValueAt(i),
119 current->LocationAt(i),
120 slot_ix++);
121 }
122
123 // Iterate on the outer environment.
124 previous = current;
125 current = current->outer();
126 }
127 // The previous pointer is now the outermost environment.
128 ASSERT(previous != NULL);
129
130 // For the outermost environment, set caller PC, caller PP, and caller FP.
131 builder->AddCallerPp(slot_ix++);
132 // PC marker.
133 builder->AddPcMarker(previous->code(), slot_ix++);
134 builder->AddCallerFp(slot_ix++);
135 builder->AddCallerPc(slot_ix++);
136
137 // For the outermost environment, set the incoming arguments.
138 for (intptr_t i = previous->fixed_parameter_count() - 1; i >= 0; i--) {
139 builder->AddCopy(previous->ValueAt(i), previous->LocationAt(i), slot_ix++);
140 }
141
142 const DeoptInfo& deopt_info =
143 DeoptInfo::Handle(builder->CreateDeoptInfo(deopt_table));
144 return deopt_info.raw();
58 } 145 }
59 146
60 147
61 void CompilerDeoptInfoWithStub::GenerateCode(FlowGraphCompiler* compiler, 148 void CompilerDeoptInfoWithStub::GenerateCode(FlowGraphCompiler* compiler,
62 intptr_t stub_ix) { 149 intptr_t stub_ix) {
63 UNIMPLEMENTED(); 150 // Calls do not need stubs, they share a deoptimization trampoline.
151 ASSERT(reason() != ICData::kDeoptAtCall);
152 Assembler* assem = compiler->assembler();
153 #define __ assem->
154 __ Comment("Deopt stub for id %" Pd "", deopt_id());
155 __ Bind(entry_label());
156 if (FLAG_trap_on_deoptimization) {
157 __ hlt(0);
158 }
159
160 ASSERT(deopt_env() != NULL);
161
162 __ BranchLink(&StubCode::DeoptimizeLabel(), PP);
163 set_pc_offset(assem->CodeSize());
164 #undef __
64 } 165 }
65 166
66 167
67 #define __ assembler()-> 168 #define __ assembler()->
68 169
69 170
70 // Fall through if bool_register contains null. 171 // Fall through if bool_register contains null.
71 void FlowGraphCompiler::GenerateBoolToJump(Register bool_register, 172 void FlowGraphCompiler::GenerateBoolToJump(Register bool_register,
72 Label* is_true, 173 Label* is_true,
73 Label* is_false) { 174 Label* is_false) {
(...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after
425 return SubtypeTestCache::null(); 526 return SubtypeTestCache::null();
426 } 527 }
427 } 528 }
428 return GenerateUninstantiatedTypeTest(token_pos, 529 return GenerateUninstantiatedTypeTest(token_pos,
429 type, 530 type,
430 is_instance_lbl, 531 is_instance_lbl,
431 is_not_instance_lbl); 532 is_not_instance_lbl);
432 } 533 }
433 534
434 535
536 // If instanceof type test cannot be performed successfully at compile time and
537 // therefore eliminated, optimize it by adding inlined tests for:
538 // - NULL -> return false.
539 // - Smi -> compile time subtype check (only if dst class is not parameterized).
540 // - Class equality (only if class is not parameterized).
541 // Inputs:
542 // - R0: object.
543 // - R1: instantiator type arguments or raw_null.
544 // - R2: instantiator or raw_null.
545 // Returns:
546 // - true or false in R0.
435 void FlowGraphCompiler::GenerateInstanceOf(intptr_t token_pos, 547 void FlowGraphCompiler::GenerateInstanceOf(intptr_t token_pos,
436 intptr_t deopt_id, 548 intptr_t deopt_id,
437 const AbstractType& type, 549 const AbstractType& type,
438 bool negate_result, 550 bool negate_result,
439 LocationSummary* locs) { 551 LocationSummary* locs) {
440 UNIMPLEMENTED(); 552 ASSERT(type.IsFinalized() && !type.IsMalformed() && !type.IsMalbounded());
553
554 // Preserve instantiator (R2) and its type arguments (R1).
555 __ Push(R2);
556 __ Push(R1);
557
558 Label is_instance, is_not_instance;
559 // If type is instantiated and non-parameterized, we can inline code
560 // checking whether the tested instance is a Smi.
561 if (type.IsInstantiated()) {
562 // A null object is only an instance of Object and dynamic, which has
563 // already been checked above (if the type is instantiated). So we can
564 // return false here if the instance is null (and if the type is
565 // instantiated).
566 // We can only inline this null check if the type is instantiated at compile
567 // time, since an uninstantiated type at compile time could be Object or
568 // dynamic at run time.
569 __ CompareObject(R0, Object::null_object(), PP);
570 __ b(&is_not_instance, EQ);
571 }
572
573 // Generate inline instanceof test.
574 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle();
575 test_cache = GenerateInlineInstanceof(token_pos, type,
576 &is_instance, &is_not_instance);
577
578 // test_cache is null if there is no fall-through.
579 Label done;
580 if (!test_cache.IsNull()) {
581 // Generate runtime call.
582 // Load instantiator (R2) and its type arguments (R1).
583 __ ldr(R1, Address(SP, 0 * kWordSize));
584 __ ldr(R2, Address(SP, 1 * kWordSize));
585 __ PushObject(Object::ZoneHandle(), PP); // Make room for the result.
586 __ Push(R0); // Push the instance.
587 __ PushObject(type, PP); // Push the type.
588 // Push instantiator (R2) and its type arguments (R1).
589 __ Push(R2);
590 __ Push(R1);
591 __ LoadObject(R0, test_cache, PP);
592 __ Push(R0);
593 GenerateRuntimeCall(token_pos, deopt_id, kInstanceofRuntimeEntry, 5, locs);
594 // Pop the parameters supplied to the runtime entry. The result of the
595 // instanceof runtime call will be left as the result of the operation.
596 __ Drop(5);
597 if (negate_result) {
598 __ Pop(R1);
599 __ LoadObject(R0, Bool::True(), PP);
600 __ CompareRegisters(R1, R0);
601 __ b(&done, NE);
602 __ LoadObject(R0, Bool::False(), PP);
603 } else {
604 __ Pop(R0);
605 }
606 __ b(&done);
607 }
608 __ Bind(&is_not_instance);
609 __ LoadObject(R0, Bool::Get(negate_result), PP);
610 __ b(&done);
611
612 __ Bind(&is_instance);
613 __ LoadObject(R0, Bool::Get(!negate_result), PP);
614 __ Bind(&done);
615 // Remove instantiator (R2) and its type arguments (R1).
616 __ Drop(2);
441 } 617 }
442 618
443 619
444 // Optimize assignable type check by adding inlined tests for: 620 // Optimize assignable type check by adding inlined tests for:
445 // - NULL -> return NULL. 621 // - NULL -> return NULL.
446 // - Smi -> compile time subtype check (only if dst class is not parameterized). 622 // - Smi -> compile time subtype check (only if dst class is not parameterized).
447 // - Class equality (only if class is not parameterized). 623 // - Class equality (only if class is not parameterized).
448 // Inputs: 624 // Inputs:
449 // - R0: instance being type checked. 625 // - R0: instance being type checked.
450 // - R1: instantiator type arguments or raw_null. 626 // - R1: instantiator type arguments or raw_null.
(...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after
750 __ b(&null_args_loop_condition); 926 __ b(&null_args_loop_condition);
751 __ Bind(&null_args_loop); 927 __ Bind(&null_args_loop);
752 __ str(TMP, original_argument_addr); 928 __ str(TMP, original_argument_addr);
753 __ Bind(&null_args_loop_condition); 929 __ Bind(&null_args_loop_condition);
754 __ subs(R8, R8, Operand(1)); 930 __ subs(R8, R8, Operand(1));
755 __ b(&null_args_loop, PL); 931 __ b(&null_args_loop, PL);
756 } 932 }
757 933
758 934
759 void FlowGraphCompiler::GenerateInlinedGetter(intptr_t offset) { 935 void FlowGraphCompiler::GenerateInlinedGetter(intptr_t offset) {
760 UNIMPLEMENTED(); 936 // LR: return address.
937 // SP: receiver.
938 // Sequence node has one return node, its input is load field node.
939 __ Comment("Inlined Getter");
940 __ LoadFromOffset(R0, SP, 0 * kWordSize);
941 __ LoadFromOffset(R0, R0, offset - kHeapObjectTag);
942 __ ret();
761 } 943 }
762 944
763 945
764 void FlowGraphCompiler::GenerateInlinedSetter(intptr_t offset) { 946 void FlowGraphCompiler::GenerateInlinedSetter(intptr_t offset) {
765 UNIMPLEMENTED(); 947 UNIMPLEMENTED();
766 } 948 }
767 949
768 950
769 void FlowGraphCompiler::EmitFrameEntry() { 951 void FlowGraphCompiler::EmitFrameEntry() {
770 const Function& function = parsed_function().function(); 952 const Function& function = parsed_function().function();
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
909 1091
910 VisitBlocks(); 1092 VisitBlocks();
911 1093
912 __ hlt(0); 1094 __ hlt(0);
913 GenerateDeferredCode(); 1095 GenerateDeferredCode();
914 // Emit function patching code. This will be swapped with the first 3 1096 // Emit function patching code. This will be swapped with the first 3
915 // instructions at entry point. 1097 // instructions at entry point.
916 AddCurrentDescriptor(PcDescriptors::kPatchCode, 1098 AddCurrentDescriptor(PcDescriptors::kPatchCode,
917 Isolate::kNoDeoptId, 1099 Isolate::kNoDeoptId,
918 0); // No token position. 1100 0); // No token position.
919 // This is patched up to a point in FrameEntry where the PP for the 1101 __ BranchFixed(&StubCode::FixCallersTargetLabel());
920 // current function is in R13 instead of PP.
921 __ BranchPatchable(&StubCode::FixCallersTargetLabel(), R13);
922 1102
923 AddCurrentDescriptor(PcDescriptors::kLazyDeoptJump, 1103 AddCurrentDescriptor(PcDescriptors::kLazyDeoptJump,
924 Isolate::kNoDeoptId, 1104 Isolate::kNoDeoptId,
925 0); // No token position. 1105 0); // No token position.
926 // TODO(zra): Can I use a normal BranchPatchable here? Probably have to change 1106 // TODO(zra): Can I use a normal BranchPatchable here? Probably have to change
927 // the CodePatcher. 1107 // the CodePatcher.
928 __ BranchFixed(&StubCode::DeoptimizeLazyLabel()); 1108 __ BranchFixed(&StubCode::DeoptimizeLazyLabel());
929 } 1109 }
930 1110
931 1111
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
999 } 1179 }
1000 1180
1001 1181
1002 void FlowGraphCompiler::EmitOptimizedInstanceCall( 1182 void FlowGraphCompiler::EmitOptimizedInstanceCall(
1003 ExternalLabel* target_label, 1183 ExternalLabel* target_label,
1004 const ICData& ic_data, 1184 const ICData& ic_data,
1005 intptr_t argument_count, 1185 intptr_t argument_count,
1006 intptr_t deopt_id, 1186 intptr_t deopt_id,
1007 intptr_t token_pos, 1187 intptr_t token_pos,
1008 LocationSummary* locs) { 1188 LocationSummary* locs) {
1009 UNIMPLEMENTED(); 1189 ASSERT(Array::Handle(ic_data.arguments_descriptor()).Length() > 0);
1190 // Each ICData propagated from unoptimized to optimized code contains the
1191 // function that corresponds to the Dart function of that IC call. Due
1192 // to inlining in optimized code, that function may not correspond to the
1193 // top-level function (parsed_function().function()) which could be
1194 // reoptimized and which counter needs to be incremented.
1195 // Pass the function explicitly, it is used in IC stub.
1196
1197 __ LoadObject(R6, parsed_function().function(), PP);
1198 __ LoadObject(R5, ic_data, PP);
1199 GenerateDartCall(deopt_id,
1200 token_pos,
1201 target_label,
1202 PcDescriptors::kIcCall,
1203 locs);
1204 __ Drop(argument_count);
1010 } 1205 }
1011 1206
1012 1207
1013 void FlowGraphCompiler::EmitInstanceCall(ExternalLabel* target_label, 1208 void FlowGraphCompiler::EmitInstanceCall(ExternalLabel* target_label,
1014 const ICData& ic_data, 1209 const ICData& ic_data,
1015 intptr_t argument_count, 1210 intptr_t argument_count,
1016 intptr_t deopt_id, 1211 intptr_t deopt_id,
1017 intptr_t token_pos, 1212 intptr_t token_pos,
1018 LocationSummary* locs) { 1213 LocationSummary* locs) {
1019 ASSERT(Array::Handle(ic_data.arguments_descriptor()).Length() > 0); 1214 ASSERT(Array::Handle(ic_data.arguments_descriptor()).Length() > 0);
1020 __ LoadObject(R5, ic_data, PP); 1215 __ LoadObject(R5, ic_data, PP);
1021 GenerateDartCall(deopt_id, 1216 GenerateDartCall(deopt_id,
1022 token_pos, 1217 token_pos,
1023 target_label, 1218 target_label,
1024 PcDescriptors::kIcCall, 1219 PcDescriptors::kIcCall,
1025 locs); 1220 locs);
1026 __ Drop(argument_count); 1221 __ Drop(argument_count);
1027 } 1222 }
1028 1223
1029 1224
1030 void FlowGraphCompiler::EmitMegamorphicInstanceCall( 1225 void FlowGraphCompiler::EmitMegamorphicInstanceCall(
1031 const ICData& ic_data, 1226 const ICData& ic_data,
1032 intptr_t argument_count, 1227 intptr_t argument_count,
1033 intptr_t deopt_id, 1228 intptr_t deopt_id,
1034 intptr_t token_pos, 1229 intptr_t token_pos,
1035 LocationSummary* locs) { 1230 LocationSummary* locs) {
1036 UNIMPLEMENTED(); 1231 MegamorphicCacheTable* table = Isolate::Current()->megamorphic_cache_table();
1232 const String& name = String::Handle(ic_data.target_name());
1233 const Array& arguments_descriptor =
1234 Array::ZoneHandle(ic_data.arguments_descriptor());
1235 ASSERT(!arguments_descriptor.IsNull() && (arguments_descriptor.Length() > 0));
1236 const MegamorphicCache& cache =
1237 MegamorphicCache::ZoneHandle(table->Lookup(name, arguments_descriptor));
1238 Label not_smi, load_cache;
1239 __ LoadFromOffset(R0, SP, (argument_count - 1) * kWordSize);
1240 __ tsti(R0, kSmiTagMask);
1241 __ b(&not_smi, NE);
1242 __ LoadImmediate(R0, Smi::RawValue(kSmiCid), PP);
1243 __ b(&load_cache);
1244
1245 __ Bind(&not_smi);
1246 __ LoadClassId(R0, R0);
1247 __ SmiTag(R0);
1248
1249 // R0: class ID of the receiver (smi).
1250 __ Bind(&load_cache);
1251 __ LoadObject(R1, cache, PP);
1252 __ LoadFieldFromOffset(R2, R1, MegamorphicCache::buckets_offset());
1253 __ LoadFieldFromOffset(R1, R1, MegamorphicCache::mask_offset());
1254 // R2: cache buckets array.
1255 // R1: mask.
1256 __ mov(R3, R0);
1257
1258 Label loop, update, call_target_function;
1259 __ b(&loop);
1260
1261 __ Bind(&update);
1262 __ add(R3, R3, Operand(Smi::RawValue(1)));
1263 __ Bind(&loop);
1264 __ and_(R3, R3, Operand(R1));
1265 const intptr_t base = Array::data_offset();
1266 // R3 is smi tagged, but table entries are 8 bytes, so LSL 2.
1267 __ add(TMP, R2, Operand(R3, LSL, 2));
1268 __ LoadFieldFromOffset(R4, TMP, base);
1269
1270 ASSERT(kIllegalCid == 0);
1271 __ tst(R4, Operand(R4));
1272 __ b(&call_target_function, EQ);
1273 __ CompareRegisters(R4, R0);
1274 __ b(&update, NE);
1275
1276 __ Bind(&call_target_function);
1277 // Call the target found in the cache. For a class id match, this is a
1278 // proper target for the given name and arguments descriptor. If the
1279 // illegal class id was found, the target is a cache miss handler that can
1280 // be invoked as a normal Dart function.
1281 __ add(TMP, R2, Operand(R3, LSL, 2));
1282 __ LoadFieldFromOffset(R0, TMP, base + kWordSize);
1283 __ LoadFieldFromOffset(R1, R0, Function::code_offset());
1284 __ LoadFieldFromOffset(R1, R1, Code::instructions_offset());
1285 __ LoadObject(R5, ic_data, PP);
1286 __ LoadObject(R4, arguments_descriptor, PP);
1287 __ AddImmediate(R1, R1, Instructions::HeaderSize() - kHeapObjectTag, PP);
1288 __ blr(R1);
1289 AddCurrentDescriptor(PcDescriptors::kOther, Isolate::kNoDeoptId, token_pos);
1290 RecordSafepoint(locs);
1291 AddDeoptIndexAtCall(Isolate::ToDeoptAfter(deopt_id), token_pos);
1292 __ Drop(argument_count);
1037 } 1293 }
1038 1294
1039 1295
1040 void FlowGraphCompiler::EmitUnoptimizedStaticCall( 1296 void FlowGraphCompiler::EmitUnoptimizedStaticCall(
1041 const Function& target_function, 1297 const Function& target_function,
1042 const Array& arguments_descriptor, 1298 const Array& arguments_descriptor,
1043 intptr_t argument_count, 1299 intptr_t argument_count,
1044 intptr_t deopt_id, 1300 intptr_t deopt_id,
1045 intptr_t token_pos, 1301 intptr_t token_pos,
1046 LocationSummary* locs) { 1302 LocationSummary* locs) {
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1078 } 1334 }
1079 1335
1080 1336
1081 void FlowGraphCompiler::EmitOptimizedStaticCall( 1337 void FlowGraphCompiler::EmitOptimizedStaticCall(
1082 const Function& function, 1338 const Function& function,
1083 const Array& arguments_descriptor, 1339 const Array& arguments_descriptor,
1084 intptr_t argument_count, 1340 intptr_t argument_count,
1085 intptr_t deopt_id, 1341 intptr_t deopt_id,
1086 intptr_t token_pos, 1342 intptr_t token_pos,
1087 LocationSummary* locs) { 1343 LocationSummary* locs) {
1088 UNIMPLEMENTED(); 1344 __ LoadObject(R4, arguments_descriptor, PP);
1345 // Do not use the code from the function, but let the code be patched so that
1346 // we can record the outgoing edges to other code.
1347 GenerateDartCall(deopt_id,
1348 token_pos,
1349 &StubCode::CallStaticFunctionLabel(),
1350 PcDescriptors::kOptStaticCall,
1351 locs);
1352 AddStaticCallTarget(function);
1353 __ Drop(argument_count);
1089 } 1354 }
1090 1355
1091 1356
1092 void FlowGraphCompiler::EmitEqualityRegConstCompare(Register reg, 1357 void FlowGraphCompiler::EmitEqualityRegConstCompare(Register reg,
1093 const Object& obj, 1358 const Object& obj,
1094 bool needs_number_check, 1359 bool needs_number_check,
1095 intptr_t token_pos) { 1360 intptr_t token_pos) {
1096 UNIMPLEMENTED(); 1361 if (needs_number_check) {
1362 ASSERT(!obj.IsMint() && !obj.IsDouble() && !obj.IsBigint());
1363 __ Push(reg);
1364 __ PushObject(obj, PP);
1365 if (is_optimizing()) {
1366 __ BranchLinkPatchable(
1367 &StubCode::OptimizedIdenticalWithNumberCheckLabel());
1368 } else {
1369 __ BranchLinkPatchable(
1370 &StubCode::UnoptimizedIdenticalWithNumberCheckLabel());
1371 }
1372 if (token_pos != Scanner::kNoSourcePos) {
1373 AddCurrentDescriptor(PcDescriptors::kRuntimeCall,
1374 Isolate::kNoDeoptId,
1375 token_pos);
1376 }
1377 __ Drop(1); // Discard constant.
1378 __ Pop(reg); // Restore 'reg'.
1379 return;
1380 }
1381
1382 __ CompareObject(reg, obj, PP);
1097 } 1383 }
1098 1384
1099 1385
1100 void FlowGraphCompiler::EmitEqualityRegRegCompare(Register left, 1386 void FlowGraphCompiler::EmitEqualityRegRegCompare(Register left,
1101 Register right, 1387 Register right,
1102 bool needs_number_check, 1388 bool needs_number_check,
1103 intptr_t token_pos) { 1389 intptr_t token_pos) {
1104 if (needs_number_check) { 1390 if (needs_number_check) {
1105 __ Push(left); 1391 __ Push(left);
1106 __ Push(right); 1392 __ Push(right);
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
1179 1465
1180 1466
1181 void FlowGraphCompiler::EmitTestAndCall(const ICData& ic_data, 1467 void FlowGraphCompiler::EmitTestAndCall(const ICData& ic_data,
1182 Register class_id_reg, 1468 Register class_id_reg,
1183 intptr_t argument_count, 1469 intptr_t argument_count,
1184 const Array& argument_names, 1470 const Array& argument_names,
1185 Label* deopt, 1471 Label* deopt,
1186 intptr_t deopt_id, 1472 intptr_t deopt_id,
1187 intptr_t token_index, 1473 intptr_t token_index,
1188 LocationSummary* locs) { 1474 LocationSummary* locs) {
1189 UNIMPLEMENTED(); 1475 ASSERT(is_optimizing());
1476 ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0));
1477 Label match_found;
1478 const intptr_t len = ic_data.NumberOfChecks();
1479 GrowableArray<CidTarget> sorted(len);
1480 SortICDataByCount(ic_data, &sorted);
1481 ASSERT(class_id_reg != R4);
1482 ASSERT(len > 0); // Why bother otherwise.
1483 const Array& arguments_descriptor =
1484 Array::ZoneHandle(ArgumentsDescriptor::New(argument_count,
1485 argument_names));
1486 __ LoadObject(R4, arguments_descriptor, PP);
1487 for (intptr_t i = 0; i < len; i++) {
1488 const bool is_last_check = (i == (len - 1));
1489 Label next_test;
1490 __ CompareImmediate(class_id_reg, sorted[i].cid, PP);
1491 if (is_last_check) {
1492 __ b(deopt, NE);
1493 } else {
1494 __ b(&next_test, NE);
1495 }
1496 // Do not use the code from the function, but let the code be patched so
1497 // that we can record the outgoing edges to other code.
1498 GenerateDartCall(deopt_id,
1499 token_index,
1500 &StubCode::CallStaticFunctionLabel(),
1501 PcDescriptors::kOptStaticCall,
1502 locs);
1503 const Function& function = *sorted[i].target;
1504 AddStaticCallTarget(function);
1505 __ Drop(argument_count);
1506 if (!is_last_check) {
1507 __ b(&match_found);
1508 }
1509 __ Bind(&next_test);
1510 }
1511 __ Bind(&match_found);
1190 } 1512 }
1191 1513
1192 1514
1193 // Do not implement or use this function. 1515 // Do not implement or use this function.
1194 FieldAddress FlowGraphCompiler::ElementAddressForIntIndex(intptr_t cid, 1516 FieldAddress FlowGraphCompiler::ElementAddressForIntIndex(intptr_t cid,
1195 intptr_t index_scale, 1517 intptr_t index_scale,
1196 Register array, 1518 Register array,
1197 intptr_t index) { 1519 intptr_t index) {
1198 UNREACHABLE(); 1520 UNREACHABLE();
1199 return FieldAddress(array, index); 1521 return FieldAddress(array, index);
(...skipping 26 matching lines...) Expand all
1226 UNREACHABLE(); 1548 UNREACHABLE();
1227 return FieldAddress(array, index); 1549 return FieldAddress(array, index);
1228 } 1550 }
1229 1551
1230 1552
1231 #undef __ 1553 #undef __
1232 #define __ compiler_->assembler()-> 1554 #define __ compiler_->assembler()->
1233 1555
1234 1556
1235 void ParallelMoveResolver::EmitMove(int index) { 1557 void ParallelMoveResolver::EmitMove(int index) {
1236 UNIMPLEMENTED(); 1558 MoveOperands* move = moves_[index];
1559 const Location source = move->src();
1560 const Location destination = move->dest();
1561
1562 if (source.IsRegister()) {
1563 if (destination.IsRegister()) {
1564 __ mov(destination.reg(), source.reg());
1565 } else {
1566 ASSERT(destination.IsStackSlot());
1567 const intptr_t dest_offset = destination.ToStackSlotOffset();
1568 __ StoreToOffset(source.reg(), FP, dest_offset);
1569 }
1570 } else if (source.IsStackSlot()) {
1571 if (destination.IsRegister()) {
1572 const intptr_t source_offset = source.ToStackSlotOffset();
1573 __ LoadFromOffset(destination.reg(), FP, source_offset);
1574 } else {
1575 ASSERT(destination.IsStackSlot());
1576 const intptr_t source_offset = source.ToStackSlotOffset();
1577 const intptr_t dest_offset = destination.ToStackSlotOffset();
1578 __ LoadFromOffset(TMP, FP, source_offset);
1579 __ StoreToOffset(TMP, FP, dest_offset);
1580 }
1581 } else if (source.IsFpuRegister()) {
1582 if (destination.IsFpuRegister()) {
1583 __ fmovdd(destination.fpu_reg(), source.fpu_reg());
1584 } else {
1585 if (destination.IsDoubleStackSlot()) {
1586 const intptr_t dest_offset = destination.ToStackSlotOffset();
1587 VRegister src = source.fpu_reg();
1588 __ StoreDToOffset(src, FP, dest_offset);
1589 } else {
1590 ASSERT(destination.IsQuadStackSlot());
1591 UNIMPLEMENTED();
1592 }
1593 }
1594 } else if (source.IsDoubleStackSlot()) {
1595 if (destination.IsFpuRegister()) {
1596 const intptr_t dest_offset = source.ToStackSlotOffset();
1597 const VRegister dst = destination.fpu_reg();
1598 __ LoadDFromOffset(dst, FP, dest_offset);
1599 } else {
1600 ASSERT(destination.IsDoubleStackSlot());
1601 const intptr_t source_offset = source.ToStackSlotOffset();
1602 const intptr_t dest_offset = destination.ToStackSlotOffset();
1603 __ LoadDFromOffset(VTMP, FP, source_offset);
1604 __ StoreDToOffset(VTMP, FP, dest_offset);
1605 }
1606 } else if (source.IsQuadStackSlot()) {
1607 UNIMPLEMENTED();
1608 } else {
1609 ASSERT(source.IsConstant());
1610 const Object& constant = source.constant();
1611 if (destination.IsRegister()) {
1612 __ LoadObject(destination.reg(), constant, PP);
1613 } else if (destination.IsFpuRegister()) {
1614 const VRegister dst = destination.fpu_reg();
1615 __ LoadObject(TMP, constant, PP);
1616 __ LoadDFieldFromOffset(dst, TMP, Double::value_offset());
1617 } else {
1618 ASSERT(destination.IsStackSlot());
1619 const intptr_t dest_offset = destination.ToStackSlotOffset();
1620 __ LoadObject(TMP, constant, PP);
1621 __ StoreToOffset(TMP, FP, dest_offset);
1622 }
1623 }
1624
1625 move->Eliminate();
1237 } 1626 }
1238 1627
1239 1628
1240 void ParallelMoveResolver::EmitSwap(int index) { 1629 void ParallelMoveResolver::EmitSwap(int index) {
1241 UNIMPLEMENTED(); 1630 MoveOperands* move = moves_[index];
1631 const Location source = move->src();
1632 const Location destination = move->dest();
1633
1634 if (source.IsRegister() && destination.IsRegister()) {
1635 ASSERT(source.reg() != TMP);
1636 ASSERT(destination.reg() != TMP);
1637 __ mov(TMP, source.reg());
1638 __ mov(source.reg(), destination.reg());
1639 __ mov(destination.reg(), TMP);
1640 } else if (source.IsRegister() && destination.IsStackSlot()) {
1641 Exchange(source.reg(), destination.ToStackSlotOffset());
1642 } else if (source.IsStackSlot() && destination.IsRegister()) {
1643 Exchange(destination.reg(), source.ToStackSlotOffset());
1644 } else if (source.IsStackSlot() && destination.IsStackSlot()) {
1645 Exchange(source.ToStackSlotOffset(), destination.ToStackSlotOffset());
1646 } else if (source.IsFpuRegister() && destination.IsFpuRegister()) {
1647 const VRegister dst = destination.fpu_reg();
1648 const VRegister src = source.fpu_reg();
1649 __ fmovdd(VTMP, src);
1650 __ fmovdd(src, dst);
1651 __ fmovdd(dst, VTMP);
1652 } else if (source.IsFpuRegister() || destination.IsFpuRegister()) {
1653 ASSERT(destination.IsDoubleStackSlot() ||
1654 destination.IsQuadStackSlot() ||
1655 source.IsDoubleStackSlot() ||
1656 source.IsQuadStackSlot());
1657 bool double_width = destination.IsDoubleStackSlot() ||
1658 source.IsDoubleStackSlot();
1659 VRegister reg = source.IsFpuRegister() ? source.fpu_reg()
1660 : destination.fpu_reg();
1661 const intptr_t slot_offset = source.IsFpuRegister()
1662 ? destination.ToStackSlotOffset()
1663 : source.ToStackSlotOffset();
1664
1665 if (double_width) {
1666 __ LoadDFromOffset(VTMP, FP, slot_offset);
1667 __ StoreDToOffset(reg, FP, slot_offset);
1668 __ fmovdd(reg, VTMP);
1669 } else {
1670 UNIMPLEMENTED();
1671 }
1672 } else if (source.IsDoubleStackSlot() && destination.IsDoubleStackSlot()) {
1673 const intptr_t source_offset = source.ToStackSlotOffset();
1674 const intptr_t dest_offset = destination.ToStackSlotOffset();
1675
1676 ScratchFpuRegisterScope ensure_scratch(this, VTMP);
1677 VRegister scratch = ensure_scratch.reg();
1678 __ LoadDFromOffset(VTMP, FP, source_offset);
1679 __ LoadDFromOffset(scratch, FP, dest_offset);
1680 __ StoreDToOffset(VTMP, FP, dest_offset);
1681 __ StoreDToOffset(scratch, FP, source_offset);
1682 } else if (source.IsQuadStackSlot() && destination.IsQuadStackSlot()) {
1683 UNIMPLEMENTED();
1684 } else {
1685 UNREACHABLE();
1686 }
1687
1688 // The swap of source and destination has executed a move from source to
1689 // destination.
1690 move->Eliminate();
1691
1692 // Any unperformed (including pending) move with a source of either
1693 // this move's source or destination needs to have their source
1694 // changed to reflect the state of affairs after the swap.
1695 for (int i = 0; i < moves_.length(); ++i) {
1696 const MoveOperands& other_move = *moves_[i];
1697 if (other_move.Blocks(source)) {
1698 moves_[i]->set_src(destination);
1699 } else if (other_move.Blocks(destination)) {
1700 moves_[i]->set_src(source);
1701 }
1702 }
1242 } 1703 }
1243 1704
1244 1705
1245 void ParallelMoveResolver::MoveMemoryToMemory(const Address& dst, 1706 void ParallelMoveResolver::MoveMemoryToMemory(const Address& dst,
1246 const Address& src) { 1707 const Address& src) {
1247 UNIMPLEMENTED(); 1708 UNIMPLEMENTED();
1248 } 1709 }
1249 1710
1250 1711
1251 void ParallelMoveResolver::StoreObject(const Address& dst, const Object& obj) { 1712 void ParallelMoveResolver::StoreObject(const Address& dst, const Object& obj) {
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
1296 void ParallelMoveResolver::RestoreFpuScratch(FpuRegister reg) { 1757 void ParallelMoveResolver::RestoreFpuScratch(FpuRegister reg) {
1297 UNIMPLEMENTED(); 1758 UNIMPLEMENTED();
1298 } 1759 }
1299 1760
1300 1761
1301 #undef __ 1762 #undef __
1302 1763
1303 } // namespace dart 1764 } // namespace dart
1304 1765
1305 #endif // defined TARGET_ARCH_ARM64 1766 #endif // defined TARGET_ARCH_ARM64
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_compiler_arm.cc ('k') | runtime/vm/flow_graph_compiler_ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698