From 67a61e96c7f495aab9691773d27c74e294d279bd Mon Sep 17 00:00:00 2001 From: "kmillikin@chromium.org" Date: Mon, 3 Aug 2009 07:55:48 +0000 Subject: [PATCH] Restructure to support recursive invocation of the CFG builder. Add support for stack-allocated variables when run with multipass. There is no liveness analysis and they are currently always allocated to memory. Review URL: http://codereview.chromium.org/159701 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@2604 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/arm/cfg-arm.cc | 26 +++++++++-- src/cfg.cc | 88 +++++++++++++++++++++-------------- src/cfg.h | 106 +++++++++++++++++++++++++++++++++---------- src/compiler.cc | 5 +- src/ia32/cfg-ia32.cc | 27 +++++++++-- src/x64/cfg-x64.cc | 26 +++++++++-- 6 files changed, 210 insertions(+), 68 deletions(-) diff --git a/src/arm/cfg-arm.cc b/src/arm/cfg-arm.cc index 8d14b103cd..109067bea2 100644 --- a/src/arm/cfg-arm.cc +++ b/src/arm/cfg-arm.cc @@ -56,9 +56,10 @@ void EntryNode::Compile(MacroAssembler* masm) { Comment cmnt(masm, "[ EntryNode"); __ stm(db_w, sp, r1.bit() | cp.bit() | fp.bit() | lr.bit()); __ add(fp, sp, Operand(2 * kPointerSize)); - if (local_count_ > 0) { + int count = CfgGlobals::current()->fun()->scope()->num_stack_slots(); + if (count > 0) { __ mov(ip, Operand(Factory::undefined_value())); - for (int i = 0; i < local_count_; i++) { + for (int i = 0; i < count; i++) { __ push(ip); } } @@ -84,7 +85,8 @@ void ExitNode::Compile(MacroAssembler* masm) { } __ mov(sp, fp); __ ldm(ia_w, sp, fp.bit() | lr.bit()); - __ add(sp, sp, Operand((parameter_count_ + 1) * kPointerSize)); + int count = CfgGlobals::current()->fun()->scope()->num_parameters(); + __ add(sp, sp, Operand((count + 1) * kPointerSize)); __ Jump(lr); } @@ -99,6 +101,24 @@ void Constant::ToRegister(MacroAssembler* masm, Register reg) { __ mov(reg, Operand(handle_)); } + +void SlotLocation::ToRegister(MacroAssembler* masm, Register reg) { + switch (type_) { + case Slot::PARAMETER: { + int count = CfgGlobals::current()->fun()->scope()->num_parameters(); + __ ldr(reg, MemOperand(fp, (1 + count - index_) * kPointerSize)); + break; + } + case Slot::LOCAL: { + const int kOffset = JavaScriptFrameConstants::kLocal0Offset; + __ ldr(reg, MemOperand(fp, kOffset - index_ * kPointerSize)); + break; + } + default: + UNREACHABLE(); + } +} + #undef __ } } // namespace v8::internal diff --git a/src/cfg.cc b/src/cfg.cc index 82fdbf6cb3..bad1441170 100644 --- a/src/cfg.cc +++ b/src/cfg.cc @@ -36,32 +36,37 @@ namespace v8 { namespace internal { -ExitNode* Cfg::global_exit_ = NULL; +CfgGlobals* CfgGlobals::top_ = NULL; -void CfgNode::Reset() { +CfgGlobals::CfgGlobals(FunctionLiteral* fun) + : global_fun_(fun), + global_exit_(new ExitNode()), #ifdef DEBUG - node_counter_ = 0; + node_counter_(0), #endif -} - - -void Cfg::Reset(FunctionLiteral* fun) { - global_exit_ = new ExitNode(fun); - CfgNode::Reset(); + previous_(top_) { + top_ = this; } #define BAILOUT(reason) \ do { return NULL; } while (false) -Cfg* Cfg::Build(FunctionLiteral* fun) { +Cfg* Cfg::Build() { + FunctionLiteral* fun = CfgGlobals::current()->fun(); + if (fun->scope()->num_heap_slots() > 0) { + BAILOUT("function has context slots"); + } + if (fun->scope()->arguments() != NULL) { + BAILOUT("function uses .arguments"); + } + ZoneList* body = fun->body(); if (body->is_empty()) { BAILOUT("empty function body"); } - Cfg::Reset(fun); StatementBuilder builder; builder.VisitStatements(body); Cfg* cfg = builder.cfg(); @@ -71,16 +76,16 @@ Cfg* Cfg::Build(FunctionLiteral* fun) { if (cfg->has_exit()) { BAILOUT("control path without explicit return"); } - cfg->PrependEntryNode(fun); + cfg->PrependEntryNode(); return cfg; } #undef BAILOUT -void Cfg::PrependEntryNode(FunctionLiteral* fun) { +void Cfg::PrependEntryNode() { ASSERT(!is_empty()); - entry_ = new EntryNode(fun, InstructionBlock::cast(entry())); + entry_ = new EntryNode(InstructionBlock::cast(entry())); } @@ -93,21 +98,12 @@ void Cfg::Append(Instruction* instr) { void Cfg::AppendReturnInstruction(Value* value) { Append(new ReturnInstr(value)); - InstructionBlock::cast(exit_)->set_successor(global_exit_); + ExitNode* global_exit = CfgGlobals::current()->exit(); + InstructionBlock::cast(exit_)->set_successor(global_exit); exit_ = NULL; } -EntryNode::EntryNode(FunctionLiteral* fun, InstructionBlock* succ) - : successor_(succ), local_count_(fun->scope()->num_stack_slots()) { -} - - -ExitNode::ExitNode(FunctionLiteral* fun) - : parameter_count_(fun->scope()->num_parameters()) { -} - - void InstructionBlock::Unmark() { if (is_marked_) { is_marked_ = false; @@ -124,16 +120,19 @@ void EntryNode::Unmark() { } -void ExitNode::Unmark() {} +void ExitNode::Unmark() { + is_marked_ = false; +} -Handle Cfg::Compile(FunctionLiteral* fun, Handle