Support optimization of named function literals.
authorkmillikin@chromium.org <kmillikin@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 31 May 2011 11:54:46 +0000 (11:54 +0000)
committerkmillikin@chromium.org <kmillikin@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 31 May 2011 11:54:46 +0000 (11:54 +0000)
Introduce a Hydrogen value for the value denoted by the function name.

R=fschneider@chromium.org,mnaganov@chromium.org
BUG=
TEST=

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

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

12 files changed:
src/arm/lithium-arm.cc
src/arm/lithium-arm.h
src/arm/lithium-codegen-arm.cc
src/hydrogen-instructions.h
src/hydrogen.cc
src/ia32/lithium-codegen-ia32.cc
src/ia32/lithium-ia32.cc
src/ia32/lithium-ia32.h
src/x64/lithium-codegen-x64.cc
src/x64/lithium-x64.cc
src/x64/lithium-x64.h
test/cctest/cctest.status

index d4c2ac1..a3b6b95 100644 (file)
@@ -1195,6 +1195,11 @@ LInstruction* LChunkBuilder::DoPushArgument(HPushArgument* instr) {
 }
 
 
+LInstruction* LChunkBuilder::DoThisFunction(HThisFunction* instr) {
+  return instr->HasNoUses() ? NULL : DefineAsRegister(new LThisFunction);
+}
+
+
 LInstruction* LChunkBuilder::DoContext(HContext* instr) {
   return instr->HasNoUses() ? NULL : DefineAsRegister(new LContext);
 }
index 1dbdd19..817d780 100644 (file)
@@ -169,6 +169,7 @@ class LCodeGen;
   V(StringLength)                               \
   V(SubI)                                       \
   V(TaggedToI)                                  \
+  V(ThisFunction)                               \
   V(Throw)                                      \
   V(ToFastProperties)                           \
   V(Typeof)                                     \
@@ -1440,6 +1441,11 @@ class LPushArgument: public LTemplateInstruction<0, 1, 0> {
 };
 
 
