Revision: 3196
Author: [email protected]
Date: Mon Nov  2 04:04:35 2009
Log: Support for function calls on an arbitrary expression that returns
a function in the top-level compiler.

e.g.

function f() { return (function() { return true; }) }
f()()


Review URL: http://codereview.chromium.org/346029
http://code.google.com/p/v8/source/detail?r=3196

Modified:
  /branches/bleeding_edge/src/arm/fast-codegen-arm.cc
  /branches/bleeding_edge/src/compiler.cc
  /branches/bleeding_edge/src/ia32/fast-codegen-ia32.cc
  /branches/bleeding_edge/src/x64/fast-codegen-x64.cc
  /branches/bleeding_edge/test/mjsunit/compiler/function-call.js

=======================================
--- /branches/bleeding_edge/src/arm/fast-codegen-arm.cc Mon Nov  2 03:01:47  
2009
+++ /branches/bleeding_edge/src/arm/fast-codegen-arm.cc Mon Nov  2 04:04:35  
2009
@@ -723,8 +723,13 @@

  void FastCodeGenerator::VisitCall(Call* expr) {
    Expression* fun = expr->expression();
-
-  if (fun->AsProperty() != NULL) {
+  Variable* var = fun->AsVariableProxy()->AsVariable();
+
+  if (var != NULL &&
+      var->is_possibly_eval()) {
+    // Call to eval.
+    UNREACHABLE();
+  } else if (fun->AsProperty() != NULL) {
      // Call on a property.
      Property* prop = fun->AsProperty();
      Literal* key = prop->key()->AsLiteral();
@@ -755,9 +760,8 @@
        __ str(r1, MemOperand(sp));
        EmitCallWithStub(expr);
      }
-  } else if (fun->AsVariableProxy()->AsVariable() != NULL) {
+  } else if (var != NULL) {
      // Call on a global variable
-    Variable* var = fun->AsVariableProxy()->AsVariable();
      ASSERT(var != NULL && !var->is_this() && var->is_global());
      ASSERT(!var->is_possibly_eval());
      __ mov(r1, Operand(var->name()));
@@ -765,10 +769,19 @@
      __ ldr(r0, CodeGenerator::GlobalObject());
      __ stm(db_w, sp, r1.bit() | r0.bit());
      EmitCallWithIC(expr, RelocInfo::CODE_TARGET_CONTEXT);
-  } else {
-    // Calls we cannot handle right now.
-    // Should bailout in the CodeGenSelector.
+  } else if (var != NULL && var->slot() != NULL &&
+             var->slot()->type() == Slot::LOOKUP) {
+    // Call inside a with-statement
      UNREACHABLE();
+  } else {
+    // Call with an arbitrary function expression.
+    Visit(expr->expression());
+    // Load global receiver object.
+    __ ldr(r1, CodeGenerator::GlobalObject());
+    __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset));
+    __ push(r1);
+    // Emit function call.
+    EmitCallWithStub(expr);
    }
  }

=======================================
--- /branches/bleeding_edge/src/compiler.cc     Mon Nov  2 03:01:47 2009
+++ /branches/bleeding_edge/src/compiler.cc     Mon Nov  2 04:04:35 2009
@@ -791,6 +791,9 @@

    // Check for supported calls
    if (var != NULL && var->is_possibly_eval()) {
+    // ----------------------------------
+    // JavaScript example: 'eval(arg)'  // eval is not known to be shadowed
+    // ----------------------------------
      BAILOUT("Call to a function named 'eval'");
    } else if (var != NULL && !var->is_this() && var->is_global()) {
      // ----------------------------------
@@ -811,8 +814,17 @@
        ProcessExpression(prop->key(), Expression::kValue);
        CHECK_BAILOUT;
      }
