Revision: 3099 Author: [email protected] Date: Wed Oct 21 02:17:39 2009 Log: 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 http://code.google.com/p/v8/source/detail?r=3099 Modified: /branches/bleeding_edge/src/arm/codegen-arm.h /branches/bleeding_edge/src/arm/fast-codegen-arm.cc /branches/bleeding_edge/src/codegen.cc /branches/bleeding_edge/src/codegen.h /branches/bleeding_edge/src/compiler.cc /branches/bleeding_edge/src/fast-codegen.cc /branches/bleeding_edge/src/fast-codegen.h /branches/bleeding_edge/src/ia32/codegen-ia32.h /branches/bleeding_edge/src/ia32/fast-codegen-ia32.cc /branches/bleeding_edge/src/x64/codegen-x64.h /branches/bleeding_edge/src/x64/fast-codegen-x64.cc ======================================= --- /branches/bleeding_edge/src/arm/codegen-arm.h Tue Oct 20 06:37:26 2009 +++ /branches/bleeding_edge/src/arm/codegen-arm.h Wed Oct 21 02:17:39 2009 @@ -330,10 +330,11 @@ 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 @@ friend class JumpTarget; friend class Reference; friend class FastCodeGenerator; + friend class CodeGenSelector; DISALLOW_COPY_AND_ASSIGN(CodeGenerator); }; ======================================= --- /branches/bleeding_edge/src/arm/fast-codegen-arm.cc Tue Oct 20 06:37:26 2009 +++ /branches/bleeding_edge/src/arm/fast-codegen-arm.cc Wed Oct 21 02:17:39 2009 @@ -84,6 +84,10 @@ LeaveCC, lo); } + + { Comment cmnt(masm_, "[ Declarations"); + VisitDeclarations(fun->scope()->declarations()); + } { Comment cmnt(masm_, "[ Body"); VisitStatements(fun->body()); @@ -102,6 +106,25 @@ __ Jump(lr); } } + + +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) { @@ -134,6 +157,29 @@ __ add(sp, sp, Operand((num_parameters + 1) * kPointerSize)); __ Jump(lr); } + + +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) { @@ -222,6 +268,74 @@ } } } + + +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 ======================================= --- /branches/bleeding_edge/src/codegen.cc Thu Oct 15 08:27:37 2009 +++ /branches/bleeding_edge/src/codegen.cc Wed Oct 21 02:17:39 2009 @@ -274,7 +274,7 @@ } -static Handle<Code> ComputeLazyCompile(int argc) { +Handle<Code> CodeGenerator::ComputeLazyCompile(int argc) { CALL_HEAP_FUNCTION(StubCache::ComputeLazyCompile(argc), Code); } ======================================= --- /branches/bleeding_edge/src/codegen.h Thu Oct 15 08:27:37 2009 +++ /branches/bleeding_edge/src/codegen.h Wed Oct 21 02:17:39 2009 @@ -56,6 +56,7 @@ // ~CodeGenerator // ProcessDeferred // GenCode +// ComputeLazyCompile // BuildBoilerplate // ComputeCallInitialize // ComputeCallInitializeInLoop ======================================= --- /branches/bleeding_edge/src/compiler.cc Tue Oct 20 06:37:26 2009 +++ /branches/bleeding_edge/src/compiler.cc Wed Oct 21 02:17:39 2009 @@ -51,6 +51,7 @@ CodeGenTag Select(FunctionLiteral* fun); private: + void VisitDeclarations(ZoneList<Declaration*>* decls); void VisitStatements(ZoneList<Statement*>* stmts); // AST node visit functions. @@ -107,7 +108,7 @@ 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 @@ 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 @@ } 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::VisitFunctionLiteral(FunctionLiteral* expr) { - BAILOUT("FunctionLiteral"); + if (!expr->AllowsLazyCompilation()) { + BAILOUT("FunctionLiteral does not allow lazy compilation"); + } } @@ -674,7 +696,25 @@ 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::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; + } } ======================================= --- /branches/bleeding_edge/src/fast-codegen.cc Mon Oct 19 03:36:42 2009 +++ /branches/bleeding_edge/src/fast-codegen.cc Wed Oct 21 02:17:39 2009 @@ -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()); @@ -65,6 +68,95 @@ } 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) { @@ -97,11 +189,6 @@ void FastCodeGenerator::VisitDeclaration(Declaration* decl) { UNREACHABLE(); } - - -void FastCodeGenerator::VisitBlock(Block* stmt) { - UNREACHABLE(); -} void FastCodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) { @@ -172,11 +259,6 @@ void FastCodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) { UNREACHABLE(); } - - -void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) { - UNREACHABLE(); -} void FastCodeGenerator::VisitFunctionBoilerplateLiteral( @@ -229,21 +311,11 @@ void FastCodeGenerator::VisitProperty(Property* expr) { UNREACHABLE(); } - - -void FastCodeGenerator::VisitCall(Call* expr) { - UNREACHABLE(); -} void FastCodeGenerator::VisitCallNew(CallNew* expr) { UNREACHABLE(); } - - -void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) { - UNREACHABLE(); -} void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { ======================================= --- /branches/bleeding_edge/src/fast-codegen.h Thu Oct 15 08:27:37 2009 +++ /branches/bleeding_edge/src/fast-codegen.h Wed Oct 21 02:17:39 2009 @@ -38,17 +38,23 @@ 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 @@ MacroAssembler* masm_; FunctionLiteral* function_; + Handle<Script> script_; + bool is_eval_; DISALLOW_COPY_AND_ASSIGN(FastCodeGenerator); }; ======================================= --- /branches/bleeding_edge/src/ia32/codegen-ia32.h Tue Oct 20 06:37:26 2009 +++ /branches/bleeding_edge/src/ia32/codegen-ia32.h Wed Oct 21 02:17:39 2009 @@ -511,10 +511,11 @@ 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 @@ friend class Reference; friend class Result; friend class FastCodeGenerator; + friend class CodeGenSelector; friend class CodeGeneratorPatcher; // Used in test-log-stack-tracer.cc ======================================= --- /branches/bleeding_edge/src/ia32/fast-codegen-ia32.cc Tue Oct 20 06:37:26 2009 +++ /branches/bleeding_edge/src/ia32/fast-codegen-ia32.cc Wed Oct 21 02:17:39 2009 @@ -74,6 +74,10 @@ __ CallStub(&stub); __ bind(&ok); } + + { Comment cmnt(masm_, "[ Declarations"); + VisitDeclarations(fun->scope()->declarations()); + } { Comment cmnt(masm_, "[ Body"); VisitStatements(fun->body()); @@ -92,6 +96,23 @@ __ ret((fun->scope()->num_parameters() + 1) * kPointerSize); } } + + +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) { @@ -124,6 +145,28 @@ __ pop(ebp); __ ret((function_->scope()->num_parameters() + 1) * kPointerSize); } + + +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) { @@ -211,6 +254,70 @@ } } } + + +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 ======================================= --- /branches/bleeding_edge/src/x64/codegen-x64.h Tue Oct 20 06:37:26 2009 +++ /branches/bleeding_edge/src/x64/codegen-x64.h Wed Oct 21 02:17:39 2009 @@ -511,10 +511,11 @@ 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 @@ friend class Reference; friend class Result; friend class FastCodeGenerator; + friend class CodeGenSelector; friend class CodeGeneratorPatcher; // Used in test-log-stack-tracer.cc ======================================= --- /branches/bleeding_edge/src/x64/fast-codegen-x64.cc Tue Oct 20 06:37:26 2009 +++ /branches/bleeding_edge/src/x64/fast-codegen-x64.cc Wed Oct 21 02:17:39 2009 @@ -73,6 +73,10 @@ __ CallStub(&stub); __ bind(&ok); } + + { Comment cmnt(masm_, "[ Declarations"); + VisitDeclarations(fun->scope()->declarations()); + } { Comment cmnt(masm_, "[ Body"); VisitStatements(fun->body()); @@ -100,6 +104,23 @@ #endif } } + + +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) { @@ -141,6 +162,28 @@ } #endif } + + +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) { @@ -225,6 +268,70 @@ } } } + + +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 --~--~---------~--~----~------------~-------~--~----~ v8-dev mailing list [email protected] http://groups.google.com/group/v8-dev -~----------~----~----~----~------~----~------~--~---
