Chromium Code Reviews| 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 |