Commit 29477592 authored by cwzwarich@webkit.org's avatar cwzwarich@webkit.org

2008-06-14 Cameron Zwarich <cwzwarich@uwaterloo.ca>

        Reviewed by Maciej.

        Make code generation not use a temporary for the left-hand side of an
        expression if the right-hand side is a local variable.

        * VM/CodeGenerator.cpp:
        (KJS::CodeGenerator::isLocal):
        * VM/CodeGenerator.h:
        (KJS::CodeGenerator::leftHandSideNeedsCopy):
        (KJS::CodeGenerator::emitNodeForLeftHandSide):
        * kjs/nodes.cpp:
        (KJS::ResolveNode::isPure):
        (KJS::BracketAccessorNode::emitCode):
        (KJS::AddNode::emitCode):
        (KJS::SubNode::emitCode):
        (KJS::ReadModifyResolveNode::emitCode):
        (KJS::AssignDotNode::emitCode):
        (KJS::ReadModifyDotNode::emitCode):
        (KJS::AssignBracketNode::emitCode):
        (KJS::ReadModifyBracketNode::emitCode):
        * kjs/nodes.h:
        (KJS::ExpressionNode::):
        (KJS::BooleanNode::):
        (KJS::NumberNode::):
        (KJS::StringNode::):


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@34555 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent ec650339
2008-06-14 Cameron Zwarich <cwzwarich@uwaterloo.ca>
Reviewed by Maciej.
Make code generation not use a temporary for the left-hand side of an
expression if the right-hand side is a local variable.
* VM/CodeGenerator.cpp:
(KJS::CodeGenerator::isLocal):
* VM/CodeGenerator.h:
(KJS::CodeGenerator::leftHandSideNeedsCopy):
(KJS::CodeGenerator::emitNodeForLeftHandSide):
* kjs/nodes.cpp:
(KJS::ResolveNode::isPure):
(KJS::BracketAccessorNode::emitCode):
(KJS::AddNode::emitCode):
(KJS::SubNode::emitCode):
(KJS::ReadModifyResolveNode::emitCode):
(KJS::AssignDotNode::emitCode):
(KJS::ReadModifyDotNode::emitCode):
(KJS::AssignBracketNode::emitCode):
(KJS::ReadModifyBracketNode::emitCode):
* kjs/nodes.h:
(KJS::ExpressionNode::):
(KJS::BooleanNode::):
(KJS::NumberNode::):
(KJS::StringNode::):
2008-06-14 Darin Adler <darin@apple.com>
Reviewed by Sam.
......
......@@ -343,6 +343,14 @@ RegisterID* CodeGenerator::registerForLocalConstInit(const Identifier& ident)
return &m_locals[localsIndex(entry.getIndex())];
}
bool CodeGenerator::isLocal(const Identifier& ident)
{
if (ident == m_propertyNames->thisIdentifier)
return true;
return shouldOptimizeLocals() && symbolTable().contains(ident.ustring().rep());
}
bool CodeGenerator::isLocalConstant(const Identifier& ident)
{
return symbolTable().get(ident.ustring().rep()).isReadOnly();
......
......@@ -108,6 +108,7 @@ namespace KJS {
// Returns the register storing "this"
RegisterID* thisRegister() { return &m_thisRegister; }
bool isLocal(const Identifier&);
bool isLocalConstant(const Identifier&);
// Returns the next available temporary register. Registers returned by
......@@ -171,14 +172,14 @@ namespace KJS {
return emitNode(0, n);
}
ALWAYS_INLINE bool leftHandSideNeedsCopy(bool rightHasAssignments, bool rightIsConstant)
ALWAYS_INLINE bool leftHandSideNeedsCopy(bool rightHasAssignments, bool rightIsPure)
{
return (m_codeType != FunctionCode || m_codeBlock->needsFullScopeChain || rightHasAssignments) && !rightIsConstant;
return (m_codeType != FunctionCode || m_codeBlock->needsFullScopeChain || rightHasAssignments) && !rightIsPure;
}
ALWAYS_INLINE PassRefPtr<RegisterID> emitNodeForLeftHandSide(ExpressionNode* n, bool rightHasAssignments, bool rightIsConstant)
ALWAYS_INLINE PassRefPtr<RegisterID> emitNodeForLeftHandSide(ExpressionNode* n, bool rightHasAssignments, bool rightIsPure)
{
if (leftHandSideNeedsCopy(rightHasAssignments, rightIsConstant)) {
if (leftHandSideNeedsCopy(rightHasAssignments, rightIsPure)) {
PassRefPtr<RegisterID> dst = newTemporary();
emitNode(dst.get(), n);
return dst;
......
......@@ -327,6 +327,11 @@ RegisterID* ThisNode::emitCode(CodeGenerator& generator, RegisterID* dst)
// ------------------------------ ResolveNode ----------------------------------
bool ResolveNode::isPure(CodeGenerator& generator) const
{
return generator.isLocal(m_ident);
}
RegisterID* ResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
{
if (RegisterID* local = generator.registerForLocal(m_ident))
......@@ -402,7 +407,7 @@ RegisterID* PropertyListNode::emitCode(CodeGenerator& generator, RegisterID* dst
RegisterID* BracketAccessorNode::emitCode(CodeGenerator& generator, RegisterID* dst)
{
RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_subscriptHasAssignments, m_subscript.get()->isConstant());
RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_subscriptHasAssignments, m_subscript.get()->isPure(generator));
RegisterID* property = generator.emitNode(m_subscript.get());
return generator.emitGetByVal(generator.finalDestination(dst), base.get(), property);
......@@ -823,14 +828,14 @@ RegisterID* ModNode::emitCode(CodeGenerator& generator, RegisterID* dst)
RegisterID* AddNode::emitCode(CodeGenerator& generator, RegisterID* dst)
{
RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_term1.get(), m_rightHasAssignments, m_term2.get()->isConstant());
RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_term1.get(), m_rightHasAssignments, m_term2.get()->isPure(generator));
RegisterID* src2 = generator.emitNode(m_term2.get());
return generator.emitAdd(generator.finalDestination(dst, src1.get()), src1.get(), src2);
}
RegisterID* SubNode::emitCode(CodeGenerator& generator, RegisterID* dst)
{
RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_term1.get(), m_rightHasAssignments, m_term2.get()->isConstant());
RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_term1.get(), m_rightHasAssignments, m_term2.get()->isPure(generator));
RegisterID* src2 = generator.emitNode(m_term2.get());
return generator.emitSub(generator.finalDestination(dst, src1.get()), src1.get(), src2);
}
......@@ -1048,7 +1053,7 @@ RegisterID* ReadModifyResolveNode::emitCode(CodeGenerator& generator, RegisterID
return emitReadModifyAssignment(generator, generator.finalDestination(dst), local, src2, m_operator);
}
if (generator.leftHandSideNeedsCopy(m_rightHasAssignments, m_right.get()->isConstant())) {
if (generator.leftHandSideNeedsCopy(m_rightHasAssignments, m_right.get()->isPure(generator))) {
RefPtr<RegisterID> result = generator.newTemporary();
generator.emitMove(result.get(), local);
RegisterID* src2 = generator.emitNode(m_right.get());
......@@ -1108,7 +1113,7 @@ RegisterID* AssignResolveNode::emitCode(CodeGenerator& generator, RegisterID* ds
RegisterID* AssignDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
{
RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_rightHasAssignments, m_right.get()->isConstant());
RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_rightHasAssignments, m_right.get()->isPure(generator));
RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
RegisterID* result = generator.emitNode(value.get(), m_right.get());
generator.emitPutById(base.get(), m_ident, result);
......@@ -1119,7 +1124,7 @@ RegisterID* AssignDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
RegisterID* ReadModifyDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
{
RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_rightHasAssignments, m_right.get()->isConstant());
RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_rightHasAssignments, m_right.get()->isPure(generator));
RefPtr<RegisterID> value = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident);
RegisterID* change = generator.emitNode(m_right.get());
RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), change, m_operator);
......@@ -1137,8 +1142,8 @@ RegisterID* AssignErrorNode::emitCode(CodeGenerator& generator, RegisterID*)
RegisterID* AssignBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
{
RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_subscriptHasAssignments || m_rightHasAssignments, m_subscript.get()->isConstant() && m_right.get()->isConstant());
RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript.get(), m_rightHasAssignments, m_right.get()->isConstant());
RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_subscriptHasAssignments || m_rightHasAssignments, m_subscript.get()->isPure(generator) && m_right.get()->isPure(generator));
RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript.get(), m_rightHasAssignments, m_right.get()->isPure(generator));
RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
RegisterID* result = generator.emitNode(value.get(), m_right.get());
generator.emitPutByVal(base.get(), property.get(), result);
......@@ -1147,8 +1152,8 @@ RegisterID* AssignBracketNode::emitCode(CodeGenerator& generator, RegisterID* ds
RegisterID* ReadModifyBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
{
RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_subscriptHasAssignments || m_rightHasAssignments, m_subscript.get()->isConstant() && m_right.get()->isConstant());
RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript.get(), m_rightHasAssignments, m_right.get()->isConstant());
RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_subscriptHasAssignments || m_rightHasAssignments, m_subscript.get()->isPure(generator) && m_right.get()->isPure(generator));
RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript.get(), m_rightHasAssignments, m_right.get()->isPure(generator));
RefPtr<RegisterID> value = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property.get());
RegisterID* change = generator.emitNode(m_right.get());
......
......@@ -208,7 +208,7 @@ namespace KJS {
}
virtual bool isNumber() const KJS_FAST_CALL { return false; }
virtual bool isConstant() const KJS_FAST_CALL { return false; }
virtual bool isPure(CodeGenerator&) const KJS_FAST_CALL { return false; }
virtual bool isLocation() const KJS_FAST_CALL { return false; }
virtual bool isResolveNode() const KJS_FAST_CALL { return false; }
virtual bool isBracketAccessorNode() const KJS_FAST_CALL { return false; }
......@@ -261,7 +261,7 @@ namespace KJS {
virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
virtual bool isConstant() const KJS_FAST_CALL { return true; }
virtual bool isPure(CodeGenerator&) const KJS_FAST_CALL { return true; }
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecPrimary; }
......@@ -283,7 +283,7 @@ namespace KJS {
virtual Precedence precedence() const { return signbit(m_double) ? PrecUnary : PrecPrimary; }
virtual bool isNumber() const KJS_FAST_CALL { return true; }
virtual bool isConstant() const KJS_FAST_CALL { return true; }
virtual bool isPure(CodeGenerator&) const KJS_FAST_CALL { return true; }
double value() const KJS_FAST_CALL { return m_double; }
virtual void setValue(double d) KJS_FAST_CALL { m_double = d; }
......@@ -316,7 +316,7 @@ namespace KJS {
virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
virtual bool isConstant() const KJS_FAST_CALL { return true; }
virtual bool isPure(CodeGenerator&) const KJS_FAST_CALL { return true; }
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecPrimary; }
......@@ -371,6 +371,7 @@ namespace KJS {
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecPrimary; }
virtual bool isPure(CodeGenerator&) const KJS_FAST_CALL;
virtual bool isLocation() const KJS_FAST_CALL { return true; }
virtual bool isResolveNode() const KJS_FAST_CALL { return true; }
const Identifier& identifier() const KJS_FAST_CALL { return m_ident; }
......
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