Adding declaration of global variables and functions in new compiler.
Adding calls to global functions to the new compiler. Review URL: http://codereview.chromium.org/302002 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3099 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
cd2065be00
commit
88371e63f6
@ -330,10 +330,11 @@ class CodeGenerator: public AstVisitor {
|
||||
const InlineRuntimeLUT& new_entry,
|
||||
InlineRuntimeLUT* old_entry);
|
||||
|
||||
static Handle<Code> ComputeLazyCompile(int argc);
|
||||
Handle<JSFunction> BuildBoilerplate(FunctionLiteral* node);
|
||||
void ProcessDeclarations(ZoneList<Declaration*>* declarations);
|
||||
|
||||
Handle<Code> ComputeCallInitialize(int argc, InLoopFlag in_loop);
|
||||
static Handle<Code> ComputeCallInitialize(int argc, InLoopFlag in_loop);
|
||||
|
||||
// Declare global variables and functions in the given array of
|
||||
// name/value pairs.
|
||||
@ -426,6 +427,7 @@ class CodeGenerator: public AstVisitor {
|
||||
friend class JumpTarget;
|
||||
friend class Reference;
|
||||
friend class FastCodeGenerator;
|
||||
friend class CodeGenSelector;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(CodeGenerator);
|
||||
};
|
||||
|
@ -85,6 +85,10 @@ void FastCodeGenerator::Generate(FunctionLiteral* fun) {
|
||||
lo);
|
||||
}
|
||||
|
||||
{ Comment cmnt(masm_, "[ Declarations");
|
||||
VisitDeclarations(fun->scope()->declarations());
|
||||
}
|
||||
|
||||
{ Comment cmnt(masm_, "[ Body");
|
||||
VisitStatements(fun->body());
|
||||
}
|
||||
@ -104,6 +108,25 @@ void FastCodeGenerator::Generate(FunctionLiteral* fun) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
|
||||
// Call the runtime to declare the globals.
|
||||
__ mov(r0, Operand(pairs));
|
||||
__ push(r0);
|
||||
__ push(cp); // The context is the second argument.
|
||||
__ mov(r0, Operand(Smi::FromInt(is_eval_ ? 1 : 0)));
|
||||
__ push(r0);
|
||||
__ CallRuntime(Runtime::kDeclareGlobals, 3);
|
||||
// Return value is ignored.
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitBlock(Block* stmt) {
|
||||
Comment cmnt(masm_, "[ Block");
|
||||
SetStatementPosition(stmt);
|
||||
VisitStatements(stmt->statements());
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) {
|
||||
Comment cmnt(masm_, "[ ExpressionStatement");
|
||||
SetStatementPosition(stmt);
|
||||
@ -136,6 +159,29 @@ void FastCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
|
||||
Comment cmnt(masm_, "[ FunctionLiteral");
|
||||
|
||||
// Build the function boilerplate and instantiate it.
|
||||
Handle<JSFunction> boilerplate = BuildBoilerplate(expr);
|
||||
if (HasStackOverflow()) return;
|
||||
|
||||
ASSERT(boilerplate->IsBoilerplate());
|
||||
|
||||
// Create a new closure.
|
||||
__ mov(r0, Operand(boilerplate));
|
||||
__ push(r0);
|
||||
__ push(cp);
|
||||
__ CallRuntime(Runtime::kNewClosure, 2);
|
||||
|
||||
if (expr->location().is_temporary()) {
|
||||
__ push(r0);
|
||||
} else {
|
||||
ASSERT(expr->location().is_nowhere());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
|
||||
Comment cmnt(masm_, "[ VariableProxy");
|
||||
Expression* rewrite = expr->var()->rewrite();
|
||||
@ -224,4 +270,72 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitCall(Call* expr) {
|
||||
Comment cmnt(masm_, "[ Call");
|
||||
Expression* fun = expr->expression();
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
Variable* var = fun->AsVariableProxy()->AsVariable();
|
||||
ASSERT(var != NULL && !var->is_this() && var->is_global());
|
||||
ASSERT(!var->is_possibly_eval());
|
||||
|
||||
__ mov(r0, Operand(var->name()));
|
||||
__ push(r0);
|
||||
// Push global object (receiver)
|
||||
__ ldr(r0, CodeGenerator::GlobalObject());
|
||||
__ push(r0);
|
||||
int arg_count = args->length();
|
||||
for (int i = 0; i < arg_count; i++) {
|
||||
Visit(args->at(i));
|
||||
ASSERT(!args->at(i)->location().is_nowhere());
|
||||
if (args->at(i)->location().is_constant()) {
|
||||
ASSERT(args->at(i)->AsLiteral() != NULL);
|
||||
__ mov(r0, Operand(args->at(i)->AsLiteral()->handle()));
|
||||
__ push(r0);
|
||||
}
|
||||
}
|
||||
// Record source position for debugger
|
||||
SetSourcePosition(expr->position());
|
||||
// Call the IC initialization code.
|
||||
Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count,
|
||||
NOT_IN_LOOP);
|
||||
__ Call(ic, RelocInfo::CODE_TARGET_CONTEXT);
|
||||
// Restore context register.
|
||||
__ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
|
||||
if (expr->location().is_temporary()) {
|
||||
__ str(r0, MemOperand(sp));
|
||||
} else {
|
||||
ASSERT(expr->location().is_nowhere());
|
||||
__ pop();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
|
||||
Comment cmnt(masm_, "[ CallRuntime");
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
Runtime::Function* function = expr->function();
|
||||
|
||||
ASSERT(function != NULL);
|
||||
|
||||
// Push the arguments ("left-to-right").
|
||||
int arg_count = args->length();
|
||||
for (int i = 0; i < arg_count; i++) {
|
||||
Visit(args->at(i));
|
||||
ASSERT(!args->at(i)->location().is_nowhere());
|
||||
if (args->at(i)->location().is_constant()) {
|
||||
ASSERT(args->at(i)->AsLiteral() != NULL);
|
||||
__ mov(r0, Operand(args->at(i)->AsLiteral()->handle()));
|
||||
__ push(r0);
|
||||
}
|
||||
}
|
||||
|
||||
__ CallRuntime(function, arg_count);
|
||||
if (expr->location().is_temporary()) {
|
||||
__ push(r0);
|
||||
} else {
|
||||
ASSERT(expr->location().is_nowhere());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} } // namespace v8::internal
|
||||
|
@ -274,7 +274,7 @@ void CodeGenerator::SetFunctionInfo(Handle<JSFunction> fun,
|
||||
}
|
||||
|
||||
|
||||
static Handle<Code> ComputeLazyCompile(int argc) {
|
||||
Handle<Code> CodeGenerator::ComputeLazyCompile(int argc) {
|
||||
CALL_HEAP_FUNCTION(StubCache::ComputeLazyCompile(argc), Code);
|
||||
}
|
||||
|
||||
|
@ -56,6 +56,7 @@
|
||||
// ~CodeGenerator
|
||||
// ProcessDeferred
|
||||
// GenCode
|
||||
// ComputeLazyCompile
|
||||
// BuildBoilerplate
|
||||
// ComputeCallInitialize
|
||||
// ComputeCallInitializeInLoop
|
||||
|
@ -51,6 +51,7 @@ class CodeGenSelector: public AstVisitor {
|
||||
CodeGenTag Select(FunctionLiteral* fun);
|
||||
|
||||
private:
|
||||
void VisitDeclarations(ZoneList<Declaration*>* decls);
|
||||
void VisitStatements(ZoneList<Statement*>* stmts);
|
||||
|
||||
// AST node visit functions.
|
||||
@ -107,7 +108,7 @@ static Handle<Code> MakeCode(FunctionLiteral* literal,
|
||||
CodeGenSelector selector;
|
||||
CodeGenSelector::CodeGenTag code_gen = selector.Select(literal);
|
||||
if (code_gen == CodeGenSelector::FAST) {
|
||||
return FastCodeGenerator::MakeCode(literal, script);
|
||||
return FastCodeGenerator::MakeCode(literal, script, is_eval);
|
||||
}
|
||||
ASSERT(code_gen == CodeGenSelector::NORMAL);
|
||||
}
|
||||
@ -450,14 +451,22 @@ bool Compiler::CompileLazy(Handle<SharedFunctionInfo> shared,
|
||||
CodeGenSelector::CodeGenTag CodeGenSelector::Select(FunctionLiteral* fun) {
|
||||
Scope* scope = fun->scope();
|
||||
|
||||
if (!scope->is_global_scope()) return NORMAL;
|
||||
if (!scope->is_global_scope()) {
|
||||
if (FLAG_trace_bailout) PrintF("Non-global scope\n");
|
||||
return NORMAL;
|
||||
}
|
||||
ASSERT(scope->num_heap_slots() == 0);
|
||||
ASSERT(scope->arguments() == NULL);
|
||||
|
||||
if (!scope->declarations()->is_empty()) return NORMAL;
|
||||
if (fun->materialized_literal_count() > 0) return NORMAL;
|
||||
if (fun->materialized_literal_count() > 0) {
|
||||
if (FLAG_trace_bailout) PrintF("Unsupported literal\n");
|
||||
return NORMAL;
|
||||
}
|
||||
|
||||
has_supported_syntax_ = true;
|
||||
VisitDeclarations(fun->scope()->declarations());
|
||||
if (!has_supported_syntax_) return NORMAL;
|
||||
|
||||
VisitStatements(fun->body());
|
||||
return has_supported_syntax_ ? FAST : NORMAL;
|
||||
}
|
||||
@ -479,21 +488,32 @@ CodeGenSelector::CodeGenTag CodeGenSelector::Select(FunctionLiteral* fun) {
|
||||
} while (false)
|
||||
|
||||
|
||||
void CodeGenSelector::VisitDeclarations(ZoneList<Declaration*>* decls) {
|
||||
for (int i = 0; i < decls->length(); i++) {
|
||||
Visit(decls->at(i));
|
||||
CHECK_BAILOUT;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CodeGenSelector::VisitStatements(ZoneList<Statement*>* stmts) {
|
||||
for (int i = 0, len = stmts->length(); i < len; i++) {
|
||||
CHECK_BAILOUT;
|
||||
Visit(stmts->at(i));
|
||||
CHECK_BAILOUT;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CodeGenSelector::VisitDeclaration(Declaration* decl) {
|
||||
BAILOUT("Declaration");
|
||||
Variable* var = decl->proxy()->var();
|
||||
if (!var->is_global() || var->mode() == Variable::CONST) {
|
||||
BAILOUT("Non-global declaration");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CodeGenSelector::VisitBlock(Block* stmt) {
|
||||
BAILOUT("Block");
|
||||
VisitStatements(stmt->statements());
|
||||
}
|
||||
|
||||
|
||||
@ -581,7 +601,9 @@ void CodeGenSelector::VisitDebuggerStatement(DebuggerStatement* stmt) {
|
||||
|
||||
|
||||
void CodeGenSelector::VisitFunctionLiteral(FunctionLiteral* expr) {
|
||||
BAILOUT("FunctionLiteral");
|
||||
if (!expr->AllowsLazyCompilation()) {
|
||||
BAILOUT("FunctionLiteral does not allow lazy compilation");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -674,7 +696,25 @@ void CodeGenSelector::VisitProperty(Property* expr) {
|
||||
|
||||
|
||||
void CodeGenSelector::VisitCall(Call* expr) {
|
||||
BAILOUT("Call");
|
||||
Expression* fun = expr->expression();
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
Variable* var = fun->AsVariableProxy()->AsVariable();
|
||||
|
||||
// Check for supported calls
|
||||
if (var != NULL && var->is_possibly_eval()) {
|
||||
BAILOUT("Call to a function named 'eval'");
|
||||
} else if (var != NULL && !var->is_this() && var->is_global()) {
|
||||
// ----------------------------------
|
||||
// JavaScript example: 'foo(1, 2, 3)' // foo is global
|
||||
// ----------------------------------
|
||||
} else {
|
||||
BAILOUT("Call to a non-global function");
|
||||
}
|
||||
// Check all arguments to the call
|
||||
for (int i = 0; i < args->length(); i++) {
|
||||
Visit(args->at(i));
|
||||
CHECK_BAILOUT;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -684,7 +724,17 @@ void CodeGenSelector::VisitCallNew(CallNew* expr) {
|
||||
|
||||
|
||||
void CodeGenSelector::VisitCallRuntime(CallRuntime* expr) {
|
||||
BAILOUT("CallRuntime");
|
||||
// In case of JS runtime function bail out.
|
||||
if (expr->function() == NULL) BAILOUT("CallRuntime");
|
||||
// Check for inline runtime call
|
||||
if (expr->name()->Get(0) == '_' &&
|
||||
CodeGenerator::FindInlineRuntimeLUT(expr->name()) != NULL) {
|
||||
BAILOUT("InlineRuntimeCall");
|
||||
}
|
||||
for (int i = 0; i < expr->arguments()->length(); i++) {
|
||||
Visit(expr->arguments()->at(i));
|
||||
CHECK_BAILOUT;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -29,16 +29,19 @@
|
||||
|
||||
#include "codegen-inl.h"
|
||||
#include "fast-codegen.h"
|
||||
#include "stub-cache.h"
|
||||
#include "debug.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
Handle<Code> FastCodeGenerator::MakeCode(FunctionLiteral* fun,
|
||||
Handle<Script> script) {
|
||||
Handle<Script> script,
|
||||
bool is_eval) {
|
||||
CodeGenerator::MakeCodePrologue(fun);
|
||||
const int kInitialBufferSize = 4 * KB;
|
||||
MacroAssembler masm(NULL, kInitialBufferSize);
|
||||
FastCodeGenerator cgen(&masm);
|
||||
FastCodeGenerator cgen(&masm, script, is_eval);
|
||||
cgen.Generate(fun);
|
||||
if (cgen.HasStackOverflow()) {
|
||||
ASSERT(!Top::has_pending_exception());
|
||||
@ -66,6 +69,95 @@ int FastCodeGenerator::SlotOffset(Slot* slot) {
|
||||
return offset;
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitDeclarations(
|
||||
ZoneList<Declaration*>* declarations) {
|
||||
int length = declarations->length();
|
||||
int globals = 0;
|
||||
for (int i = 0; i < length; i++) {
|
||||
Declaration* node = declarations->at(i);
|
||||
Variable* var = node->proxy()->var();
|
||||
Slot* slot = var->slot();
|
||||
|
||||
// If it was not possible to allocate the variable at compile
|
||||
// time, we need to "declare" it at runtime to make sure it
|
||||
// actually exists in the local context.
|
||||
if ((slot != NULL && slot->type() == Slot::LOOKUP) || !var->is_global()) {
|
||||
UNREACHABLE();
|
||||
} else {
|
||||
// Count global variables and functions for later processing
|
||||
globals++;
|
||||
}
|
||||
}
|
||||
|
||||
// Return in case of no declared global functions or variables.
|
||||
if (globals == 0) return;
|
||||
|
||||
// Compute array of global variable and function declarations.
|
||||
Handle<FixedArray> array = Factory::NewFixedArray(2 * globals, TENURED);
|
||||
for (int j = 0, i = 0; i < length; i++) {
|
||||
Declaration* node = declarations->at(i);
|
||||
Variable* var = node->proxy()->var();
|
||||
Slot* slot = var->slot();
|
||||
|
||||
if ((slot == NULL || slot->type() != Slot::LOOKUP) && var->is_global()) {
|
||||
array->set(j++, *(var->name()));
|
||||
if (node->fun() == NULL) {
|
||||
if (var->mode() == Variable::CONST) {
|
||||
// In case this is const property use the hole.
|
||||
array->set_the_hole(j++);
|
||||
} else {
|
||||
array->set_undefined(j++);
|
||||
}
|
||||
} else {
|
||||
Handle<JSFunction> function = BuildBoilerplate(node->fun());
|
||||
// Check for stack-overflow exception.
|
||||
if (HasStackOverflow()) return;
|
||||
array->set(j++, *function);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Invoke the platform-dependent code generator to do the actual
|
||||
// declaration the global variables and functions.
|
||||
DeclareGlobals(array);
|
||||
}
|
||||
|
||||
Handle<JSFunction> FastCodeGenerator::BuildBoilerplate(FunctionLiteral* fun) {
|
||||
#ifdef DEBUG
|
||||
// We should not try to compile the same function literal more than
|
||||
// once.
|
||||
fun->mark_as_compiled();
|
||||
#endif
|
||||
|
||||
// Generate code
|
||||
Handle<Code> code = CodeGenerator::ComputeLazyCompile(fun->num_parameters());
|
||||
// Check for stack-overflow exception.
|
||||
if (code.is_null()) {
|
||||
SetStackOverflow();
|
||||
return Handle<JSFunction>::null();
|
||||
}
|
||||
|
||||
// Create a boilerplate function.
|
||||
Handle<JSFunction> function =
|
||||
Factory::NewFunctionBoilerplate(fun->name(),
|
||||
fun->materialized_literal_count(),
|
||||
code);
|
||||
CodeGenerator::SetFunctionInfo(function, fun, false, script_);
|
||||
|
||||
#ifdef ENABLE_DEBUGGER_SUPPORT
|
||||
// Notify debugger that a new function has been added.
|
||||
Debugger::OnNewFunction(function);
|
||||
#endif
|
||||
|
||||
// Set the expected number of properties for instances and return
|
||||
// the resulting function.
|
||||
SetExpectedNofPropertiesFromEstimate(function,
|
||||
fun->expected_property_count());
|
||||
return function;
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::SetFunctionPosition(FunctionLiteral* fun) {
|
||||
if (FLAG_debug_info) {
|
||||
CodeGenerator::RecordPositions(masm_, fun->start_position());
|
||||
@ -99,11 +191,6 @@ void FastCodeGenerator::VisitDeclaration(Declaration* decl) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitBlock(Block* stmt) {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) {
|
||||
UNREACHABLE();
|
||||
}
|
||||
@ -174,11 +261,6 @@ void FastCodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitFunctionBoilerplateLiteral(
|
||||
FunctionBoilerplateLiteral* expr) {
|
||||
UNREACHABLE();
|
||||
@ -231,21 +313,11 @@ void FastCodeGenerator::VisitProperty(Property* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitCall(Call* expr) {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitCallNew(CallNew* expr) {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
@ -38,17 +38,23 @@ namespace internal {
|
||||
|
||||
class FastCodeGenerator: public AstVisitor {
|
||||
public:
|
||||
explicit FastCodeGenerator(MacroAssembler* masm)
|
||||
: masm_(masm), function_(NULL) {
|
||||
FastCodeGenerator(MacroAssembler* masm, Handle<Script> script, bool is_eval)
|
||||
: masm_(masm), function_(NULL), script_(script), is_eval_(is_eval) {
|
||||
}
|
||||
|
||||
static Handle<Code> MakeCode(FunctionLiteral* fun, Handle<Script> script);
|
||||
static Handle<Code> MakeCode(FunctionLiteral* fun,
|
||||
Handle<Script> script,
|
||||
bool is_eval);
|
||||
|
||||
void Generate(FunctionLiteral* fun);
|
||||
|
||||
private:
|
||||
int SlotOffset(Slot* slot);
|
||||
|
||||
void VisitDeclarations(ZoneList<Declaration*>* declarations);
|
||||
Handle<JSFunction> BuildBoilerplate(FunctionLiteral* fun);
|
||||
void DeclareGlobals(Handle<FixedArray> pairs);
|
||||
|
||||
void SetFunctionPosition(FunctionLiteral* fun);
|
||||
void SetReturnPosition(FunctionLiteral* fun);
|
||||
void SetStatementPosition(Statement* stmt);
|
||||
@ -61,6 +67,8 @@ class FastCodeGenerator: public AstVisitor {
|
||||
|
||||
MacroAssembler* masm_;
|
||||
FunctionLiteral* function_;
|
||||
Handle<Script> script_;
|
||||
bool is_eval_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(FastCodeGenerator);
|
||||
};
|
||||
|
@ -511,10 +511,11 @@ class CodeGenerator: public AstVisitor {
|
||||
const InlineRuntimeLUT& new_entry,
|
||||
InlineRuntimeLUT* old_entry);
|
||||
|
||||
static Handle<Code> ComputeLazyCompile(int argc);
|
||||
Handle<JSFunction> BuildBoilerplate(FunctionLiteral* node);
|
||||
void ProcessDeclarations(ZoneList<Declaration*>* declarations);
|
||||
|
||||
Handle<Code> ComputeCallInitialize(int argc, InLoopFlag in_loop);
|
||||
static Handle<Code> ComputeCallInitialize(int argc, InLoopFlag in_loop);
|
||||
|
||||
// Declare global variables and functions in the given array of
|
||||
// name/value pairs.
|
||||
@ -617,6 +618,7 @@ class CodeGenerator: public AstVisitor {
|
||||
friend class Reference;
|
||||
friend class Result;
|
||||
friend class FastCodeGenerator;
|
||||
friend class CodeGenSelector;
|
||||
|
||||
friend class CodeGeneratorPatcher; // Used in test-log-stack-tracer.cc
|
||||
|
||||
|
@ -75,6 +75,10 @@ void FastCodeGenerator::Generate(FunctionLiteral* fun) {
|
||||
__ bind(&ok);
|
||||
}
|
||||
|
||||
{ Comment cmnt(masm_, "[ Declarations");
|
||||
VisitDeclarations(fun->scope()->declarations());
|
||||
}
|
||||
|
||||
{ Comment cmnt(masm_, "[ Body");
|
||||
VisitStatements(fun->body());
|
||||
}
|
||||
@ -94,6 +98,23 @@ void FastCodeGenerator::Generate(FunctionLiteral* fun) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
|
||||
// Call the runtime to declare the globals.
|
||||
__ push(Immediate(pairs));
|
||||
__ push(esi); // The context is the second argument.
|
||||
__ push(Immediate(Smi::FromInt(is_eval_ ? 1 : 0)));
|
||||
__ CallRuntime(Runtime::kDeclareGlobals, 3);
|
||||
// Return value is ignored.
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitBlock(Block* stmt) {
|
||||
Comment cmnt(masm_, "[ Block");
|
||||
SetStatementPosition(stmt);
|
||||
VisitStatements(stmt->statements());
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) {
|
||||
Comment cmnt(masm_, "[ ExpressionStatement");
|
||||
SetStatementPosition(stmt);
|
||||
@ -126,6 +147,28 @@ void FastCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
|
||||
Comment cmnt(masm_, "[ FunctionLiteral");
|
||||
|
||||
// Build the function boilerplate and instantiate it.
|
||||
Handle<JSFunction> boilerplate = BuildBoilerplate(expr);
|
||||
if (HasStackOverflow()) return;
|
||||
|
||||
ASSERT(boilerplate->IsBoilerplate());
|
||||
|
||||
// Create a new closure.
|
||||
__ push(Immediate(boilerplate));
|
||||
__ push(esi);
|
||||
__ CallRuntime(Runtime::kNewClosure, 2);
|
||||
|
||||
if (expr->location().is_temporary()) {
|
||||
__ push(eax);
|
||||
} else {
|
||||
ASSERT(expr->location().is_nowhere());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
|
||||
Comment cmnt(masm_, "[ VariableProxy");
|
||||
Expression* rewrite = expr->var()->rewrite();
|
||||
@ -213,4 +256,68 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitCall(Call* expr) {
|
||||
Expression* fun = expr->expression();
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
Variable* var = fun->AsVariableProxy()->AsVariable();
|
||||
ASSERT(var != NULL && !var->is_this() && var->is_global());
|
||||
ASSERT(!var->is_possibly_eval());
|
||||
|
||||
__ push(Immediate(var->name()));
|
||||
// Push global object (receiver).
|
||||
__ push(CodeGenerator::GlobalObject());
|
||||
int arg_count = args->length();
|
||||
for (int i = 0; i < arg_count; i++) {
|
||||
Visit(args->at(i));
|
||||
ASSERT(!args->at(i)->location().is_nowhere());
|
||||
if (args->at(i)->location().is_constant()) {
|
||||
ASSERT(args->at(i)->AsLiteral() != NULL);
|
||||
__ push(Immediate(args->at(i)->AsLiteral()->handle()));
|
||||
}
|
||||
}
|
||||
// Record source position for debugger
|
||||
SetSourcePosition(expr->position());
|
||||
// Call the IC initialization code.
|
||||
Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count,
|
||||
NOT_IN_LOOP);
|
||||
__ call(ic, RelocInfo::CODE_TARGET_CONTEXT);
|
||||
// Restore context register.
|
||||
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
|
||||
// Discard the function left on TOS.
|
||||
if (expr->location().is_temporary()) {
|
||||
__ mov(Operand(esp, 0), eax);
|
||||
} else {
|
||||
ASSERT(expr->location().is_nowhere());
|
||||
__ pop(eax);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
|
||||
Comment cmnt(masm_, "[ CallRuntime");
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
Runtime::Function* function = expr->function();
|
||||
|
||||
ASSERT(function != NULL);
|
||||
|
||||
// Push the arguments ("left-to-right").
|
||||
int arg_count = args->length();
|
||||
for (int i = 0; i < arg_count; i++) {
|
||||
Visit(args->at(i));
|
||||
ASSERT(!args->at(i)->location().is_nowhere());
|
||||
if (args->at(i)->location().is_constant()) {
|
||||
ASSERT(args->at(i)->AsLiteral() != NULL);
|
||||
__ push(Immediate(args->at(i)->AsLiteral()->handle()));
|
||||
}
|
||||
}
|
||||
|
||||
__ CallRuntime(function, arg_count);
|
||||
if (expr->location().is_temporary()) {
|
||||
__ push(eax);
|
||||
} else {
|
||||
ASSERT(expr->location().is_nowhere());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} } // namespace v8::internal
|
||||
|
@ -511,10 +511,11 @@ class CodeGenerator: public AstVisitor {
|
||||
static bool PatchInlineRuntimeEntry(Handle<String> name,
|
||||
const InlineRuntimeLUT& new_entry,
|
||||
InlineRuntimeLUT* old_entry);
|
||||
static Handle<Code> ComputeLazyCompile(int argc);
|
||||
Handle<JSFunction> BuildBoilerplate(FunctionLiteral* node);
|
||||
void ProcessDeclarations(ZoneList<Declaration*>* declarations);
|
||||
|
||||
Handle<Code> ComputeCallInitialize(int argc, InLoopFlag in_loop);
|
||||
static Handle<Code> ComputeCallInitialize(int argc, InLoopFlag in_loop);
|
||||
|
||||
// Declare global variables and functions in the given array of
|
||||
// name/value pairs.
|
||||
@ -617,6 +618,7 @@ class CodeGenerator: public AstVisitor {
|
||||
friend class Reference;
|
||||
friend class Result;
|
||||
friend class FastCodeGenerator;
|
||||
friend class CodeGenSelector;
|
||||
|
||||
friend class CodeGeneratorPatcher; // Used in test-log-stack-tracer.cc
|
||||
|
||||
|
@ -74,6 +74,10 @@ void FastCodeGenerator::Generate(FunctionLiteral* fun) {
|
||||
__ bind(&ok);
|
||||
}
|
||||
|
||||
{ Comment cmnt(masm_, "[ Declarations");
|
||||
VisitDeclarations(fun->scope()->declarations());
|
||||
}
|
||||
|
||||
{ Comment cmnt(masm_, "[ Body");
|
||||
VisitStatements(fun->body());
|
||||
}
|
||||
@ -102,6 +106,23 @@ void FastCodeGenerator::Generate(FunctionLiteral* fun) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
|
||||
// Call the runtime to declare the globals.
|
||||
__ Push(pairs);
|
||||
__ push(rsi); // The context is the second argument.
|
||||
__ Push(Smi::FromInt(is_eval_ ? 1 : 0));
|
||||
__ CallRuntime(Runtime::kDeclareGlobals, 3);
|
||||
// Return value is ignored.
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitBlock(Block* stmt) {
|
||||
Comment cmnt(masm_, "[ Block");
|
||||
SetStatementPosition(stmt);
|
||||
VisitStatements(stmt->statements());
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) {
|
||||
Comment cmnt(masm_, "[ ExpressionStatement");
|
||||
SetStatementPosition(stmt);
|
||||
@ -143,6 +164,28 @@ void FastCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
|
||||
Comment cmnt(masm_, "[ FunctionLiteral");
|
||||
|
||||
// Build the function boilerplate and instantiate it.
|
||||
Handle<JSFunction> boilerplate = BuildBoilerplate(expr);
|
||||
if (HasStackOverflow()) return;
|
||||
|
||||
ASSERT(boilerplate->IsBoilerplate());
|
||||
|
||||
// Create a new closure.
|
||||
__ Push(boilerplate);
|
||||
__ push(rsi);
|
||||
__ CallRuntime(Runtime::kNewClosure, 2);
|
||||
|
||||
if (expr->location().is_temporary()) {
|
||||
__ push(rax);
|
||||
} else {
|
||||
ASSERT(expr->location().is_nowhere());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
|
||||
Comment cmnt(masm_, "[ VariableProxy");
|
||||
Expression* rewrite = expr->var()->rewrite();
|
||||
@ -227,4 +270,68 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitCall(Call* expr) {
|
||||
Expression* fun = expr->expression();
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
Variable* var = fun->AsVariableProxy()->AsVariable();
|
||||
ASSERT(var != NULL && !var->is_this() && var->is_global());
|
||||
ASSERT(!var->is_possibly_eval());
|
||||
|
||||
__ Push(var->name());
|
||||
// Push global object (receiver).
|
||||
__ push(CodeGenerator::GlobalObject());
|
||||
int arg_count = args->length();
|
||||
for (int i = 0; i < arg_count; i++) {
|
||||
Visit(args->at(i));
|
||||
ASSERT(!args->at(i)->location().is_nowhere());
|
||||
if (args->at(i)->location().is_constant()) {
|
||||
ASSERT(args->at(i)->AsLiteral() != NULL);
|
||||
__ Push(args->at(i)->AsLiteral()->handle());
|
||||
}
|
||||
}
|
||||
// Record source position for debugger
|
||||
SetSourcePosition(expr->position());
|
||||
// Call the IC initialization code.
|
||||
Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count,
|
||||
NOT_IN_LOOP);
|
||||
__ call(ic, RelocInfo::CODE_TARGET_CONTEXT);
|
||||
// Restore context register.
|
||||
__ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
|
||||
// Discard the function left on TOS.
|
||||
if (expr->location().is_temporary()) {
|
||||
__ movq(Operand(rsp, 0), rax);
|
||||
} else {
|
||||
ASSERT(expr->location().is_nowhere());
|
||||
__ pop(rax);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
|
||||
Comment cmnt(masm_, "[ CallRuntime");
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
Runtime::Function* function = expr->function();
|
||||
|
||||
ASSERT(function != NULL);
|
||||
|
||||
// Push the arguments ("left-to-right").
|
||||
int arg_count = args->length();
|
||||
for (int i = 0; i < arg_count; i++) {
|
||||
Visit(args->at(i));
|
||||
ASSERT(!args->at(i)->location().is_nowhere());
|
||||
if (args->at(i)->location().is_constant()) {
|
||||
ASSERT(args->at(i)->AsLiteral() != NULL);
|
||||
__ Push(args->at(i)->AsLiteral()->handle());
|
||||
}
|
||||
}
|
||||
|
||||
__ CallRuntime(function, arg_count);
|
||||
if (expr->location().is_temporary()) {
|
||||
__ push(rax);
|
||||
} else {
|
||||
ASSERT(expr->location().is_nowhere());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} } // namespace v8::internal
|
||||
|
Loading…
Reference in New Issue
Block a user