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 "vm/ast_printer.h" | 10 #include "vm/ast_printer.h" |
| 11 #include "vm/code_generator.h" | 11 #include "vm/code_generator.h" |
| 12 #include "vm/disassembler.h" | 12 #include "vm/disassembler.h" |
| 13 #include "vm/longjump.h" | 13 #include "vm/longjump.h" |
| 14 #include "vm/parser.h" | 14 #include "vm/parser.h" |
| 15 #include "vm/stub_code.h" | 15 #include "vm/stub_code.h" |
| 16 | 16 |
| 17 namespace dart { | 17 namespace dart { |
| 18 | 18 |
| 19 DECLARE_FLAG(bool, print_ast); | 19 DECLARE_FLAG(bool, print_ast); |
| 20 DECLARE_FLAG(bool, print_scopes); | 20 DECLARE_FLAG(bool, print_scopes); |
| 21 DECLARE_FLAG(bool, trace_functions); | 21 DECLARE_FLAG(bool, trace_functions); |
| 22 | 22 |
| 23 FlowGraphCompiler::FlowGraphCompiler( | |
| 24 Assembler* assembler, | |
| 25 const ParsedFunction& parsed_function, | |
| 26 const GrowableArray<BlockEntryInstr*>* blocks) | |
| 27 : assembler_(assembler), | |
| 28 parsed_function_(parsed_function), | |
| 29 blocks_(blocks), | |
| 30 block_info_(blocks->length()), | |
| 31 current_block_(NULL), | |
| 32 pc_descriptors_list_(new CodeGenerator::DescriptorList()), | |
| 33 stack_local_count_(0) { | |
| 34 for (int i = 0; i < blocks->length(); ++i) { | |
| 35 block_info_.Add(new BlockInfo()); | |
| 36 } | |
| 37 } | |
| 38 | |
| 39 | |
| 23 void FlowGraphCompiler::Bailout(const char* reason) { | 40 void FlowGraphCompiler::Bailout(const char* reason) { |
| 24 const char* kFormat = "FlowGraphCompiler Bailout: %s %s."; | 41 const char* kFormat = "FlowGraphCompiler Bailout: %s %s."; |
| 25 const char* function_name = parsed_function_.function().ToCString(); | 42 const char* function_name = parsed_function_.function().ToCString(); |
| 26 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1; | 43 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1; |
| 27 char* chars = reinterpret_cast<char*>( | 44 char* chars = reinterpret_cast<char*>( |
| 28 Isolate::Current()->current_zone()->Allocate(len)); | 45 Isolate::Current()->current_zone()->Allocate(len)); |
| 29 OS::SNPrint(chars, len, kFormat, function_name, reason); | 46 OS::SNPrint(chars, len, kFormat, function_name, reason); |
| 30 const Error& error = Error::Handle( | 47 const Error& error = Error::Handle( |
| 31 LanguageError::New(String::Handle(String::New(chars)))); | 48 LanguageError::New(String::Handle(String::New(chars)))); |
| 32 Isolate::Current()->long_jump_base()->Jump(1, error); | 49 Isolate::Current()->long_jump_base()->Jump(1, error); |
| (...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 253 __ popq(RBX); // Reciever. | 270 __ popq(RBX); // Reciever. |
| 254 __ pushq(RAX); | 271 __ pushq(RAX); |
| 255 __ pushq(RBX); | 272 __ pushq(RBX); |
| 256 __ pushq(RAX); | 273 __ pushq(RAX); |
| 257 EmitInstanceCall(comp->node_id(), comp->token_index(), function_name, 2, | 274 EmitInstanceCall(comp->node_id(), comp->token_index(), function_name, 2, |
| 258 Array::ZoneHandle(), 1); | 275 Array::ZoneHandle(), 1); |
| 259 __ popq(RAX); | 276 __ popq(RAX); |
| 260 } | 277 } |
| 261 | 278 |
| 262 | 279 |
| 280 void FlowGraphCompiler::VisitBlocks( | |
| 281 const GrowableArray<BlockEntryInstr*>& blocks) { | |
| 282 for (intptr_t i = blocks.length() - 1; i >= 0; --i) { | |
| 283 // Compile the block entry. | |
| 284 current_block_ = blocks[i]; | |
| 285 Instruction* instr = current_block()->Accept(this); | |
| 286 // Compile all successors until an exit, branch, or a block entry. | |
| 287 while ((instr != NULL) && !instr->IsBlockEntry()) { | |
| 288 instr = instr->Accept(this); | |
| 289 } | |
| 290 | |
| 291 if ((instr != NULL) && instr->IsBlockEntry()) { | |
| 292 // Block ended with a "goto". We can fall through if it is the | |
| 293 // next block in the list. Otherwise, we need a jump. | |
| 294 if (i == 0 || (blocks[i - 1] != instr)) { | |
| 295 int number = BlockEntryInstr::cast(instr)->block_number(); | |
|
srdjan
2012/03/07 22:23:06
Discussed in the team and talked with Ivan: Please
Kevin Millikin (Google)
2012/03/08 09:59:53
Removed the static member function from class Bloc
| |
| 296 __ jmp(&block_info_[number]->label); | |
| 297 } | |
| 298 } | |
| 299 } | |
| 300 } | |
| 301 | |
| 302 | |
| 263 void FlowGraphCompiler::VisitJoinEntry(JoinEntryInstr* instr) { | 303 void FlowGraphCompiler::VisitJoinEntry(JoinEntryInstr* instr) { |
| 264 Bailout("JoinEntryInstr"); | 304 __ Bind(&block_info_[instr->block_number()]->label); |
| 265 } | 305 } |
| 266 | 306 |
| 267 | 307 |
| 268 void FlowGraphCompiler::VisitTargetEntry(TargetEntryInstr* instr) { | 308 void FlowGraphCompiler::VisitTargetEntry(TargetEntryInstr* instr) { |
| 269 // Since we don't handle branching control flow yet, there is nothing to do. | 309 __ Bind(&block_info_[instr->block_number()]->label); |
| 270 } | 310 } |
| 271 | 311 |
| 272 | 312 |
| 273 void FlowGraphCompiler::VisitPickTemp(PickTempInstr* instr) { | 313 void FlowGraphCompiler::VisitPickTemp(PickTempInstr* instr) { |
| 274 // Semantics is to copy a stack-allocated temporary to the top of stack. | 314 // Semantics is to copy a stack-allocated temporary to the top of stack. |
| 275 // Destination index d is assumed the new top of stack after the | 315 // Destination index d is assumed the new top of stack after the |
| 276 // operation, so d-1 is the current top of stack and so d-s-1 is the | 316 // operation, so d-1 is the current top of stack and so d-s-1 is the |
| 277 // offset to source index s. | 317 // offset to source index s. |
| 278 intptr_t offset = instr->destination() - instr->source() - 1; | 318 intptr_t offset = instr->destination() - instr->source() - 1; |
| 279 ASSERT(offset >= 0); | 319 ASSERT(offset >= 0); |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 342 __ nop(1); | 382 __ nop(1); |
| 343 __ nop(1); | 383 __ nop(1); |
| 344 __ nop(1); | 384 __ nop(1); |
| 345 AddCurrentDescriptor(PcDescriptors::kReturn, | 385 AddCurrentDescriptor(PcDescriptors::kReturn, |
| 346 AstNode::kNoId, | 386 AstNode::kNoId, |
| 347 instr->token_index()); | 387 instr->token_index()); |
| 348 } | 388 } |
| 349 | 389 |
| 350 | 390 |
| 351 void FlowGraphCompiler::VisitBranch(BranchInstr* instr) { | 391 void FlowGraphCompiler::VisitBranch(BranchInstr* instr) { |
| 352 Bailout("BranchInstr"); | 392 // Determine if the true branch is fall through (!negated) or the false |
| 393 // branch is. They cannot both be backwards branches. | |
| 394 int index = blocks_->length() - current_block()->block_number() - 1; | |
|
srdjan
2012/03/07 22:23:06
intptr_t
Kevin Millikin (Google)
2012/03/08 09:59:53
Done.
| |
| 395 ASSERT(index != 0); | |
|
srdjan
2012/03/07 22:23:06
Maybe safer: (index > 0).
Kevin Millikin (Google)
2012/03/08 09:59:53
Done.
| |
| 396 | |
| 397 bool negated = ((*blocks_)[index - 1] == instr->false_successor()); | |
| 398 ASSERT(!negated == ((*blocks_)[index - 1] == instr->true_successor())); | |
| 399 | |
| 400 LoadValue(instr->value()); | |
| 401 __ LoadObject(RDX, Bool::ZoneHandle(Bool::True())); | |
| 402 __ cmpq(RAX, RDX); | |
| 403 if (negated) { | |
| 404 __ j(EQUAL, &block_info_[instr->true_successor()->block_number()]->label); | |
| 405 | |
|
srdjan
2012/03/07 22:23:06
Empty line?
Kevin Millikin (Google)
2012/03/08 09:59:53
Deleted.
| |
| 406 } else { | |
| 407 __ j(NOT_EQUAL, | |
| 408 &block_info_[instr->false_successor()->block_number()]->label); | |
| 409 } | |
| 353 } | 410 } |
| 354 | 411 |
| 355 | 412 |
| 356 void FlowGraphCompiler::CompileGraph() { | 413 void FlowGraphCompiler::CompileGraph() { |
| 357 const Function& function = parsed_function_.function(); | 414 const Function& function = parsed_function_.function(); |
| 358 if ((function.num_optional_parameters() != 0)) { | 415 if ((function.num_optional_parameters() != 0)) { |
| 359 Bailout("function has optional parameters"); | 416 Bailout("function has optional parameters"); |
| 360 } | 417 } |
| 361 LocalScope* scope = parsed_function_.node_sequence()->scope(); | 418 LocalScope* scope = parsed_function_.node_sequence()->scope(); |
| 362 LocalScope* context_owner = NULL; | 419 LocalScope* context_owner = NULL; |
| 363 const int parameter_count = function.num_fixed_parameters(); | 420 const int parameter_count = function.num_fixed_parameters(); |
| 364 const int first_parameter_index = 1 + parameter_count; | 421 const int first_parameter_index = 1 + parameter_count; |
| 365 const int first_local_index = -1; | 422 const int first_local_index = -1; |
| 366 int first_free_frame_index = | 423 int first_free_frame_index = |
| 367 scope->AllocateVariables(first_parameter_index, | 424 scope->AllocateVariables(first_parameter_index, |
| 368 parameter_count, | 425 parameter_count, |
| 369 first_local_index, | 426 first_local_index, |
| 370 scope, | 427 scope, |
| 371 &context_owner); | 428 &context_owner); |
| 372 set_stack_local_count(first_local_index - first_free_frame_index); | 429 set_stack_local_count(first_local_index - first_free_frame_index); |
| 373 | 430 |
| 374 if (blocks_->length() != 1) Bailout("more than 1 basic block"); | |
| 375 | |
| 376 // Specialized version of entry code from CodeGenerator::GenerateEntryCode. | 431 // Specialized version of entry code from CodeGenerator::GenerateEntryCode. |
| 377 __ EnterFrame(stack_local_count() * kWordSize); | 432 __ EnterFrame(stack_local_count() * kWordSize); |
| 378 #ifdef DEBUG | 433 #ifdef DEBUG |
| 379 const bool check_arguments = true; | 434 const bool check_arguments = true; |
| 380 #else | 435 #else |
| 381 const bool check_arguments = function.IsClosureFunction(); | 436 const bool check_arguments = function.IsClosureFunction(); |
| 382 #endif | 437 #endif |
| 383 if (check_arguments) { | 438 if (check_arguments) { |
| 384 // Check that num_fixed <= argc <= num_params. | 439 // Check that num_fixed <= argc <= num_params. |
| 385 Label argc_in_range; | 440 Label argc_in_range; |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 488 void FlowGraphCompiler::FinalizeExceptionHandlers(const Code& code) { | 543 void FlowGraphCompiler::FinalizeExceptionHandlers(const Code& code) { |
| 489 // We don't compile exception handlers yet. | 544 // We don't compile exception handlers yet. |
| 490 code.set_exception_handlers( | 545 code.set_exception_handlers( |
| 491 ExceptionHandlers::Handle(ExceptionHandlers::New(0))); | 546 ExceptionHandlers::Handle(ExceptionHandlers::New(0))); |
| 492 } | 547 } |
| 493 | 548 |
| 494 | 549 |
| 495 } // namespace dart | 550 } // namespace dart |
| 496 | 551 |
| 497 #endif // defined TARGET_ARCH_X64 | 552 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |