Changeset 36976 in webkit for trunk/JavaScriptCore/kjs/nodes.cpp


Ignore:
Timestamp:
Sep 26, 2008, 6:44:15 PM (17 years ago)
Author:
[email protected]
Message:

2008-09-26 Gavin Barraclough <[email protected]>

Reviewed by Maciej Stachowiak & Oliver Hunt.

Add support for reusing temporary JSNumberCells. This change is based on the observation
that if the result of certain operations is a JSNumberCell and is consumed by a subsequent
operation that would produce a JSNumberCell, we can reuse the object rather than allocating
a fresh one. E.g. given the expression ((a * b) * c), we can statically determine that
(a * b) will have a numeric result (or else it will have thrown an exception), so the result
will either be a JSNumberCell or a JSImmediate.

This patch changes three areas of JSC:

  • The AST now tracks type information about the result of each node.
  • This information is consumed in bytecode compilation, and certain bytecode operations now carry the statically determined type information about their operands.
  • CTI uses the information in a number of fashions:
    • Where an operand to certain arithmetic operations is reusable, it will plant code to try to perform the operation in JIT code & reuse the cell, where appropriate.
    • Where it can be statically determined that an operand can only be numeric (typically the result of another arithmetic operation) the code will not redundantly check that the JSCell is a JSNumberCell.
    • Where either of the operands to an add are non-numeric do not plant an optimized arithmetic code path, just call straight out to the C function.

