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

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

Issue 10382234: Introduce locations based code generation. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 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
OLDNEW
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698