+2008-06-13 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+
+ Reviewed by Maciej.
+
+ Eliminate the use of temporaries to store the left hand side of an
+ expression when the right hand side is a constant. This slightly
+ improves the generated bytecode for a few SunSpider tests, but it is
+ mostly in preparation for fixing
+
+ Bug 19484: More instructions needs to use temporary registers
+ <https://bugs.webkit.org/show_bug.cgi?id=19484>
+
+ * VM/CodeGenerator.h:
+ (KJS::CodeGenerator::leftHandSideNeedsCopy):
+ (KJS::CodeGenerator::emitNodeForLeftHandSide):
+ * kjs/nodes.cpp:
+ (KJS::BracketAccessorNode::emitCode):
+ (KJS::ReadModifyResolveNode::emitCode):
+ (KJS::AssignDotNode::emitCode):
+ (KJS::ReadModifyDotNode::emitCode):
+ (KJS::AssignBracketNode::emitCode):
+ (KJS::ReadModifyBracketNode::emitCode):
+ * kjs/nodes.h:
+ (KJS::ExpressionNode::):
+ (KJS::FalseNode::):
+ (KJS::TrueNode::):
+ (KJS::NumberNode::):
+ (KJS::StringNode::):
+
2008-06-13 Maciej Stachowiak <mjs@apple.com>
Reviewed by Oliver.
return emitNode(0, n);
}
- ALWAYS_INLINE bool leftHandSideNeedsCopy(bool rightHasAssignments)
+ ALWAYS_INLINE bool leftHandSideNeedsCopy(bool rightHasAssignments, bool rightIsConstant)
{
- return m_codeType != FunctionCode || m_codeBlock->needsFullScopeChain || rightHasAssignments;
+ return (m_codeType != FunctionCode || m_codeBlock->needsFullScopeChain || rightHasAssignments) && !rightIsConstant;
}
- ALWAYS_INLINE PassRefPtr<RegisterID> emitNodeForLeftHandSide(ExpressionNode* n, bool rightHasAssignments)
+ ALWAYS_INLINE PassRefPtr<RegisterID> emitNodeForLeftHandSide(ExpressionNode* n, bool rightHasAssignments, bool rightIsConstant)
{
- if (leftHandSideNeedsCopy(rightHasAssignments)) {
+ if (leftHandSideNeedsCopy(rightHasAssignments, rightIsConstant)) {
PassRefPtr<RegisterID> dst = newTemporary();
emitNode(dst.get(), n);
return dst;
RegisterID* BracketAccessorNode::emitCode(CodeGenerator& generator, RegisterID* dst)
{
- RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_subscriptHasAssignments);
+ RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_subscriptHasAssignments, m_subscript.get()->isConstant());
RegisterID* property = generator.emitNode(m_subscript.get());
return generator.emitGetByVal(generator.finalDestination(dst), base.get(), property);
return emitReadModifyAssignment(generator, generator.finalDestination(dst), local, src2, m_operator);
}
- if (generator.leftHandSideNeedsCopy(m_rightHasAssignments) && !m_right.get()->isNumber()) {
+ if (generator.leftHandSideNeedsCopy(m_rightHasAssignments, m_right.get()->isConstant())) {
RefPtr<RegisterID> result = generator.newTemporary();
generator.emitMove(result.get(), local);
RegisterID* src2 = generator.emitNode(m_right.get());
RegisterID* AssignDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
{
- RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_rightHasAssignments);
+ RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_rightHasAssignments, m_right.get()->isConstant());
RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
RegisterID* result = generator.emitNode(value.get(), m_right.get());
generator.emitPutById(base.get(), m_ident, result);
RegisterID* ReadModifyDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
{
- RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_rightHasAssignments);
+ RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_rightHasAssignments, m_right.get()->isConstant());
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);
RegisterID* AssignBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
{
- RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_subscriptHasAssignments || m_rightHasAssignments);
- RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript.get(), m_rightHasAssignments);
+ 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> value = generator.destinationForAssignResult(dst);
RegisterID* result = generator.emitNode(value.get(), m_right.get());
generator.emitPutByVal(base.get(), property.get(), result);
RegisterID* ReadModifyBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
{
- RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_subscriptHasAssignments || m_rightHasAssignments);
- RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript.get(), m_rightHasAssignments);
+ 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> value = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property.get());
RegisterID* change = generator.emitNode(m_right.get());
}
virtual bool isNumber() const KJS_FAST_CALL { return false; }
+ virtual bool isConstant() 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; }
virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+ virtual bool isConstant() const KJS_FAST_CALL { return true; }
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecPrimary; }
};
virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+ virtual bool isConstant() const KJS_FAST_CALL { return true; }
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecPrimary; }
};
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; }
double value() const KJS_FAST_CALL { return m_double; }
virtual void setValue(double d) KJS_FAST_CALL { m_double = d; }
virtual RegisterID* emitCode(CodeGenerator&, RegisterID* = 0) KJS_FAST_CALL;
+ virtual bool isConstant() const KJS_FAST_CALL { return true; }
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecPrimary; }