Allow inlining of named function expressions containing ThisFunction reference.
authorfschneider@chromium.org <fschneider@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 19 Oct 2011 11:41:22 +0000 (11:41 +0000)
committerfschneider@chromium.org <fschneider@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 19 Oct 2011 11:41:22 +0000 (11:41 +0000)
Named function expression have an implicit local variable that
refers to the current function (ThisFunction). Before we only could inline
anonymous function expressions like:

A.prototype.foo = function() {}

as opposed to

A.prototype.foo = function foo() {}

This change enables inlining function of expressions like this.
Review URL: http://codereview.chromium.org/8346032

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

src/arm/lithium-arm.h
src/arm/lithium-codegen-arm.cc
src/ast.cc
src/hydrogen-instructions.h
src/hydrogen.cc
src/ia32/lithium-codegen-ia32.cc
src/ia32/lithium-ia32.h
src/x64/lithium-codegen-x64.cc
src/x64/lithium-x64.h

index f4df669179c1351509bd83bae687fbf4b43d9cb4..80e07a12f4d17fdc5d21da72fe529e1030e5a533 100644 (file)
@@ -1276,7 +1276,9 @@ class LPushArgument: public LTemplateInstruction<0, 1, 0> {
 
 
 class LThisFunction: public LTemplateInstruction<1, 0, 0> {
+ public:
   DECLARE_CONCRETE_INSTRUCTION(ThisFunction, "this-function")
+  DECLARE_HYDROGEN_ACCESSOR(ThisFunction)
 };
 
 
index 683853faa181084d94af1f18a5a88ddf24177ee8..e1b71f4d5d1c3b277cde9670c75fa87496fb84db 100644 (file)
@@ -2786,7 +2786,7 @@ void LCodeGen::DoPushArgument(LPushArgument* instr) {
 
 void LCodeGen::DoThisFunction(LThisFunction* instr) {
   Register result = ToRegister(instr->result());
-  __ ldr(result, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
+  LoadHeapObject(result, instr->hydrogen()->closure());
 }
 
 
index 21173b4bf92bbdf7c8422b0ab045e145baecbc83..9e34bc0e815ab3836f07f95ae51dbc27e2c85ae8 100644 (file)
@@ -465,7 +465,7 @@ bool FunctionLiteral::IsInlineable() const {
 
 
 bool ThisFunction::IsInlineable() const {
-  return false;
+  return true;
 }
 
 
index a18a64c9ab2aeb12101e0ec46eb794ea07ad8df9..6bce2d1694013ee91a0b22f4498484242c6a224d 100644 (file)
@@ -1347,7 +1347,7 @@ class HPushArgument: public HUnaryOperation {
 
 class HThisFunction: public HTemplateInstruction<0> {
  public:
-  HThisFunction() {
+  explicit HThisFunction(Handle<JSFunction> closure) : closure_(closure) {
     set_representation(Representation::Tagged());
     SetFlag(kUseGVN);
   }
@@ -1356,10 +1356,18 @@ class HThisFunction: public HTemplateInstruction<0> {
     return Representation::None();
   }
 
+  Handle<JSFunction> closure() const { return closure_; }
+
   DECLARE_CONCRETE_INSTRUCTION(ThisFunction)
 
  protected:
-  virtual bool DataEquals(HValue* other) { return true; }
+  virtual bool DataEquals(HValue* other) {
+    HThisFunction* b = HThisFunction::cast(other);
+    return *closure() == *b->closure();
+  }
+
+ private:
+  Handle<JSFunction> closure_;
 };
 
 
index 692bcd38b3898cda1e261a8a88b9b114b4a0ea1f..4fcef23bdacdd23acb9ade347f93c5e420893854 100644 (file)
@@ -6001,7 +6001,8 @@ void HGraphBuilder::VisitThisFunction(ThisFunction* expr) {
   ASSERT(!HasStackOverflow());
   ASSERT(current_block() != NULL);
   ASSERT(current_block()->HasPredecessor());
-  HThisFunction* self = new(zone()) HThisFunction;
+  HThisFunction* self = new(zone()) HThisFunction(
+      function_state()->compilation_info()->closure());
   return ast_context()->ReturnInstruction(self, expr->id());
 }
 
index e648b6cec8b0e23f533a5a150d747f23eb8fdc64..68602e0baa6c4ca388cf7713aa5bb550c546c6e3 100644 (file)
@@ -2626,7 +2626,7 @@ void LCodeGen::DoPushArgument(LPushArgument* instr) {
 
 void LCodeGen::DoThisFunction(LThisFunction* instr) {
   Register result = ToRegister(instr->result());
-  __ mov(result, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
+  LoadHeapObject(result, instr->hydrogen()->closure());
 }
 
 
index dc92b09b27f0cab4b50dcfd9ee33db971c9248e6..d23563532c09e34ee2b7a9ac47cd2abd3e8df421 100644 (file)
@@ -1311,7 +1311,9 @@ class LPushArgument: public LTemplateInstruction<0, 1, 0> {
 
 
 class LThisFunction: public LTemplateInstruction<1, 0, 0> {
+ public:
   DECLARE_CONCRETE_INSTRUCTION(ThisFunction, "this-function")
+  DECLARE_HYDROGEN_ACCESSOR(ThisFunction)
 };
 
 
index 391affe60478bd4238cfee22fa09d6e2a081f792..f17b70db640181dc6dad3abc46730e5af43b7f82 100644 (file)
@@ -2572,7 +2572,7 @@ void LCodeGen::DoPushArgument(LPushArgument* instr) {
 
 void LCodeGen::DoThisFunction(LThisFunction* instr) {
   Register result = ToRegister(instr->result());
-  __ movq(result, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
+  LoadHeapObject(result, instr->hydrogen()->closure());
 }
 
 
index 32292b625946a0c04f03c20854ef5eba17d31279..515a3082b50d0758f0781042117628fa85f9a101 100644 (file)
@@ -1276,7 +1276,9 @@ class LPushArgument: public LTemplateInstruction<0, 1, 0> {
 
 
 class LThisFunction: public LTemplateInstruction<1, 0, 0> {
+ public:
   DECLARE_CONCRETE_INSTRUCTION(ThisFunction, "this-function")
+  DECLARE_HYDROGEN_ACCESSOR(ThisFunction)
 };