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
-~----------~----~----~----~------~----~------~--~---

Reply via email to