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

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

Issue 10831261: Build and use stack maps in the SSA compiler. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 4 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_XXX. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_XXX.
6 6
7 #include "vm/flow_graph_compiler.h" 7 #include "vm/flow_graph_compiler.h"
8 8
9 #include "vm/dart_entry.h" 9 #include "vm/dart_entry.h"
10 #include "vm/debugger.h" 10 #include "vm/debugger.h"
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
70 const GrowableArray<BlockEntryInstr*>& block_order, 70 const GrowableArray<BlockEntryInstr*>& block_order,
71 bool is_optimizing, 71 bool is_optimizing,
72 bool is_ssa, 72 bool is_ssa,
73 bool is_leaf) 73 bool is_leaf)
74 : assembler_(assembler), 74 : assembler_(assembler),
75 parsed_function_(parsed_function), 75 parsed_function_(parsed_function),
76 block_order_(block_order), 76 block_order_(block_order),
77 current_block_(NULL), 77 current_block_(NULL),
78 exception_handlers_list_(NULL), 78 exception_handlers_list_(NULL),
79 pc_descriptors_list_(NULL), 79 pc_descriptors_list_(NULL),
80 stackmap_table_builder_(NULL), 80 stackmap_table_builder_(is_ssa ? new StackmapTableBuilder() : NULL),
81 block_info_(block_order.length()), 81 block_info_(block_order.length()),
82 deopt_stubs_(), 82 deopt_stubs_(),
83 object_table_(GrowableObjectArray::Handle(GrowableObjectArray::New())), 83 object_table_(GrowableObjectArray::Handle(GrowableObjectArray::New())),
84 is_optimizing_(is_optimizing), 84 is_optimizing_(is_optimizing),
85 is_ssa_(is_ssa), 85 is_ssa_(is_ssa),
86 is_dart_leaf_(is_leaf), 86 is_dart_leaf_(is_leaf),
87 bool_true_(Bool::ZoneHandle(Bool::True())), 87 bool_true_(Bool::ZoneHandle(Bool::True())),
88 bool_false_(Bool::ZoneHandle(Bool::False())), 88 bool_false_(Bool::ZoneHandle(Bool::False())),
89 double_class_(Class::ZoneHandle( 89 double_class_(Class::ZoneHandle(
90 Isolate::Current()->object_store()->double_class())), 90 Isolate::Current()->object_store()->double_class())),
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
136 136
137 void FlowGraphCompiler::VisitBlocks() { 137 void FlowGraphCompiler::VisitBlocks() {
138 for (intptr_t i = 0; i < block_order().length(); ++i) { 138 for (intptr_t i = 0; i < block_order().length(); ++i) {
139 ASSERT(frame_register_allocator()->IsSpilled()); 139 ASSERT(frame_register_allocator()->IsSpilled());
140 assembler()->Comment("B%d", i); 140 assembler()->Comment("B%d", i);
141 // Compile the block entry. 141 // Compile the block entry.
142 BlockEntryInstr* entry = block_order()[i]; 142 BlockEntryInstr* entry = block_order()[i];
143 set_current_block(entry); 143 set_current_block(entry);
144 entry->PrepareEntry(this); 144 entry->PrepareEntry(this);
145 // Compile all successors until an exit, branch, or a block entry. 145 // Compile all successors until an exit, branch, or a block entry.
146 Instruction* instr = entry;
147 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) { 146 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) {
148 instr = it.Current(); 147 Instruction* instr = it.Current();
149 if (FLAG_code_comments) EmitComment(instr); 148 if (FLAG_code_comments) EmitComment(instr);
150 if (instr->IsParallelMove()) { 149 if (instr->IsParallelMove()) {
151 parallel_move_resolver_.EmitNativeCode(instr->AsParallelMove()); 150 parallel_move_resolver_.EmitNativeCode(instr->AsParallelMove());
152 } else { 151 } else {
153 ASSERT(instr->locs() != NULL); 152 ASSERT(instr->locs() != NULL);
154 EmitInstructionPrologue(instr); 153 EmitInstructionPrologue(instr);
155 pending_deoptimization_env_ = instr->env(); 154 pending_deoptimization_env_ = instr->env();
156 instr->EmitNativeCode(this); 155 instr->EmitNativeCode(this);
157 } 156 }
158 } 157 }
159 if (instr->next() != NULL) {
160 BlockEntryInstr* successor = instr->next()->AsBlockEntry();
161 ASSERT(successor != NULL);
162 frame_register_allocator()->Spill();
163 if (!IsNextBlock(successor)) {
164 assembler()->jmp(GetBlockLabel(successor));
165 }
166 }
167 } 158 }
168 } 159 }
169 160
170 161
171 void FlowGraphCompiler::Bailout(const char* reason) { 162 void FlowGraphCompiler::Bailout(const char* reason) {
172 const char* kFormat = "FlowGraphCompiler Bailout: %s %s."; 163 const char* kFormat = "FlowGraphCompiler Bailout: %s %s.";
173 const char* function_name = parsed_function().function().ToCString(); 164 const char* function_name = parsed_function().function().ToCString();
174 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1; 165 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1;
175 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len); 166 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
176 OS::SNPrint(chars, len, kFormat, function_name, reason); 167 OS::SNPrint(chars, len, kFormat, function_name, reason);
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
287 278
288 279
289 void FlowGraphCompiler::FinalizeStackmaps(const Code& code) { 280 void FlowGraphCompiler::FinalizeStackmaps(const Code& code) {
290 if (stackmap_table_builder_ == NULL) { 281 if (stackmap_table_builder_ == NULL) {
291 // The unoptimizing compiler has no stack maps. 282 // The unoptimizing compiler has no stack maps.
292 code.set_stackmaps(Array::Handle()); 283 code.set_stackmaps(Array::Handle());
293 } else { 284 } else {
294 // Finalize the stack map array and add it to the code object. 285 // Finalize the stack map array and add it to the code object.
295 code.set_stackmaps( 286 code.set_stackmaps(
296 Array::Handle(stackmap_table_builder_->FinalizeStackmaps(code))); 287 Array::Handle(stackmap_table_builder_->FinalizeStackmaps(code)));
288 ASSERT(is_ssa() && is_optimizing());
297 } 289 }
298 } 290 }
299 291
300 292
301 void FlowGraphCompiler::FinalizeVarDescriptors(const Code& code) { 293 void FlowGraphCompiler::FinalizeVarDescriptors(const Code& code) {
302 const LocalVarDescriptors& var_descs = LocalVarDescriptors::Handle( 294 const LocalVarDescriptors& var_descs = LocalVarDescriptors::Handle(
303 parsed_function_.node_sequence()->scope()->GetVarDescriptors( 295 parsed_function_.node_sequence()->scope()->GetVarDescriptors(
304 parsed_function_.function())); 296 parsed_function_.function()));
305 code.set_var_descriptors(var_descs); 297 code.set_var_descriptors(var_descs);
306 } 298 }
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
352 } 344 }
353 345
354 346
355 void FlowGraphCompiler::GenerateInstanceCall( 347 void FlowGraphCompiler::GenerateInstanceCall(
356 intptr_t deopt_id, 348 intptr_t deopt_id,
357 intptr_t token_pos, 349 intptr_t token_pos,
358 intptr_t try_index, 350 intptr_t try_index,
359 const String& function_name, 351 const String& function_name,
360 intptr_t argument_count, 352 intptr_t argument_count,
361 const Array& argument_names, 353 const Array& argument_names,
362 intptr_t checked_argument_count) { 354 intptr_t checked_argument_count,
355 BitmapBuilder* stack_bitmap) {
363 ASSERT(!IsLeaf()); 356 ASSERT(!IsLeaf());
364 ASSERT(frame_register_allocator()->IsSpilled()); 357 ASSERT(frame_register_allocator()->IsSpilled());
365 ICData& ic_data = 358 ICData& ic_data =
366 ICData::ZoneHandle(ICData::New(parsed_function().function(), 359 ICData::ZoneHandle(ICData::New(parsed_function().function(),
367 function_name, 360 function_name,
368 deopt_id, 361 deopt_id,
369 checked_argument_count)); 362 checked_argument_count));
370 const Array& arguments_descriptor = 363 const Array& arguments_descriptor =
371 DartEntry::ArgumentsDescriptor(argument_count, argument_names); 364 DartEntry::ArgumentsDescriptor(argument_count, argument_names);
372 uword label_address = 0; 365 uword label_address = 0;
373 switch (checked_argument_count) { 366 switch (checked_argument_count) {
374 case 1: 367 case 1:
375 label_address = StubCode::OneArgCheckInlineCacheEntryPoint(); 368 label_address = StubCode::OneArgCheckInlineCacheEntryPoint();
376 break; 369 break;
377 case 2: 370 case 2:
378 label_address = StubCode::TwoArgsCheckInlineCacheEntryPoint(); 371 label_address = StubCode::TwoArgsCheckInlineCacheEntryPoint();
379 break; 372 break;
380 default: 373 default:
381 UNIMPLEMENTED(); 374 UNIMPLEMENTED();
382 } 375 }
383 ExternalLabel target_label("InlineCache", label_address); 376 ExternalLabel target_label("InlineCache", label_address);
384 377
385 const intptr_t descr_offset = EmitInstanceCall(&target_label, 378 const intptr_t descr_offset = EmitInstanceCall(&target_label,
386 ic_data, 379 ic_data,
387 arguments_descriptor, 380 arguments_descriptor,
388 argument_count); 381 argument_count);
382 if (is_ssa() && (stack_bitmap != NULL)) {
383 stackmap_table_builder_->AddEntry(descr_offset, stack_bitmap);
384 }
389 pc_descriptors_list()->AddDescriptor(PcDescriptors::kIcCall, 385 pc_descriptors_list()->AddDescriptor(PcDescriptors::kIcCall,
390 descr_offset, 386 descr_offset,
391 deopt_id, 387 deopt_id,
392 token_pos, 388 token_pos,
393 try_index); 389 try_index);
394 } 390 }
395 391
396 392
397 void FlowGraphCompiler::GenerateStaticCall(intptr_t deopt_id, 393 void FlowGraphCompiler::GenerateStaticCall(intptr_t deopt_id,
398 intptr_t token_pos, 394 intptr_t token_pos,
399 intptr_t try_index, 395 intptr_t try_index,
400 const Function& function, 396 const Function& function,
401 intptr_t argument_count, 397 intptr_t argument_count,
402 const Array& argument_names) { 398 const Array& argument_names,
399 BitmapBuilder* stack_bitmap) {
403 ASSERT(frame_register_allocator()->IsSpilled()); 400 ASSERT(frame_register_allocator()->IsSpilled());
404 401
405 const Array& arguments_descriptor = 402 const Array& arguments_descriptor =
406 DartEntry::ArgumentsDescriptor(argument_count, argument_names); 403 DartEntry::ArgumentsDescriptor(argument_count, argument_names);
407 const intptr_t descr_offset = EmitStaticCall(function, 404 const intptr_t descr_offset = EmitStaticCall(function,
408 arguments_descriptor, 405 arguments_descriptor,
409 argument_count); 406 argument_count);
407 if (is_ssa() && (stack_bitmap != NULL)) {
Vyacheslav Egorov (Google) 2012/08/13 12:54:46 we should make as hard as possible to pass NULLs f
Kevin Millikin (Google) 2012/08/13 15:10:37 Agreed. I think we'll actually want to just make
408 stackmap_table_builder_->AddEntry(descr_offset, stack_bitmap);
409 }
410 pc_descriptors_list()->AddDescriptor(PcDescriptors::kFuncCall, 410 pc_descriptors_list()->AddDescriptor(PcDescriptors::kFuncCall,
411 descr_offset, 411 descr_offset,
412 deopt_id, 412 deopt_id,
413 token_pos, 413 token_pos,
414 try_index); 414 try_index);
415 } 415 }
416 416
417 417
418 void FlowGraphCompiler::GenerateNumberTypeCheck(Register kClassIdReg, 418 void FlowGraphCompiler::GenerateNumberTypeCheck(Register kClassIdReg,
419 const AbstractType& type, 419 const AbstractType& type,
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
478 comp->try_index()); 478 comp->try_index());
479 479
480 const intptr_t kNumArguments = 2; 480 const intptr_t kNumArguments = 2;
481 const intptr_t kNumArgsChecked = 1; // Type-feedback. 481 const intptr_t kNumArgsChecked = 1; // Type-feedback.
482 GenerateInstanceCall(comp->deopt_id(), 482 GenerateInstanceCall(comp->deopt_id(),
483 comp->token_pos(), 483 comp->token_pos(),
484 comp->try_index(), 484 comp->try_index(),
485 function_name, 485 function_name,
486 kNumArguments, 486 kNumArguments,
487 Array::ZoneHandle(), // No optional arguments. 487 Array::ZoneHandle(), // No optional arguments.
488 kNumArgsChecked); 488 kNumArgsChecked,
489 comp->locs()->stack_bitmap());
489 } 490 }
490 491
491 492
492 void FlowGraphCompiler::EmitTestAndCall(const ICData& ic_data, 493 void FlowGraphCompiler::EmitTestAndCall(const ICData& ic_data,
493 Register class_id_reg, 494 Register class_id_reg,
494 intptr_t arg_count, 495 intptr_t arg_count,
495 const Array& arg_names, 496 const Array& arg_names,
496 Label* deopt, 497 Label* deopt,
497 Label* done, 498 Label* done,
498 intptr_t deopt_id, 499 intptr_t deopt_id,
499 intptr_t token_index, 500 intptr_t token_index,
500 intptr_t try_index) { 501 intptr_t try_index,
502 BitmapBuilder* stack_bitmap) {
501 ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0)); 503 ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0));
502 Label match_found; 504 Label match_found;
503 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { 505 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) {
504 const bool is_last_check = (i == (ic_data.NumberOfChecks() - 1)); 506 const bool is_last_check = (i == (ic_data.NumberOfChecks() - 1));
505 Label next_test; 507 Label next_test;
506 assembler()->cmpl(class_id_reg, Immediate(ic_data.GetReceiverClassIdAt(i))); 508 assembler()->cmpl(class_id_reg, Immediate(ic_data.GetReceiverClassIdAt(i)));
507 if (is_last_check) { 509 if (is_last_check) {
508 assembler()->j(NOT_EQUAL, deopt); 510 assembler()->j(NOT_EQUAL, deopt);
509 } else { 511 } else {
510 assembler()->j(NOT_EQUAL, &next_test); 512 assembler()->j(NOT_EQUAL, &next_test);
511 } 513 }
512 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(i)); 514 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(i));
513 GenerateStaticCall(deopt_id, 515 GenerateStaticCall(deopt_id,
514 token_index, 516 token_index,
515 try_index, 517 try_index,
516 target, 518 target,
517 arg_count, 519 arg_count,
518 arg_names); 520 arg_names,
521 stack_bitmap);
519 if (!is_last_check) { 522 if (!is_last_check) {
520 assembler()->jmp(&match_found); 523 assembler()->jmp(&match_found);
521 } 524 }
522 assembler()->Bind(&next_test); 525 assembler()->Bind(&next_test);
523 } 526 }
524 assembler()->Bind(&match_found); 527 assembler()->Bind(&match_found);
525 if (done != NULL) { 528 if (done != NULL) {
526 assembler()->jmp(done); 529 assembler()->jmp(done);
527 } 530 }
528 } 531 }
(...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after
855 return; 858 return;
856 } 859 }
857 } 860 }
858 861
859 // This move is not blocked. 862 // This move is not blocked.
860 EmitMove(index); 863 EmitMove(index);
861 } 864 }
862 865
863 866
864 } // namespace dart 867 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698