+  } else if (var != NULL && var->slot() != NULL &&
+             var->slot()->type() == Slot::LOOKUP) {
+    // ----------------------------------
+    // JavaScript example: 'with (obj) foo(1, 2, 3)'  // foo is in obj
+    // ----------------------------------
+    BAILOUT("Call inside a with-statement");
    } else {
-    BAILOUT("Unsupported call to a function");
+    // ----------------------------------
+    // JavaScript example: 'foo(1, 2, 3)'  // foo is any expression, not  
global
+    // ----------------------------------
+    ProcessExpression(fun, Expression::kValue);
    }
    // Check all arguments to the call.  (Relies on TEMP meaning STACK.)
    for (int i = 0; i < args->length(); i++) {
=======================================
--- /branches/bleeding_edge/src/ia32/fast-codegen-ia32.cc       Mon Nov  2  
03:01:47 2009
+++ /branches/bleeding_edge/src/ia32/fast-codegen-ia32.cc       Mon Nov  2  
04:04:35 2009
@@ -745,8 +745,13 @@

  void FastCodeGenerator::VisitCall(Call* expr) {
    Expression* fun = expr->expression();
-
-  if (fun->AsProperty() != NULL) {
+  Variable* var = fun->AsVariableProxy()->AsVariable();
+
+  if (var != NULL &&
+      var->is_possibly_eval()) {
+    // Call to eval.
+    UNREACHABLE();
+  } else if (fun->AsProperty() != NULL) {
      // Call on a property.
      Property* prop = fun->AsProperty();
      Literal* key = prop->key()->AsLiteral();
@@ -782,19 +787,28 @@
        }
        EmitCallWithStub(expr);
      }
-  } else if (fun->AsVariableProxy()->AsVariable() != NULL) {
+  } else if (var != NULL) {
      // Call on a global variable
-    Variable* var = fun->AsVariableProxy()->AsVariable();
-    ASSERT(var != NULL && !var->is_this() && var->is_global());
+    ASSERT(var != NULL);
+    ASSERT(!var->is_this());
+    ASSERT(var->is_global());
      ASSERT(!var->is_possibly_eval());
      __ push(Immediate(var->name()));
      // Push global object (receiver).
      __ push(CodeGenerator::GlobalObject());
      EmitCallWithIC(expr, RelocInfo::CODE_TARGET_CONTEXT);
-  } else {
-    // Calls we cannot handle right now.
-    // Should bailout in the CodeGenSelector.
+  } else if (var != NULL && var->slot() != NULL &&
+             var->slot()->type() == Slot::LOOKUP) {
+    // Call inside a with-statement
      UNREACHABLE();
+  } else {
+    // Call with an arbitrary function expression.
+    Visit(expr->expression());
+    // Load global receiver object.
+    __ mov(ebx, CodeGenerator::GlobalObject());
+    __ push(FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset));
+    // Emit function call.
+    EmitCallWithStub(expr);
    }
  }

=======================================
--- /branches/bleeding_edge/src/x64/fast-codegen-x64.cc Mon Nov  2 03:01:47  
2009
+++ /branches/bleeding_edge/src/x64/fast-codegen-x64.cc Mon Nov  2 04:04:35  
2009
@@ -760,8 +760,13 @@

  void FastCodeGenerator::VisitCall(Call* expr) {
    Expression* fun = expr->expression();
-
-  if (fun->AsProperty() != NULL) {
+  Variable* var = fun->AsVariableProxy()->AsVariable();
+
+  if (var != NULL &&
+      var->is_possibly_eval()) {
+    // Call to eval.
+    UNREACHABLE();
+  } else if (fun->AsProperty() != NULL) {
      // Call on a property.
      Property* prop = fun->AsProperty();
      Literal* key = prop->key()->AsLiteral();
@@ -797,19 +802,26 @@
        }
        EmitCallWithStub(expr);
      }
-  } else if (fun->AsVariableProxy()->AsVariable() != NULL) {
+  } else if (var != NULL) {
      // Call on a global variable
-    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());
      EmitCallWithIC(expr, RelocInfo::CODE_TARGET_CONTEXT);
-  } else {
-    // Calls we cannot handle right now.
-    // Should bailout in the CodeGenSelector.
+  } else if (var != NULL && var->slot() != NULL &&
+             var->slot()->type() == Slot::LOOKUP) {
+    // Call inside a with-statement
      UNREACHABLE();
+  } else {
+    // Call with an arbitrary function expression.
+    Visit(expr->expression());
+    // Load global receiver object.
+    __ movq(rbx, CodeGenerator::GlobalObject());
+    __ push(FieldOperand(rbx, GlobalObject::kGlobalReceiverOffset));
+    // Emit function call.
+    EmitCallWithStub(expr);
    }
  }

=======================================
--- /branches/bleeding_edge/test/mjsunit/compiler/function-call.js      Fri Oct 
 
30 03:22:31 2009
+++ /branches/bleeding_edge/test/mjsunit/compiler/function-call.js      Mon Nov 
  
2 04:04:35 2009
@@ -46,3 +46,7 @@
  a = b[c](10);
  assertEquals(10, a);

+// Call on a function expression
+function g() { return f; }
+a = g()(8);
+assertEquals(8, a);

--~--~---------~--~----~------------~-------~--~----~
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
-~----------~----~----~----~------~----~------~--~---

Reply via email to