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_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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |