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) {
}
LInstruction* LChunkBuilder::DoThisFunction(HThisFunction* instr) {
return instr->HasNoUses() ? NULL : DefineAsRegister(new LThisFunction);
}
LInstruction* LChunkBuilder::DoContext(HContext* instr) {
return instr->HasNoUses() ? NULL : DefineAsRegister(new LContext);
}
......
......@@ -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")
......
......@@ -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);
......
......@@ -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; }
......
......@@ -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());
}
......
......@@ -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));
......
......@@ -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);
}
......
......@@ -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")
......
......@@ -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);
......
......@@ -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);
}
......
......@@ -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")
......
......@@ -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
......
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