Changeset 58902 in webkit for trunk/JavaScriptCore
- Timestamp:
- May 6, 2010, 12:39:54 PM (15 years ago)
- Location:
- trunk/JavaScriptCore
- Files:
-
- 13 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/ChangeLog
r58885 r58902 1 2010-05-06 Oliver Hunt <[email protected]> 2 3 Reviewed by Geoffrey Garen. 4 5 Improve performance of single character string compares 6 https://bugs.webkit.org/show_bug.cgi?id=38659 7 8 Add logic to the jit to identify comparisons to single character string literals 9 and then just perform the comparison inline, rather than ignoring the evidence 10 and attempting to perform an integer comparison. 11 12 Multiple changes required -- add jnlesseq opcode, add helper function to identify 13 single character string constants, add a helper to load single character strings. 14 Then add the 32_64 and normal codepaths to the JIT. 15 16 * assembler/MacroAssemblerX86Common.h: 17 (JSC::MacroAssemblerX86Common::load16): 18 * bytecode/CodeBlock.cpp: 19 (JSC::CodeBlock::dump): 20 * bytecode/Opcode.h: 21 * bytecompiler/BytecodeGenerator.cpp: 22 (JSC::BytecodeGenerator::emitJumpIfTrue): 23 * interpreter/Interpreter.cpp: 24 (JSC::Interpreter::privateExecute): 25 * jit/JIT.cpp: 26 (JSC::JIT::privateCompileMainPass): 27 (JSC::JIT::privateCompileSlowCases): 28 * jit/JIT.h: 29 * jit/JITArithmetic.cpp: 30 (JSC::JIT::emit_op_jnless): 31 (JSC::JIT::emitSlow_op_jnless): 32 (JSC::JIT::emit_op_jless): 33 (JSC::JIT::emitSlow_op_jless): 34 (JSC::JIT::emit_op_jlesseq): 35 (JSC::JIT::emit_op_jnlesseq): 36 (JSC::JIT::emitSlow_op_jlesseq): 37 (JSC::JIT::emitSlow_op_jnlesseq): 38 * jit/JITArithmetic32_64.cpp: 39 (JSC::JIT::emit_op_jnless): 40 (JSC::JIT::emitSlow_op_jnless): 41 (JSC::JIT::emit_op_jless): 42 (JSC::JIT::emitSlow_op_jless): 43 (JSC::JIT::emit_op_jlesseq): 44 (JSC::JIT::emit_op_jnlesseq): 45 (JSC::JIT::emitSlow_op_jlesseq): 46 (JSC::JIT::emitSlow_op_jnlesseq): 47 (JSC::JIT::emitBinaryDoubleOp): 48 * jit/JITInlineMethods.h: 49 (JSC::JIT::emitLoadCharacterString): 50 (JSC::JIT::isOperandConstantImmediateChar): 51 * jit/JSInterfaceJIT.h: 52 (JSC::ThunkHelpers::stringImplDataOffset): 53 (JSC::ThunkHelpers::jsStringLengthOffset): 54 (JSC::ThunkHelpers::jsStringValueOffset): 55 Moved from ThunkGenerators to make it possible to share. 56 * jit/ThunkGenerators.cpp: 57 1 58 2010-05-06 Martin Robinson <[email protected]> 2 59 -
trunk/JavaScriptCore/assembler/MacroAssemblerX86Common.h
r58562 r58902 365 365 { 366 366 m_assembler.movzwl_mr(address.offset, address.base, address.index, address.scale, dest); 367 } 368 369 void load16(Address address, RegisterID dest) 370 { 371 m_assembler.movzwl_mr(address.offset, address.base, dest); 367 372 } 368 373 -
trunk/JavaScriptCore/bytecode/CodeBlock.cpp
r58705 r58902 932 932 break; 933 933 } 934 case op_jlesseq: { 935 int r0 = (++it)->u.operand; 936 int r1 = (++it)->u.operand; 937 int offset = (++it)->u.operand; 938 printf("[%4d] jlesseq\t\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset); 939 break; 940 } 934 941 case op_loop_if_lesseq: { 935 942 int r0 = (++it)->u.operand; -
trunk/JavaScriptCore/bytecode/Opcode.h
r57955 r58902 139 139 macro(op_jnlesseq, 4) \ 140 140 macro(op_jless, 4) \ 141 macro(op_jlesseq, 4) \ 141 142 macro(op_jmp_scopes, 3) \ 142 143 macro(op_loop, 2) \ -
trunk/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
r57955 r58902 636 636 return target; 637 637 } 638 } else if (m_lastOpcodeID == op_lesseq && !target->isForward()) {638 } else if (m_lastOpcodeID == op_lesseq) { 639 639 int dstIndex; 640 640 int src1Index; … … 647 647 648 648 size_t begin = instructions().size(); 649 emitOpcode( op_loop_if_lesseq);649 emitOpcode(target->isForward() ? op_jlesseq : op_loop_if_lesseq); 650 650 instructions().append(src1Index); 651 651 instructions().append(src2Index); -
trunk/JavaScriptCore/interpreter/Interpreter.cpp
r58012 r58902 3210 3210 3211 3211 vPC += OPCODE_LENGTH(op_jnlesseq); 3212 NEXT_INSTRUCTION(); 3213 } 3214 DEFINE_OPCODE(op_jlesseq) { 3215 /* jlesseq src1(r) src2(r) target(offset) 3216 3217 Checks whether register src1 is less than or equal to 3218 register src2, as with the ECMAScript '<=' operator, 3219 and then jumps to offset target from the current instruction, 3220 if and only if the result of the comparison is true. 3221 */ 3222 JSValue src1 = callFrame->r(vPC[1].u.operand).jsValue(); 3223 JSValue src2 = callFrame->r(vPC[2].u.operand).jsValue(); 3224 int target = vPC[3].u.operand; 3225 3226 bool result = jsLessEq(callFrame, src1, src2); 3227 CHECK_FOR_EXCEPTION(); 3228 3229 if (result) { 3230 vPC += target; 3231 NEXT_INSTRUCTION(); 3232 } 3233 3234 vPC += OPCODE_LENGTH(op_jlesseq); 3212 3235 NEXT_INSTRUCTION(); 3213 3236 } -
trunk/JavaScriptCore/jit/JIT.cpp
r58562 r58902 251 251 DEFINE_OP(op_jnless) 252 252 DEFINE_OP(op_jless) 253 DEFINE_OP(op_jlesseq) 253 254 DEFINE_OP(op_jnlesseq) 254 255 DEFINE_OP(op_jsr) … … 402 403 DEFINE_SLOWCASE_OP(op_jnless) 403 404 DEFINE_SLOWCASE_OP(op_jless) 405 DEFINE_SLOWCASE_OP(op_jlesseq) 404 406 DEFINE_SLOWCASE_OP(op_jnlesseq) 405 407 DEFINE_SLOWCASE_OP(op_jtrue) -
trunk/JavaScriptCore/jit/JIT.h
r58562 r58902 673 673 void emit_op_jnless(Instruction*); 674 674 void emit_op_jless(Instruction*); 675 void emit_op_jlesseq(Instruction*, bool invert = false); 675 676 void emit_op_jnlesseq(Instruction*); 676 677 void emit_op_jsr(Instruction*); … … 760 761 void emitSlow_op_jnless(Instruction*, Vector<SlowCaseEntry>::iterator&); 761 762 void emitSlow_op_jless(Instruction*, Vector<SlowCaseEntry>::iterator&); 763 void emitSlow_op_jlesseq(Instruction*, Vector<SlowCaseEntry>::iterator&, bool invert = false); 762 764 void emitSlow_op_jnlesseq(Instruction*, Vector<SlowCaseEntry>::iterator&); 763 765 void emitSlow_op_jtrue(Instruction*, Vector<SlowCaseEntry>::iterator&); … … 813 815 JSValue getConstantOperand(unsigned src); 814 816 bool isOperandConstantImmediateInt(unsigned src); 817 bool isOperandConstantImmediateChar(unsigned src); 815 818 816 819 Jump getSlowCase(Vector<SlowCaseEntry>::iterator& iter) … … 836 839 void restoreReturnAddressBeforeReturn(Address); 837 840 841 // Loads the character value of a single character string into dst. 842 void emitLoadCharacterString(RegisterID src, RegisterID dst, JumpList& failures); 843 838 844 void emitTimeoutCheck(); 839 845 #ifndef NDEBUG -
trunk/JavaScriptCore/jit/JITArithmetic.cpp
r58562 r58902 311 311 // - int immediate to int immediate 312 312 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 } 313 331 if (isOperandConstantImmediateInt(op2)) { 314 332 emitGetVirtualRegister(op1, regT0); … … 348 366 // - constant int immediate to floating-point number 349 367 // - 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 } 350 380 351 381 if (isOperandConstantImmediateInt(op2)) { … … 496 526 // - int immediate to int immediate 497 527 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 } 498 546 if (isOperandConstantImmediateInt(op2)) { 499 547 emitGetVirtualRegister(op1, regT0); … … 533 581 // - constant int immediate to floating-point number 534 582 // - 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 } 535 595 536 596 if (isOperandConstantImmediateInt(op2)) { … … 670 730 } 671 731 672 void JIT::emit_op_j nlesseq(Instruction* currentInstruction)732 void JIT::emit_op_jlesseq(Instruction* currentInstruction, bool invert) 673 733 { 674 734 unsigned op1 = currentInstruction[1].u.operand; … … 681 741 // - int immediate to int immediate 682 742 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 } 683 761 if (isOperandConstantImmediateInt(op2)) { 684 762 emitGetVirtualRegister(op1, regT0); … … 689 767 int32_t op2imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2))); 690 768 #endif 691 addJump(branch32( GreaterThan, regT0, Imm32(op2imm)), target);769 addJump(branch32(invert ? GreaterThan : LessThanOrEqual, regT0, Imm32(op2imm)), target); 692 770 } else if (isOperandConstantImmediateInt(op1)) { 693 771 emitGetVirtualRegister(op2, regT1); … … 698 776 int32_t op1imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op1))); 699 777 #endif 700 addJump(branch32( LessThan, regT1, Imm32(op1imm)), target);778 addJump(branch32(invert ? LessThan : GreaterThanOrEqual, regT1, Imm32(op1imm)), target); 701 779 } else { 702 780 emitGetVirtualRegisters(op1, regT0, op2, regT1); … … 704 782 emitJumpSlowCaseIfNotImmediateInteger(regT1); 705 783 706 addJump(branch32( GreaterThan, regT0, regT1), target);707 } 708 } 709 710 void JIT::emitSlow_op_j nlesseq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)784 addJump(branch32(invert ? GreaterThan : LessThanOrEqual, regT0, regT1), target); 785 } 786 } 787 788 void JIT::emitSlow_op_jlesseq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter, bool invert) 711 789 { 712 790 unsigned op1 = currentInstruction[1].u.operand; … … 719 797 // - floating-point number to floating-point number. 720 798 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 721 812 if (isOperandConstantImmediateInt(op2)) { 722 813 linkSlowCase(iter); … … 741 832 convertInt32ToDouble(regT1, fpRegT1); 742 833 743 emitJumpSlowToHot(branchDouble( DoubleLessThanOrUnordered, fpRegT1, fpRegT0), target);834 emitJumpSlowToHot(branchDouble(invert ? DoubleLessThanOrUnordered : DoubleGreaterThanOrEqual, fpRegT1, fpRegT0), target); 744 835 745 836 emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnlesseq)); … … 758 849 stubCall.addArgument(op2, regT2); 759 850 stubCall.call(); 760 emitJumpSlowToHot(branchTest32( Zero, regT0), target);851 emitJumpSlowToHot(branchTest32(invert ? Zero : NonZero, regT0), target); 761 852 762 853 } else if (isOperandConstantImmediateInt(op1)) { … … 782 873 convertInt32ToDouble(regT0, fpRegT0); 783 874 784 emitJumpSlowToHot(branchDouble( DoubleLessThanOrUnordered, fpRegT1, fpRegT0), target);875 emitJumpSlowToHot(branchDouble(invert ? DoubleLessThanOrUnordered : DoubleGreaterThanOrEqual, fpRegT1, fpRegT0), target); 785 876 786 877 emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnlesseq)); … … 799 890 stubCall.addArgument(regT1); 800 891 stubCall.call(); 801 emitJumpSlowToHot(branchTest32( Zero, regT0), target);892 emitJumpSlowToHot(branchTest32(invert ? Zero : NonZero, regT0), target); 802 893 803 894 } else { … … 828 919 #endif 829 920 830 emitJumpSlowToHot(branchDouble( DoubleLessThanOrUnordered, fpRegT1, fpRegT0), target);921 emitJumpSlowToHot(branchDouble(invert ? DoubleLessThanOrUnordered : DoubleGreaterThanOrEqual, fpRegT1, fpRegT0), target); 831 922 832 923 emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnlesseq)); … … 851 942 stubCall.addArgument(regT1); 852 943 stubCall.call(); 853 emitJumpSlowToHot(branchTest32(Zero, regT0), target); 854 } 944 emitJumpSlowToHot(branchTest32(invert ? Zero : NonZero, regT0), target); 945 } 946 } 947 948 void JIT::emit_op_jnlesseq(Instruction* currentInstruction) 949 { 950 emit_op_jlesseq(currentInstruction, true); 951 } 952 953 void JIT::emitSlow_op_jnlesseq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) 954 { 955 emitSlow_op_jlesseq(currentInstruction, iter, true); 855 956 } 856 957 -
trunk/JavaScriptCore/jit/JITArithmetic32_64.cpp
r58562 r58902 95 95 JumpList notInt32Op2; 96 96 97 // Int32 less. 97 // Character less. 98 if (isOperandConstantImmediateChar(op1)) { 99 emitLoad(op2, regT1, regT0); 100 addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::CellTag))); 101 JumpList failures; 102 emitLoadCharacterString(regT0, regT0, failures); 103 addSlowCase(failures); 104 addJump(branch32(LessThanOrEqual, regT0, Imm32(asString(getConstantOperand(op1))->tryGetValue()[0])), target); 105 return; 106 } 107 if (isOperandConstantImmediateChar(op2)) { 108 emitLoad(op1, regT1, regT0); 109 addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::CellTag))); 110 JumpList failures; 111 emitLoadCharacterString(regT0, regT0, failures); 112 addSlowCase(failures); 113 addJump(branch32(GreaterThanOrEqual, regT0, Imm32(asString(getConstantOperand(op2))->tryGetValue()[0])), target); 114 return; 115 } 98 116 if (isOperandConstantImmediateInt(op1)) { 117 // Int32 less. 99 118 emitLoad(op2, regT3, regT2); 100 119 notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); … … 129 148 unsigned target = currentInstruction[3].u.operand; 130 149 131 if (!supportsFloatingPoint()) { 132 if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2)) 150 if (isOperandConstantImmediateChar(op1) || isOperandConstantImmediateChar(op2)) { 151 linkSlowCase(iter); 152 linkSlowCase(iter); 153 linkSlowCase(iter); 154 linkSlowCase(iter); 155 } else { 156 if (!supportsFloatingPoint()) { 157 if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2)) 158 linkSlowCase(iter); // int32 check 133 159 linkSlowCase(iter); // int32 check 134 linkSlowCase(iter); // int32 check 135 } else { 136 if (!isOperandConstantImmediateInt(op1)) { 137 linkSlowCase(iter); // double check 138 linkSlowCase(iter); // int32 check 160 } else { 161 if (!isOperandConstantImmediateInt(op1)) { 162 linkSlowCase(iter); // double check 163 linkSlowCase(iter); // int32 check 164 } 165 if (isOperandConstantImmediateInt(op1) || !isOperandConstantImmediateInt(op2)) 166 linkSlowCase(iter); // double check 139 167 } 140 if (isOperandConstantImmediateInt(op1) || !isOperandConstantImmediateInt(op2))141 linkSlowCase(iter); // double check142 168 } 143 169 … … 158 184 JumpList notInt32Op2; 159 185 160 // Int32 less. 186 // Character less. 187 if (isOperandConstantImmediateChar(op1)) { 188 emitLoad(op2, regT1, regT0); 189 addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::CellTag))); 190 JumpList failures; 191 emitLoadCharacterString(regT0, regT0, failures); 192 addSlowCase(failures); 193 addJump(branch32(GreaterThan, regT0, Imm32(asString(getConstantOperand(op1))->tryGetValue()[0])), target); 194 return; 195 } 196 if (isOperandConstantImmediateChar(op2)) { 197 emitLoad(op1, regT1, regT0); 198 addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::CellTag))); 199 JumpList failures; 200 emitLoadCharacterString(regT0, regT0, failures); 201 addSlowCase(failures); 202 addJump(branch32(LessThan, regT0, Imm32(asString(getConstantOperand(op2))->tryGetValue()[0])), target); 203 return; 204 } 161 205 if (isOperandConstantImmediateInt(op1)) { 162 206 emitLoad(op2, regT3, regT2); … … 191 235 unsigned op2 = currentInstruction[2].u.operand; 192 236 unsigned target = currentInstruction[3].u.operand; 193 194 if (!supportsFloatingPoint()) { 195 if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2)) 237 238 if (isOperandConstantImmediateChar(op1) || isOperandConstantImmediateChar(op2)) { 239 linkSlowCase(iter); 240 linkSlowCase(iter); 241 linkSlowCase(iter); 242 linkSlowCase(iter); 243 } else { 244 if (!supportsFloatingPoint()) { 245 if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2)) 246 linkSlowCase(iter); // int32 check 196 247 linkSlowCase(iter); // int32 check 197 linkSlowCase(iter); // int32 check 198 } else { 199 if (!isOperandConstantImmediateInt(op1)) { 200 linkSlowCase(iter); // double check 201 linkSlowCase(iter); // int32 check 248 } else { 249 if (!isOperandConstantImmediateInt(op1)) { 250 linkSlowCase(iter); // double check 251 linkSlowCase(iter); // int32 check 252 } 253 if (isOperandConstantImmediateInt(op1) || !isOperandConstantImmediateInt(op2)) 254 linkSlowCase(iter); // double check 202 255 } 203 if (isOperandConstantImmediateInt(op1) || !isOperandConstantImmediateInt(op2)) 204 linkSlowCase(iter); // double check 205 } 206 256 } 207 257 JITStubCall stubCall(this, cti_op_jless); 208 258 stubCall.addArgument(op1); … … 212 262 } 213 263 214 void JIT::emit_op_j nlesseq(Instruction* currentInstruction)264 void JIT::emit_op_jlesseq(Instruction* currentInstruction, bool invert) 215 265 { 216 266 unsigned op1 = currentInstruction[1].u.operand; … … 221 271 JumpList notInt32Op2; 222 272 223 // Int32 less. 273 // Character less. 274 if (isOperandConstantImmediateChar(op1)) { 275 emitLoad(op2, regT1, regT0); 276 addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::CellTag))); 277 JumpList failures; 278 emitLoadCharacterString(regT0, regT0, failures); 279 addSlowCase(failures); 280 addJump(branch32(invert ? LessThan : GreaterThanOrEqual, regT0, Imm32(asString(getConstantOperand(op1))->tryGetValue()[0])), target); 281 return; 282 } 283 if (isOperandConstantImmediateChar(op2)) { 284 emitLoad(op1, regT1, regT0); 285 addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::CellTag))); 286 JumpList failures; 287 emitLoadCharacterString(regT0, regT0, failures); 288 addSlowCase(failures); 289 addJump(branch32(invert ? GreaterThan : LessThanOrEqual, regT0, Imm32(asString(getConstantOperand(op2))->tryGetValue()[0])), target); 290 return; 291 } 224 292 if (isOperandConstantImmediateInt(op1)) { 225 293 emitLoad(op2, regT3, regT2); 226 294 notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); 227 addJump(branch32( LessThan, regT2, Imm32(getConstantOperand(op1).asInt32())), target);295 addJump(branch32(invert ? LessThan : GreaterThan, regT2, Imm32(getConstantOperand(op1).asInt32())), target); 228 296 } else if (isOperandConstantImmediateInt(op2)) { 229 297 emitLoad(op1, regT1, regT0); 230 298 notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); 231 addJump(branch32( GreaterThan, regT0, Imm32(getConstantOperand(op2).asInt32())), target);299 addJump(branch32(invert ? GreaterThan : LessThanOrEqual, regT0, Imm32(getConstantOperand(op2).asInt32())), target); 232 300 } else { 233 301 emitLoad2(op1, regT1, regT0, op2, regT3, regT2); 234 302 notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); 235 303 notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); 236 addJump(branch32( GreaterThan, regT0, regT2), target);304 addJump(branch32(invert ? GreaterThan : LessThanOrEqual, regT0, regT2), target); 237 305 } 238 306 … … 245 313 246 314 // Double less. 247 emitBinaryDoubleOp( op_jnlesseq, target, op1, op2, OperandTypes(), notInt32Op1, notInt32Op2, !isOperandConstantImmediateInt(op1), isOperandConstantImmediateInt(op1) || !isOperandConstantImmediateInt(op2));315 emitBinaryDoubleOp(invert ? op_jnlesseq : op_jlesseq, target, op1, op2, OperandTypes(), notInt32Op1, notInt32Op2, !isOperandConstantImmediateInt(op1), isOperandConstantImmediateInt(op1) || !isOperandConstantImmediateInt(op2)); 248 316 end.link(this); 249 317 } 250 318 251 void JIT::emitSlow_op_j nlesseq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)319 void JIT::emitSlow_op_jlesseq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter, bool invert) 252 320 { 253 321 unsigned op1 = currentInstruction[1].u.operand; … … 255 323 unsigned target = currentInstruction[3].u.operand; 256 324 257 if (!supportsFloatingPoint()) { 258 if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2)) 325 if (isOperandConstantImmediateChar(op1) || isOperandConstantImmediateChar(op2)) { 326 linkSlowCase(iter); 327 linkSlowCase(iter); 328 linkSlowCase(iter); 329 linkSlowCase(iter); 330 } else { 331 if (!supportsFloatingPoint()) { 332 if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2)) 333 linkSlowCase(iter); // int32 check 259 334 linkSlowCase(iter); // int32 check 260 linkSlowCase(iter); // int32 check 261 } else { 262 if (!isOperandConstantImmediateInt(op1)) { 263 linkSlowCase(iter); // double check 264 linkSlowCase(iter); // int32 check 335 } else { 336 if (!isOperandConstantImmediateInt(op1)) { 337 linkSlowCase(iter); // double check 338 linkSlowCase(iter); // int32 check 339 } 340 if (isOperandConstantImmediateInt(op1) || !isOperandConstantImmediateInt(op2)) 341 linkSlowCase(iter); // double check 265 342 } 266 if (isOperandConstantImmediateInt(op1) || !isOperandConstantImmediateInt(op2))267 linkSlowCase(iter); // double check268 343 } 269 344 … … 272 347 stubCall.addArgument(op2); 273 348 stubCall.call(); 274 emitJumpSlowToHot(branchTest32(Zero, regT0), target); 349 emitJumpSlowToHot(branchTest32(invert ? Zero : NonZero, regT0), target); 350 } 351 352 void JIT::emit_op_jnlesseq(Instruction* currentInstruction) 353 { 354 emit_op_jlesseq(currentInstruction, true); 355 } 356 357 void JIT::emitSlow_op_jnlesseq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) 358 { 359 emitSlow_op_jlesseq(currentInstruction, iter, true); 275 360 } 276 361 … … 984 1069 addJump(branchDouble(DoubleLessThan, fpRegT2, fpRegT0), dst); 985 1070 break; 1071 case op_jlesseq: 1072 emitLoadDouble(op1, fpRegT2); 1073 addJump(branchDouble(DoubleLessThanOrEqual, fpRegT2, fpRegT0), dst); 1074 break; 986 1075 case op_jnlesseq: 987 1076 emitLoadDouble(op1, fpRegT2); … … 1044 1133 emitLoadDouble(op2, fpRegT1); 1045 1134 addJump(branchDouble(DoubleLessThanOrUnordered, fpRegT1, fpRegT0), dst); 1135 break; 1136 case op_jlesseq: 1137 emitLoadDouble(op2, fpRegT1); 1138 addJump(branchDouble(DoubleLessThanOrEqual, fpRegT1, fpRegT0), dst); 1046 1139 break; 1047 1140 default: -
trunk/JavaScriptCore/jit/JITInlineMethods.h
r58469 r58902 94 94 } 95 95 96 ALWAYS_INLINE void JIT::emitLoadCharacterString(RegisterID src, RegisterID dst, JumpList& failures) 97 { 98 failures.append(branchPtr(NotEqual, Address(src), ImmPtr(m_globalData->jsStringVPtr))); 99 failures.append(branchTest32(NonZero, Address(src, OBJECT_OFFSETOF(JSString, m_fiberCount)))); 100 failures.append(branch32(NotEqual, MacroAssembler::Address(src, ThunkHelpers::jsStringLengthOffset()), Imm32(1))); 101 loadPtr(MacroAssembler::Address(src, ThunkHelpers::jsStringValueOffset()), dst); 102 loadPtr(MacroAssembler::Address(dst, ThunkHelpers::stringImplDataOffset()), dst); 103 load16(MacroAssembler::Address(dst, 0), dst); 104 } 105 96 106 ALWAYS_INLINE void JIT::emitGetFromCallFrameHeader32(RegisterFile::CallFrameHeaderEntry entry, RegisterID to, RegisterID from) 97 107 { … … 323 333 #endif 324 334 #endif 335 336 ALWAYS_INLINE bool JIT::isOperandConstantImmediateChar(unsigned src) 337 { 338 return m_codeBlock->isConstantRegisterIndex(src) && getConstantOperand(src).isString() && asString(getConstantOperand(src).asCell())->length() == 1; 339 } 325 340 326 341 #if USE(JSVALUE32_64) -
trunk/JavaScriptCore/jit/JSInterfaceJIT.h
r58469 r58902 176 176 }; 177 177 178 struct ThunkHelpers { 179 static unsigned stringImplDataOffset() { return WebCore::StringImpl::dataOffset(); } 180 static unsigned jsStringLengthOffset() { return OBJECT_OFFSETOF(JSString, m_length); } 181 static unsigned jsStringValueOffset() { return OBJECT_OFFSETOF(JSString, m_value); } 182 }; 183 178 184 #if USE(JSVALUE32_64) 179 185 inline JSInterfaceJIT::Jump JSInterfaceJIT::emitLoadJSCell(unsigned virtualRegisterIndex, RegisterID payload) -
trunk/JavaScriptCore/jit/ThunkGenerators.cpp
r58712 r58902 33 33 34 34 namespace JSC { 35 36 struct ThunkHelpers {37 static unsigned stringImplDataOffset() { return WebCore::StringImpl::dataOffset(); }38 static unsigned jsStringLengthOffset() { return OBJECT_OFFSETOF(JSString, m_length); }39 static unsigned jsStringValueOffset() { return OBJECT_OFFSETOF(JSString, m_value); }40 };41 35 42 36 static void stringCharLoad(SpecializedThunkJIT& jit)
Note:
See TracChangeset
for help on using the changeset viewer.