Reviewers: fschneider, Mikhail Naganov (Chromium),
Description:
Support optimization of named function literals.
Introduce a Hydrogen value for the value denoted by the function name.
[email protected],[email protected]
BUG=
TEST=
Please review this at http://codereview.chromium.org/7083024/
SVN Base: https://v8.googlecode.com/svn/branches/bleeding_edge
Affected files:
M src/arm/lithium-arm.h
M src/arm/lithium-arm.cc
M src/arm/lithium-codegen-arm.cc
M src/hydrogen-instructions.h
M src/hydrogen.cc
M src/ia32/lithium-codegen-ia32.cc
M src/ia32/lithium-ia32.h
M src/ia32/lithium-ia32.cc
M src/x64/lithium-codegen-x64.cc
M src/x64/lithium-x64.h
M src/x64/lithium-x64.cc
M test/cctest/cctest.status
Index: src/arm/lithium-arm.cc
diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc
index
d4c2ac1ba5551f2eaf357b533670ae9d821b5d29..a3b6b95659ec2868d3b12f24fb62dd35fefcbb57
100644
--- a/src/arm/lithium-arm.cc
+++ b/src/arm/lithium-arm.cc
@@ -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: src/arm/lithium-arm.h
diff --git a/src/arm/lithium-arm.h b/src/arm/lithium-arm.h
index
1dbdd19c8c795ba1fb9093c3c514140d0eda67e0..817d780e333d35aab1b198a74c690b72f55b9084
100644
--- a/src/arm/lithium-arm.h
+++ b/src/arm/lithium-arm.h
@@ -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: src/arm/lithium-codegen-arm.cc
diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc
index
01f95a706496c54fda400dd3ed75c04fbaa29c05..03ca4aa4dee160f6e2a8dee999cc47c74a115c2f
100644
--- a/src/arm/lithium-codegen-arm.cc
+++ b/src/arm/lithium-codegen-arm.cc
@@ -2787,6 +2787,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: src/hydrogen-instructions.h
diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h
index
40da1b944b7da8e07f02d19919f760dc431b49c9..48662becd63cf963f4af97fa32cdf3a4772fbdda
100644
--- a/src/hydrogen-instructions.h
+++ b/src/hydrogen-instructions.h
@@ -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: src/hydrogen.cc
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index
a03ceb46de9f98b4fd5e5b997a8075c6d13c7d4a..cf8d2695136938fe7290301f13ee002c193c46ac
100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -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: src/ia32/lithium-codegen-ia32.cc
diff --git a/src/ia32/lithium-codegen-ia32.cc
b/src/ia32/lithium-codegen-ia32.cc
index
19df65c28a034abae34b507f12b3c82dfd07a18f..50422c28731c17b72b9736d397a510c33c70479a
100644
--- a/src/ia32/lithium-codegen-ia32.cc
+++ b/src/ia32/lithium-codegen-ia32.cc
@@ -2676,6 +2676,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: src/ia32/lithium-ia32.cc
diff --git a/src/ia32/lithium-ia32.cc b/src/ia32/lithium-ia32.cc
index
ea2534360e0dddd8479c066383e8b04fa7669fd3..1a9316c55945434e0fb8efcb1a7bb6138c1c6815
100644
--- a/src/ia32/lithium-ia32.cc
+++ b/src/ia32/lithium-ia32.cc
@@ -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: src/ia32/lithium-ia32.h
diff --git a/src/ia32/lithium-ia32.h b/src/ia32/lithium-ia32.h
index
5904791e5f22448168874ff83e972d6034dc3e8a..37f87cde4fda0ac227797afa5c8975d5497957ce
100644
--- a/src/ia32/lithium-ia32.h
+++ b/src/ia32/lithium-ia32.h
@@ -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: src/x64/lithium-codegen-x64.cc
diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc
index
fe71ff53d6796c6eeab380d4f44222aea8c3852d..e3ae8d83c5ad5fe427163db1d7cef67af7a03dca
100644
--- a/src/x64/lithium-codegen-x64.cc
+++ b/src/x64/lithium-codegen-x64.cc
@@ -2678,6 +2678,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: src/x64/lithium-x64.cc
diff --git a/src/x64/lithium-x64.cc b/src/x64/lithium-x64.cc
index
8ac73078e58a75604eb568bccbfc995cfcd06509..517870ffd420b8e1acec1e3adcc99ca13ffa2ac9
100644
--- a/src/x64/lithium-x64.cc
+++ b/src/x64/lithium-x64.cc
@@ -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: src/x64/lithium-x64.h
diff --git a/src/x64/lithium-x64.h b/src/x64/lithium-x64.h
index
e2f33b16dc1743571a57d1ea050ee88ddbbda70d..c0d989dc6c54885b43dc8d085602f803de5aa0eb
100644
--- a/src/x64/lithium-x64.h
+++ b/src/x64/lithium-x64.h
@@ -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: test/cctest/cctest.status
diff --git a/test/cctest/cctest.status b/test/cctest/cctest.status
index
01a8222e0b9c84264ffd1b0763cbbcf2a6de450d..62bc82faf6243821129f372a407d670891751b05
100644
--- a/test/cctest/cctest.status
+++ b/test/cctest/cctest.status
@@ -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
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev