OLD | NEW |
---|---|
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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_X64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. |
6 #if defined(TARGET_ARCH_X64) | 6 #if defined(TARGET_ARCH_X64) |
7 | 7 |
8 #include "vm/flow_graph_compiler.h" | 8 #include "vm/flow_graph_compiler.h" |
9 | 9 |
10 #include "lib/error.h" | 10 #include "lib/error.h" |
(...skipping 14 matching lines...) Expand all Loading... | |
25 DEFINE_FLAG(bool, print_scopes, false, "Print scopes of local variables."); | 25 DEFINE_FLAG(bool, print_scopes, false, "Print scopes of local variables."); |
26 DEFINE_FLAG(bool, trace_functions, false, "Trace entry of each function."); | 26 DEFINE_FLAG(bool, trace_functions, false, "Trace entry of each function."); |
27 DECLARE_FLAG(bool, enable_type_checks); | 27 DECLARE_FLAG(bool, enable_type_checks); |
28 DECLARE_FLAG(bool, intrinsify); | 28 DECLARE_FLAG(bool, intrinsify); |
29 DECLARE_FLAG(bool, optimization_counter_threshold); | 29 DECLARE_FLAG(bool, optimization_counter_threshold); |
30 DECLARE_FLAG(bool, print_ast); | 30 DECLARE_FLAG(bool, print_ast); |
31 DECLARE_FLAG(bool, report_usage_count); | 31 DECLARE_FLAG(bool, report_usage_count); |
32 DECLARE_FLAG(bool, code_comments); | 32 DECLARE_FLAG(bool, code_comments); |
33 | 33 |
34 | 34 |
35 static Register ToRegister(Location loc) { | |
36 return RegisterLocation::Cast(loc).reg(); | |
37 } | |
38 | |
39 | |
35 FlowGraphCompiler::FlowGraphCompiler( | 40 FlowGraphCompiler::FlowGraphCompiler( |
36 Assembler* assembler, | 41 Assembler* assembler, |
37 const ParsedFunction& parsed_function, | 42 const ParsedFunction& parsed_function, |
38 const GrowableArray<BlockEntryInstr*>& block_order, | 43 const GrowableArray<BlockEntryInstr*>& block_order, |
39 bool is_optimizing) | 44 bool is_optimizing) |
40 : FlowGraphVisitor(block_order), | 45 : FlowGraphVisitor(block_order), |
41 assembler_(assembler), | 46 assembler_(assembler), |
42 parsed_function_(parsed_function), | 47 parsed_function_(parsed_function), |
43 block_info_(block_order.length()), | 48 block_info_(block_order.length()), |
44 current_block_(NULL), | 49 current_block_(NULL), |
(...skipping 494 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
539 EmitInstanceCall(comp->cid(), | 544 EmitInstanceCall(comp->cid(), |
540 comp->token_index(), | 545 comp->token_index(), |
541 comp->try_index(), | 546 comp->try_index(), |
542 comp->function_name(), | 547 comp->function_name(), |
543 comp->ArgumentCount(), | 548 comp->ArgumentCount(), |
544 comp->argument_names(), | 549 comp->argument_names(), |
545 comp->checked_argument_count()); | 550 comp->checked_argument_count()); |
546 } | 551 } |
547 | 552 |
548 | 553 |
554 LocationSummary* StrictCompareComp::MakeLocationSummary() { | |
srdjan
2012/05/18 18:00:14
In unoptimizing compiler this is the same for all
Vyacheslav Egorov (Google)
2012/05/20 12:07:46
Preallocating and reusing proves to be hard becaus
srdjan
2012/05/21 16:05:22
Valid points, good suggestion. Let's not do anythi
| |
555 LocationSummary* summary = new LocationSummary(2); | |
556 summary->SetInputLocationAt( | |
557 0, UnallocatedLocation(UnallocatedLocation::REGISTER)); | |
558 summary->SetInputLocationAt( | |
559 1, UnallocatedLocation(UnallocatedLocation::REGISTER)); | |
srdjan
2012/05/18 18:00:14
Too verbose.
Vyacheslav Egorov (Google)
2012/05/20 12:07:46
introduced a helper function and shortened method
| |
560 summary->set_result_location( | |
561 UnallocatedLocation(UnallocatedLocation::SAME_AS_FIRST_INPUT)); | |
562 return summary; | |
srdjan
2012/05/18 18:00:14
As you said, this does not belong here. Maybe in a
Vyacheslav Egorov (Google)
2012/05/20 12:07:46
moved to intermediate_language_x64.cc
| |
563 } | |
564 | |
565 | |
549 void FlowGraphCompiler::VisitStrictCompare(StrictCompareComp* comp) { | 566 void FlowGraphCompiler::VisitStrictCompare(StrictCompareComp* comp) { |
550 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | 567 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); |
551 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); | 568 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); |
552 LoadValue(RDX, comp->right()); | 569 |
553 LoadValue(RAX, comp->left()); | 570 Register left = ToRegister(comp->GetLocationSummary()->InputLocationAt(0)); |
554 __ cmpq(RAX, RDX); | 571 Register right = ToRegister(comp->GetLocationSummary()->InputLocationAt(1)); |
572 Register result = ToRegister(comp->GetLocationSummary()->result_location()); | |
srdjan
2012/05/18 18:00:14
Too verbose, maybe:
comp->locs()->in(0)->AsRegiste
Vyacheslav Egorov (Google)
2012/05/20 12:07:46
Done.
| |
573 | |
574 __ cmpq(left, right); | |
555 Label load_true, done; | 575 Label load_true, done; |
556 if (comp->kind() == Token::kEQ_STRICT) { | 576 if (comp->kind() == Token::kEQ_STRICT) { |
557 __ j(EQUAL, &load_true, Assembler::kNearJump); | 577 __ j(EQUAL, &load_true, Assembler::kNearJump); |
558 } else { | 578 } else { |
559 __ j(NOT_EQUAL, &load_true, Assembler::kNearJump); | 579 __ j(NOT_EQUAL, &load_true, Assembler::kNearJump); |
560 } | 580 } |
561 __ LoadObject(RAX, bool_false); | 581 __ LoadObject(result, bool_false); |
562 __ jmp(&done, Assembler::kNearJump); | 582 __ jmp(&done, Assembler::kNearJump); |
563 __ Bind(&load_true); | 583 __ Bind(&load_true); |
564 __ LoadObject(RAX, bool_true); | 584 __ LoadObject(result, bool_true); |
565 __ Bind(&done); | 585 __ Bind(&done); |
566 } | 586 } |
567 | 587 |
568 | 588 |
569 void FlowGraphCompiler::VisitEqualityCompare(EqualityCompareComp* comp) { | 589 void FlowGraphCompiler::VisitEqualityCompare(EqualityCompareComp* comp) { |
570 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | 590 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); |
571 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); | 591 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); |
572 const Immediate raw_null = | 592 const Immediate raw_null = |
573 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 593 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
574 Label done, load_true, non_null_compare; | 594 Label done, load_true, non_null_compare; |
(...skipping 540 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1115 | 1135 |
1116 ASSERT(!comp->exception_var().is_captured()); | 1136 ASSERT(!comp->exception_var().is_captured()); |
1117 ASSERT(!comp->stacktrace_var().is_captured()); | 1137 ASSERT(!comp->stacktrace_var().is_captured()); |
1118 __ movq(Address(RBP, comp->exception_var().index() * kWordSize), | 1138 __ movq(Address(RBP, comp->exception_var().index() * kWordSize), |
1119 kExceptionObjectReg); | 1139 kExceptionObjectReg); |
1120 __ movq(Address(RBP, comp->stacktrace_var().index() * kWordSize), | 1140 __ movq(Address(RBP, comp->stacktrace_var().index() * kWordSize), |
1121 kStackTraceObjectReg); | 1141 kStackTraceObjectReg); |
1122 } | 1142 } |
1123 | 1143 |
1124 | 1144 |
1145 static Register AllocateFreeRegister(bool* blocked_registers) { | |
srdjan
2012/05/18 18:00:14
I would rather use BitVector or GrowableArray sinc
Vyacheslav Egorov (Google)
2012/05/20 12:07:46
both are zone allocated which seems unnecessary ex
| |
1146 for (int regno = 0; regno < kNumberOfCpuRegisters; regno++) { | |
1147 if (!blocked_registers[regno]) { | |
1148 blocked_registers[regno] = true; | |
1149 return static_cast<Register>(regno); | |
srdjan
2012/05/18 18:00:14
The register allocation needs also to move out of
Vyacheslav Egorov (Google)
2012/05/20 12:07:46
Moved simple register allocator into LocationSumma
| |
1150 } | |
1151 } | |
1152 UNREACHABLE(); | |
1153 return kNoRegister; | |
1154 } | |
1155 | |
1156 | |
1157 static void AllocateRegisters(LocationSummary* summary) { | |
1158 bool blocked_registers[kNumberOfCpuRegisters] = { false }; | |
1159 | |
1160 for (intptr_t i = 0; i < summary->InputLocationsCount(); i++) { | |
1161 Location loc = summary->InputLocationAt(i); | |
1162 if (loc.kind() == Location::REGISTER) { | |
1163 ASSERT(!blocked_registers[ToRegister(loc)]); | |
1164 blocked_registers[loc.value()] = true; | |
1165 } | |
1166 } | |
1167 | |
1168 for (intptr_t i = 0; i < summary->InputLocationsCount(); i++) { | |
1169 Location loc = summary->InputLocationAt(i); | |
1170 if (loc.kind() == Location::UNALLOCATED) { | |
1171 ASSERT(UnallocatedLocation::Cast(loc).policy() == | |
1172 UnallocatedLocation::REGISTER); | |
1173 summary->SetInputLocationAt(i, RegisterLocation( | |
1174 AllocateFreeRegister(blocked_registers))); | |
1175 } | |
1176 } | |
1177 | |
1178 Location result_location = summary->result_location(); | |
1179 if (result_location.kind() == Location::UNALLOCATED) { | |
1180 switch (UnallocatedLocation::Cast(result_location).policy()) { | |
1181 case UnallocatedLocation::REGISTER: | |
1182 result_location = RegisterLocation( | |
1183 AllocateFreeRegister(blocked_registers)); | |
1184 break; | |
1185 case UnallocatedLocation::SAME_AS_FIRST_INPUT: | |
1186 result_location = summary->InputLocationAt(0); | |
1187 break; | |
1188 } | |
1189 summary->set_result_location(result_location); | |
1190 } | |
1191 } | |
1192 | |
1193 | |
1194 void FlowGraphCompiler::EmitInstructionPrologue(Instruction* instr) { | |
1195 LocationSummary* summary = instr->GetLocationSummary(); | |
1196 | |
1197 // Check if current instruction has any special location requirements. | |
1198 if (summary == NULL) return; | |
1199 | |
1200 AllocateRegisters(summary); | |
1201 | |
1202 // Load instruction inputs into allocated registers. | |
1203 for (intptr_t i = summary->InputLocationsCount() - 1; i >= 0; i--) { | |
1204 Location loc = summary->InputLocationAt(i); | |
1205 if (loc.kind() == Location::REGISTER) { | |
1206 __ popq(ToRegister(loc)); | |
1207 } | |
1208 } | |
1209 } | |
1210 | |
1211 | |
1125 void FlowGraphCompiler::VisitBlocks() { | 1212 void FlowGraphCompiler::VisitBlocks() { |
1126 for (intptr_t i = 0; i < block_order_.length(); ++i) { | 1213 for (intptr_t i = 0; i < block_order_.length(); ++i) { |
1127 __ Comment("B%d", i); | 1214 __ Comment("B%d", i); |
1128 // Compile the block entry. | 1215 // Compile the block entry. |
1129 current_block_ = block_order_[i]; | 1216 current_block_ = block_order_[i]; |
1130 Instruction* instr = current_block()->Accept(this); | 1217 Instruction* instr = current_block()->Accept(this); |
1131 // Compile all successors until an exit, branch, or a block entry. | 1218 // Compile all successors until an exit, branch, or a block entry. |
1132 while ((instr != NULL) && !instr->IsBlockEntry()) { | 1219 while ((instr != NULL) && !instr->IsBlockEntry()) { |
1133 if (FLAG_code_comments) EmitComment(instr); | 1220 if (FLAG_code_comments) EmitComment(instr); |
1221 EmitInstructionPrologue(instr); | |
1134 instr = instr->Accept(this); | 1222 instr = instr->Accept(this); |
1135 } | 1223 } |
1136 | 1224 |
1137 BlockEntryInstr* successor = | 1225 BlockEntryInstr* successor = |
1138 (instr == NULL) ? NULL : instr->AsBlockEntry(); | 1226 (instr == NULL) ? NULL : instr->AsBlockEntry(); |
1139 if (successor != NULL) { | 1227 if (successor != NULL) { |
1140 // Block ended with a "goto". We can fall through if it is the | 1228 // Block ended with a "goto". We can fall through if it is the |
1141 // next block in the list. Otherwise, we need a jump. | 1229 // next block in the list. Otherwise, we need a jump. |
1142 if ((i == block_order_.length() - 1) || | 1230 if ((i == block_order_.length() - 1) || |
1143 (block_order_[i + 1] != successor)) { | 1231 (block_order_[i + 1] != successor)) { |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1175 } | 1263 } |
1176 | 1264 |
1177 | 1265 |
1178 void FlowGraphCompiler::VisitDo(DoInstr* instr) { | 1266 void FlowGraphCompiler::VisitDo(DoInstr* instr) { |
1179 instr->computation()->Accept(this); | 1267 instr->computation()->Accept(this); |
1180 } | 1268 } |
1181 | 1269 |
1182 | 1270 |
1183 void FlowGraphCompiler::VisitBind(BindInstr* instr) { | 1271 void FlowGraphCompiler::VisitBind(BindInstr* instr) { |
1184 instr->computation()->Accept(this); | 1272 instr->computation()->Accept(this); |
1185 __ pushq(RAX); | 1273 |
1274 if (instr->GetLocationSummary() == NULL) { | |
1275 // If instruction does not have special location requirements | |
1276 // then it returns result in register RAX. | |
1277 __ pushq(RAX); | |
1278 } else { | |
1279 __ pushq(ToRegister(instr->GetLocationSummary()->result_location())); | |
1280 } | |
1186 } | 1281 } |
1187 | 1282 |
1188 | 1283 |
1189 void FlowGraphCompiler::VisitReturn(ReturnInstr* instr) { | 1284 void FlowGraphCompiler::VisitReturn(ReturnInstr* instr) { |
1190 LoadValue(RAX, instr->value()); | 1285 LoadValue(RAX, instr->value()); |
1191 if (!is_optimizing()) { | 1286 if (!is_optimizing()) { |
1192 // Count only in unoptimized code. | 1287 // Count only in unoptimized code. |
1193 // TODO(srdjan): Replace the counting code with a type feedback | 1288 // TODO(srdjan): Replace the counting code with a type feedback |
1194 // collection and counting stub. | 1289 // collection and counting stub. |
1195 const Function& function = | 1290 const Function& function = |
(...skipping 518 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1714 | 1809 |
1715 | 1810 |
1716 void FlowGraphCompiler::FinalizeComments(const Code& code) { | 1811 void FlowGraphCompiler::FinalizeComments(const Code& code) { |
1717 code.set_comments(assembler_->GetCodeComments()); | 1812 code.set_comments(assembler_->GetCodeComments()); |
1718 } | 1813 } |
1719 | 1814 |
1720 | 1815 |
1721 } // namespace dart | 1816 } // namespace dart |
1722 | 1817 |
1723 #endif // defined TARGET_ARCH_X64 | 1818 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |