Ignore:
Timestamp:
May 7, 2009, 1:27:58 AM (16 years ago)
Author:
[email protected]
Message:

2009-05-07 Gavin Barraclough <[email protected]>

Reviewed by NOBODY (OOPS!).

Enable op_strcat across += assignments. This patch allows the lhs of a read/modify node
to be included within the concatenation operation, and also modifies the implementation
of the concatenation to attempt to reuse and cat onto the leftmost string, rather than
always allocating a new empty output string to copy into (as was previously the behaviour).

~0.5% progression, due to a 3%-3.5% progression on the string tests (particularly validate).

  • parser/Nodes.cpp: (JSC::BinaryOpNode::emitStrcat): (JSC::emitReadModifyAssignment): (JSC::ReadModifyResolveNode::emitBytecode): (JSC::ReadModifyDotNode::emitBytecode): (JSC::ReadModifyBracketNode::emitBytecode):
  • parser/Nodes.h:
  • runtime/Operations.h: (JSC::concatenateStrings):
  • runtime/UString.cpp: (JSC::UString::reserveCapacity):
  • runtime/UString.h:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/parser/Nodes.cpp

    r43331 r43339  
    11761176// least one left child that is also an add that can be determined to be operating on strings.
    11771177//
    1178 // Fixme: This method should correctly support concatenation on read-modify nodes (+=)
    1179 //        but disabling this due to performance degradation (op_strcat needs to be able
    1180 //        to append to the existing string).
    1181 //
    1182 RegisterID* BinaryOpNode::emitStrcat(BytecodeGenerator& generator, RegisterID* dst, RegisterID* lhs)
     1178RegisterID* BinaryOpNode::emitStrcat(BytecodeGenerator& generator, RegisterID* dst, RegisterID* lhs, ReadModifyResolveNode* emitExpressionInfoForMe)
    11831179{
    11841180    ASSERT(isAdd());
     
    12571253    ASSERT(temporaryRegisters.size() >= 3);
    12581254
     1255    // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated.
     1256    // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now.
     1257    if (emitExpressionInfoForMe)
     1258        generator.emitExpressionInfo(emitExpressionInfoForMe->divot(), emitExpressionInfoForMe->startOffset(), emitExpressionInfoForMe->endOffset());
     1259
    12591260    // If there is an assignment convert the lhs now.  This will also copy lhs to
    12601261    // the temporary register we allocated for it.
     
    14091410
    14101411// FIXME: should this be moved to be a method on BytecodeGenerator?
    1411 static ALWAYS_INLINE RegisterID* emitReadModifyAssignment(BytecodeGenerator& generator, RegisterID* dst, RegisterID* src1, RegisterID* src2, Operator oper, OperandTypes types)
     1412static ALWAYS_INLINE RegisterID* emitReadModifyAssignment(BytecodeGenerator& generator, RegisterID* dst, RegisterID* src1, ExpressionNode* m_right, Operator oper, OperandTypes types, ReadModifyResolveNode* emitExpressionInfoForMe = 0)
    14121413{
    14131414    OpcodeID opcodeID;
     
    14201421            break;
    14211422        case OpPlusEq:
     1423            if (m_right->isAdd() && m_right->resultDescriptor().definitelyIsString())
     1424                return static_cast<AddNode*>(m_right)->emitStrcat(generator, dst, src1, emitExpressionInfoForMe);
    14221425            opcodeID = op_add;
    14231426            break;
     
    14501453            return dst;
    14511454    }
    1452    
     1455
     1456    RegisterID* src2 = generator.emitNode(m_right);
     1457
     1458    // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated.
     1459    // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now.
     1460    if (emitExpressionInfoForMe)
     1461        generator.emitExpressionInfo(emitExpressionInfoForMe->divot(), emitExpressionInfoForMe->startOffset(), emitExpressionInfoForMe->endOffset());
     1462
    14531463    return generator.emitBinaryOp(opcodeID, dst, src1, src2, types);
    14541464}
     
    14581468    if (RegisterID* local = generator.registerFor(m_ident)) {
    14591469        if (generator.isLocalConstant(m_ident)) {
    1460             RegisterID* src2 = generator.emitNode(m_right.get());
    1461             return emitReadModifyAssignment(generator, generator.finalDestination(dst), local, src2, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
     1470            return emitReadModifyAssignment(generator, generator.finalDestination(dst), local, m_right.get(), m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
    14621471        }
    14631472       
     
    14651474            RefPtr<RegisterID> result = generator.newTemporary();
    14661475            generator.emitMove(result.get(), local);
    1467             RegisterID* src2 = generator.emitNode(m_right.get());
    1468             emitReadModifyAssignment(generator, result.get(), result.get(), src2, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
     1476            emitReadModifyAssignment(generator, result.get(), result.get(), m_right.get(), m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
    14691477            generator.emitMove(local, result.get());
    14701478            return generator.moveToDestinationIfNeeded(dst, result.get());
    14711479        }
    14721480       
    1473         RegisterID* src2 = generator.emitNode(m_right.get());
    1474         RegisterID* result = emitReadModifyAssignment(generator, local, local, src2, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
     1481        RegisterID* result = emitReadModifyAssignment(generator, local, local, m_right.get(), m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
    14751482        return generator.moveToDestinationIfNeeded(dst, result);
    14761483    }
     
    14811488    if (generator.findScopedProperty(m_ident, index, depth, true, globalObject) && index != missingSymbolMarker()) {
    14821489        RefPtr<RegisterID> src1 = generator.emitGetScopedVar(generator.tempDestination(dst), depth, index, globalObject);
    1483         RegisterID* src2 = generator.emitNode(m_right.get());
    1484         RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), src2, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
     1490        RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), m_right.get(), m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
    14851491        generator.emitPutScopedVar(depth, index, result, globalObject);
    14861492        return result;
     
    14901496    generator.emitExpressionInfo(divot() - startOffset() + m_ident.size(), m_ident.size(), 0);
    14911497    RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), src1.get(), m_ident);
    1492     RegisterID* src2 = generator.emitNode(m_right.get());
    1493     generator.emitExpressionInfo(divot(), startOffset(), endOffset());
    1494     RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), src2, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
     1498    RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), m_right.get(), m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()), this);
    14951499    return generator.emitPutById(base.get(), m_ident, result);
    14961500}
     
    15791583    generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
    15801584    RefPtr<RegisterID> value = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident);
    1581     RegisterID* change = generator.emitNode(m_right.get());
    1582     RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), change, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
     1585    RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), m_right.get(), m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
    15831586
    15841587    generator.emitExpressionInfo(divot(), startOffset(), endOffset());
     
    16511654    generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
    16521655    RefPtr<RegisterID> value = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property.get());
    1653     RegisterID* change = generator.emitNode(m_right.get());
    1654     RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), change, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
     1656    RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), m_right.get(), m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
    16551657
    16561658    generator.emitExpressionInfo(divot(), startOffset(), endOffset());
Note: See TracChangeset for help on using the changeset viewer.