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
This commit is contained in:
parent
3d070f1f0c
commit
67a61e96c7
@ -56,9 +56,10 @@ void EntryNode::Compile(MacroAssembler* masm) {
|
|||||||
Comment cmnt(masm, "[ EntryNode");
|
Comment cmnt(masm, "[ EntryNode");
|
||||||
__ stm(db_w, sp, r1.bit() | cp.bit() | fp.bit() | lr.bit());
|
__ stm(db_w, sp, r1.bit() | cp.bit() | fp.bit() | lr.bit());
|
||||||
__ add(fp, sp, Operand(2 * kPointerSize));
|
__ 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()));
|
__ mov(ip, Operand(Factory::undefined_value()));
|
||||||
for (int i = 0; i < local_count_; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
__ push(ip);
|
__ push(ip);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -84,7 +85,8 @@ void ExitNode::Compile(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
__ mov(sp, fp);
|
__ mov(sp, fp);
|
||||||
__ ldm(ia_w, sp, fp.bit() | lr.bit());
|
__ 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);
|
__ Jump(lr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,6 +101,24 @@ void Constant::ToRegister(MacroAssembler* masm, Register reg) {
|
|||||||
__ mov(reg, Operand(handle_));
|
__ 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 __
|
#undef __
|
||||||
|
|
||||||
} } // namespace v8::internal
|
} } // namespace v8::internal
|
||||||
|
88
src/cfg.cc
88
src/cfg.cc
@ -36,32 +36,37 @@ namespace v8 {
|
|||||||
namespace internal {
|
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
|
#ifdef DEBUG
|
||||||
node_counter_ = 0;
|
node_counter_(0),
|
||||||
#endif
|
#endif
|
||||||
}
|
previous_(top_) {
|
||||||
|
top_ = this;
|
||||||
|
|
||||||
void Cfg::Reset(FunctionLiteral* fun) {
|
|
||||||
global_exit_ = new ExitNode(fun);
|
|
||||||
CfgNode::Reset();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#define BAILOUT(reason) \
|
#define BAILOUT(reason) \
|
||||||
do { return NULL; } while (false)
|
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<Statement*>* body = fun->body();
|
ZoneList<Statement*>* body = fun->body();
|
||||||
if (body->is_empty()) {
|
if (body->is_empty()) {
|
||||||
BAILOUT("empty function body");
|
BAILOUT("empty function body");
|
||||||
}
|
}
|
||||||
|
|
||||||
Cfg::Reset(fun);
|
|
||||||
StatementBuilder builder;
|
StatementBuilder builder;
|
||||||
builder.VisitStatements(body);
|
builder.VisitStatements(body);
|
||||||
Cfg* cfg = builder.cfg();
|
Cfg* cfg = builder.cfg();
|
||||||
@ -71,16 +76,16 @@ Cfg* Cfg::Build(FunctionLiteral* fun) {
|
|||||||
if (cfg->has_exit()) {
|
if (cfg->has_exit()) {
|
||||||
BAILOUT("control path without explicit return");
|
BAILOUT("control path without explicit return");
|
||||||
}
|
}
|
||||||
cfg->PrependEntryNode(fun);
|
cfg->PrependEntryNode();
|
||||||
return cfg;
|
return cfg;
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef BAILOUT
|
#undef BAILOUT
|
||||||
|
|
||||||
|
|
||||||
void Cfg::PrependEntryNode(FunctionLiteral* fun) {
|
void Cfg::PrependEntryNode() {
|
||||||
ASSERT(!is_empty());
|
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) {
|
void Cfg::AppendReturnInstruction(Value* value) {
|
||||||
Append(new ReturnInstr(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;
|
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() {
|
void InstructionBlock::Unmark() {
|
||||||
if (is_marked_) {
|
if (is_marked_) {
|
||||||
is_marked_ = false;
|
is_marked_ = false;
|
||||||
@ -124,16 +120,19 @@ void EntryNode::Unmark() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void ExitNode::Unmark() {}
|
void ExitNode::Unmark() {
|
||||||
|
is_marked_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Handle<Code> Cfg::Compile(FunctionLiteral* fun, Handle<Script> script) {
|
Handle<Code> Cfg::Compile(Handle<Script> script) {
|
||||||
const int kInitialBufferSize = 4 * KB;
|
const int kInitialBufferSize = 4 * KB;
|
||||||
MacroAssembler* masm = new MacroAssembler(NULL, kInitialBufferSize);
|
MacroAssembler* masm = new MacroAssembler(NULL, kInitialBufferSize);
|
||||||
entry()->Compile(masm);
|
entry()->Compile(masm);
|
||||||
entry()->Unmark();
|
entry()->Unmark();
|
||||||
CodeDesc desc;
|
CodeDesc desc;
|
||||||
masm->GetCode(&desc);
|
masm->GetCode(&desc);
|
||||||
|
FunctionLiteral* fun = CfgGlobals::current()->fun();
|
||||||
ZoneScopeInfo info(fun->scope());
|
ZoneScopeInfo info(fun->scope());
|
||||||
InLoopFlag in_loop = fun->loop_nesting() ? IN_LOOP : NOT_IN_LOOP;
|
InLoopFlag in_loop = fun->loop_nesting() ? IN_LOOP : NOT_IN_LOOP;
|
||||||
Code::Flags flags = Code::ComputeFlags(Code::FUNCTION, in_loop);
|
Code::Flags flags = Code::ComputeFlags(Code::FUNCTION, in_loop);
|
||||||
@ -149,8 +148,9 @@ Handle<Code> Cfg::Compile(FunctionLiteral* fun, Handle<Script> script) {
|
|||||||
PrintF("--- Raw source ---\n");
|
PrintF("--- Raw source ---\n");
|
||||||
StringInputBuffer stream(String::cast(script->source()));
|
StringInputBuffer stream(String::cast(script->source()));
|
||||||
stream.Seek(fun->start_position());
|
stream.Seek(fun->start_position());
|
||||||
// fun->end_position() points to the last character in the stream. We
|
// fun->end_position() points to the last character in the
|
||||||
// need to compensate by adding one to calculate the length.
|
// stream. We need to compensate by adding one to calculate the
|
||||||
|
// length.
|
||||||
int source_len = fun->end_position() - fun->start_position() + 1;
|
int source_len = fun->end_position() - fun->start_position() + 1;
|
||||||
for (int i = 0; i < source_len; i++) {
|
for (int i = 0; i < source_len; i++) {
|
||||||
if (stream.has_more()) PrintF("%c", stream.GetNext());
|
if (stream.has_more()) PrintF("%c", stream.GetNext());
|
||||||
@ -207,7 +207,15 @@ void ExpressionBuilder::VisitSlot(Slot* expr) {
|
|||||||
|
|
||||||
|
|
||||||
void ExpressionBuilder::VisitVariableProxy(VariableProxy* expr) {
|
void ExpressionBuilder::VisitVariableProxy(VariableProxy* expr) {
|
||||||
BAILOUT("VariableProxy");
|
Expression* rewrite = expr->var()->rewrite();
|
||||||
|
if (rewrite == NULL || rewrite->AsSlot() == NULL) {
|
||||||
|
BAILOUT("unsupported variable (not a slot)");
|
||||||
|
}
|
||||||
|
Slot* slot = rewrite->AsSlot();
|
||||||
|
if (slot->type() != Slot::PARAMETER && slot->type() != Slot::LOCAL) {
|
||||||
|
BAILOUT("unsupported slot type (not a parameter or local)");
|
||||||
|
}
|
||||||
|
value_ = new SlotLocation(slot->type(), slot->index());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -416,7 +424,24 @@ void Cfg::Print() {
|
|||||||
|
|
||||||
|
|
||||||
void Constant::Print() {
|
void Constant::Print() {
|
||||||
|
PrintF("Constant(");
|
||||||
handle_->Print();
|
handle_->Print();
|
||||||
|
PrintF(")");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SlotLocation::Print() {
|
||||||
|
PrintF("Slot(");
|
||||||
|
switch (type_) {
|
||||||
|
case Slot::PARAMETER:
|
||||||
|
PrintF("PARAMETER, %d)", index_);
|
||||||
|
break;
|
||||||
|
case Slot::LOCAL:
|
||||||
|
PrintF("LOCAL, %d)", index_);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -427,9 +452,6 @@ void ReturnInstr::Print() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int CfgNode::node_counter_ = 0;
|
|
||||||
|
|
||||||
|
|
||||||
void InstructionBlock::Print() {
|
void InstructionBlock::Print() {
|
||||||
if (!is_marked_) {
|
if (!is_marked_) {
|
||||||
is_marked_ = true;
|
is_marked_ = true;
|
||||||
|
106
src/cfg.h
106
src/cfg.h
@ -33,6 +33,47 @@
|
|||||||
namespace v8 {
|
namespace v8 {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
|
class ExitNode;
|
||||||
|
|
||||||
|
// A convenient class to keep 'global' values when building a CFG. Since
|
||||||
|
// CFG construction can be invoked recursively, CFG globals are stacked.
|
||||||
|
class CfgGlobals BASE_EMBEDDED {
|
||||||
|
public:
|
||||||
|
explicit CfgGlobals(FunctionLiteral* fun);
|
||||||
|
|
||||||
|
~CfgGlobals() { top_ = previous_; }
|
||||||
|
|
||||||
|
static CfgGlobals* current() {
|
||||||
|
ASSERT(top_ != NULL);
|
||||||
|
return top_;
|
||||||
|
}
|
||||||
|
|
||||||
|
FunctionLiteral* fun() { return global_fun_; }
|
||||||
|
|
||||||
|
ExitNode* exit() { return global_exit_; }
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
int next_number() { return node_counter_++; }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
private:
|
||||||
|
static CfgGlobals* top_;
|
||||||
|
|
||||||
|
// Function literal currently compiling.
|
||||||
|
FunctionLiteral* global_fun_;
|
||||||
|
|
||||||
|
// Shared global exit node for all returns from the same function.
|
||||||
|
ExitNode* global_exit_;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
// Used to number nodes when printing.
|
||||||
|
int node_counter_;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
CfgGlobals* previous_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
// Values appear in instructions. They represent trivial source
|
// Values appear in instructions. They represent trivial source
|
||||||
// expressions: ones with no side effects and that do not require code to be
|
// expressions: ones with no side effects and that do not require code to be
|
||||||
// generated.
|
// generated.
|
||||||
@ -66,6 +107,37 @@ class Constant : public Value {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Locations are values that can be stored into ('lvalues').
|
||||||
|
class Location : public Value {
|
||||||
|
public:
|
||||||
|
virtual ~Location() {}
|
||||||
|
|
||||||
|
virtual void ToRegister(MacroAssembler* masm, Register reg) = 0;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
virtual void Print() = 0;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// SlotLocations represent parameters and stack-allocated (i.e.,
|
||||||
|
// non-context) local variables.
|
||||||
|
class SlotLocation : public Location {
|
||||||
|
public:
|
||||||
|
SlotLocation(Slot::Type type, int index) : type_(type), index_(index) {}
|
||||||
|
|
||||||
|
void ToRegister(MacroAssembler* masm, Register reg);
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
void Print();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
private:
|
||||||
|
Slot::Type type_;
|
||||||
|
int index_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
// Instructions are computations. The represent non-trivial source
|
// Instructions are computations. The represent non-trivial source
|
||||||
// expressions: typically ones that have side effects and require code to
|
// expressions: typically ones that have side effects and require code to
|
||||||
// be generated.
|
// be generated.
|
||||||
@ -114,8 +186,6 @@ class CfgNode : public ZoneObject {
|
|||||||
|
|
||||||
bool is_marked() { return is_marked_; }
|
bool is_marked() { return is_marked_; }
|
||||||
|
|
||||||
static void Reset();
|
|
||||||
|
|
||||||
virtual bool is_block() { return false; }
|
virtual bool is_block() { return false; }
|
||||||
|
|
||||||
virtual void Unmark() = 0;
|
virtual void Unmark() = 0;
|
||||||
@ -124,7 +194,7 @@ class CfgNode : public ZoneObject {
|
|||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
int number() {
|
int number() {
|
||||||
if (number_ == -1) number_ = node_counter_++;
|
if (number_ == -1) number_ = CfgGlobals::current()->next_number();
|
||||||
return number_;
|
return number_;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,8 +206,6 @@ class CfgNode : public ZoneObject {
|
|||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
int number_;
|
int number_;
|
||||||
|
|
||||||
static int node_counter_;
|
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -182,7 +250,7 @@ class InstructionBlock : public CfgNode {
|
|||||||
// containing the function's first instruction.
|
// containing the function's first instruction.
|
||||||
class EntryNode : public CfgNode {
|
class EntryNode : public CfgNode {
|
||||||
public:
|
public:
|
||||||
EntryNode(FunctionLiteral* fun, InstructionBlock* succ);
|
explicit EntryNode(InstructionBlock* succ) : successor_(succ) {}
|
||||||
|
|
||||||
virtual ~EntryNode() {}
|
virtual ~EntryNode() {}
|
||||||
|
|
||||||
@ -196,7 +264,6 @@ class EntryNode : public CfgNode {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
InstructionBlock* successor_;
|
InstructionBlock* successor_;
|
||||||
int local_count_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -205,7 +272,7 @@ class EntryNode : public CfgNode {
|
|||||||
// the blocks returning from the function.
|
// the blocks returning from the function.
|
||||||
class ExitNode : public CfgNode {
|
class ExitNode : public CfgNode {
|
||||||
public:
|
public:
|
||||||
explicit ExitNode(FunctionLiteral* fun);
|
ExitNode() {}
|
||||||
|
|
||||||
virtual ~ExitNode() {}
|
virtual ~ExitNode() {}
|
||||||
|
|
||||||
@ -216,16 +283,13 @@ class ExitNode : public CfgNode {
|
|||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
void Print();
|
void Print();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
|
||||||
int parameter_count_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// A CFG is a consists of a linked structure of nodes. It has a single
|
// A CFG consists of a linked structure of nodes. It has a single entry
|
||||||
// entry node and optionally an exit node. There is a distinguished global
|
// node and optionally an exit node. There is a distinguished global exit
|
||||||
// exit node that is used as the successor of all blocks that return from
|
// node that is used as the successor of all blocks that return from the
|
||||||
// the function.
|
// function.
|
||||||
//
|
//
|
||||||
// Fragments of control-flow graphs, produced when traversing the statements
|
// Fragments of control-flow graphs, produced when traversing the statements
|
||||||
// and expressions in the source AST, are represented by the same class.
|
// and expressions in the source AST, are represented by the same class.
|
||||||
@ -241,7 +305,7 @@ class Cfg : public ZoneObject {
|
|||||||
explicit Cfg(InstructionBlock* block) : entry_(block), exit_(block) {}
|
explicit Cfg(InstructionBlock* block) : entry_(block), exit_(block) {}
|
||||||
|
|
||||||
// Build the CFG for a function.
|
// Build the CFG for a function.
|
||||||
static Cfg* Build(FunctionLiteral* fun);
|
static Cfg* Build();
|
||||||
|
|
||||||
// The entry and exit nodes.
|
// The entry and exit nodes.
|
||||||
CfgNode* entry() { return entry_; }
|
CfgNode* entry() { return entry_; }
|
||||||
@ -256,7 +320,7 @@ class Cfg : public ZoneObject {
|
|||||||
|
|
||||||
// Add an entry node to a CFG fragment. It is no longer a fragment
|
// Add an entry node to a CFG fragment. It is no longer a fragment
|
||||||
// (instructions cannot be prepended).
|
// (instructions cannot be prepended).
|
||||||
void PrependEntryNode(FunctionLiteral* fun);
|
void PrependEntryNode();
|
||||||
|
|
||||||
// Append an instruction to the end of a CFG fragment. Assumes it has an
|
// Append an instruction to the end of a CFG fragment. Assumes it has an
|
||||||
// available exit.
|
// available exit.
|
||||||
@ -266,7 +330,7 @@ class Cfg : public ZoneObject {
|
|||||||
// longer has an available exit node.
|
// longer has an available exit node.
|
||||||
void AppendReturnInstruction(Value* value);
|
void AppendReturnInstruction(Value* value);
|
||||||
|
|
||||||
Handle<Code> Compile(FunctionLiteral* fun, Handle<Script> script);
|
Handle<Code> Compile(Handle<Script> script);
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
// Support for printing.
|
// Support for printing.
|
||||||
@ -274,12 +338,6 @@ class Cfg : public ZoneObject {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Reset static variables before building the CFG for a function.
|
|
||||||
static void Reset(FunctionLiteral* fun);
|
|
||||||
|
|
||||||
// Shared global exit nodes for all returns from the same function.
|
|
||||||
static ExitNode* global_exit_;
|
|
||||||
|
|
||||||
// Entry and exit nodes.
|
// Entry and exit nodes.
|
||||||
CfgNode* entry_;
|
CfgNode* entry_;
|
||||||
CfgNode* exit_;
|
CfgNode* exit_;
|
||||||
|
@ -80,7 +80,8 @@ static Handle<Code> MakeCode(FunctionLiteral* literal,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (FLAG_multipass) {
|
if (FLAG_multipass) {
|
||||||
Cfg* cfg = Cfg::Build(literal);
|
CfgGlobals scope(literal);
|
||||||
|
Cfg* cfg = Cfg::Build();
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (FLAG_print_cfg && cfg != NULL) {
|
if (FLAG_print_cfg && cfg != NULL) {
|
||||||
SmartPointer<char> name = literal->name()->ToCString();
|
SmartPointer<char> name = literal->name()->ToCString();
|
||||||
@ -90,7 +91,7 @@ static Handle<Code> MakeCode(FunctionLiteral* literal,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (cfg != NULL) {
|
if (cfg != NULL) {
|
||||||
return cfg->Compile(literal, script);
|
return cfg->Compile(script);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,9 +59,10 @@ void EntryNode::Compile(MacroAssembler* masm) {
|
|||||||
__ mov(ebp, esp);
|
__ mov(ebp, esp);
|
||||||
__ push(esi);
|
__ push(esi);
|
||||||
__ push(edi);
|
__ push(edi);
|
||||||
if (local_count_ > 0) {
|
int count = CfgGlobals::current()->fun()->scope()->num_stack_slots();
|
||||||
|
if (count > 0) {
|
||||||
__ Set(eax, Immediate(Factory::undefined_value()));
|
__ Set(eax, Immediate(Factory::undefined_value()));
|
||||||
for (int i = 0; i < local_count_; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
__ push(eax);
|
__ push(eax);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -97,7 +98,8 @@ void ExitNode::Compile(MacroAssembler* masm) {
|
|||||||
__ RecordJSReturn();
|
__ RecordJSReturn();
|
||||||
__ mov(esp, ebp);
|
__ mov(esp, ebp);
|
||||||
__ pop(ebp);
|
__ pop(ebp);
|
||||||
__ ret((parameter_count_ + 1) * kPointerSize);
|
int count = CfgGlobals::current()->fun()->scope()->num_parameters();
|
||||||
|
__ ret((count + 1) * kPointerSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -111,6 +113,25 @@ void Constant::ToRegister(MacroAssembler* masm, Register reg) {
|
|||||||
__ mov(reg, Immediate(handle_));
|
__ mov(reg, Immediate(handle_));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SlotLocation::ToRegister(MacroAssembler* masm, Register reg) {
|
||||||
|
switch (type_) {
|
||||||
|
case Slot::PARAMETER: {
|
||||||
|
int count = CfgGlobals::current()->fun()->scope()->num_parameters();
|
||||||
|
__ mov(reg, Operand(ebp, (1 + count - index_) * kPointerSize));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Slot::LOCAL: {
|
||||||
|
const int kOffset = JavaScriptFrameConstants::kLocal0Offset;
|
||||||
|
__ mov(reg, Operand(ebp, kOffset - index_ * kPointerSize));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#undef __
|
#undef __
|
||||||
|
|
||||||
} } // namespace v8::internal
|
} } // namespace v8::internal
|
||||||
|
@ -60,10 +60,11 @@ void EntryNode::Compile(MacroAssembler* masm) {
|
|||||||
__ movq(rbp, rsp);
|
__ movq(rbp, rsp);
|
||||||
__ push(rsi);
|
__ push(rsi);
|
||||||
__ push(rdi);
|
__ push(rdi);
|
||||||
if (local_count_ > 0) {
|
int count = CfgGlobals::current()->fun()->scope()->num_stack_slots();
|
||||||
|
if (count > 0) {
|
||||||
__ movq(kScratchRegister, Factory::undefined_value(),
|
__ movq(kScratchRegister, Factory::undefined_value(),
|
||||||
RelocInfo::EMBEDDED_OBJECT);
|
RelocInfo::EMBEDDED_OBJECT);
|
||||||
for (int i = 0; i < local_count_; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
__ push(kScratchRegister);
|
__ push(kScratchRegister);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -101,7 +102,8 @@ void ExitNode::Compile(MacroAssembler* masm) {
|
|||||||
__ RecordJSReturn();
|
__ RecordJSReturn();
|
||||||
__ movq(rsp, rbp);
|
__ movq(rsp, rbp);
|
||||||
__ pop(rbp);
|
__ pop(rbp);
|
||||||
__ ret((parameter_count_ + 1) * kPointerSize);
|
int count = CfgGlobals::current()->fun()->scope()->num_parameters();
|
||||||
|
__ ret((count + 1) * kPointerSize);
|
||||||
// Add padding that will be overwritten by a debugger breakpoint.
|
// Add padding that will be overwritten by a debugger breakpoint.
|
||||||
// "movq rsp, rbp; pop rbp" has length 5. "ret k" has length 2.
|
// "movq rsp, rbp; pop rbp" has length 5. "ret k" has length 2.
|
||||||
const int kPadding = Debug::kX64JSReturnSequenceLength - 5 - 2;
|
const int kPadding = Debug::kX64JSReturnSequenceLength - 5 - 2;
|
||||||
@ -121,6 +123,24 @@ void Constant::ToRegister(MacroAssembler* masm, Register reg) {
|
|||||||
__ Move(reg, handle_);
|
__ Move(reg, handle_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SlotLocation::ToRegister(MacroAssembler* masm, Register reg) {
|
||||||
|
switch (type_) {
|
||||||
|
case Slot::PARAMETER: {
|
||||||
|
int count = CfgGlobals::current()->fun()->scope()->num_parameters();
|
||||||
|
__ movq(reg, Operand(rbp, (1 + count - index_) * kPointerSize));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Slot::LOCAL: {
|
||||||
|
const int kOffset = JavaScriptFrameConstants::kLocal0Offset;
|
||||||
|
__ movq(reg, Operand(rbp, kOffset - index_ * kPointerSize));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#undef __
|
#undef __
|
||||||
|
|
||||||
} } // namespace v8::internal
|
} } // namespace v8::internal
|
||||||
|
Loading…
Reference in New Issue
Block a user