Ignore:
Timestamp:
May 6, 2010, 12:39:54 PM (15 years ago)
Author:
[email protected]
Message:

2010-05-06 Oliver Hunt <[email protected]>

Reviewed by Geoffrey Garen.

Improve performance of single character string compares
https://bugs.webkit.org/show_bug.cgi?id=38659

Add logic to the jit to identify comparisons to single character string literals
and then just perform the comparison inline, rather than ignoring the evidence
and attempting to perform an integer comparison.

Multiple changes required -- add jnlesseq opcode, add helper function to identify
single character string constants, add a helper to load single character strings.
Then add the 32_64 and normal codepaths to the JIT.

  • assembler/MacroAssemblerX86Common.h: (JSC::MacroAssemblerX86Common::load16):
  • bytecode/CodeBlock.cpp: (JSC::CodeBlock::dump):
  • bytecode/Opcode.h:
  • bytecompiler/BytecodeGenerator.cpp: (JSC::BytecodeGenerator::emitJumpIfTrue):
  • interpreter/Interpreter.cpp: (JSC::Interpreter::privateExecute):
  • jit/JIT.cpp: (JSC::JIT::privateCompileMainPass): (JSC::JIT::privateCompileSlowCases):
  • jit/JIT.h:
  • jit/JITArithmetic.cpp: (JSC::JIT::emit_op_jnless): (JSC::JIT::emitSlow_op_jnless): (JSC::JIT::emit_op_jless): (JSC::JIT::emitSlow_op_jless): (JSC::JIT::emit_op_jlesseq): (JSC::JIT::emit_op_jnlesseq): (JSC::JIT::emitSlow_op_jlesseq): (JSC::JIT::emitSlow_op_jnlesseq):
  • jit/JITArithmetic32_64.cpp: (JSC::JIT::emit_op_jnless): (JSC::JIT::emitSlow_op_jnless): (JSC::JIT::emit_op_jless): (JSC::JIT::emitSlow_op_jless): (JSC::JIT::emit_op_jlesseq): (JSC::JIT::emit_op_jnlesseq): (JSC::JIT::emitSlow_op_jlesseq): (JSC::JIT::emitSlow_op_jnlesseq): (JSC::JIT::emitBinaryDoubleOp):
  • jit/JITInlineMethods.h: (JSC::JIT::emitLoadCharacterString): (JSC::JIT::isOperandConstantImmediateChar):
  • jit/JSInterfaceJIT.h: (JSC::ThunkHelpers::stringImplDataOffset): (JSC::ThunkHelpers::jsStringLengthOffset): (JSC::ThunkHelpers::jsStringValueOffset): Moved from ThunkGenerators to make it possible to share.
  • jit/ThunkGenerators.cpp:

2010-05-06 Oliver Hunt <[email protected]>

Reviewed by Geoffrey Garen.

Improve performance of single character string compares
https://bugs.webkit.org/show_bug.cgi?id=38659

