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_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 |