+6% Sunspider (10% progression on 3D, 16% progression on math, 60% progression on access-nbody),
+1% v8-tests (improvements in raytrace & crypto)

  • VM/CTI.cpp: Add optimized code generation with reuse of temporary JSNumberCells.
  • VM/CTI.h:
  • kjs/JSNumberCell.h:
  • masm/X86Assembler.h:
  • VM/CodeBlock.cpp: Add type information to specific bytecodes.
  • VM/CodeGenerator.cpp:
  • VM/CodeGenerator.h:
  • VM/Machine.cpp:
  • kjs/nodes.cpp: Track static type information for nodes.
  • kjs/nodes.h:
  • kjs/ResultDescriptor.h: (Added)
  • JavaScriptCore.xcodeproj/project.pbxproj:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/kjs/nodes.cpp

    r36872 r36976  
    142142Node::Node(JSGlobalData* globalData)
    143143    : ParserRefCounted(globalData)
    144     , m_expectedReturnType(ObjectType)
    145 {
    146     m_line = globalData->lexer->lineNo();
    147 }
    148 
    149 Node::Node(JSGlobalData* globalData, JSType expectedReturn)
    150     : ParserRefCounted(globalData)
    151     , m_expectedReturnType(expectedReturn)
    152144{
    153145    m_line = globalData->lexer->lineNo();
     
    664656                return 0;
    665657            RefPtr<RegisterID> r0 = generator.emitUnexpectedLoad(generator.finalDestination(dst), (m_operator == OpPlusPlus) ? 1.0 : -1.0);
    666             return generator.emitBinaryOp(op_add, r0.get(), local, r0.get());
     658            return generator.emitBinaryOp(op_add, r0.get(), local, r0.get(), OperandTypes());
    667659        }
    668660
     
    755747    RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator));
    756748    RegisterID* src2 = generator.emitNode(m_expr2.get());
    757     return generator.emitBinaryOp(opcode, generator.finalDestination(dst, src1.get()), src1.get(), src2);
     749    return generator.emitBinaryOp(opcode, generator.finalDestination(dst, src1.get()), src1.get(), src2, OperandTypes(m_expr1->resultDescriptor(), m_expr2->resultDescriptor()));
    758750}
    759751
     
    781773    RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator));
    782774    RegisterID* src2 = generator.emitNode(m_expr2.get());
    783     return generator.emitBinaryOp(opcode(), generator.finalDestination(dst, src1.get()), src2, src1.get());
     775    return generator.emitBinaryOp(opcode(), generator.finalDestination(dst, src1.get()), src2, src1.get(), OperandTypes(m_expr2->resultDescriptor(), m_expr1->resultDescriptor()));
    784776}
    785777
     
    789781    RegisterID* src2 = generator.emitNode(m_expr2.get());
    790782    generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
    791     return generator.emitBinaryOp(opcode(), generator.finalDestination(dst, src1.get()), src1.get(), src2);
     783    return generator.emitBinaryOp(opcode(), generator.finalDestination(dst, src1.get()), src1.get(), src2, OperandTypes(m_expr1->resultDescriptor(), m_expr2->resultDescriptor()));
    792784}
    793785
     
    847839
    848840// FIXME: should this be moved to be a method on CodeGenerator?
    849 static ALWAYS_INLINE RegisterID* emitReadModifyAssignment(CodeGenerator& generator, RegisterID* dst, RegisterID* src1, RegisterID* src2, Operator oper)
     841static ALWAYS_INLINE RegisterID* emitReadModifyAssignment(CodeGenerator& generator, RegisterID* dst, RegisterID* src1, RegisterID* src2, Operator oper, OperandTypes types)
    850842{
    851843    OpcodeID opcode;
     
    889881    }
    890882   
    891     return generator.emitBinaryOp(opcode, dst, src1, src2);
     883    return generator.emitBinaryOp(opcode, dst, src1, src2, types);
    892884}
    893885
     
    897889        if (generator.isLocalConstant(m_ident)) {
    898890            RegisterID* src2 = generator.emitNode(m_right.get());
    899             return emitReadModifyAssignment(generator, generator.finalDestination(dst), local, src2, m_operator);
     891            return emitReadModifyAssignment(generator, generator.finalDestination(dst), local, src2, m_operator, OperandTypes(ResultType::unknown(), m_right->resultDescriptor()));
    900892        }
    901893       
     
    904896            generator.emitMove(result.get(), local);
    905897            RegisterID* src2 = generator.emitNode(m_right.get());
    906             emitReadModifyAssignment(generator, result.get(), result.get(), src2, m_operator);
     898            emitReadModifyAssignment(generator, result.get(), result.get(), src2, m_operator, OperandTypes(ResultType::unknown(), m_right->resultDescriptor()));
    907899            generator.emitMove(local, result.get());
    908900            return generator.moveToDestinationIfNeeded(dst, result.get());
     
    910902       
    911903        RegisterID* src2 = generator.emitNode(m_right.get());
    912         RegisterID* result = emitReadModifyAssignment(generator, local, local, src2, m_operator);
     904        RegisterID* result = emitReadModifyAssignment(generator, local, local, src2, m_operator, OperandTypes(ResultType::unknown(), m_right->resultDescriptor()));
    913905        return generator.moveToDestinationIfNeeded(dst, result);
    914906    }
     
    920912        RefPtr<RegisterID> src1 = generator.emitGetScopedVar(generator.tempDestination(dst), depth, index, globalObject);
    921913        RegisterID* src2 = generator.emitNode(m_right.get());
    922         RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), src2, m_operator);
     914        RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), src2, m_operator, OperandTypes(ResultType::unknown(), m_right->resultDescriptor()));
    923915        generator.emitPutScopedVar(depth, index, result, globalObject);
    924916        return result;
     
    930922    RegisterID* src2 = generator.emitNode(m_right.get());
    931923    generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
    932     RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), src2, m_operator);
     924    RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), src2, m_operator, OperandTypes(ResultType::unknown(), m_right->resultDescriptor()));
    933925    return generator.emitPutById(base.get(), m_ident, result);
    934926}
     
    986978    RefPtr<RegisterID> value = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident);
    987979    RegisterID* change = generator.emitNode(m_right.get());
    988     RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), change, m_operator);
     980    RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), change, m_operator, OperandTypes(ResultType::unknown(), m_right->resultDescriptor()));
    989981
    990982    generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
     
    10211013    RefPtr<RegisterID> value = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property.get());
    10221014    RegisterID* change = generator.emitNode(m_right.get());
    1023     RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), change, m_operator);
     1015    RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), change, m_operator, OperandTypes(ResultType::unknown(), m_right->resultDescriptor()));
    10241016
    10251017    generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
     
    15681560            RefPtr<RegisterID> clauseVal = generator.newTemporary();
    15691561            generator.emitNode(clauseVal.get(), list->getClause()->expr());
    1570             generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression);
     1562            generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression, OperandTypes());
    15711563            labelVector.append(generator.newLabel());
    15721564            generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get());
     
    15761568            RefPtr<RegisterID> clauseVal = generator.newTemporary();
    15771569            generator.emitNode(clauseVal.get(), list->getClause()->expr());
    1578             generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression);
     1570            generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression, OperandTypes());
    15791571            labelVector.append(generator.newLabel());
    15801572            generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get());
Note: See TracChangeset for help on using the changeset viewer.