Add many tests of <, >, <=, >=, ==, ===, !=, !== as the existing
tests were woefully inadequate.

  • fast/js/comparison-operators-expected.txt: Added.
  • fast/js/comparison-operators-greater-expected.txt: Added.
  • fast/js/comparison-operators-greater.html: Added.
  • fast/js/comparison-operators-less-expected.txt: Added.
  • fast/js/comparison-operators-less.html: Added.
  • fast/js/comparison-operators.html: Added.
  • fast/js/script-tests/comparison-operators-greater.js: Added. (description.makeTest.func.f.toString): (description.makeTest): (doTest):
  • fast/js/script-tests/comparison-operators-less.js: Added. (description.makeTest.func.f.toString): (description.makeTest): (doTest):
  • fast/js/script-tests/comparison-operators.js: Added. (description.makeTest.func.f.toString): (description.makeTest): (doTest):
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/jit/JITArithmetic.cpp

    r58562 r58902  
    311311    // - int immediate to int immediate
    312312
     313    if (isOperandConstantImmediateChar(op1)) {
     314        emitGetVirtualRegister(op2, regT0);
     315        addSlowCase(emitJumpIfNotJSCell(regT0));
     316        JumpList failures;
     317        emitLoadCharacterString(regT0, regT0, failures);
     318        addSlowCase(failures);
     319        addJump(branch32(LessThanOrEqual, regT0, Imm32(asString(getConstantOperand(op1))->tryGetValue()[0])), target);
     320        return;
     321    }
     322    if (isOperandConstantImmediateChar(op2)) {
     323        emitGetVirtualRegister(op1, regT0);
     324        addSlowCase(emitJumpIfNotJSCell(regT0));
     325        JumpList failures;
     326        emitLoadCharacterString(regT0, regT0, failures);
     327        addSlowCase(failures);
     328        addJump(branch32(GreaterThanOrEqual, regT0, Imm32(asString(getConstantOperand(op2))->tryGetValue()[0])), target);
     329        return;
     330    }
    313331    if (isOperandConstantImmediateInt(op2)) {
    314332        emitGetVirtualRegister(op1, regT0);
     
    348366    // - constant int immediate to floating-point number
    349367    // - floating-point number to floating-point number.
     368    if (isOperandConstantImmediateChar(op1) || isOperandConstantImmediateChar(op2)) {
     369        linkSlowCase(iter);
     370        linkSlowCase(iter);
     371        linkSlowCase(iter);
     372        linkSlowCase(iter);
     373        JITStubCall stubCall(this, cti_op_jlesseq);
     374        stubCall.addArgument(op1, regT0);
     375        stubCall.addArgument(op2, regT1);
     376        stubCall.call();
     377        emitJumpSlowToHot(branchTest32(Zero, regT0), target);
     378        return;
     379    }
    350380
    351381    if (isOperandConstantImmediateInt(op2)) {
     
    496526    // - int immediate to int immediate
    497527
     528    if (isOperandConstantImmediateChar(op1)) {
     529        emitGetVirtualRegister(op2, regT0);
     530        addSlowCase(emitJumpIfNotJSCell(regT0));
     531        JumpList failures;
     532        emitLoadCharacterString(regT0, regT0, failures);
     533        addSlowCase(failures);
     534        addJump(branch32(GreaterThan, regT0, Imm32(asString(getConstantOperand(op1))->tryGetValue()[0])), target);
     535        return;
     536    }
     537    if (isOperandConstantImmediateChar(op2)) {
     538        emitGetVirtualRegister(op1, regT0);
     539        addSlowCase(emitJumpIfNotJSCell(regT0));
     540        JumpList failures;
     541        emitLoadCharacterString(regT0, regT0, failures);
     542        addSlowCase(failures);
     543        addJump(branch32(LessThan, regT0, Imm32(asString(getConstantOperand(op2))->tryGetValue()[0])), target);
     544        return;
     545    }
    498546    if (isOperandConstantImmediateInt(op2)) {
    499547        emitGetVirtualRegister(op1, regT0);
     
    533581    // - constant int immediate to floating-point number
    534582    // - floating-point number to floating-point number.
     583    if (isOperandConstantImmediateChar(op1) || isOperandConstantImmediateChar(op2)) {
     584        linkSlowCase(iter);
     585        linkSlowCase(iter);
     586        linkSlowCase(iter);
     587        linkSlowCase(iter);
     588        JITStubCall stubCall(this, cti_op_jlesseq);
     589        stubCall.addArgument(op1, regT0);
     590        stubCall.addArgument(op2, regT1);
     591        stubCall.call();
     592        emitJumpSlowToHot(branchTest32(NonZero, regT0), target);
     593        return;
     594    }
    535595
    536596    if (isOperandConstantImmediateInt(op2)) {
     
    670730}
    671731
    672 void JIT::emit_op_jnlesseq(Instruction* currentInstruction)
     732void JIT::emit_op_jlesseq(Instruction* currentInstruction, bool invert)
    673733{
    674734    unsigned op1 = currentInstruction[1].u.operand;
     
    681741    // - int immediate to int immediate
    682742
     743    if (isOperandConstantImmediateChar(op1)) {
     744        emitGetVirtualRegister(op2, regT0);
     745        addSlowCase(emitJumpIfNotJSCell(regT0));
     746        JumpList failures;
     747        emitLoadCharacterString(regT0, regT0, failures);
     748        addSlowCase(failures);
     749        addJump(branch32(invert ? LessThan : GreaterThanOrEqual, regT0, Imm32(asString(getConstantOperand(op1))->tryGetValue()[0])), target);
     750        return;
     751    }
     752    if (isOperandConstantImmediateChar(op2)) {
     753        emitGetVirtualRegister(op1, regT0);
     754        addSlowCase(emitJumpIfNotJSCell(regT0));
     755        JumpList failures;
     756        emitLoadCharacterString(regT0, regT0, failures);
     757        addSlowCase(failures);
     758        addJump(branch32(invert ? GreaterThan : LessThanOrEqual, regT0, Imm32(asString(getConstantOperand(op2))->tryGetValue()[0])), target);
     759        return;
     760    }
    683761    if (isOperandConstantImmediateInt(op2)) {
    684762        emitGetVirtualRegister(op1, regT0);
     
    689767        int32_t op2imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2)));
    690768#endif
    691         addJump(branch32(GreaterThan, regT0, Imm32(op2imm)), target);
     769        addJump(branch32(invert ? GreaterThan : LessThanOrEqual, regT0, Imm32(op2imm)), target);
    692770    } else if (isOperandConstantImmediateInt(op1)) {
    693771        emitGetVirtualRegister(op2, regT1);
     
    698776        int32_t op1imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op1)));
    699777#endif
    700         addJump(branch32(LessThan, regT1, Imm32(op1imm)), target);
     778        addJump(branch32(invert ? LessThan : GreaterThanOrEqual, regT1, Imm32(op1imm)), target);
    701779    } else {
    702780        emitGetVirtualRegisters(op1, regT0, op2, regT1);
     
    704782        emitJumpSlowCaseIfNotImmediateInteger(regT1);
    705783
    706         addJump(branch32(GreaterThan, regT0, regT1), target);
    707     }
    708 }
    709 
    710 void JIT::emitSlow_op_jnlesseq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
     784        addJump(branch32(invert ? GreaterThan : LessThanOrEqual, regT0, regT1), target);
     785    }
     786}
     787
     788void JIT::emitSlow_op_jlesseq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter, bool invert)
    711789{
    712790    unsigned op1 = currentInstruction[1].u.operand;
     
    719797    // - floating-point number to floating-point number.
    720798
     799    if (isOperandConstantImmediateChar(op1) || isOperandConstantImmediateChar(op2)) {
     800        linkSlowCase(iter);
     801        linkSlowCase(iter);
     802        linkSlowCase(iter);
     803        linkSlowCase(iter);
     804        JITStubCall stubCall(this, cti_op_jlesseq);
     805        stubCall.addArgument(op1, regT0);
     806        stubCall.addArgument(op2, regT1);
     807        stubCall.call();
     808        emitJumpSlowToHot(branchTest32(invert ? Zero : NonZero, regT0), target);
     809        return;
     810    }
     811
    721812    if (isOperandConstantImmediateInt(op2)) {
    722813        linkSlowCase(iter);
     
    741832            convertInt32ToDouble(regT1, fpRegT1);
    742833
    743             emitJumpSlowToHot(branchDouble(DoubleLessThanOrUnordered, fpRegT1, fpRegT0), target);
     834            emitJumpSlowToHot(branchDouble(invert ? DoubleLessThanOrUnordered : DoubleGreaterThanOrEqual, fpRegT1, fpRegT0), target);
    744835
    745836            emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnlesseq));
     
    758849        stubCall.addArgument(op2, regT2);
    759850        stubCall.call();
    760         emitJumpSlowToHot(branchTest32(Zero, regT0), target);
     851        emitJumpSlowToHot(branchTest32(invert ? Zero : NonZero, regT0), target);
    761852
    762853    } else if (isOperandConstantImmediateInt(op1)) {
     
    782873            convertInt32ToDouble(regT0, fpRegT0);
    783874
    784             emitJumpSlowToHot(branchDouble(DoubleLessThanOrUnordered, fpRegT1, fpRegT0), target);
     875            emitJumpSlowToHot(branchDouble(invert ? DoubleLessThanOrUnordered : DoubleGreaterThanOrEqual, fpRegT1, fpRegT0), target);
    785876
    786877            emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnlesseq));
     
    799890        stubCall.addArgument(regT1);
    800891        stubCall.call();
    801         emitJumpSlowToHot(branchTest32(Zero, regT0), target);
     892        emitJumpSlowToHot(branchTest32(invert ? Zero : NonZero, regT0), target);
    802893
    803894    } else {
     
    828919#endif
    829920
    830             emitJumpSlowToHot(branchDouble(DoubleLessThanOrUnordered, fpRegT1, fpRegT0), target);
     921            emitJumpSlowToHot(branchDouble(invert ? DoubleLessThanOrUnordered : DoubleGreaterThanOrEqual, fpRegT1, fpRegT0), target);
    831922
    832923            emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnlesseq));
     
    851942        stubCall.addArgument(regT1);
    852943        stubCall.call();
    853         emitJumpSlowToHot(branchTest32(Zero, regT0), target);
    854     }
     944        emitJumpSlowToHot(branchTest32(invert ? Zero : NonZero, regT0), target);
     945    }
     946}
     947
     948void JIT::emit_op_jnlesseq(Instruction* currentInstruction)
     949{
     950    emit_op_jlesseq(currentInstruction, true);
     951}
     952
     953void JIT::emitSlow_op_jnlesseq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
     954{
     955    emitSlow_op_jlesseq(currentInstruction, iter, true);
    855956}
    856957
Note: See TracChangeset for help on using the changeset viewer.