Support optimization of named function literals.

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
parent 544191e7
...@@ -1195,6 +1195,11 @@ LInstruction* LChunkBuilder::DoPushArgument(HPushArgument* instr) { ...@@ -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) { LInstruction* LChunkBuilder::DoContext(HContext* instr) {
return instr->HasNoUses() ? NULL : DefineAsRegister(new LContext); return instr->HasNoUses() ? NULL : DefineAsRegister(new LContext);
} }
......
...@@ -169,6 +169,7 @@ class LCodeGen; ...@@ -169,6 +169,7 @@ class LCodeGen;
V(StringLength) \ V(StringLength) \
V(SubI) \ V(SubI) \
V(TaggedToI) \ V(TaggedToI) \
V(ThisFunction) \
V(Throw) \ V(Throw) \
V(ToFastProperties) \ V(ToFastProperties) \
V(Typeof) \ V(Typeof) \
...@@ -1440,6 +1441,11 @@ class LPushArgument: public LTemplateInstruction<0, 1, 0> { ...@@ -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> { class LContext: public LTemplateInstruction<1, 0, 0> {
public: public:
DECLARE_CONCRETE_INSTRUCTION(Context, "context") DECLARE_CONCRETE_INSTRUCTION(Context, "context")
......
...@@ -2801,6 +2801,12 @@ void LCodeGen::DoPushArgument(LPushArgument* instr) { ...@@ -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) { void LCodeGen::DoContext(LContext* instr) {
Register result = ToRegister(instr->result()); Register result = ToRegister(instr->result());
__ mov(result, cp); __ mov(result, cp);
......
...@@ -101,15 +101,14 @@ class LChunkBuilder; ...@@ -101,15 +101,14 @@ class LChunkBuilder;
V(EnterInlined) \ V(EnterInlined) \
V(ExternalArrayLength) \ V(ExternalArrayLength) \
V(FixedArrayLength) \ V(FixedArrayLength) \
V(ToInt32) \
V(ForceRepresentation) \ V(ForceRepresentation) \
V(FunctionLiteral) \ V(FunctionLiteral) \
V(GetCachedArrayIndex) \ V(GetCachedArrayIndex) \
V(GlobalObject) \ V(GlobalObject) \
V(GlobalReceiver) \ V(GlobalReceiver) \
V(Goto) \ V(Goto) \
V(HasInstanceType) \
V(HasCachedArrayIndex) \ V(HasCachedArrayIndex) \
V(HasInstanceType) \
V(In) \ V(In) \
V(InstanceOf) \ V(InstanceOf) \
V(InstanceOfKnownGlobal) \ V(InstanceOfKnownGlobal) \
...@@ -152,8 +151,8 @@ class LChunkBuilder; ...@@ -152,8 +151,8 @@ class LChunkBuilder;
V(StoreGlobalCell) \ V(StoreGlobalCell) \
V(StoreGlobalGeneric) \ V(StoreGlobalGeneric) \
V(StoreKeyedFastElement) \ V(StoreKeyedFastElement) \
V(StoreKeyedSpecializedArrayElement) \
V(StoreKeyedGeneric) \ V(StoreKeyedGeneric) \
V(StoreKeyedSpecializedArrayElement) \
V(StoreNamedField) \ V(StoreNamedField) \
V(StoreNamedGeneric) \ V(StoreNamedGeneric) \
V(StringAdd) \ V(StringAdd) \
...@@ -162,8 +161,10 @@ class LChunkBuilder; ...@@ -162,8 +161,10 @@ class LChunkBuilder;
V(StringLength) \ V(StringLength) \
V(Sub) \ V(Sub) \
V(Test) \ V(Test) \
V(ThisFunction) \
V(Throw) \ V(Throw) \
V(ToFastProperties) \ V(ToFastProperties) \
V(ToInt32) \
V(Typeof) \ V(Typeof) \
V(TypeofIs) \ V(TypeofIs) \
V(UnaryMathOperation) \ V(UnaryMathOperation) \
...@@ -1302,6 +1303,24 @@ class HPushArgument: public HUnaryOperation { ...@@ -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> { class HContext: public HTemplateInstruction<0> {
public: public:
HContext() { HContext() {
...@@ -1313,7 +1332,7 @@ class HContext: public HTemplateInstruction<0> { ...@@ -1313,7 +1332,7 @@ class HContext: public HTemplateInstruction<0> {
return Representation::None(); return Representation::None();
} }
DECLARE_CONCRETE_INSTRUCTION(Context); DECLARE_CONCRETE_INSTRUCTION(Context)
protected: protected:
virtual bool DataEquals(HValue* other) { return true; } virtual bool DataEquals(HValue* other) { return true; }
......
...@@ -2308,9 +2308,6 @@ HInstruction* HGraphBuilder::PreProcessCall(HCall<V>* call) { ...@@ -2308,9 +2308,6 @@ HInstruction* HGraphBuilder::PreProcessCall(HCall<V>* call) {
void HGraphBuilder::SetupScope(Scope* scope) { 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( HConstant* undefined_constant = new(zone()) HConstant(
isolate()->factory()->undefined_value(), Representation::Tagged()); isolate()->factory()->undefined_value(), Representation::Tagged());
AddInstruction(undefined_constant); AddInstruction(undefined_constant);
...@@ -5361,7 +5358,8 @@ void HGraphBuilder::VisitThisFunction(ThisFunction* expr) { ...@@ -5361,7 +5358,8 @@ void HGraphBuilder::VisitThisFunction(ThisFunction* expr) {
ASSERT(!HasStackOverflow()); ASSERT(!HasStackOverflow());
ASSERT(current_block() != NULL); ASSERT(current_block() != NULL);
ASSERT(current_block()->HasPredecessor()); ASSERT(current_block()->HasPredecessor());
return Bailout("ThisFunction"); HThisFunction* self = new(zone()) HThisFunction;
return ast_context()->ReturnInstruction(self, expr->id());
} }
......
...@@ -2689,6 +2689,12 @@ void LCodeGen::DoPushArgument(LPushArgument* instr) { ...@@ -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) { void LCodeGen::DoContext(LContext* instr) {
Register result = ToRegister(instr->result()); Register result = ToRegister(instr->result());
__ mov(result, Operand(ebp, StandardFrameConstants::kContextOffset)); __ mov(result, Operand(ebp, StandardFrameConstants::kContextOffset));
......
...@@ -1203,6 +1203,11 @@ LInstruction* LChunkBuilder::DoPushArgument(HPushArgument* instr) { ...@@ -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) { LInstruction* LChunkBuilder::DoContext(HContext* instr) {
return instr->HasNoUses() ? NULL : DefineAsRegister(new LContext); return instr->HasNoUses() ? NULL : DefineAsRegister(new LContext);
} }
......
...@@ -163,6 +163,7 @@ class LCodeGen; ...@@ -163,6 +163,7 @@ class LCodeGen;
V(StringLength) \ V(StringLength) \
V(SubI) \ V(SubI) \
V(TaggedToI) \ V(TaggedToI) \
V(ThisFunction) \
V(Throw) \ V(Throw) \
V(ToFastProperties) \ V(ToFastProperties) \
V(Typeof) \ V(Typeof) \
...@@ -1471,6 +1472,11 @@ class LPushArgument: public LTemplateInstruction<0, 1, 0> { ...@@ -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> { class LContext: public LTemplateInstruction<1, 0, 0> {
public: public:
DECLARE_CONCRETE_INSTRUCTION(Context, "context") DECLARE_CONCRETE_INSTRUCTION(Context, "context")
......
...@@ -2693,6 +2693,12 @@ void LCodeGen::DoPushArgument(LPushArgument* instr) { ...@@ -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) { void LCodeGen::DoContext(LContext* instr) {
Register result = ToRegister(instr->result()); Register result = ToRegister(instr->result());
__ movq(result, rsi); __ movq(result, rsi);
......
...@@ -1191,6 +1191,11 @@ LInstruction* LChunkBuilder::DoPushArgument(HPushArgument* instr) { ...@@ -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) { LInstruction* LChunkBuilder::DoContext(HContext* instr) {
return instr->HasNoUses() ? NULL : DefineAsRegister(new LContext); return instr->HasNoUses() ? NULL : DefineAsRegister(new LContext);
} }
......
...@@ -169,6 +169,7 @@ class LCodeGen; ...@@ -169,6 +169,7 @@ class LCodeGen;
V(StringLength) \ V(StringLength) \
V(SubI) \ V(SubI) \
V(TaggedToI) \ V(TaggedToI) \
V(ThisFunction) \
V(Throw) \ V(Throw) \
V(ToFastProperties) \ V(ToFastProperties) \
V(Typeof) \ V(Typeof) \
...@@ -1441,6 +1442,11 @@ class LPushArgument: public LTemplateInstruction<0, 1, 0> { ...@@ -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> { class LContext: public LTemplateInstruction<1, 0, 0> {
public: public:
DECLARE_CONCRETE_INSTRUCTION(Context, "context") DECLARE_CONCRETE_INSTRUCTION(Context, "context")
......
...@@ -36,6 +36,9 @@ test-debug/DebuggerAgent: PASS, (PASS || FAIL) if $system == linux ...@@ -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. # BUG(382): Weird test. Can't guarantee that it never times out.
test-api/ApplyInterruption: PASS || TIMEOUT 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 # These tests always fail. They are here to test test.py. If
# they don't fail then test.py has failed. # they don't fail then test.py has failed.
test-serialize/TestThatAlwaysFails: FAIL test-serialize/TestThatAlwaysFails: FAIL
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment