Changeset 51735 in webkit
- Timestamp:
- Dec 6, 2009 1:42:03 AM (14 years ago)
- Location:
- trunk
- Files:
-
- 17 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/ChangeLog
r51724 r51735 1 2009-12-05 Maciej Stachowiak <mjs@apple.com> 2 3 Reviewed by Oliver Hunt. 4 5 conway benchmark spends half it's time in op_less (jump fusion fails) 6 https://bugs.webkit.org/show_bug.cgi?id=32190 7 8 <1% speedup on SunSpider and V8 9 2x speedup on "conway" benchmark 10 11 Two optimizations: 12 1) Improve codegen for logical operators &&, || and ! in a condition context 13 14 When generating code for combinations of &&, || and !, in a 15 condition context (i.e. in an if statement or loop condition), we 16 used to produce a value, and then separately jump based on its 17 truthiness. Now we pass the false and true targets in, and let the 18 logical operators generate jumps directly. This helps in four 19 ways: 20 21 a) Individual clauses of a short-circuit logical operator can now 22 jump directly to the then or else clause of an if statement (or to 23 the top or exit of a loop) instead of jumping to a jump. 24 25 b) It used to be that jump fusion with the condition of the first 26 clause of a logical operator was inhibited, because the register 27 was ref'd to be used later, in the actual condition jump; this no 28 longer happens since a jump straight to the final target is 29 generated directly. 30 31 c) It used to be that jump fusion with the condition of the second 32 clause of a logical operator was inhibited, because there was a 33 jump target right after the second clause and before the actual 34 condition jump. But now it's no longer necessary for the first 35 clause to jump there so jump fusion is not blocked. 36 37 d) We avoid generating excess mov statements in some cases. 38 39 As a concrete example this source: 40 41 if (!((x < q && y < q) || (t < q && z < q))) { 42 // ... 43 } 44 45 Used to generate this bytecode: 46 47 [ 34] less r1, r-15, r-19 48 [ 38] jfalse r1, 7(->45) 49 [ 41] less r1, r-16, r-19 50 [ 45] jtrue r1, 14(->59) 51 [ 48] less r1, r-17, r-19 52 [ 52] jfalse r1, 7(->59) 53 [ 55] less r1, r-18, r-19 54 [ 59] jtrue r1, 17(->76) 55 56 And now generates this bytecode (also taking advantage of the second optimization below): 57 58 [ 34] jnless r-15, r-19, 8(->42) 59 [ 38] jless r-16, r-19, 26(->64) 60 [ 42] jnless r-17, r-19, 8(->50) 61 [ 46] jless r-18, r-19, 18(->64) 62 63 Note the jump fusion and the fact that there's less jump 64 indirection - three of the four jumps go straight to the target 65 clause instead of indirecting through another jump. 66 67 2) Implement jless opcode to take advantage of the above, since we'll now often generate 68 a less followed by a jtrue where fusion is not forbidden. 69 70 * parser/Nodes.h: 71 (JSC::ExpressionNode::hasConditionContextCodegen): Helper function to determine 72 whether a node supports special conditional codegen. Return false as this is the default. 73 (JSC::ExpressionNode::emitBytecodeInConditionContext): Assert not reached - only really 74 defined for nodes that do have conditional codegen. 75 (JSC::UnaryOpNode::expr): Add const version. 76 (JSC::LogicalNotNode::hasConditionContextCodegen): Returne true only if subexpression 77 supports it. 78 (JSC::LogicalOpNode::hasConditionContextCodegen): Return true. 79 * parser/Nodes.cpp: 80 (JSC::LogicalNotNode::emitBytecodeInConditionContext): Implemented - just swap 81 the true and false targets for the child node. 82 (JSC::LogicalOpNode::emitBytecodeInConditionContext): Implemented - handle jumps 83 directly, improving codegen quality. Also handles further nested conditional codegen. 84 (JSC::ConditionalNode::emitBytecode): Use condition context codegen when available. 85 (JSC::IfNode::emitBytecode): ditto 86 (JSC::IfElseNode::emitBytecode): ditto 87 (JSC::DoWhileNode::emitBytecode): ditto 88 (JSC::WhileNode::emitBytecode): ditto 89 (JSC::ForNode::emitBytecode): ditto 90 91 * bytecode/Opcode.h: 92 - Added loop_if_false opcode - needed now that falsey jumps can be backwards. 93 - Added jless opcode to take advantage of new fusion opportunities. 94 * bytecode/CodeBlock.cpp: 95 (JSC::CodeBlock::dump): Handle above. 96 * bytecompiler/BytecodeGenerator.cpp: 97 (JSC::BytecodeGenerator::emitJumpIfTrue): Add peephole for less + jtrue ==> jless. 98 (JSC::BytecodeGenerator::emitJumpIfFalse): Add handling of backwrds falsey jumps. 99 * bytecompiler/BytecodeGenerator.h: 100 (JSC::BytecodeGenerator::emitNodeInConditionContext): Wrapper to handle tracking of 101 overly deep expressions etc. 102 * interpreter/Interpreter.cpp: 103 (JSC::Interpreter::privateExecute): Implement the two new opcodes (loop_if_false, jless). 104 * jit/JIT.cpp: 105 (JSC::JIT::privateCompileMainPass): Implement JIT support for the two new opcodes. 106 (JSC::JIT::privateCompileSlowCases): ditto 107 * jit/JIT.h: 108 * jit/JITArithmetic.cpp: 109 (JSC::JIT::emit_op_jless): 110 (JSC::JIT::emitSlow_op_jless): ditto 111 (JSC::JIT::emitBinaryDoubleOp): ditto 112 * jit/JITOpcodes.cpp: 113 (JSC::JIT::emitSlow_op_loop_if_less): ditto 114 (JSC::JIT::emit_op_loop_if_false): ditto 115 (JSC::JIT::emitSlow_op_loop_if_false): ditto 116 * jit/JITStubs.cpp: 117 * jit/JITStubs.h: 118 (JSC::): 119 1 120 2009-12-04 Kent Hansen <kent.hansen@nokia.com> 2 121 -
trunk/JavaScriptCore/bytecode/CodeBlock.cpp
r50538 r51735 877 877 break; 878 878 } 879 case op_loop_if_false: { 880 printConditionalJump(exec, begin, it, location, "loop_if_false"); 881 break; 882 } 879 883 case op_jfalse: { 880 884 printConditionalJump(exec, begin, it, location, "jfalse"); … … 915 919 int offset = (++it)->u.operand; 916 920 printf("[%4d] loop_if_less\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).c_str(), registerName(exec, r1).c_str(), offset, location + offset); 921 break; 922 } 923 case op_jless: { 924 int r0 = (++it)->u.operand; 925 int r1 = (++it)->u.operand; 926 int offset = (++it)->u.operand; 927 printf("[%4d] jless\t\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).c_str(), registerName(exec, r1).c_str(), offset, location + offset); 917 928 break; 918 929 } -
trunk/JavaScriptCore/bytecode/Opcode.h
r50254 r51735 129 129 macro(op_jnless, 4) \ 130 130 macro(op_jnlesseq, 4) \ 131 macro(op_jless, 4) \ 131 132 macro(op_jmp_scopes, 3) \ 132 133 macro(op_loop, 2) \ 133 134 macro(op_loop_if_true, 3) \ 135 macro(op_loop_if_false, 3) \ 134 136 macro(op_loop_if_less, 4) \ 135 137 macro(op_loop_if_lesseq, 4) \ -
trunk/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
r50916 r51735 617 617 PassRefPtr<Label> BytecodeGenerator::emitJumpIfTrue(RegisterID* cond, Label* target) 618 618 { 619 if (m_lastOpcodeID == op_less && !target->isForward()) {619 if (m_lastOpcodeID == op_less) { 620 620 int dstIndex; 621 621 int src1Index; … … 628 628 629 629 size_t begin = instructions().size(); 630 emitOpcode( op_loop_if_less);630 emitOpcode(target->isForward() ? op_jless : op_loop_if_less); 631 631 instructions().append(src1Index); 632 632 instructions().append(src2Index); … … 693 693 PassRefPtr<Label> BytecodeGenerator::emitJumpIfFalse(RegisterID* cond, Label* target) 694 694 { 695 ASSERT(target->isForward()); 696 697 if (m_lastOpcodeID == op_less) { 695 if (m_lastOpcodeID == op_less && target->isForward()) { 698 696 int dstIndex; 699 697 int src1Index; … … 712 710 return target; 713 711 } 714 } else if (m_lastOpcodeID == op_lesseq ) {712 } else if (m_lastOpcodeID == op_lesseq && target->isForward()) { 715 713 int dstIndex; 716 714 int src1Index; … … 739 737 740 738 size_t begin = instructions().size(); 741 emitOpcode( op_jtrue);739 emitOpcode(target->isForward() ? op_jtrue : op_loop_if_true); 742 740 instructions().append(srcIndex); 743 741 instructions().append(target->bind(begin, instructions().size())); 744 742 return target; 745 743 } 746 } else if (m_lastOpcodeID == op_eq_null ) {744 } else if (m_lastOpcodeID == op_eq_null && target->isForward()) { 747 745 int dstIndex; 748 746 int srcIndex; … … 759 757 return target; 760 758 } 761 } else if (m_lastOpcodeID == op_neq_null ) {759 } else if (m_lastOpcodeID == op_neq_null && target->isForward()) { 762 760 int dstIndex; 763 761 int srcIndex; … … 777 775 778 776 size_t begin = instructions().size(); 779 emitOpcode( op_jfalse);777 emitOpcode(target->isForward() ? op_jfalse : op_loop_if_false); 780 778 instructions().append(cond->index()); 781 779 instructions().append(target->bind(begin, instructions().size())); -
trunk/JavaScriptCore/bytecompiler/BytecodeGenerator.h
r50254 r51735 193 193 } 194 194 195 void emitNodeInConditionContext(ExpressionNode* n, Label* trueTarget, Label* falseTarget, bool fallThroughMeansTrue) 196 { 197 if (!m_codeBlock->numberOfLineInfos() || m_codeBlock->lastLineInfo().lineNumber != n->lineNo()) { 198 LineInfo info = { instructions().size(), n->lineNo() }; 199 m_codeBlock->addLineInfo(info); 200 } 201 if (m_emitNodeDepth >= s_maxEmitNodeDepth) 202 emitThrowExpressionTooDeepException(); 203 ++m_emitNodeDepth; 204 n->emitBytecodeInConditionContext(*this, trueTarget, falseTarget, fallThroughMeansTrue); 205 --m_emitNodeDepth; 206 } 207 195 208 void emitExpressionInfo(unsigned divot, unsigned startOffset, unsigned endOffset) 196 209 { -
trunk/JavaScriptCore/interpreter/Interpreter.cpp
r51671 r51735 2648 2648 NEXT_INSTRUCTION(); 2649 2649 } 2650 DEFINE_OPCODE(op_loop_if_false) { 2651 /* loop_if_true cond(r) target(offset) 2652 2653 Jumps to offset target from the current instruction, if and 2654 only if register cond converts to boolean as false. 2655 2656 Additionally this loop instruction may terminate JS execution is 2657 the JS timeout is reached. 2658 */ 2659 int cond = vPC[1].u.operand; 2660 int target = vPC[2].u.operand; 2661 if (!callFrame->r(cond).jsValue().toBoolean(callFrame)) { 2662 vPC += target; 2663 CHECK_FOR_TIMEOUT(); 2664 NEXT_INSTRUCTION(); 2665 } 2666 2667 vPC += OPCODE_LENGTH(op_loop_if_true); 2668 NEXT_INSTRUCTION(); 2669 } 2650 2670 DEFINE_OPCODE(op_jtrue) { 2651 2671 /* jtrue cond(r) target(offset) … … 2809 2829 2810 2830 vPC += OPCODE_LENGTH(op_jnless); 2831 NEXT_INSTRUCTION(); 2832 } 2833 DEFINE_OPCODE(op_jless) { 2834 /* jless src1(r) src2(r) target(offset) 2835 2836 Checks whether register src1 is less than register src2, as 2837 with the ECMAScript '<' operator, and then jumps to offset 2838 target from the current instruction, if and only if the 2839 result of the comparison is true. 2840 */ 2841 JSValue src1 = callFrame->r(vPC[1].u.operand).jsValue(); 2842 JSValue src2 = callFrame->r(vPC[2].u.operand).jsValue(); 2843 int target = vPC[3].u.operand; 2844 2845 bool result = jsLess(callFrame, src1, src2); 2846 CHECK_FOR_EXCEPTION(); 2847 2848 if (result) { 2849 vPC += target; 2850 NEXT_INSTRUCTION(); 2851 } 2852 2853 vPC += OPCODE_LENGTH(op_jless); 2811 2854 NEXT_INSTRUCTION(); 2812 2855 } -
trunk/JavaScriptCore/jit/JIT.cpp
r50981 r51735 251 251 DEFINE_OP(op_jneq_ptr) 252 252 DEFINE_OP(op_jnless) 253 DEFINE_OP(op_jless) 253 254 DEFINE_OP(op_jnlesseq) 254 255 DEFINE_OP(op_jsr) … … 259 260 DEFINE_OP(op_loop_if_lesseq) 260 261 DEFINE_OP(op_loop_if_true) 262 DEFINE_OP(op_loop_if_false) 261 263 DEFINE_OP(op_lshift) 262 264 DEFINE_OP(op_method_check) … … 390 392 DEFINE_SLOWCASE_OP(op_jfalse) 391 393 DEFINE_SLOWCASE_OP(op_jnless) 394 DEFINE_SLOWCASE_OP(op_jless) 392 395 DEFINE_SLOWCASE_OP(op_jnlesseq) 393 396 DEFINE_SLOWCASE_OP(op_jtrue) … … 395 398 DEFINE_SLOWCASE_OP(op_loop_if_lesseq) 396 399 DEFINE_SLOWCASE_OP(op_loop_if_true) 400 DEFINE_SLOWCASE_OP(op_loop_if_false) 397 401 DEFINE_SLOWCASE_OP(op_lshift) 398 402 DEFINE_SLOWCASE_OP(op_method_check) -
trunk/JavaScriptCore/jit/JIT.h
r50982 r51735 737 737 void emit_op_jneq_ptr(Instruction*); 738 738 void emit_op_jnless(Instruction*); 739 void emit_op_jless(Instruction*); 739 740 void emit_op_jnlesseq(Instruction*); 740 741 void emit_op_jsr(Instruction*); … … 745 746 void emit_op_loop_if_lesseq(Instruction*); 746 747 void emit_op_loop_if_true(Instruction*); 748 void emit_op_loop_if_false(Instruction*); 747 749 void emit_op_lshift(Instruction*); 748 750 void emit_op_method_check(Instruction*); … … 819 821 void emitSlow_op_jfalse(Instruction*, Vector<SlowCaseEntry>::iterator&); 820 822 void emitSlow_op_jnless(Instruction*, Vector<SlowCaseEntry>::iterator&); 823 void emitSlow_op_jless(Instruction*, Vector<SlowCaseEntry>::iterator&); 821 824 void emitSlow_op_jnlesseq(Instruction*, Vector<SlowCaseEntry>::iterator&); 822 825 void emitSlow_op_jtrue(Instruction*, Vector<SlowCaseEntry>::iterator&); … … 824 827 void emitSlow_op_loop_if_lesseq(Instruction*, Vector<SlowCaseEntry>::iterator&); 825 828 void emitSlow_op_loop_if_true(Instruction*, Vector<SlowCaseEntry>::iterator&); 829 void emitSlow_op_loop_if_false(Instruction*, Vector<SlowCaseEntry>::iterator&); 826 830 void emitSlow_op_lshift(Instruction*, Vector<SlowCaseEntry>::iterator&); 827 831 void emitSlow_op_method_check(Instruction*, Vector<SlowCaseEntry>::iterator&); -
trunk/JavaScriptCore/jit/JITArithmetic.cpp
r50599 r51735 147 147 stubCall.call(); 148 148 emitJumpSlowToHot(branchTest32(Zero, regT0), target); 149 } 150 151 void JIT::emit_op_jless(Instruction* currentInstruction) 152 { 153 unsigned op1 = currentInstruction[1].u.operand; 154 unsigned op2 = currentInstruction[2].u.operand; 155 unsigned target = currentInstruction[3].u.operand; 156 157 JumpList notInt32Op1; 158 JumpList notInt32Op2; 159 160 // Int32 less. 161 if (isOperandConstantImmediateInt(op1)) { 162 emitLoad(op2, regT3, regT2); 163 notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); 164 addJump(branch32(GreaterThan, regT2, Imm32(getConstantOperand(op1).asInt32())), target); 165 } else if (isOperandConstantImmediateInt(op2)) { 166 emitLoad(op1, regT1, regT0); 167 notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); 168 addJump(branch32(LessThan, regT0, Imm32(getConstantOperand(op2).asInt32())), target); 169 } else { 170 emitLoad2(op1, regT1, regT0, op2, regT3, regT2); 171 notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); 172 notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); 173 addJump(branch32(LessThan, regT0, regT2), target); 174 } 175 176 if (!supportsFloatingPoint()) { 177 addSlowCase(notInt32Op1); 178 addSlowCase(notInt32Op2); 179 return; 180 } 181 Jump end = jump(); 182 183 // Double less. 184 emitBinaryDoubleOp(op_jless, target, op1, op2, OperandTypes(), notInt32Op1, notInt32Op2, !isOperandConstantImmediateInt(op1), isOperandConstantImmediateInt(op1) || !isOperandConstantImmediateInt(op2)); 185 end.link(this); 186 } 187 188 void JIT::emitSlow_op_jless(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) 189 { 190 unsigned op1 = currentInstruction[1].u.operand; 191 unsigned op2 = currentInstruction[2].u.operand; 192 unsigned target = currentInstruction[3].u.operand; 193 194 if (!supportsFloatingPoint()) { 195 if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2)) 196 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 202 } 203 if (isOperandConstantImmediateInt(op1) || !isOperandConstantImmediateInt(op2)) 204 linkSlowCase(iter); // double check 205 } 206 207 JITStubCall stubCall(this, cti_op_jless); 208 stubCall.addArgument(op1); 209 stubCall.addArgument(op2); 210 stubCall.call(); 211 emitJumpSlowToHot(branchTest32(NonZero, regT0), target); 149 212 } 150 213 … … 832 895 addJump(branchDouble(DoubleLessThanOrEqualOrUnordered, fpRegT0, fpRegT2), dst); 833 896 break; 897 case op_jless: 898 emitLoadDouble(op1, fpRegT2); 899 addJump(branchDouble(DoubleLessThan, fpRegT2, fpRegT0), dst); 900 break; 834 901 case op_jnlesseq: 835 902 emitLoadDouble(op1, fpRegT2); … … 885 952 addJump(branchDouble(DoubleLessThanOrEqualOrUnordered, fpRegT1, fpRegT0), dst); 886 953 break; 954 case op_jless: 955 emitLoadDouble(op2, fpRegT1); 956 addJump(branchDouble(DoubleLessThan, fpRegT0, fpRegT1), dst); 957 break; 887 958 case op_jnlesseq: 888 959 emitLoadDouble(op2, fpRegT1); … … 1453 1524 stubCall.call(); 1454 1525 emitJumpSlowToHot(branchTest32(Zero, regT0), target); 1526 } 1527 } 1528 1529 void JIT::emit_op_jless(Instruction* currentInstruction) 1530 { 1531 unsigned op1 = currentInstruction[1].u.operand; 1532 unsigned op2 = currentInstruction[2].u.operand; 1533 unsigned target = currentInstruction[3].u.operand; 1534 1535 // We generate inline code for the following cases in the fast path: 1536 // - int immediate to constant int immediate 1537 // - constant int immediate to int immediate 1538 // - int immediate to int immediate 1539 1540 if (isOperandConstantImmediateInt(op2)) { 1541 emitGetVirtualRegister(op1, regT0); 1542 emitJumpSlowCaseIfNotImmediateInteger(regT0); 1543 #if USE(JSVALUE64) 1544 int32_t op2imm = getConstantOperandImmediateInt(op2); 1545 #else 1546 int32_t op2imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2))); 1547 #endif 1548 addJump(branch32(LessThan, regT0, Imm32(op2imm)), target); 1549 } else if (isOperandConstantImmediateInt(op1)) { 1550 emitGetVirtualRegister(op2, regT1); 1551 emitJumpSlowCaseIfNotImmediateInteger(regT1); 1552 #if USE(JSVALUE64) 1553 int32_t op1imm = getConstantOperandImmediateInt(op1); 1554 #else 1555 int32_t op1imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op1))); 1556 #endif 1557 addJump(branch32(GreaterThan, regT1, Imm32(op1imm)), target); 1558 } else { 1559 emitGetVirtualRegisters(op1, regT0, op2, regT1); 1560 emitJumpSlowCaseIfNotImmediateInteger(regT0); 1561 emitJumpSlowCaseIfNotImmediateInteger(regT1); 1562 1563 addJump(branch32(LessThan, regT0, regT1), target); 1564 } 1565 } 1566 1567 void JIT::emitSlow_op_jless(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) 1568 { 1569 unsigned op1 = currentInstruction[1].u.operand; 1570 unsigned op2 = currentInstruction[2].u.operand; 1571 unsigned target = currentInstruction[3].u.operand; 1572 1573 // We generate inline code for the following cases in the slow path: 1574 // - floating-point number to constant int immediate 1575 // - constant int immediate to floating-point number 1576 // - floating-point number to floating-point number. 1577 1578 if (isOperandConstantImmediateInt(op2)) { 1579 linkSlowCase(iter); 1580 1581 if (supportsFloatingPoint()) { 1582 #if USE(JSVALUE64) 1583 Jump fail1 = emitJumpIfNotImmediateNumber(regT0); 1584 addPtr(tagTypeNumberRegister, regT0); 1585 movePtrToDouble(regT0, fpRegT0); 1586 #else 1587 Jump fail1; 1588 if (!m_codeBlock->isKnownNotImmediate(op1)) 1589 fail1 = emitJumpIfNotJSCell(regT0); 1590 1591 Jump fail2 = checkStructure(regT0, m_globalData->numberStructure.get()); 1592 loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0); 1593 #endif 1594 1595 int32_t op2imm = getConstantOperand(op2).asInt32(); 1596 1597 move(Imm32(op2imm), regT1); 1598 convertInt32ToDouble(regT1, fpRegT1); 1599 1600 emitJumpSlowToHot(branchDouble(DoubleLessThan, fpRegT0, fpRegT1), target); 1601 1602 emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless)); 1603 1604 #if USE(JSVALUE64) 1605 fail1.link(this); 1606 #else 1607 if (!m_codeBlock->isKnownNotImmediate(op1)) 1608 fail1.link(this); 1609 fail2.link(this); 1610 #endif 1611 } 1612 1613 JITStubCall stubCall(this, cti_op_jless); 1614 stubCall.addArgument(regT0); 1615 stubCall.addArgument(op2, regT2); 1616 stubCall.call(); 1617 emitJumpSlowToHot(branchTest32(Zero, regT0), target); 1618 1619 } else if (isOperandConstantImmediateInt(op1)) { 1620 linkSlowCase(iter); 1621 1622 if (supportsFloatingPoint()) { 1623 #if USE(JSVALUE64) 1624 Jump fail1 = emitJumpIfNotImmediateNumber(regT1); 1625 addPtr(tagTypeNumberRegister, regT1); 1626 movePtrToDouble(regT1, fpRegT1); 1627 #else 1628 Jump fail1; 1629 if (!m_codeBlock->isKnownNotImmediate(op2)) 1630 fail1 = emitJumpIfNotJSCell(regT1); 1631 1632 Jump fail2 = checkStructure(regT1, m_globalData->numberStructure.get()); 1633 loadDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT1); 1634 #endif 1635 1636 int32_t op1imm = getConstantOperand(op1).asInt32(); 1637 1638 move(Imm32(op1imm), regT0); 1639 convertInt32ToDouble(regT0, fpRegT0); 1640 1641 emitJumpSlowToHot(branchDouble(DoubleLessThan, fpRegT0, fpRegT1), target); 1642 1643 emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless)); 1644 1645 #if USE(JSVALUE64) 1646 fail1.link(this); 1647 #else 1648 if (!m_codeBlock->isKnownNotImmediate(op2)) 1649 fail1.link(this); 1650 fail2.link(this); 1651 #endif 1652 } 1653 1654 JITStubCall stubCall(this, cti_op_jless); 1655 stubCall.addArgument(op1, regT2); 1656 stubCall.addArgument(regT1); 1657 stubCall.call(); 1658 emitJumpSlowToHot(branchTest32(Zero, regT0), target); 1659 1660 } else { 1661 linkSlowCase(iter); 1662 1663 if (supportsFloatingPoint()) { 1664 #if USE(JSVALUE64) 1665 Jump fail1 = emitJumpIfNotImmediateNumber(regT0); 1666 Jump fail2 = emitJumpIfNotImmediateNumber(regT1); 1667 Jump fail3 = emitJumpIfImmediateInteger(regT1); 1668 addPtr(tagTypeNumberRegister, regT0); 1669 addPtr(tagTypeNumberRegister, regT1); 1670 movePtrToDouble(regT0, fpRegT0); 1671 movePtrToDouble(regT1, fpRegT1); 1672 #else 1673 Jump fail1; 1674 if (!m_codeBlock->isKnownNotImmediate(op1)) 1675 fail1 = emitJumpIfNotJSCell(regT0); 1676 1677 Jump fail2; 1678 if (!m_codeBlock->isKnownNotImmediate(op2)) 1679 fail2 = emitJumpIfNotJSCell(regT1); 1680 1681 Jump fail3 = checkStructure(regT0, m_globalData->numberStructure.get()); 1682 Jump fail4 = checkStructure(regT1, m_globalData->numberStructure.get()); 1683 loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0); 1684 loadDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT1); 1685 #endif 1686 1687 emitJumpSlowToHot(branchDouble(DoubleLessThan, fpRegT0, fpRegT1), target); 1688 1689 emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless)); 1690 1691 #if USE(JSVALUE64) 1692 fail1.link(this); 1693 fail2.link(this); 1694 fail3.link(this); 1695 #else 1696 if (!m_codeBlock->isKnownNotImmediate(op1)) 1697 fail1.link(this); 1698 if (!m_codeBlock->isKnownNotImmediate(op2)) 1699 fail2.link(this); 1700 fail3.link(this); 1701 fail4.link(this); 1702 #endif 1703 } 1704 1705 linkSlowCase(iter); 1706 JITStubCall stubCall(this, cti_op_jless); 1707 stubCall.addArgument(regT0); 1708 stubCall.addArgument(regT1); 1709 stubCall.call(); 1710 emitJumpSlowToHot(branchTest32(NotZero, regT0), target); 1455 1711 } 1456 1712 } -
trunk/JavaScriptCore/jit/JITOpcodes.cpp
r51671 r51735 455 455 linkSlowCase(iter); // int32 check 456 456 457 JITStubCall stubCall(this, cti_op_ loop_if_less);457 JITStubCall stubCall(this, cti_op_jless); 458 458 stubCall.addArgument(op1); 459 459 stubCall.addArgument(op2); … … 742 742 stubCall.call(); 743 743 emitJumpSlowToHot(branchTest32(NonZero, regT0), target); 744 } 745 746 void JIT::emit_op_loop_if_false(Instruction* currentInstruction) 747 { 748 unsigned cond = currentInstruction[1].u.operand; 749 unsigned target = currentInstruction[2].u.operand; 750 751 emitTimeoutCheck(); 752 753 emitLoad(cond, regT1, regT0); 754 755 Jump isTrue = branch32(Equal, regT1, Imm32(JSValue::TrueTag)); 756 addJump(branch32(Equal, regT1, Imm32(JSValue::FalseTag)), target); 757 758 Jump isNotInteger = branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)); 759 Jump isTrue2 = branch32(NotEqual, regT0, Imm32(0)); 760 addJump(jump(), target); 761 762 if (supportsFloatingPoint()) { 763 isNotInteger.link(this); 764 765 addSlowCase(branch32(Above, regT1, Imm32(JSValue::LowestTag))); 766 767 zeroDouble(fpRegT0); 768 emitLoadDouble(cond, fpRegT1); 769 addJump(branchDouble(DoubleEqualOrUnordered, fpRegT0, fpRegT1), target); 770 } else 771 addSlowCase(isNotInteger); 772 773 isTrue.link(this); 774 isTrue2.link(this); 775 } 776 777 void JIT::emitSlow_op_loop_if_false(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) 778 { 779 unsigned cond = currentInstruction[1].u.operand; 780 unsigned target = currentInstruction[2].u.operand; 781 782 linkSlowCase(iter); 783 784 JITStubCall stubCall(this, cti_op_jtrue); 785 stubCall.addArgument(cond); 786 stubCall.call(); 787 emitJumpSlowToHot(branchTest32(Zero, regT0), target); 744 788 } 745 789 -
trunk/JavaScriptCore/jit/JITStubs.cpp
r51671 r51735 1120 1120 } 1121 1121 1122 DEFINE_STUB_FUNCTION(int, op_loop_if_less)1123 {1124 STUB_INIT_STACK_FRAME(stackFrame);1125 1126 JSValue src1 = stackFrame.args[0].jsValue();1127 JSValue src2 = stackFrame.args[1].jsValue();1128 CallFrame* callFrame = stackFrame.callFrame;1129 1130 bool result = jsLess(callFrame, src1, src2);1131 CHECK_FOR_EXCEPTION_AT_END();1132 return result;1133 }1134 1135 1122 DEFINE_STUB_FUNCTION(int, op_loop_if_lesseq) 1136 1123 { … … 2098 2085 } 2099 2086 2100 DEFINE_STUB_FUNCTION(int, op_loop_if_true)2101 {2102 STUB_INIT_STACK_FRAME(stackFrame);2103 2104 JSValue src1 = stackFrame.args[0].jsValue();2105 2106 CallFrame* callFrame = stackFrame.callFrame;2107 2108 bool result = src1.toBoolean(callFrame);2109 CHECK_FOR_EXCEPTION_AT_END();2110 return result;2111 }2112 2113 2087 DEFINE_STUB_FUNCTION(int, op_load_varargs) 2114 2088 { -
trunk/JavaScriptCore/jit/JITStubs.h
r50594 r51735 336 336 int JIT_STUB cti_op_jtrue(STUB_ARGS_DECLARATION); 337 337 int JIT_STUB cti_op_load_varargs(STUB_ARGS_DECLARATION); 338 int JIT_STUB cti_op_loop_if_less(STUB_ARGS_DECLARATION);339 338 int JIT_STUB cti_op_loop_if_lesseq(STUB_ARGS_DECLARATION); 340 int JIT_STUB cti_op_loop_if_true(STUB_ARGS_DECLARATION);341 339 int JIT_STUB cti_timeout_check(STUB_ARGS_DECLARATION); 342 340 int JIT_STUB cti_has_property(STUB_ARGS_DECLARATION); -
trunk/JavaScriptCore/parser/Nodes.cpp
r50916 r51735 812 812 } 813 813 814 815 // ------------------------------ LogicalNotNode ----------------------------------- 816 817 void LogicalNotNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, bool fallThroughMeansTrue) 818 { 819 ASSERT(expr()->hasConditionContextCodegen()); 820 821 // reverse the true and false targets 822 generator.emitNodeInConditionContext(expr(), falseTarget, trueTarget, !fallThroughMeansTrue); 823 } 824 825 814 826 // ------------------------------ Binary Operation Nodes ----------------------------------- 815 827 … … 1018 1030 } 1019 1031 1032 void LogicalOpNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, bool fallThroughMeansTrue) 1033 { 1034 if (m_expr1->hasConditionContextCodegen()) { 1035 RefPtr<Label> afterExpr1 = generator.newLabel(); 1036 if (m_operator == OpLogicalAnd) 1037 generator.emitNodeInConditionContext(m_expr1, afterExpr1.get(), falseTarget, true); 1038 else 1039 generator.emitNodeInConditionContext(m_expr1, trueTarget, afterExpr1.get(), false); 1040 generator.emitLabel(afterExpr1.get()); 1041 } else { 1042 RegisterID* temp = generator.emitNode(m_expr1); 1043 if (m_operator == OpLogicalAnd) 1044 generator.emitJumpIfFalse(temp, falseTarget); 1045 else 1046 generator.emitJumpIfTrue(temp, trueTarget); 1047 } 1048 1049 if (m_expr2->hasConditionContextCodegen()) 1050 generator.emitNodeInConditionContext(m_expr2, trueTarget, falseTarget, fallThroughMeansTrue); 1051 else { 1052 RegisterID* temp = generator.emitNode(m_expr2); 1053 if (fallThroughMeansTrue) 1054 generator.emitJumpIfFalse(temp, falseTarget); 1055 else 1056 generator.emitJumpIfTrue(temp, trueTarget); 1057 } 1058 } 1059 1020 1060 // ------------------------------ ConditionalNode ------------------------------ 1021 1061 … … 1026 1066 RefPtr<Label> afterElse = generator.newLabel(); 1027 1067 1028 RegisterID* cond = generator.emitNode(m_logical); 1029 generator.emitJumpIfFalse(cond, beforeElse.get()); 1068 if (m_logical->hasConditionContextCodegen()) { 1069 RefPtr<Label> beforeThen = generator.newLabel(); 1070 generator.emitNodeInConditionContext(m_logical, beforeThen.get(), beforeElse.get(), true); 1071 generator.emitLabel(beforeThen.get()); 1072 } else { 1073 RegisterID* cond = generator.emitNode(m_logical); 1074 generator.emitJumpIfFalse(cond, beforeElse.get()); 1075 } 1030 1076 1031 1077 generator.emitNode(newDst.get(), m_expr1); … … 1344 1390 RefPtr<Label> afterThen = generator.newLabel(); 1345 1391 1346 RegisterID* cond = generator.emitNode(m_condition); 1347 generator.emitJumpIfFalse(cond, afterThen.get()); 1392 if (m_condition->hasConditionContextCodegen()) { 1393 RefPtr<Label> beforeThen = generator.newLabel(); 1394 generator.emitNodeInConditionContext(m_condition, beforeThen.get(), afterThen.get(), true); 1395 generator.emitLabel(beforeThen.get()); 1396 } else { 1397 RegisterID* cond = generator.emitNode(m_condition); 1398 generator.emitJumpIfFalse(cond, afterThen.get()); 1399 } 1348 1400 1349 1401 generator.emitNode(dst, m_ifBlock); … … 1363 1415 RefPtr<Label> afterElse = generator.newLabel(); 1364 1416 1365 RegisterID* cond = generator.emitNode(m_condition); 1366 generator.emitJumpIfFalse(cond, beforeElse.get()); 1417 if (m_condition->hasConditionContextCodegen()) { 1418 RefPtr<Label> beforeThen = generator.newLabel(); 1419 generator.emitNodeInConditionContext(m_condition, beforeThen.get(), beforeElse.get(), true); 1420 generator.emitLabel(beforeThen.get()); 1421 } else { 1422 RegisterID* cond = generator.emitNode(m_condition); 1423 generator.emitJumpIfFalse(cond, beforeElse.get()); 1424 } 1367 1425 1368 1426 generator.emitNode(dst, m_ifBlock); … … 1394 1452 generator.emitLabel(scope->continueTarget()); 1395 1453 generator.emitDebugHook(WillExecuteStatement, m_expr->lineNo(), m_expr->lineNo()); 1396 RegisterID* cond = generator.emitNode(m_expr); 1397 generator.emitJumpIfTrue(cond, topOfLoop.get()); 1454 if (m_expr->hasConditionContextCodegen()) 1455 generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), false); 1456 else { 1457 RegisterID* cond = generator.emitNode(m_expr); 1458 generator.emitJumpIfTrue(cond, topOfLoop.get()); 1459 } 1398 1460 1399 1461 generator.emitLabel(scope->breakTarget()); … … 1416 1478 generator.emitLabel(scope->continueTarget()); 1417 1479 generator.emitDebugHook(WillExecuteStatement, m_expr->lineNo(), m_expr->lineNo()); 1418 RegisterID* cond = generator.emitNode(m_expr); 1419 generator.emitJumpIfTrue(cond, topOfLoop.get()); 1480 1481 if (m_expr->hasConditionContextCodegen()) 1482 generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), false); 1483 else { 1484 RegisterID* cond = generator.emitNode(m_expr); 1485 generator.emitJumpIfTrue(cond, topOfLoop.get()); 1486 } 1420 1487 1421 1488 generator.emitLabel(scope->breakTarget()); … … 1451 1518 generator.emitLabel(condition.get()); 1452 1519 if (m_expr2) { 1453 RegisterID* cond = generator.emitNode(m_expr2); 1454 generator.emitJumpIfTrue(cond, topOfLoop.get()); 1520 if (m_expr2->hasConditionContextCodegen()) 1521 generator.emitNodeInConditionContext(m_expr2, topOfLoop.get(), scope->breakTarget(), false); 1522 else { 1523 RegisterID* cond = generator.emitNode(m_expr2); 1524 generator.emitJumpIfTrue(cond, topOfLoop.get()); 1525 } 1455 1526 } else 1456 1527 generator.emitJump(topOfLoop.get()); -
trunk/JavaScriptCore/parser/Nodes.h
r47775 r51735 41 41 class BytecodeGenerator; 42 42 class FunctionBodyNode; 43 class Label; 43 44 class PropertyListNode; 44 45 class ReadModifyResolveNode; … … 152 153 virtual bool isSimpleArray() const { return false; } 153 154 virtual bool isAdd() const { return false; } 155 virtual bool hasConditionContextCodegen() const { return false; } 156 157 virtual void emitBytecodeInConditionContext(BytecodeGenerator&, Label*, Label*, bool) { ASSERT_NOT_REACHED(); } 154 158 155 159 virtual ExpressionNode* stripUnaryPlus() { return this; } … … 758 762 protected: 759 763 ExpressionNode* expr() { return m_expr; } 764 const ExpressionNode* expr() const { return m_expr; } 760 765 761 766 private: … … 789 794 public: 790 795 LogicalNotNode(JSGlobalData*, ExpressionNode*); 796 private: 797 void emitBytecodeInConditionContext(BytecodeGenerator&, Label* trueTarget, Label* falseTarget, bool fallThroughMeansTrue); 798 virtual bool hasConditionContextCodegen() const { return expr()->hasConditionContextCodegen(); } 791 799 }; 792 800 … … 953 961 private: 954 962 virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); 963 void emitBytecodeInConditionContext(BytecodeGenerator&, Label* trueTarget, Label* falseTarget, bool fallThroughMeansTrue); 964 virtual bool hasConditionContextCodegen() const { return true; } 955 965 956 966 ExpressionNode* m_expr1; -
trunk/LayoutTests/ChangeLog
r51734 r51735 1 2009-12-05 Maciej Stachowiak <mjs@apple.com> 2 3 Reviewed by Oliver Hunt. 4 5 conway benchmark spends half it's time in op_less (jump fusion fails) 6 https://bugs.webkit.org/show_bug.cgi?id=32190 7 8 * fast/js/codegen-loops-logical-nodes-expected.txt: 9 * fast/js/script-tests/codegen-loops-logical-nodes.js: Update to test some newly 10 sensitive cases of codegen that were not already covered. 11 1 12 2009-12-05 Philippe Normand <pnormand@igalia.com> 2 13 -
trunk/LayoutTests/fast/js/codegen-loops-logical-nodes-expected.txt
r34758 r51735 28 28 PASS dowhile_and_less() is true 29 29 PASS dowhile_and_lesseq() is true 30 PASS while_not_or_eq() is false 31 PASS while_not_or_neq() is false 32 PASS while_not_or_less() is false 33 PASS while_not_or_lesseq() is false 34 PASS while_not_and_eq() is false 35 PASS while_not_and_neq() is false 36 PASS while_not_and_less() is false 37 PASS while_not_and_lesseq() is false 38 PASS for_not_or_eq() is false 39 PASS for_not_or_neq() is false 40 PASS for_not_or_less() is false 41 PASS for_not_or_lesseq() is false 42 PASS for_not_and_eq() is false 43 PASS for_not_and_neq() is false 44 PASS for_not_and_less() is false 45 PASS for_not_and_lesseq() is false 46 PASS dowhile_not_or_eq() is false 47 PASS dowhile_not_or_neq() is false 48 PASS dowhile_not_or_less() is false 49 PASS dowhile_not_or_lesseq() is false 50 PASS dowhile_not_and_eq() is false 51 PASS dowhile_not_and_neq() is false 52 PASS dowhile_not_and_less() is false 53 PASS dowhile_not_and_lesseq() is false 54 PASS float_while_or_eq() is true 55 PASS float_while_or_neq() is true 56 PASS float_while_or_less() is true 57 PASS float_while_or_lesseq() is true 58 PASS float_while_and_eq() is true 59 PASS float_while_and_neq() is true 60 PASS float_while_and_less() is true 61 PASS float_while_and_lesseq() is true 62 PASS float_for_or_eq() is true 63 PASS float_for_or_neq() is true 64 PASS float_for_or_less() is true 65 PASS float_for_or_lesseq() is true 66 PASS float_for_and_eq() is true 67 PASS float_for_and_neq() is true 68 PASS float_for_and_less() is true 69 PASS float_for_and_lesseq() is true 70 PASS float_dowhile_or_eq() is true 71 PASS float_dowhile_or_neq() is true 72 PASS float_dowhile_or_less() is true 73 PASS float_dowhile_or_lesseq() is true 74 PASS float_dowhile_and_eq() is true 75 PASS float_dowhile_and_neq() is true 76 PASS float_dowhile_and_less() is true 77 PASS float_dowhile_and_lesseq() is true 78 PASS float_while_not_or_eq() is false 79 PASS float_while_not_or_neq() is false 80 PASS float_while_not_or_less() is false 81 PASS float_while_not_or_lesseq() is false 82 PASS float_while_not_and_eq() is false 83 PASS float_while_not_and_neq() is false 84 PASS float_while_not_and_less() is false 85 PASS float_while_not_and_lesseq() is false 86 PASS float_for_not_or_eq() is false 87 PASS float_for_not_or_neq() is false 88 PASS float_for_not_or_less() is false 89 PASS float_for_not_or_lesseq() is false 90 PASS float_for_not_and_eq() is false 91 PASS float_for_not_and_neq() is false 92 PASS float_for_not_and_less() is false 93 PASS float_for_not_and_lesseq() is false 94 PASS float_dowhile_not_or_eq() is false 95 PASS float_dowhile_not_or_neq() is false 96 PASS float_dowhile_not_or_less() is false 97 PASS float_dowhile_not_or_lesseq() is false 98 PASS float_dowhile_not_and_eq() is false 99 PASS float_dowhile_not_and_neq() is false 100 PASS float_dowhile_not_and_less() is false 30 101 PASS successfullyParsed is true 31 102 -
trunk/LayoutTests/fast/js/script-tests/codegen-loops-logical-nodes.js
r48651 r51735 267 267 shouldBeTrue("dowhile_and_lesseq()"); 268 268 269 function while_not_or_eq() 270 { 271 var a = 0; 272 while (!(a == 0 || a == 0)) 273 return true; 274 return false; 275 } 276 277 shouldBeFalse("while_not_or_eq()"); 278 279 function while_not_or_neq() 280 { 281 var a = 0; 282 while (!(a != 1 || a != 1)) 283 return true; 284 return false; 285 } 286 287 shouldBeFalse("while_not_or_neq()"); 288 289 function while_not_or_less() 290 { 291 var a = 0; 292 while (!(a < 1 || a < 1)) 293 return true; 294 return false; 295 } 296 297 shouldBeFalse("while_not_or_less()"); 298 299 function while_not_or_lesseq() 300 { 301 var a = 0; 302 while (!(a <= 1 || a <= 1)) 303 return true; 304 return false; 305 } 306 307 shouldBeFalse("while_not_or_lesseq()"); 308 309 function while_not_and_eq() 310 { 311 var a = 0; 312 while (!(a == 0 && a == 0)) 313 return true; 314 return false; 315 } 316 317 shouldBeFalse("while_not_and_eq()"); 318 319 function while_not_and_neq() 320 { 321 var a = 0; 322 while (!(a != 1 && a != 1)) 323 return true; 324 return false; 325 } 326 327 shouldBeFalse("while_not_and_neq()"); 328 329 function while_not_and_less() 330 { 331 var a = 0; 332 while (!(a < 1 && a < 1)) 333 return true; 334 return false; 335 } 336 337 shouldBeFalse("while_not_and_less()"); 338 339 function while_not_and_lesseq() 340 { 341 var a = 0; 342 while (!(a <= 1 && a <= 1)) 343 return true; 344 return false; 345 } 346 347 shouldBeFalse("while_not_and_lesseq()"); 348 349 function for_not_or_eq() 350 { 351 for (var a = 0; !(a == 0 || a == 0); ) 352 return true; 353 return false; 354 } 355 356 shouldBeFalse("for_not_or_eq()"); 357 358 function for_not_or_neq() 359 { 360 for (var a = 0; !(a != 1 || a != 1); ) 361 return true; 362 return false; 363 } 364 365 shouldBeFalse("for_not_or_neq()"); 366 367 function for_not_or_less() 368 { 369 for (var a = 0; !(a < 1 || a < 1); ) 370 return true; 371 return false; 372 } 373 374 shouldBeFalse("for_not_or_less()"); 375 376 function for_not_or_lesseq() 377 { 378 for (var a = 0; !(a <= 1 || a <= 1); ) 379 return true; 380 return false; 381 } 382 383 shouldBeFalse("for_not_or_lesseq()"); 384 385 function for_not_and_eq() 386 { 387 for (var a = 0; !(a == 0 && a == 0); ) 388 return true; 389 return false; 390 } 391 392 shouldBeFalse("for_not_and_eq()"); 393 394 function for_not_and_neq() 395 { 396 for (var a = 0; !(a != 1 && a != 1); ) 397 return true; 398 return false; 399 } 400 401 shouldBeFalse("for_not_and_neq()"); 402 403 function for_not_and_less() 404 { 405 for (var a = 0; !(a < 1 && a < 1); ) 406 return true; 407 return false; 408 } 409 410 shouldBeFalse("for_not_and_less()"); 411 412 function for_not_and_lesseq() 413 { 414 for (var a = 0; !(a <= 1 && a <= 1); ) 415 return true; 416 return false; 417 } 418 419 shouldBeFalse("for_not_and_lesseq()"); 420 421 function dowhile_not_or_eq() 422 { 423 var a = 0; 424 var i = 0; 425 do { 426 if (i > 0) 427 return true; 428 i++; 429 } while (!(a == 0 || a == 0)) 430 return false; 431 } 432 433 shouldBeFalse("dowhile_not_or_eq()"); 434 435 function dowhile_not_or_neq() 436 { 437 var a = 0; 438 var i = 0; 439 do { 440 if (i > 0) 441 return true; 442 i++; 443 } while (!(a != 1 || a != 1)) 444 return false; 445 } 446 447 shouldBeFalse("dowhile_not_or_neq()"); 448 449 function dowhile_not_or_less() 450 { 451 var a = 0; 452 var i = 0; 453 do { 454 if (i > 0) 455 return true; 456 i++; 457 } while (!(a < 1 || a < 1)) 458 return false; 459 } 460 461 shouldBeFalse("dowhile_not_or_less()"); 462 463 function dowhile_not_or_lesseq() 464 { 465 var a = 0; 466 var i = 0; 467 do { 468 if (i > 0) 469 return true; 470 i++; 471 } while (!(a <= 1 || a <= 1)) 472 return false; 473 } 474 475 shouldBeFalse("dowhile_not_or_lesseq()"); 476 477 function dowhile_not_and_eq() 478 { 479 var a = 0; 480 var i = 0; 481 do { 482 if (i > 0) 483 return true; 484 i++; 485 } while (!(a == 0 && a == 0)) 486 return false; 487 } 488 489 shouldBeFalse("dowhile_not_and_eq()"); 490 491 function dowhile_not_and_neq() 492 { 493 var a = 0; 494 var i = 0; 495 do { 496 if (i > 0) 497 return true; 498 i++; 499 } while (!(a != 1 && a != 1)) 500 return false; 501 } 502 503 shouldBeFalse("dowhile_not_and_neq()"); 504 505 function dowhile_not_and_less() 506 { 507 var a = 0; 508 var i = 0; 509 do { 510 if (i > 0) 511 return true; 512 i++; 513 } while (!(a < 1 && a < 1)) 514 return false; 515 } 516 517 shouldBeFalse("dowhile_not_and_less()"); 518 519 function dowhile_not_and_lesseq() 520 { 521 var a = 0; 522 var i = 0; 523 do { 524 if (i > 0) 525 return true; 526 i++; 527 } while (!(a <= 1 && a <= 1)) 528 return false; 529 } 530 531 shouldBeFalse("dowhile_not_and_lesseq()"); 532 533 function float_while_or_eq() 534 { 535 var a = 0.1; 536 while (a == 0.1 || a == 0.1) 537 return true; 538 return false; 539 } 540 541 shouldBeTrue("float_while_or_eq()"); 542 543 function float_while_or_neq() 544 { 545 var a = 0.1; 546 while (a != 1.1 || a != 1.1) 547 return true; 548 return false; 549 } 550 551 shouldBeTrue("float_while_or_neq()"); 552 553 function float_while_or_less() 554 { 555 var a = 0.1; 556 while (a < 1.1 || a < 1.1) 557 return true; 558 return false; 559 } 560 561 shouldBeTrue("float_while_or_less()"); 562 563 function float_while_or_lesseq() 564 { 565 var a = 0.1; 566 while (a <= 1.1 || a <= 1.1) 567 return true; 568 return false; 569 } 570 571 shouldBeTrue("float_while_or_lesseq()"); 572 573 function float_while_and_eq() 574 { 575 var a = 0.1; 576 while (a == 0.1 && a == 0.1) 577 return true; 578 return false; 579 } 580 581 shouldBeTrue("float_while_and_eq()"); 582 583 function float_while_and_neq() 584 { 585 var a = 0.1; 586 while (a != 1.1 && a != 1.1) 587 return true; 588 return false; 589 } 590 591 shouldBeTrue("float_while_and_neq()"); 592 593 function float_while_and_less() 594 { 595 var a = 0.1; 596 while (a < 1.1 && a < 1.1) 597 return true; 598 return false; 599 } 600 601 shouldBeTrue("float_while_and_less()"); 602 603 function float_while_and_lesseq() 604 { 605 var a = 0.1; 606 while (a <= 1.1 && a <= 1.1) 607 return true; 608 return false; 609 } 610 611 shouldBeTrue("float_while_and_lesseq()"); 612 613 function float_for_or_eq() 614 { 615 for (var a = 0.1; a == 0.1 || a == 0.1; ) 616 return true; 617 return false; 618 } 619 620 shouldBeTrue("float_for_or_eq()"); 621 622 function float_for_or_neq() 623 { 624 for (var a = 0.1; a != 1.1 || a != 1.1; ) 625 return true; 626 return false; 627 } 628 629 shouldBeTrue("float_for_or_neq()"); 630 631 function float_for_or_less() 632 { 633 for (var a = 0.1; a < 1.1 || a < 1.1; ) 634 return true; 635 return false; 636 } 637 638 shouldBeTrue("float_for_or_less()"); 639 640 function float_for_or_lesseq() 641 { 642 for (var a = 0.1; a <= 1.1 || a <= 1.1; ) 643 return true; 644 return false; 645 } 646 647 shouldBeTrue("float_for_or_lesseq()"); 648 649 function float_for_and_eq() 650 { 651 for (var a = 0.1; a == 0.1 && a == 0.1; ) 652 return true; 653 return false; 654 } 655 656 shouldBeTrue("float_for_and_eq()"); 657 658 function float_for_and_neq() 659 { 660 for (var a = 0.1; a != 1.1 && a != 1.1; ) 661 return true; 662 return false; 663 } 664 665 shouldBeTrue("float_for_and_neq()"); 666 667 function float_for_and_less() 668 { 669 for (var a = 0.1; a < 1.1 && a < 1.1; ) 670 return true; 671 return false; 672 } 673 674 shouldBeTrue("float_for_and_less()"); 675 676 function float_for_and_lesseq() 677 { 678 for (var a = 0.1; a <= 1.1 && a <= 1.1; ) 679 return true; 680 return false; 681 } 682 683 shouldBeTrue("float_for_and_lesseq()"); 684 685 function float_dowhile_or_eq() 686 { 687 var a = 0.1; 688 var i = 0.1; 689 do { 690 if (i > 0.1) 691 return true; 692 i++; 693 } while (a == 0.1 || a == 0.1) 694 return false; 695 } 696 697 shouldBeTrue("float_dowhile_or_eq()"); 698 699 function float_dowhile_or_neq() 700 { 701 var a = 0.1; 702 var i = 0.1; 703 do { 704 if (i > 0.1) 705 return true; 706 i++; 707 } while (a != 1.1 || a != 1.1) 708 return false; 709 } 710 711 shouldBeTrue("float_dowhile_or_neq()"); 712 713 function float_dowhile_or_less() 714 { 715 var a = 0.1; 716 var i = 0.1; 717 do { 718 if (i > 0.1) 719 return true; 720 i++; 721 } while (a < 1.1 || a < 1.1) 722 return false; 723 } 724 725 shouldBeTrue("float_dowhile_or_less()"); 726 727 function float_dowhile_or_lesseq() 728 { 729 var a = 0.1; 730 var i = 0.1; 731 do { 732 if (i > 0.1) 733 return true; 734 i++; 735 } while (a <= 1.1 || a <= 1.1) 736 return false; 737 } 738 739 shouldBeTrue("float_dowhile_or_lesseq()"); 740 741 function float_dowhile_and_eq() 742 { 743 var a = 0.1; 744 var i = 0.1; 745 do { 746 if (i > 0.1) 747 return true; 748 i++; 749 } while (a == 0.1 && a == 0.1) 750 return false; 751 } 752 753 shouldBeTrue("float_dowhile_and_eq()"); 754 755 function float_dowhile_and_neq() 756 { 757 var a = 0.1; 758 var i = 0.1; 759 do { 760 if (i > 0.1) 761 return true; 762 i++; 763 } while (a != 1.1 && a != 1.1) 764 return false; 765 } 766 767 shouldBeTrue("float_dowhile_and_neq()"); 768 769 function float_dowhile_and_less() 770 { 771 var a = 0.1; 772 var i = 0.1; 773 do { 774 if (i > 0.1) 775 return true; 776 i++; 777 } while (a < 1.1 && a < 1.1) 778 return false; 779 } 780 781 shouldBeTrue("float_dowhile_and_less()"); 782 783 function float_dowhile_and_lesseq() 784 { 785 var a = 0.1; 786 var i = 0.1; 787 do { 788 if (i > 0.1) 789 return true; 790 i++; 791 } while (a <= 1.1 && a <= 1.1) 792 return false; 793 } 794 795 shouldBeTrue("float_dowhile_and_lesseq()"); 796 797 function float_while_not_or_eq() 798 { 799 var a = 0.1; 800 while (!(a == 0.1 || a == 0.1)) 801 return true; 802 return false; 803 } 804 805 shouldBeFalse("float_while_not_or_eq()"); 806 807 function float_while_not_or_neq() 808 { 809 var a = 0.1; 810 while (!(a != 1.1 || a != 1.1)) 811 return true; 812 return false; 813 } 814 815 shouldBeFalse("float_while_not_or_neq()"); 816 817 function float_while_not_or_less() 818 { 819 var a = 0.1; 820 while (!(a < 1.1 || a < 1.1)) 821 return true; 822 return false; 823 } 824 825 shouldBeFalse("float_while_not_or_less()"); 826 827 function float_while_not_or_lesseq() 828 { 829 var a = 0.1; 830 while (!(a <= 1.1 || a <= 1.1)) 831 return true; 832 return false; 833 } 834 835 shouldBeFalse("float_while_not_or_lesseq()"); 836 837 function float_while_not_and_eq() 838 { 839 var a = 0.1; 840 while (!(a == 0.1 && a == 0.1)) 841 return true; 842 return false; 843 } 844 845 shouldBeFalse("float_while_not_and_eq()"); 846 847 function float_while_not_and_neq() 848 { 849 var a = 0.1; 850 while (!(a != 1.1 && a != 1.1)) 851 return true; 852 return false; 853 } 854 855 shouldBeFalse("float_while_not_and_neq()"); 856 857 function float_while_not_and_less() 858 { 859 var a = 0.1; 860 while (!(a < 1.1 && a < 1.1)) 861 return true; 862 return false; 863 } 864 865 shouldBeFalse("float_while_not_and_less()"); 866 867 function float_while_not_and_lesseq() 868 { 869 var a = 0.1; 870 while (!(a <= 1.1 && a <= 1.1)) 871 return true; 872 return false; 873 } 874 875 shouldBeFalse("float_while_not_and_lesseq()"); 876 877 function float_for_not_or_eq() 878 { 879 for (var a = 0.1; !(a == 0.1 || a == 0.1); ) 880 return true; 881 return false; 882 } 883 884 shouldBeFalse("float_for_not_or_eq()"); 885 886 function float_for_not_or_neq() 887 { 888 for (var a = 0.1; !(a != 1.1 || a != 1.1); ) 889 return true; 890 return false; 891 } 892 893 shouldBeFalse("float_for_not_or_neq()"); 894 895 function float_for_not_or_less() 896 { 897 for (var a = 0.1; !(a < 1.1 || a < 1.1); ) 898 return true; 899 return false; 900 } 901 902 shouldBeFalse("float_for_not_or_less()"); 903 904 function float_for_not_or_lesseq() 905 { 906 for (var a = 0.1; !(a <= 1.1 || a <= 1.1); ) 907 return true; 908 return false; 909 } 910 911 shouldBeFalse("float_for_not_or_lesseq()"); 912 913 function float_for_not_and_eq() 914 { 915 for (var a = 0.1; !(a == 0.1 && a == 0.1); ) 916 return true; 917 return false; 918 } 919 920 shouldBeFalse("float_for_not_and_eq()"); 921 922 function float_for_not_and_neq() 923 { 924 for (var a = 0.1; !(a != 1.1 && a != 1.1); ) 925 return true; 926 return false; 927 } 928 929 shouldBeFalse("float_for_not_and_neq()"); 930 931 function float_for_not_and_less() 932 { 933 for (var a = 0.1; !(a < 1.1 && a < 1.1); ) 934 return true; 935 return false; 936 } 937 938 shouldBeFalse("float_for_not_and_less()"); 939 940 function float_for_not_and_lesseq() 941 { 942 for (var a = 0.1; !(a <= 1.1 && a <= 1.1); ) 943 return true; 944 return false; 945 } 946 947 shouldBeFalse("float_for_not_and_lesseq()"); 948 949 function float_dowhile_not_or_eq() 950 { 951 var a = 0.1; 952 var i = 0.1; 953 do { 954 if (i > 0.1) 955 return true; 956 i++; 957 } while (!(a == 0.1 || a == 0.1)) 958 return false; 959 } 960 961 shouldBeFalse("float_dowhile_not_or_eq()"); 962 963 function float_dowhile_not_or_neq() 964 { 965 var a = 0.1; 966 var i = 0.1; 967 do { 968 if (i > 0.1) 969 return true; 970 i++; 971 } while (!(a != 1.1 || a != 1.1)) 972 return false; 973 } 974 975 shouldBeFalse("float_dowhile_not_or_neq()"); 976 977 function float_dowhile_not_or_less() 978 { 979 var a = 0.1; 980 var i = 0.1; 981 do { 982 if (i > 0.1) 983 return true; 984 i++; 985 } while (!(a < 1.1 || a < 1.1)) 986 return false; 987 } 988 989 shouldBeFalse("float_dowhile_not_or_less()"); 990 991 function float_dowhile_not_or_lesseq() 992 { 993 var a = 0.1; 994 var i = 0.1; 995 do { 996 if (i > 0.1) 997 return true; 998 i++; 999 } while (!(a <= 1.1 || a <= 1.1)) 1000 return false; 1001 } 1002 1003 shouldBeFalse("float_dowhile_not_or_lesseq()"); 1004 1005 function float_dowhile_not_and_eq() 1006 { 1007 var a = 0.1; 1008 var i = 0.1; 1009 do { 1010 if (i > 0.1) 1011 return true; 1012 i++; 1013 } while (!(a == 0.1 && a == 0.1)) 1014 return false; 1015 } 1016 1017 shouldBeFalse("float_dowhile_not_and_eq()"); 1018 1019 function float_dowhile_not_and_neq() 1020 { 1021 var a = 0.1; 1022 var i = 0.1; 1023 do { 1024 if (i > 0.1) 1025 return true; 1026 i++; 1027 } while (!(a != 1.1 && a != 1.1)) 1028 return false; 1029 } 1030 1031 shouldBeFalse("float_dowhile_not_and_neq()"); 1032 1033 function float_dowhile_not_and_less() 1034 { 1035 var a = 0.1; 1036 var i = 0.1; 1037 do { 1038 if (i > 0.1) 1039 return true; 1040 i++; 1041 } while (!(a < 1.1 && a < 1.1)) 1042 return false; 1043 } 1044 1045 shouldBeFalse("float_dowhile_not_and_less()"); 1046 1047 function float_dowhile_not_and_lesseq() 1048 { 1049 var a = 0.1; 1050 var i = 0.1; 1051 do { 1052 if (i > 0.1) 1053 return true; 1054 i++; 1055 } while (!(a <= 1.1 && a <= 1.1)) 1056 return false; 1057 } 1058 269 1059 var successfullyParsed = true;
Note: See TracChangeset
for help on using the changeset viewer.