+class LThisFunction: public LTemplateInstruction<1, 0, 0> {
+  DECLARE_CONCRETE_INSTRUCTION(ThisFunction, "this-function")
+};
+
+
 class LContext: public LTemplateInstruction<1, 0, 0> {
  public:
   DECLARE_CONCRETE_INSTRUCTION(Context, "context")
index 85eb90b..973145c 100644 (file)
@@ -2801,6 +2801,12 @@ void LCodeGen::DoPushArgument(LPushArgument* instr) {
 }
 
 
+void LCodeGen::DoThisFunction(LThisFunction* instr) {
+  Register result = ToRegister(instr->result());
+  __ ldr(result, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
+}
+
+
 void LCodeGen::DoContext(LContext* instr) {
   Register result = ToRegister(instr->result());
   __ mov(result, cp);
index 40da1b9..48662be 100644 (file)
@@ -101,15 +101,14 @@ class LChunkBuilder;
   V(EnterInlined)                              \
   V(ExternalArrayLength)                       \
   V(FixedArrayLength)                          \
-  V(ToInt32)                                   \
   V(ForceRepresentation)                       \
   V(FunctionLiteral)                           \
   V(GetCachedArrayIndex)                       \
   V(GlobalObject)                              \
   V(GlobalReceiver)                            \
   V(Goto)                                      \
-  V(HasInstanceType)                           \
   V(HasCachedArrayIndex)                       \
+  V(HasInstanceType)                           \
   V(In)                                        \
   V(InstanceOf)                                \
   V(InstanceOfKnownGlobal)                     \
@@ -152,8 +151,8 @@ class LChunkBuilder;
   V(StoreGlobalCell)                           \
   V(StoreGlobalGeneric)                        \
   V(StoreKeyedFastElement)                     \
-  V(StoreKeyedSpecializedArrayElement)         \
   V(StoreKeyedGeneric)                         \
+  V(StoreKeyedSpecializedArrayElement)         \
   V(StoreNamedField)                           \
   V(StoreNamedGeneric)                         \
   V(StringAdd)                                 \
@@ -162,8 +161,10 @@ class LChunkBuilder;
   V(StringLength)                              \
   V(Sub)                                       \
   V(Test)                                      \
+  V(ThisFunction)                              \
   V(Throw)                                     \
   V(ToFastProperties)                          \
+  V(ToInt32)                                   \
   V(Typeof)                                    \
   V(TypeofIs)                                  \
   V(UnaryMathOperation)                        \
@@ -1302,6 +1303,24 @@ class HPushArgument: public HUnaryOperation {
 };
 
 
+class HThisFunction: public HTemplateInstruction<0> {
+ public:
+  HThisFunction() {
+    set_representation(Representation::Tagged());
+    SetFlag(kUseGVN);
+  }
+
+  virtual Representation RequiredInputRepresentation(int index) const {
+    return Representation::None();
+  }
+
+  DECLARE_CONCRETE_INSTRUCTION(ThisFunction)
+
+ protected:
+  virtual bool DataEquals(HValue* other) { return true; }
+};
+
+
 class HContext: public HTemplateInstruction<0> {
  public:
   HContext() {
@@ -1313,7 +1332,7 @@ class HContext: public HTemplateInstruction<0> {
     return Representation::None();
   }
 
-  DECLARE_CONCRETE_INSTRUCTION(Context);
+  DECLARE_CONCRETE_INSTRUCTION(Context)
 
  protected:
   virtual bool DataEquals(HValue* other) { return true; }
index 429d902..363fe82 100644 (file)
@@ -2308,9 +2308,6 @@ HInstruction* HGraphBuilder::PreProcessCall(HCall<V>* call) {
 
 
 void HGraphBuilder::SetupScope(Scope* scope) {
-  // We don't yet handle the function name for named function expressions.
-  if (scope->function() != NULL) return Bailout("named function expression");
-
   HConstant* undefined_constant = new(zone()) HConstant(
       isolate()->factory()->undefined_value(), Representation::Tagged());
   AddInstruction(undefined_constant);
@@ -5361,7 +5358,8 @@ void HGraphBuilder::VisitThisFunction(ThisFunction* expr) {
   ASSERT(!HasStackOverflow());
   ASSERT(current_block() != NULL);
   ASSERT(current_block()->HasPredecessor());
-  return Bailout("ThisFunction");
+  HThisFunction* self = new(zone()) HThisFunction;
+  return ast_context()->ReturnInstruction(self, expr->id());
 }
 
 
index 2f84f7d..b41049d 100644 (file)
@@ -2689,6 +2689,12 @@ void LCodeGen::DoPushArgument(LPushArgument* instr) {
 }
 
 
+void LCodeGen::DoThisFunction(LThisFunction* instr) {
+  Register result = ToRegister(instr->result());
+  __ mov(result, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
+}
+
+
 void LCodeGen::DoContext(LContext* instr) {
   Register result = ToRegister(instr->result());
   __ mov(result, Operand(ebp, StandardFrameConstants::kContextOffset));
index ea25343..1a9316c 100644 (file)
@@ -1203,6 +1203,11 @@ LInstruction* LChunkBuilder::DoPushArgument(HPushArgument* instr) {
 }
 
 
+LInstruction* LChunkBuilder::DoThisFunction(HThisFunction* instr) {
+  return instr->HasNoUses() ? NULL : DefineAsRegister(new LThisFunction);
+}
+
+
 LInstruction* LChunkBuilder::DoContext(HContext* instr) {
   return instr->HasNoUses() ? NULL : DefineAsRegister(new LContext);
 }
index 5904791..37f87cd 100644 (file)
@@ -163,6 +163,7 @@ class LCodeGen;
   V(StringLength)                               \
   V(SubI)                                       \
   V(TaggedToI)                                  \
+  V(ThisFunction)                               \
   V(Throw)                                      \
   V(ToFastProperties)                           \
   V(Typeof)                                     \
@@ -1471,6 +1472,11 @@ class LPushArgument: public LTemplateInstruction<0, 1, 0> {
 };
 
 
+class LThisFunction: public LTemplateInstruction<1, 0, 0> {
+  DECLARE_CONCRETE_INSTRUCTION(ThisFunction, "this-function")
+};
+
+
 class LContext: public LTemplateInstruction<1, 0, 0> {
  public:
   DECLARE_CONCRETE_INSTRUCTION(Context, "context")
index c79f5e5..98ac81e 100644 (file)
@@ -2693,6 +2693,12 @@ void LCodeGen::DoPushArgument(LPushArgument* instr) {
 }
 
 
+void LCodeGen::DoThisFunction(LThisFunction* instr) {
+  Register result = ToRegister(instr->result());
+  __ movq(result, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
+}
+
+
 void LCodeGen::DoContext(LContext* instr) {
   Register result = ToRegister(instr->result());
   __ movq(result, rsi);
index 8ac7307..517870f 100644 (file)
@@ -1191,6 +1191,11 @@ LInstruction* LChunkBuilder::DoPushArgument(HPushArgument* instr) {
 }
 
 
+LInstruction* LChunkBuilder::DoThisFunction(HThisFunction* instr) {
+  return instr->HasNoUses() ? NULL : DefineAsRegister(new LThisFunction);
+}
+
+
 LInstruction* LChunkBuilder::DoContext(HContext* instr) {
   return instr->HasNoUses() ? NULL : DefineAsRegister(new LContext);
 }
index e2f33b1..c0d989d 100644 (file)
@@ -169,6 +169,7 @@ class LCodeGen;
   V(StringLength)                               \
   V(SubI)                                       \
   V(TaggedToI)                                  \
+  V(ThisFunction)                               \
   V(Throw)                                      \
   V(ToFastProperties)                           \
   V(Typeof)                                     \
@@ -1441,6 +1442,11 @@ class LPushArgument: public LTemplateInstruction<0, 1, 0> {
 };
 
 
+class LThisFunction: public LTemplateInstruction<1, 0, 0> {
+  DECLARE_CONCRETE_INSTRUCTION(ThisFunction, "this-function")
+};
+
+
 class LContext: public LTemplateInstruction<1, 0, 0> {
  public:
   DECLARE_CONCRETE_INSTRUCTION(Context, "context")
index 01a8222..62bc82f 100644 (file)
@@ -36,6 +36,9 @@ test-debug/DebuggerAgent: PASS, (PASS || FAIL) if $system == linux
 # BUG(382): Weird test. Can't guarantee that it never times out.
 test-api/ApplyInterruption: PASS || TIMEOUT
 
+# BUG(1417): Crashes with --stress-opt --always-opt.
+test-log/Issue23768: PASS || CRASH
+
 # These tests always fail.  They are here to test test.py.  If
 # they don't fail then test.py has failed.
 test-serialize/TestThatAlwaysFails: FAIL