Fix a latent bug in the top-level compilation of function calls.
authorkmillikin@chromium.org <kmillikin@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 3 Nov 2009 12:47:19 +0000 (12:47 +0000)
committerkmillikin@chromium.org <kmillikin@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 3 Nov 2009 12:47:19 +0000 (12:47 +0000)
Calls to a non-global variable would go through the "call to a global"
path, rather than the "call to an arbitrary (other) expression" path.

Review URL: http://codereview.chromium.org/355009

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3204 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/arm/fast-codegen-arm.cc
src/compiler.cc
src/ia32/fast-codegen-ia32.cc
src/x64/fast-codegen-x64.cc

index d21d624f0bb9c2498073104eb96f1be56ead45b8..f4d5bd11f966b0eab1e20459f9d7a1600cfd3e88 100644 (file)
@@ -769,30 +769,40 @@ void FastCodeGenerator::EmitCallWithStub(Call* expr) {
 
 
 void FastCodeGenerator::VisitCall(Call* expr) {
+  Comment cmnt(masm_, "[ Call");
   Expression* fun = expr->expression();
   Variable* var = fun->AsVariableProxy()->AsVariable();
 
-  if (var != NULL &&
-      var->is_possibly_eval()) {
-    // Call to eval.
+  if (var != NULL && var->is_possibly_eval()) {
+    // Call to the identifier 'eval'.
+    UNREACHABLE();
+  } else if (var != NULL && !var->is_this() && var->is_global()) {
+    // Call to a global variable.
+    __ mov(r1, Operand(var->name()));
+    // Push global object as receiver for the call IC lookup.
+    __ ldr(r0, CodeGenerator::GlobalObject());
+    __ stm(db_w, sp, r1.bit() | r0.bit());
+    EmitCallWithIC(expr, RelocInfo::CODE_TARGET_CONTEXT);
+  } else if (var != NULL && var->slot() != NULL &&
+             var->slot()->type() == Slot::LOOKUP) {
+    // Call to a lookup slot.
     UNREACHABLE();
   } else if (fun->AsProperty() != NULL) {
-    // Call on a property.
+    // Call to an object property.
     Property* prop = fun->AsProperty();
     Literal* key = prop->key()->AsLiteral();
     if (key != NULL && key->handle()->IsSymbol()) {
-      // Call on a named property: foo.x(1,2,3)
+      // Call to a named property, use call IC.
       __ mov(r0, Operand(key->handle()));
       __ push(r0);
       Visit(prop->obj());
-      // Use call IC.
       EmitCallWithIC(expr, RelocInfo::CODE_TARGET);
     } else {
-      // Call on a keyed property : foo[key](1,2,3)
-      // Use a keyed load IC followed by a call IC.
+      // Call to a keyed property, use keyed load IC followed by function
+      // call.
       Visit(prop->obj());
       Visit(prop->key());
-      // Record source position of property.
+      // Record source code position for IC call.
       SetSourcePosition(prop->position());
       Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
       __ Call(ic, RelocInfo::CODE_TARGET);
@@ -807,21 +817,8 @@ void FastCodeGenerator::VisitCall(Call* expr) {
       __ str(r1, MemOperand(sp));
       EmitCallWithStub(expr);
     }
-  } else if (var != NULL) {
-    // Call on a global variable
-    ASSERT(var != NULL && !var->is_this() && var->is_global());
-    ASSERT(!var->is_possibly_eval());
-    __ mov(r1, Operand(var->name()));
-    // Push global object as receiver.
-    __ ldr(r0, CodeGenerator::GlobalObject());
-    __ stm(db_w, sp, r1.bit() | r0.bit());
-    EmitCallWithIC(expr, RelocInfo::CODE_TARGET_CONTEXT);
-  } 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.
+    // Call to some other function expression.
     Visit(expr->expression());
     // Load global receiver object.
     __ ldr(r1, CodeGenerator::GlobalObject());
index 2fa41c48bc8bc16374f1fcd5aa52ce76fe5ef55d..ba96542bfe180d7674f1d3df9355306766a4806b 100644 (file)
@@ -800,18 +800,13 @@ void CodeGenSelector::VisitCall(Call* expr) {
 
   // 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'");
+    BAILOUT("call to the identifier 'eval'");
   } else if (var != NULL && !var->is_this() && var->is_global()) {
-    // ----------------------------------
-    // JavaScript example: 'foo(1, 2, 3)'  // foo is global
-    // ----------------------------------
+    // Calls to global variables are supported.
+  } else if (var != NULL && var->slot() != NULL &&
+             var->slot()->type() == Slot::LOOKUP) {
+    BAILOUT("call to a lookup slot");
   } else if (fun->AsProperty() != NULL) {
-    // ------------------------------------------------------------------
-    // JavaScript example: 'object.foo(1, 2, 3)' or 'map["key"](1, 2, 3)'
-    // ------------------------------------------------------------------
     Property* prop = fun->AsProperty();
     Literal* literal_key = prop->key()->AsLiteral();
     if (literal_key != NULL && literal_key->handle()->IsSymbol()) {
@@ -823,19 +818,11 @@ void CodeGenSelector::VisitCall(Call* expr) {
       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 {
-    // ----------------------------------
-    // JavaScript example: 'foo(1, 2, 3)'  // foo is any expression, not global
-    // ----------------------------------
+    // Otherwise the call is supported if the function expression is.
     ProcessExpression(fun, Expression::kValue);
   }
-  // Check all arguments to the call.  (Relies on TEMP meaning STACK.)
+  // Check all arguments to the call.
   for (int i = 0; i < args->length(); i++) {
     ProcessExpression(args->at(i), Expression::kValue);
     CHECK_BAILOUT;
index d512fa211e0eca94dcc50900d8ac1976a9b0767b..02c19f67f587736c9ac50be297c8b40fe85f3906 100644 (file)
@@ -787,29 +787,38 @@ void FastCodeGenerator::EmitCallWithStub(Call* expr) {
 
 
 void FastCodeGenerator::VisitCall(Call* expr) {
+  Comment cmnt(masm_, "[ Call");
   Expression* fun = expr->expression();
   Variable* var = fun->AsVariableProxy()->AsVariable();
 
-  if (var != NULL &&
-      var->is_possibly_eval()) {
-    // Call to eval.
+  if (var != NULL && var->is_possibly_eval()) {
+    // Call to the identifier 'eval'.
+    UNREACHABLE();
+  } else if (var != NULL && !var->is_this() && var->is_global()) {
+    // Call to a global variable.
+    __ push(Immediate(var->name()));
+    // Push global object as receiver for the call IC lookup.
+    __ push(CodeGenerator::GlobalObject());
+    EmitCallWithIC(expr, RelocInfo::CODE_TARGET_CONTEXT);
+  } else if (var != NULL && var->slot() != NULL &&
+             var->slot()->type() == Slot::LOOKUP) {
+    // Call to a lookup slot.
     UNREACHABLE();
   } else if (fun->AsProperty() != NULL) {
-    // Call on a property.
+    // Call to an object property.
     Property* prop = fun->AsProperty();
     Literal* key = prop->key()->AsLiteral();
     if (key != NULL && key->handle()->IsSymbol()) {
-      // Call on a named property: foo.x(1,2,3)
+      // Call to a named property, use call IC.
       __ push(Immediate(key->handle()));
       Visit(prop->obj());
-      // Use call IC.
       EmitCallWithIC(expr, RelocInfo::CODE_TARGET);
     } else {
-      // Call on a keyed property: foo[key](1,2,3)
-      // Use a keyed load IC followed by a call IC.
+      // Call to a keyed property, use keyed load IC followed by function
+      // call.
       Visit(prop->obj());
       Visit(prop->key());
-      // Record source position of property.
+      // Record source code position for IC call.
       SetSourcePosition(prop->position());
       Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
       __ call(ic, RelocInfo::CODE_TARGET);
@@ -830,22 +839,8 @@ void FastCodeGenerator::VisitCall(Call* expr) {
       }
       EmitCallWithStub(expr);
     }
-  } else if (var != NULL) {
-    // Call on a global variable
-    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 if (var != NULL && var->slot() != NULL &&
-             var->slot()->type() == Slot::LOOKUP) {
-    // Call inside a with-statement
-    UNREACHABLE();
   } else {
-    // Call with an arbitrary function expression.
+    // Call to some other function expression.
     Visit(expr->expression());
     // Load global receiver object.
     __ mov(ebx, CodeGenerator::GlobalObject());
index d5381a210cb79fd291e6e80fc46c1530bd09cff8..bdf14a544f5a24f912ab8697a0e87a26d2c930bd 100644 (file)
@@ -802,29 +802,38 @@ void FastCodeGenerator::EmitCallWithStub(Call* expr) {
 
 
 void FastCodeGenerator::VisitCall(Call* expr) {
+  Comment cmnt(masm_, "[ Call");
   Expression* fun = expr->expression();
   Variable* var = fun->AsVariableProxy()->AsVariable();
 
-  if (var != NULL &&
-      var->is_possibly_eval()) {
-    // Call to eval.
+  if (var != NULL && var->is_possibly_eval()) {
+    // Call to the identifier 'eval'.
+    UNREACHABLE();
+  } else if (var != NULL && !var->is_this() && var->is_global()) {
+    // Call to a global variable.
+    __ Push(var->name());
+    // Push global object as receiver for the call IC lookup.
+    __ push(CodeGenerator::GlobalObject());
+    EmitCallWithIC(expr, RelocInfo::CODE_TARGET_CONTEXT);
+  } else if (var != NULL && var->slot() != NULL &&
+             var->slot()->type() == Slot::LOOKUP) {
+    // Call to a lookup slot.
     UNREACHABLE();
   } else if (fun->AsProperty() != NULL) {
-    // Call on a property.
+    // Call to an object property.
     Property* prop = fun->AsProperty();
     Literal* key = prop->key()->AsLiteral();
     if (key != NULL && key->handle()->IsSymbol()) {
-      // Call on a named property: foo.x(1,2,3)
+      // Call to a named property, use call IC.
       __ Push(key->handle());
       Visit(prop->obj());
-      // Use call IC
       EmitCallWithIC(expr, RelocInfo::CODE_TARGET);
     } else {
-      // Call on a keyed property: foo[key](1,2,3)
-      // Use a keyed load IC followed by a call IC.
+      // Call to a keyed property, use keyed load IC followed by function
+      // call.
       Visit(prop->obj());
       Visit(prop->key());
-      // Record source position of property.
+      // Record source code position for IC call.
       SetSourcePosition(prop->position());
       Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
       __ call(ic, RelocInfo::CODE_TARGET);
@@ -845,20 +854,8 @@ void FastCodeGenerator::VisitCall(Call* expr) {
       }
       EmitCallWithStub(expr);
     }
-  } else if (var != NULL) {
-    // Call on a global variable
-    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 if (var != NULL && var->slot() != NULL &&
-             var->slot()->type() == Slot::LOOKUP) {
-    // Call inside a with-statement
-    UNREACHABLE();
   } else {
-    // Call with an arbitrary function expression.
+    // Call to some other function expression.
     Visit(expr->expression());
     // Load global receiver object.
     __ movq(rbx, CodeGenerator::GlobalObject());