Chromium Code Reviews| Index: runtime/vm/flow_graph_compiler_x64.cc |
| diff --git a/runtime/vm/flow_graph_compiler_x64.cc b/runtime/vm/flow_graph_compiler_x64.cc |
| index ef95acc1583b92e11aaad9c6248c6ba32a94efe7..c0c496e2bbd7483468b238f406b120c5e2aee5d1 100644 |
| --- a/runtime/vm/flow_graph_compiler_x64.cc |
| +++ b/runtime/vm/flow_graph_compiler_x64.cc |
| @@ -22,11 +22,12 @@ DECLARE_FLAG(bool, trace_functions); |
| DECLARE_FLAG(bool, disassemble); |
| void FlowGraphCompiler::Bailout(const char* reason) { |
| - const char* kFormat = "FlowGraphCompiler Bailout: %s."; |
| - intptr_t len = OS::SNPrint(NULL, 0, kFormat, reason) + 1; |
| + const char* kFormat = "FlowGraphCompiler Bailout: %s %s."; |
| + const char* function_name = parsed_function_.function().ToCString(); |
|
srdjan
2012/02/27 23:23:53
ToFullyQUalifiedCString if needed.
|
| + intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1; |
| char* chars = reinterpret_cast<char*>( |
| Isolate::Current()->current_zone()->Allocate(len)); |
| - OS::SNPrint(chars, len, kFormat, reason); |
| + OS::SNPrint(chars, len, kFormat, function_name, reason); |
| const Error& error = Error::Handle( |
| LanguageError::New(String::Handle(String::New(chars)))); |
| Isolate::Current()->long_jump_base()->Jump(1, error); |
| @@ -37,7 +38,7 @@ void FlowGraphCompiler::Bailout(const char* reason) { |
| void FlowGraphCompiler::LoadValue(Value* value) { |
| if (value->IsConstant()) { |
| - ConstantValue* constant = value->AsConstant(); |
| + ConstantVal* constant = value->AsConstant(); |
| if (constant->instance().IsSmi()) { |
| int64_t imm = reinterpret_cast<int64_t>(constant->instance().raw()); |
| __ movq(RAX, Immediate(imm)); |
| @@ -46,11 +47,59 @@ void FlowGraphCompiler::LoadValue(Value* value) { |
| } |
| } else { |
| ASSERT(value->IsTemp()); |
| - Bailout("return of non-ConstantValue value"); |
| + __ popq(RAX); |
| } |
| } |
| +void FlowGraphCompiler::VisitTemp(TempVal* val) { |
| + Bailout("TempVal"); |
| +} |
| + |
| + |
| +void FlowGraphCompiler::VisitConstant(ConstantVal* val) { |
| + Bailout("ConstantVal"); |
| +} |
| + |
| + |
| +void FlowGraphCompiler::VisitAssertAssignable(AssertAssignableComp* comp) { |
| + Bailout("AssertAssignableComp"); |
| +} |
| + |
| + |
| +void FlowGraphCompiler::VisitInstanceCall(InstanceCallComp* comp) { |
| + Bailout("InstanceCallComp"); |
| +} |
| + |
| + |
| +void FlowGraphCompiler::VisitStrictCompare(StrictCompareComp* comp) { |
| + Bailout("StrictCompareComp"); |
| +} |
| + |
| + |
| + |
| +void FlowGraphCompiler::VisitStaticCall(StaticCallComp* comp) { |
| + Bailout("StaticCallComp"); |
| +} |
| + |
| + |
| +void FlowGraphCompiler::VisitLoadLocal(LoadLocalComp* comp) { |
| + if (comp->local().is_captured()) { |
| + Bailout("load of context variable"); |
| + } |
| + __ movq(RAX, Address(RBP, comp->local().index() * kWordSize)); |
| +} |
| + |
| + |
| +void FlowGraphCompiler::VisitStoreLocal(StoreLocalComp* comp) { |
| + if (comp->local().is_captured()) { |
| + Bailout("store to context variable"); |
| + } |
| + LoadValue(comp->value()); |
| + __ movq(Address(RBP, comp->local().index() * kWordSize), RAX); |
| +} |
| + |
| + |
| void FlowGraphCompiler::VisitJoinEntry(JoinEntryInstr* instr) { |
| Bailout("JoinEntryInstr"); |
| } |
| @@ -62,12 +111,13 @@ void FlowGraphCompiler::VisitTargetEntry(TargetEntryInstr* instr) { |
| void FlowGraphCompiler::VisitDo(DoInstr* instr) { |
| - Bailout("DoInstr"); |
| + instr->computation()->Accept(this); |
| } |
| void FlowGraphCompiler::VisitBind(BindInstr* instr) { |
| - Bailout("DoInstr"); |
| + instr->computation()->Accept(this); |
| + __ pushq(RAX); |
| } |
| @@ -76,10 +126,9 @@ void FlowGraphCompiler::VisitReturn(ReturnInstr* instr) { |
| #ifdef DEBUG |
| // Check that the entry stack size matches the exit stack size. |
| - const intptr_t locals_space_size = 0; |
| __ movq(R10, RBP); |
| __ subq(R10, RSP); |
| - __ cmpq(R10, Immediate(locals_space_size)); |
| + __ cmpq(R10, Immediate(stack_local_count() * kWordSize)); |
| Label stack_ok; |
| __ j(EQUAL, &stack_ok, Assembler::kNearJump); |
| __ Stop("Exit stack size does not match the entry stack size."); |
| @@ -104,23 +153,19 @@ void FlowGraphCompiler::VisitReturn(ReturnInstr* instr) { |
| void FlowGraphCompiler::VisitBranch(BranchInstr* instr) { |
| - Bailout("VisitBranch"); |
| + Bailout("BranchInstr"); |
| } |
| void FlowGraphCompiler::CompileGraph() { |
| const Function& function = parsed_function_.function(); |
| - if ((function.num_fixed_parameters() != 0) || |
| - (function.num_optional_parameters() != 0)) { |
| - Bailout("function has parameters"); |
| + if ((function.num_optional_parameters() != 0)) { |
| + Bailout("function has optional parameters"); |
| } |
| LocalScope* scope = parsed_function_.node_sequence()->scope(); |
| - if (scope->child() != NULL) { |
| - Bailout("function has local scopes"); |
| - } |
| LocalScope* context_owner = NULL; |
| - const int first_parameter_index = 1; |
| - const int parameter_count = 0; |
| + const int parameter_count = function.num_fixed_parameters(); |
| + const int first_parameter_index = 1 + parameter_count; |
| const int first_local_index = -1; |
| int first_free_frame_index = |
| scope->AllocateVariables(first_parameter_index, |
| @@ -128,13 +173,12 @@ void FlowGraphCompiler::CompileGraph() { |
| first_local_index, |
| scope, |
| &context_owner); |
| - const int local_count = first_local_index - first_free_frame_index; |
| - if (local_count != 0) Bailout("function has locals"); |
| + set_stack_local_count(first_local_index - first_free_frame_index); |
| if (blocks_->length() != 1) Bailout("more than 1 basic block"); |
| // Specialized version of entry code from CodeGenerator::GenerateEntryCode. |
| - __ EnterFrame(0); |
| + __ EnterFrame(stack_local_count() * kWordSize); |
| #ifdef DEBUG |
| const bool check_arguments = true; |
| #else |
| @@ -145,7 +189,7 @@ void FlowGraphCompiler::CompileGraph() { |
| Label argc_in_range; |
| // Total number of args is the first Smi in args descriptor array (R10). |
| __ movq(RAX, FieldAddress(R10, Array::data_offset())); |
| - __ cmpq(RAX, Immediate(Smi::RawValue(0))); |
| + __ cmpq(RAX, Immediate(Smi::RawValue(parameter_count))); |
| __ j(EQUAL, &argc_in_range, Assembler::kNearJump); |
| if (function.IsClosureFunction()) { |
| GenerateCallRuntime(AstNode::kNoId, |
| @@ -156,11 +200,21 @@ void FlowGraphCompiler::CompileGraph() { |
| } |
| __ Bind(&argc_in_range); |
| } |
| + |
| + // Initialize locals to null. |
|
srdjan
2012/02/27 23:23:53
Shall we generate IL to describe the NULL stores i
Kevin Millikin (Google)
2012/02/28 09:13:12
It looks like they're already present in the AST,
|
| + if (stack_local_count() > 0) { |
| + __ movq(RAX, Immediate(reinterpret_cast<intptr_t>(Object::null()))); |
| + for (int i = 0; i < stack_local_count(); ++i) { |
| + // Subtract index i (locals lie at lower addresses than RBP). |
| + __ movq(Address(RBP, (first_local_index - i) * kWordSize), RAX); |
| + } |
| + } |
| + |
| // Generate stack overflow check. |
| __ movq(TMP, Immediate(Isolate::Current()->stack_limit_address())); |
| __ cmpq(RSP, Address(TMP, 0)); |
| Label no_stack_overflow; |
| - __ j(ABOVE, &no_stack_overflow); |
| + __ j(ABOVE, &no_stack_overflow, Assembler::kNearJump); |
| GenerateCallRuntime(AstNode::kNoId, |
| function.token_index(), |
| kStackOverflowRuntimeEntry); |