[SCM] WebKit Debian packaging branch, webkit-1.2, updated. upstream/1.1.90-6072-g9a69373

mjs at apple.com mjs at apple.com
Thu Apr 8 00:21:58 UTC 2010


The following commit has been merged in the webkit-1.2 branch:
commit a46c49cd9d3a36c5c7183860813fd02b6560a451
Author: mjs at apple.com <mjs at apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Sun Dec 6 09:42:03 2009 +0000

    2009-12-05  Maciej Stachowiak  <mjs at apple.com>
    
            Reviewed by Oliver Hunt.
    
            conway benchmark spends half it's time in op_less (jump fusion fails)
            https://bugs.webkit.org/show_bug.cgi?id=32190
    
            <1% speedup on SunSpider and V8
            2x speedup on "conway" benchmark
    
            Two optimizations:
            1) Improve codegen for logical operators &&, || and ! in a condition context
    
            When generating code for combinations of &&, || and !, in a
            condition context (i.e. in an if statement or loop condition), we
            used to produce a value, and then separately jump based on its
            truthiness. Now we pass the false and true targets in, and let the
            logical operators generate jumps directly. This helps in four
            ways:
    
            a) Individual clauses of a short-circuit logical operator can now
            jump directly to the then or else clause of an if statement (or to
            the top or exit of a loop) instead of jumping to a jump.
    
            b) It used to be that jump fusion with the condition of the first
            clause of a logical operator was inhibited, because the register
            was ref'd to be used later, in the actual condition jump; this no
            longer happens since a jump straight to the final target is
            generated directly.
    
            c) It used to be that jump fusion with the condition of the second
            clause of a logical operator was inhibited, because there was a
            jump target right after the second clause and before the actual
            condition jump. But now it's no longer necessary for the first
            clause to jump there so jump fusion is not blocked.
    
            d) We avoid generating excess mov statements in some cases.
    
            As a concrete example this source:
    
            if (!((x < q && y < q) || (t < q && z < q))) {
                // ...
            }
    
            Used to generate this bytecode:
    
            [  34] less              r1, r-15, r-19
            [  38] jfalse            r1, 7(->45)
            [  41] less              r1, r-16, r-19
            [  45] jtrue             r1, 14(->59)
            [  48] less              r1, r-17, r-19
            [  52] jfalse            r1, 7(->59)
            [  55] less              r1, r-18, r-19
            [  59] jtrue             r1, 17(->76)
    
            And now generates this bytecode (also taking advantage of the second optimization below):
    
            [  34] jnless            r-15, r-19, 8(->42)
            [  38] jless             r-16, r-19, 26(->64)
            [  42] jnless            r-17, r-19, 8(->50)
            [  46] jless             r-18, r-19, 18(->64)
    
            Note the jump fusion and the fact that there's less jump
            indirection - three of the four jumps go straight to the target
            clause instead of indirecting through another jump.
    
            2) Implement jless opcode to take advantage of the above, since we'll now often generate
            a less followed by a jtrue where fusion is not forbidden.
    
            * parser/Nodes.h:
            (JSC::ExpressionNode::hasConditionContextCodegen): Helper function to determine
            whether a node supports special conditional codegen. Return false as this is the default.
            (JSC::ExpressionNode::emitBytecodeInConditionContext): Assert not reached - only really
            defined for nodes that do have conditional codegen.
            (JSC::UnaryOpNode::expr): Add const version.
            (JSC::LogicalNotNode::hasConditionContextCodegen): Returne true only if subexpression
            supports it.
            (JSC::LogicalOpNode::hasConditionContextCodegen): Return true.
            * parser/Nodes.cpp:
            (JSC::LogicalNotNode::emitBytecodeInConditionContext): Implemented - just swap
            the true and false targets for the child node.
            (JSC::LogicalOpNode::emitBytecodeInConditionContext): Implemented - handle jumps
            directly, improving codegen quality. Also handles further nested conditional codegen.
            (JSC::ConditionalNode::emitBytecode): Use condition context codegen when available.
            (JSC::IfNode::emitBytecode): ditto
            (JSC::IfElseNode::emitBytecode): ditto
            (JSC::DoWhileNode::emitBytecode): ditto
            (JSC::WhileNode::emitBytecode): ditto
            (JSC::ForNode::emitBytecode): ditto
    
            * bytecode/Opcode.h:
            - Added loop_if_false opcode - needed now that falsey jumps can be backwards.
            - Added jless opcode to take advantage of new fusion opportunities.
            * bytecode/CodeBlock.cpp:
            (JSC::CodeBlock::dump): Handle above.
            * bytecompiler/BytecodeGenerator.cpp:
            (JSC::BytecodeGenerator::emitJumpIfTrue): Add peephole for less + jtrue ==> jless.
            (JSC::BytecodeGenerator::emitJumpIfFalse): Add handling of backwrds falsey jumps.
            * bytecompiler/BytecodeGenerator.h:
            (JSC::BytecodeGenerator::emitNodeInConditionContext): Wrapper to handle tracking of
            overly deep expressions etc.
            * interpreter/Interpreter.cpp:
            (JSC::Interpreter::privateExecute): Implement the two new opcodes (loop_if_false, jless).
            * jit/JIT.cpp:
            (JSC::JIT::privateCompileMainPass): Implement JIT support for the two new opcodes.
            (JSC::JIT::privateCompileSlowCases): ditto
            * jit/JIT.h:
            * jit/JITArithmetic.cpp:
            (JSC::JIT::emit_op_jless):
            (JSC::JIT::emitSlow_op_jless): ditto
            (JSC::JIT::emitBinaryDoubleOp): ditto
            * jit/JITOpcodes.cpp:
            (JSC::JIT::emitSlow_op_loop_if_less): ditto
            (JSC::JIT::emit_op_loop_if_false): ditto
            (JSC::JIT::emitSlow_op_loop_if_false): ditto
            * jit/JITStubs.cpp:
            * jit/JITStubs.h:
            (JSC::):
    2009-12-05  Maciej Stachowiak  <mjs at apple.com>
    
            Reviewed by Oliver Hunt.
    
            conway benchmark spends half it's time in op_less (jump fusion fails)
            https://bugs.webkit.org/show_bug.cgi?id=32190
    
            * fast/js/codegen-loops-logical-nodes-expected.txt:
            * fast/js/script-tests/codegen-loops-logical-nodes.js: Update to test some newly
            sensitive cases of codegen that were not already covered.
    
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@51735 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/JavaScriptCore/ChangeLog b/JavaScriptCore/ChangeLog
index 295eef3..42dc410 100644
--- a/JavaScriptCore/ChangeLog
+++ b/JavaScriptCore/ChangeLog
@@ -1,3 +1,122 @@
+2009-12-05  Maciej Stachowiak  <mjs at apple.com>
+
+        Reviewed by Oliver Hunt.
+
+        conway benchmark spends half it's time in op_less (jump fusion fails)
+        https://bugs.webkit.org/show_bug.cgi?id=32190
+
+        <1% speedup on SunSpider and V8
+        2x speedup on "conway" benchmark
+        
+        Two optimizations:
+        1) Improve codegen for logical operators &&, || and ! in a condition context
+        
+        When generating code for combinations of &&, || and !, in a
+        condition context (i.e. in an if statement or loop condition), we
+        used to produce a value, and then separately jump based on its
+        truthiness. Now we pass the false and true targets in, and let the
+        logical operators generate jumps directly. This helps in four
+        ways:
+
+        a) Individual clauses of a short-circuit logical operator can now
+        jump directly to the then or else clause of an if statement (or to
+        the top or exit of a loop) instead of jumping to a jump.
+        
+        b) It used to be that jump fusion with the condition of the first
+        clause of a logical operator was inhibited, because the register
+        was ref'd to be used later, in the actual condition jump; this no
+        longer happens since a jump straight to the final target is
+        generated directly.
+
+        c) It used to be that jump fusion with the condition of the second
+        clause of a logical operator was inhibited, because there was a
+        jump target right after the second clause and before the actual
+        condition jump. But now it's no longer necessary for the first
+        clause to jump there so jump fusion is not blocked.
+
+        d) We avoid generating excess mov statements in some cases.
+        
+        As a concrete example this source:
+        
+        if (!((x < q && y < q) || (t < q && z < q))) {
+            // ...
+        }
+        
+        Used to generate this bytecode:
+        
+        [  34] less              r1, r-15, r-19
+        [  38] jfalse            r1, 7(->45)
+        [  41] less              r1, r-16, r-19
+        [  45] jtrue             r1, 14(->59)
+        [  48] less              r1, r-17, r-19
+        [  52] jfalse            r1, 7(->59)
+        [  55] less              r1, r-18, r-19
+        [  59] jtrue             r1, 17(->76)
+        
+        And now generates this bytecode (also taking advantage of the second optimization below):
+        
+        [  34] jnless            r-15, r-19, 8(->42)
+        [  38] jless             r-16, r-19, 26(->64)
+        [  42] jnless            r-17, r-19, 8(->50)
+        [  46] jless             r-18, r-19, 18(->64)
+        
+        Note the jump fusion and the fact that there's less jump
+        indirection - three of the four jumps go straight to the target
+        clause instead of indirecting through another jump.
+        
+        2) Implement jless opcode to take advantage of the above, since we'll now often generate
+        a less followed by a jtrue where fusion is not forbidden.
+       
+        * parser/Nodes.h:
+        (JSC::ExpressionNode::hasConditionContextCodegen): Helper function to determine
+        whether a node supports special conditional codegen. Return false as this is the default.
+        (JSC::ExpressionNode::emitBytecodeInConditionContext): Assert not reached - only really
+        defined for nodes that do have conditional codegen.
+        (JSC::UnaryOpNode::expr): Add const version.
+        (JSC::LogicalNotNode::hasConditionContextCodegen): Returne true only if subexpression
+        supports it.
+        (JSC::LogicalOpNode::hasConditionContextCodegen): Return true.
+        * parser/Nodes.cpp:
+        (JSC::LogicalNotNode::emitBytecodeInConditionContext): Implemented - just swap
+        the true and false targets for the child node.
+        (JSC::LogicalOpNode::emitBytecodeInConditionContext): Implemented - handle jumps
+        directly, improving codegen quality. Also handles further nested conditional codegen.
+        (JSC::ConditionalNode::emitBytecode): Use condition context codegen when available.
+        (JSC::IfNode::emitBytecode): ditto
+        (JSC::IfElseNode::emitBytecode): ditto
+        (JSC::DoWhileNode::emitBytecode): ditto
+        (JSC::WhileNode::emitBytecode): ditto
+        (JSC::ForNode::emitBytecode): ditto
+
+        * bytecode/Opcode.h: 
+        - Added loop_if_false opcode - needed now that falsey jumps can be backwards.
+        - Added jless opcode to take advantage of new fusion opportunities.
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::dump): Handle above.
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::emitJumpIfTrue): Add peephole for less + jtrue ==> jless.
+        (JSC::BytecodeGenerator::emitJumpIfFalse): Add handling of backwrds falsey jumps.
+        * bytecompiler/BytecodeGenerator.h:
+        (JSC::BytecodeGenerator::emitNodeInConditionContext): Wrapper to handle tracking of
+        overly deep expressions etc.
+        * interpreter/Interpreter.cpp:
+        (JSC::Interpreter::privateExecute): Implement the two new opcodes (loop_if_false, jless).
+        * jit/JIT.cpp:
+        (JSC::JIT::privateCompileMainPass): Implement JIT support for the two new opcodes.
+        (JSC::JIT::privateCompileSlowCases): ditto
+        * jit/JIT.h:
+        * jit/JITArithmetic.cpp:
+        (JSC::JIT::emit_op_jless):
+        (JSC::JIT::emitSlow_op_jless): ditto
+        (JSC::JIT::emitBinaryDoubleOp): ditto
+        * jit/JITOpcodes.cpp:
+        (JSC::JIT::emitSlow_op_loop_if_less): ditto
+        (JSC::JIT::emit_op_loop_if_false): ditto
+        (JSC::JIT::emitSlow_op_loop_if_false): ditto
+        * jit/JITStubs.cpp:
+        * jit/JITStubs.h:
+        (JSC::):
+
 2009-12-04  Kent Hansen  <kent.hansen at nokia.com>
 
         Reviewed by Darin Adler.
diff --git a/JavaScriptCore/bytecode/CodeBlock.cpp b/JavaScriptCore/bytecode/CodeBlock.cpp
index 27b72f0..13bed8c 100644
--- a/JavaScriptCore/bytecode/CodeBlock.cpp
+++ b/JavaScriptCore/bytecode/CodeBlock.cpp
@@ -876,6 +876,10 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
             printConditionalJump(exec, begin, it, location, "loop_if_true");
             break;
         }
+        case op_loop_if_false: {
+            printConditionalJump(exec, begin, it, location, "loop_if_false");
+            break;
+        }
         case op_jfalse: {
             printConditionalJump(exec, begin, it, location, "jfalse");
             break;
@@ -916,6 +920,13 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
             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);
             break;
         }
+        case op_jless: {
+            int r0 = (++it)->u.operand;
+            int r1 = (++it)->u.operand;
+            int offset = (++it)->u.operand;
+            printf("[%4d] jless\t\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).c_str(), registerName(exec, r1).c_str(), offset, location + offset);
+            break;
+        }
         case op_loop_if_lesseq: {
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
diff --git a/JavaScriptCore/bytecode/Opcode.h b/JavaScriptCore/bytecode/Opcode.h
index 4facbef..e88f051 100644
--- a/JavaScriptCore/bytecode/Opcode.h
+++ b/JavaScriptCore/bytecode/Opcode.h
@@ -128,9 +128,11 @@ namespace JSC {
         macro(op_jneq_ptr, 4) \
         macro(op_jnless, 4) \
         macro(op_jnlesseq, 4) \
+        macro(op_jless, 4) \
         macro(op_jmp_scopes, 3) \
         macro(op_loop, 2) \
         macro(op_loop_if_true, 3) \
+        macro(op_loop_if_false, 3) \
         macro(op_loop_if_less, 4) \
         macro(op_loop_if_lesseq, 4) \
         macro(op_switch_imm, 4) \
diff --git a/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp b/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
index 04dae15..5e84ece 100644
--- a/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
+++ b/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
@@ -616,7 +616,7 @@ PassRefPtr<Label> BytecodeGenerator::emitJump(Label* target)
 
 PassRefPtr<Label> BytecodeGenerator::emitJumpIfTrue(RegisterID* cond, Label* target)
 {
-    if (m_lastOpcodeID == op_less && !target->isForward()) {
+    if (m_lastOpcodeID == op_less) {
         int dstIndex;
         int src1Index;
         int src2Index;
@@ -627,7 +627,7 @@ PassRefPtr<Label> BytecodeGenerator::emitJumpIfTrue(RegisterID* cond, Label* tar
             rewindBinaryOp();
 
             size_t begin = instructions().size();
-            emitOpcode(op_loop_if_less);
+            emitOpcode(target->isForward() ? op_jless : op_loop_if_less);
             instructions().append(src1Index);
             instructions().append(src2Index);
             instructions().append(target->bind(begin, instructions().size()));
@@ -692,9 +692,7 @@ PassRefPtr<Label> BytecodeGenerator::emitJumpIfTrue(RegisterID* cond, Label* tar
 
 PassRefPtr<Label> BytecodeGenerator::emitJumpIfFalse(RegisterID* cond, Label* target)
 {
-    ASSERT(target->isForward());
-
-    if (m_lastOpcodeID == op_less) {
+    if (m_lastOpcodeID == op_less && target->isForward()) {
         int dstIndex;
         int src1Index;
         int src2Index;
@@ -711,7 +709,7 @@ PassRefPtr<Label> BytecodeGenerator::emitJumpIfFalse(RegisterID* cond, Label* ta
             instructions().append(target->bind(begin, instructions().size()));
             return target;
         }
-    } else if (m_lastOpcodeID == op_lesseq) {
+    } else if (m_lastOpcodeID == op_lesseq && target->isForward()) {
         int dstIndex;
         int src1Index;
         int src2Index;
@@ -738,12 +736,12 @@ PassRefPtr<Label> BytecodeGenerator::emitJumpIfFalse(RegisterID* cond, Label* ta
             rewindUnaryOp();
 
             size_t begin = instructions().size();
-            emitOpcode(op_jtrue);
+            emitOpcode(target->isForward() ? op_jtrue : op_loop_if_true);
             instructions().append(srcIndex);
             instructions().append(target->bind(begin, instructions().size()));
             return target;
         }
-    } else if (m_lastOpcodeID == op_eq_null) {
+    } else if (m_lastOpcodeID == op_eq_null && target->isForward()) {
         int dstIndex;
         int srcIndex;
 
@@ -758,7 +756,7 @@ PassRefPtr<Label> BytecodeGenerator::emitJumpIfFalse(RegisterID* cond, Label* ta
             instructions().append(target->bind(begin, instructions().size()));
             return target;
         }
-    } else if (m_lastOpcodeID == op_neq_null) {
+    } else if (m_lastOpcodeID == op_neq_null && target->isForward()) {
         int dstIndex;
         int srcIndex;
 
@@ -776,7 +774,7 @@ PassRefPtr<Label> BytecodeGenerator::emitJumpIfFalse(RegisterID* cond, Label* ta
     }
 
     size_t begin = instructions().size();
-    emitOpcode(op_jfalse);
+    emitOpcode(target->isForward() ? op_jfalse : op_loop_if_false);
     instructions().append(cond->index());
     instructions().append(target->bind(begin, instructions().size()));
     return target;
diff --git a/JavaScriptCore/bytecompiler/BytecodeGenerator.h b/JavaScriptCore/bytecompiler/BytecodeGenerator.h
index 4648fb5..8b6a425 100644
--- a/JavaScriptCore/bytecompiler/BytecodeGenerator.h
+++ b/JavaScriptCore/bytecompiler/BytecodeGenerator.h
@@ -192,6 +192,19 @@ namespace JSC {
             return emitNode(0, n);
         }
 
+        void emitNodeInConditionContext(ExpressionNode* n, Label* trueTarget, Label* falseTarget, bool fallThroughMeansTrue)
+        {
+            if (!m_codeBlock->numberOfLineInfos() || m_codeBlock->lastLineInfo().lineNumber != n->lineNo()) {
+                LineInfo info = { instructions().size(), n->lineNo() };
+                m_codeBlock->addLineInfo(info);
+            }
+            if (m_emitNodeDepth >= s_maxEmitNodeDepth)
+                emitThrowExpressionTooDeepException();
+            ++m_emitNodeDepth;
+            n->emitBytecodeInConditionContext(*this, trueTarget, falseTarget, fallThroughMeansTrue);
+            --m_emitNodeDepth;
+        }
+
         void emitExpressionInfo(unsigned divot, unsigned startOffset, unsigned endOffset)
         { 
             divot -= m_codeBlock->sourceOffset();
diff --git a/JavaScriptCore/interpreter/Interpreter.cpp b/JavaScriptCore/interpreter/Interpreter.cpp
index ba3a7d9..1d69512 100644
--- a/JavaScriptCore/interpreter/Interpreter.cpp
+++ b/JavaScriptCore/interpreter/Interpreter.cpp
@@ -2647,6 +2647,26 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         vPC += OPCODE_LENGTH(op_loop_if_true);
         NEXT_INSTRUCTION();
     }
+    DEFINE_OPCODE(op_loop_if_false) {
+        /* loop_if_true cond(r) target(offset)
+         
+           Jumps to offset target from the current instruction, if and
+           only if register cond converts to boolean as false.
+
+           Additionally this loop instruction may terminate JS execution is
+           the JS timeout is reached.
+         */
+        int cond = vPC[1].u.operand;
+        int target = vPC[2].u.operand;
+        if (!callFrame->r(cond).jsValue().toBoolean(callFrame)) {
+            vPC += target;
+            CHECK_FOR_TIMEOUT();
+            NEXT_INSTRUCTION();
+        }
+        
+        vPC += OPCODE_LENGTH(op_loop_if_true);
+        NEXT_INSTRUCTION();
+    }
     DEFINE_OPCODE(op_jtrue) {
         /* jtrue cond(r) target(offset)
 
@@ -2810,6 +2830,29 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         vPC += OPCODE_LENGTH(op_jnless);
         NEXT_INSTRUCTION();
     }
+    DEFINE_OPCODE(op_jless) {
+        /* jless src1(r) src2(r) target(offset)
+
+           Checks whether register src1 is less than register src2, as
+           with the ECMAScript '<' operator, and then jumps to offset
+           target from the current instruction, if and only if the 
+           result of the comparison is true.
+        */
+        JSValue src1 = callFrame->r(vPC[1].u.operand).jsValue();
+        JSValue src2 = callFrame->r(vPC[2].u.operand).jsValue();
+        int target = vPC[3].u.operand;
+
+        bool result = jsLess(callFrame, src1, src2);
+        CHECK_FOR_EXCEPTION();
+        
+        if (result) {
+            vPC += target;
+            NEXT_INSTRUCTION();
+        }
+
+        vPC += OPCODE_LENGTH(op_jless);
+        NEXT_INSTRUCTION();
+    }
     DEFINE_OPCODE(op_jnlesseq) {
         /* jnlesseq src1(r) src2(r) target(offset)
 
diff --git a/JavaScriptCore/jit/JIT.cpp b/JavaScriptCore/jit/JIT.cpp
index c0d1258..585486f 100644
--- a/JavaScriptCore/jit/JIT.cpp
+++ b/JavaScriptCore/jit/JIT.cpp
@@ -250,6 +250,7 @@ void JIT::privateCompileMainPass()
         DEFINE_OP(op_jneq_null)
         DEFINE_OP(op_jneq_ptr)
         DEFINE_OP(op_jnless)
+        DEFINE_OP(op_jless)
         DEFINE_OP(op_jnlesseq)
         DEFINE_OP(op_jsr)
         DEFINE_OP(op_jtrue)
@@ -258,6 +259,7 @@ void JIT::privateCompileMainPass()
         DEFINE_OP(op_loop_if_less)
         DEFINE_OP(op_loop_if_lesseq)
         DEFINE_OP(op_loop_if_true)
+        DEFINE_OP(op_loop_if_false)
         DEFINE_OP(op_lshift)
         DEFINE_OP(op_method_check)
         DEFINE_OP(op_mod)
@@ -389,11 +391,13 @@ void JIT::privateCompileSlowCases()
         DEFINE_SLOWCASE_OP(op_instanceof)
         DEFINE_SLOWCASE_OP(op_jfalse)
         DEFINE_SLOWCASE_OP(op_jnless)
+        DEFINE_SLOWCASE_OP(op_jless)
         DEFINE_SLOWCASE_OP(op_jnlesseq)
         DEFINE_SLOWCASE_OP(op_jtrue)
         DEFINE_SLOWCASE_OP(op_loop_if_less)
         DEFINE_SLOWCASE_OP(op_loop_if_lesseq)
         DEFINE_SLOWCASE_OP(op_loop_if_true)
+        DEFINE_SLOWCASE_OP(op_loop_if_false)
         DEFINE_SLOWCASE_OP(op_lshift)
         DEFINE_SLOWCASE_OP(op_method_check)
         DEFINE_SLOWCASE_OP(op_mod)
diff --git a/JavaScriptCore/jit/JIT.h b/JavaScriptCore/jit/JIT.h
index c59a2fa..0b902b9 100644
--- a/JavaScriptCore/jit/JIT.h
+++ b/JavaScriptCore/jit/JIT.h
@@ -736,6 +736,7 @@ namespace JSC {
         void emit_op_jneq_null(Instruction*);
         void emit_op_jneq_ptr(Instruction*);
         void emit_op_jnless(Instruction*);
+        void emit_op_jless(Instruction*);
         void emit_op_jnlesseq(Instruction*);
         void emit_op_jsr(Instruction*);
         void emit_op_jtrue(Instruction*);
@@ -744,6 +745,7 @@ namespace JSC {
         void emit_op_loop_if_less(Instruction*);
         void emit_op_loop_if_lesseq(Instruction*);
         void emit_op_loop_if_true(Instruction*);
+        void emit_op_loop_if_false(Instruction*);
         void emit_op_lshift(Instruction*);
         void emit_op_method_check(Instruction*);
         void emit_op_mod(Instruction*);
@@ -818,11 +820,13 @@ namespace JSC {
         void emitSlow_op_instanceof(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_jfalse(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_jnless(Instruction*, Vector<SlowCaseEntry>::iterator&);
+        void emitSlow_op_jless(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_jnlesseq(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_jtrue(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_loop_if_less(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_loop_if_lesseq(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_loop_if_true(Instruction*, Vector<SlowCaseEntry>::iterator&);
+        void emitSlow_op_loop_if_false(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_lshift(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_method_check(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_mod(Instruction*, Vector<SlowCaseEntry>::iterator&);
diff --git a/JavaScriptCore/jit/JITArithmetic.cpp b/JavaScriptCore/jit/JITArithmetic.cpp
index 821ec0f..cef5188 100644
--- a/JavaScriptCore/jit/JITArithmetic.cpp
+++ b/JavaScriptCore/jit/JITArithmetic.cpp
@@ -148,6 +148,69 @@ void JIT::emitSlow_op_jnless(Instruction* currentInstruction, Vector<SlowCaseEnt
     emitJumpSlowToHot(branchTest32(Zero, regT0), target);
 }
 
+void JIT::emit_op_jless(Instruction* currentInstruction)
+{
+    unsigned op1 = currentInstruction[1].u.operand;
+    unsigned op2 = currentInstruction[2].u.operand;
+    unsigned target = currentInstruction[3].u.operand;
+
+    JumpList notInt32Op1;
+    JumpList notInt32Op2;
+
+    // Int32 less.
+    if (isOperandConstantImmediateInt(op1)) {
+        emitLoad(op2, regT3, regT2);
+        notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
+        addJump(branch32(GreaterThan, regT2, Imm32(getConstantOperand(op1).asInt32())), target);
+    } else if (isOperandConstantImmediateInt(op2)) {
+        emitLoad(op1, regT1, regT0);
+        notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
+        addJump(branch32(LessThan, regT0, Imm32(getConstantOperand(op2).asInt32())), target);
+    } else {
+        emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
+        notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
+        notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
+        addJump(branch32(LessThan, regT0, regT2), target);
+    }
+
+    if (!supportsFloatingPoint()) {
+        addSlowCase(notInt32Op1);
+        addSlowCase(notInt32Op2);
+        return;
+    }
+    Jump end = jump();
+
+    // Double less.
+    emitBinaryDoubleOp(op_jless, target, op1, op2, OperandTypes(), notInt32Op1, notInt32Op2, !isOperandConstantImmediateInt(op1), isOperandConstantImmediateInt(op1) || !isOperandConstantImmediateInt(op2));
+    end.link(this);
+}
+
+void JIT::emitSlow_op_jless(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+    unsigned op1 = currentInstruction[1].u.operand;
+    unsigned op2 = currentInstruction[2].u.operand;
+    unsigned target = currentInstruction[3].u.operand;
+
+    if (!supportsFloatingPoint()) {
+        if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2))
+            linkSlowCase(iter); // int32 check
+        linkSlowCase(iter); // int32 check
+    } else {
+        if (!isOperandConstantImmediateInt(op1)) {
+            linkSlowCase(iter); // double check
+            linkSlowCase(iter); // int32 check
+        }
+        if (isOperandConstantImmediateInt(op1) || !isOperandConstantImmediateInt(op2))
+            linkSlowCase(iter); // double check
+    }
+
+    JITStubCall stubCall(this, cti_op_jless);
+    stubCall.addArgument(op1);
+    stubCall.addArgument(op2);
+    stubCall.call();
+    emitJumpSlowToHot(branchTest32(NonZero, regT0), target);
+}
+
 void JIT::emit_op_jnlesseq(Instruction* currentInstruction)
 {
     unsigned op1 = currentInstruction[1].u.operand;
@@ -831,6 +894,10 @@ void JIT::emitBinaryDoubleOp(OpcodeID opcodeID, unsigned dst, unsigned op1, unsi
                 emitLoadDouble(op1, fpRegT2);
                 addJump(branchDouble(DoubleLessThanOrEqualOrUnordered, fpRegT0, fpRegT2), dst);
                 break;
+            case op_jless:
+                emitLoadDouble(op1, fpRegT2);
+                addJump(branchDouble(DoubleLessThan, fpRegT2, fpRegT0), dst);
+                break;
             case op_jnlesseq:
                 emitLoadDouble(op1, fpRegT2);
                 addJump(branchDouble(DoubleLessThanOrUnordered, fpRegT0, fpRegT2), dst);
@@ -884,6 +951,10 @@ void JIT::emitBinaryDoubleOp(OpcodeID opcodeID, unsigned dst, unsigned op1, unsi
                 emitLoadDouble(op2, fpRegT1);
                 addJump(branchDouble(DoubleLessThanOrEqualOrUnordered, fpRegT1, fpRegT0), dst);
                 break;
+            case op_jless:
+                emitLoadDouble(op2, fpRegT1);
+                addJump(branchDouble(DoubleLessThan, fpRegT0, fpRegT1), dst);
+                break;
             case op_jnlesseq:
                 emitLoadDouble(op2, fpRegT1);
                 addJump(branchDouble(DoubleLessThanOrUnordered, fpRegT1, fpRegT0), dst);
@@ -1455,6 +1526,191 @@ void JIT::emitSlow_op_jnless(Instruction* currentInstruction, Vector<SlowCaseEnt
     }
 }
 
+void JIT::emit_op_jless(Instruction* currentInstruction)
+{
+    unsigned op1 = currentInstruction[1].u.operand;
+    unsigned op2 = currentInstruction[2].u.operand;
+    unsigned target = currentInstruction[3].u.operand;
+
+    // We generate inline code for the following cases in the fast path:
+    // - int immediate to constant int immediate
+    // - constant int immediate to int immediate
+    // - int immediate to int immediate
+
+    if (isOperandConstantImmediateInt(op2)) {
+        emitGetVirtualRegister(op1, regT0);
+        emitJumpSlowCaseIfNotImmediateInteger(regT0);
+#if USE(JSVALUE64)
+        int32_t op2imm = getConstantOperandImmediateInt(op2);
+#else
+        int32_t op2imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2)));
+#endif
+        addJump(branch32(LessThan, regT0, Imm32(op2imm)), target);
+    } else if (isOperandConstantImmediateInt(op1)) {
+        emitGetVirtualRegister(op2, regT1);
+        emitJumpSlowCaseIfNotImmediateInteger(regT1);
+#if USE(JSVALUE64)
+        int32_t op1imm = getConstantOperandImmediateInt(op1);
+#else
+        int32_t op1imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op1)));
+#endif
+        addJump(branch32(GreaterThan, regT1, Imm32(op1imm)), target);
+    } else {
+        emitGetVirtualRegisters(op1, regT0, op2, regT1);
+        emitJumpSlowCaseIfNotImmediateInteger(regT0);
+        emitJumpSlowCaseIfNotImmediateInteger(regT1);
+
+        addJump(branch32(LessThan, regT0, regT1), target);
+    }
+}
+
+void JIT::emitSlow_op_jless(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+    unsigned op1 = currentInstruction[1].u.operand;
+    unsigned op2 = currentInstruction[2].u.operand;
+    unsigned target = currentInstruction[3].u.operand;
+
+    // We generate inline code for the following cases in the slow path:
+    // - floating-point number to constant int immediate
+    // - constant int immediate to floating-point number
+    // - floating-point number to floating-point number.
+
+    if (isOperandConstantImmediateInt(op2)) {
+        linkSlowCase(iter);
+
+        if (supportsFloatingPoint()) {
+#if USE(JSVALUE64)
+            Jump fail1 = emitJumpIfNotImmediateNumber(regT0);
+            addPtr(tagTypeNumberRegister, regT0);
+            movePtrToDouble(regT0, fpRegT0);
+#else
+            Jump fail1;
+            if (!m_codeBlock->isKnownNotImmediate(op1))
+                fail1 = emitJumpIfNotJSCell(regT0);
+
+            Jump fail2 = checkStructure(regT0, m_globalData->numberStructure.get());
+            loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0);
+#endif
+            
+            int32_t op2imm = getConstantOperand(op2).asInt32();
+                    
+            move(Imm32(op2imm), regT1);
+            convertInt32ToDouble(regT1, fpRegT1);
+
+            emitJumpSlowToHot(branchDouble(DoubleLessThan, fpRegT0, fpRegT1), target);
+
+            emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless));
+
+#if USE(JSVALUE64)
+            fail1.link(this);
+#else
+            if (!m_codeBlock->isKnownNotImmediate(op1))
+                fail1.link(this);
+            fail2.link(this);
+#endif
+        }
+
+        JITStubCall stubCall(this, cti_op_jless);
+        stubCall.addArgument(regT0);
+        stubCall.addArgument(op2, regT2);
+        stubCall.call();
+        emitJumpSlowToHot(branchTest32(Zero, regT0), target);
+
+    } else if (isOperandConstantImmediateInt(op1)) {
+        linkSlowCase(iter);
+
+        if (supportsFloatingPoint()) {
+#if USE(JSVALUE64)
+            Jump fail1 = emitJumpIfNotImmediateNumber(regT1);
+            addPtr(tagTypeNumberRegister, regT1);
+            movePtrToDouble(regT1, fpRegT1);
+#else
+            Jump fail1;
+            if (!m_codeBlock->isKnownNotImmediate(op2))
+                fail1 = emitJumpIfNotJSCell(regT1);
+            
+            Jump fail2 = checkStructure(regT1, m_globalData->numberStructure.get());
+            loadDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT1);
+#endif
+            
+            int32_t op1imm = getConstantOperand(op1).asInt32();
+                    
+            move(Imm32(op1imm), regT0);
+            convertInt32ToDouble(regT0, fpRegT0);
+
+            emitJumpSlowToHot(branchDouble(DoubleLessThan, fpRegT0, fpRegT1), target);
+
+            emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless));
+
+#if USE(JSVALUE64)
+            fail1.link(this);
+#else
+            if (!m_codeBlock->isKnownNotImmediate(op2))
+                fail1.link(this);
+            fail2.link(this);
+#endif
+        }
+
+        JITStubCall stubCall(this, cti_op_jless);
+        stubCall.addArgument(op1, regT2);
+        stubCall.addArgument(regT1);
+        stubCall.call();
+        emitJumpSlowToHot(branchTest32(Zero, regT0), target);
+
+    } else {
+        linkSlowCase(iter);
+
+        if (supportsFloatingPoint()) {
+#if USE(JSVALUE64)
+            Jump fail1 = emitJumpIfNotImmediateNumber(regT0);
+            Jump fail2 = emitJumpIfNotImmediateNumber(regT1);
+            Jump fail3 = emitJumpIfImmediateInteger(regT1);
+            addPtr(tagTypeNumberRegister, regT0);
+            addPtr(tagTypeNumberRegister, regT1);
+            movePtrToDouble(regT0, fpRegT0);
+            movePtrToDouble(regT1, fpRegT1);
+#else
+            Jump fail1;
+            if (!m_codeBlock->isKnownNotImmediate(op1))
+                fail1 = emitJumpIfNotJSCell(regT0);
+
+            Jump fail2;
+            if (!m_codeBlock->isKnownNotImmediate(op2))
+                fail2 = emitJumpIfNotJSCell(regT1);
+
+            Jump fail3 = checkStructure(regT0, m_globalData->numberStructure.get());
+            Jump fail4 = checkStructure(regT1, m_globalData->numberStructure.get());
+            loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0);
+            loadDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT1);
+#endif
+
+            emitJumpSlowToHot(branchDouble(DoubleLessThan, fpRegT0, fpRegT1), target);
+
+            emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless));
+
+#if USE(JSVALUE64)
+            fail1.link(this);
+            fail2.link(this);
+            fail3.link(this);
+#else
+            if (!m_codeBlock->isKnownNotImmediate(op1))
+                fail1.link(this);
+            if (!m_codeBlock->isKnownNotImmediate(op2))
+                fail2.link(this);
+            fail3.link(this);
+            fail4.link(this);
+#endif
+        }
+
+        linkSlowCase(iter);
+        JITStubCall stubCall(this, cti_op_jless);
+        stubCall.addArgument(regT0);
+        stubCall.addArgument(regT1);
+        stubCall.call();
+        emitJumpSlowToHot(branchTest32(NotZero, regT0), target);
+    }
+}
+
 void JIT::emit_op_jnlesseq(Instruction* currentInstruction)
 {
     unsigned op1 = currentInstruction[1].u.operand;
diff --git a/JavaScriptCore/jit/JITOpcodes.cpp b/JavaScriptCore/jit/JITOpcodes.cpp
index 991d4ca..aea552d 100644
--- a/JavaScriptCore/jit/JITOpcodes.cpp
+++ b/JavaScriptCore/jit/JITOpcodes.cpp
@@ -454,7 +454,7 @@ void JIT::emitSlow_op_loop_if_less(Instruction* currentInstruction, Vector<SlowC
         linkSlowCase(iter); // int32 check
     linkSlowCase(iter); // int32 check
 
-    JITStubCall stubCall(this, cti_op_loop_if_less);
+    JITStubCall stubCall(this, cti_op_jless);
     stubCall.addArgument(op1);
     stubCall.addArgument(op2);
     stubCall.call();
@@ -743,6 +743,50 @@ void JIT::emitSlow_op_loop_if_true(Instruction* currentInstruction, Vector<SlowC
     emitJumpSlowToHot(branchTest32(NonZero, regT0), target);
 }
 
+void JIT::emit_op_loop_if_false(Instruction* currentInstruction)
+{
+    unsigned cond = currentInstruction[1].u.operand;
+    unsigned target = currentInstruction[2].u.operand;
+
+    emitTimeoutCheck();
+
+    emitLoad(cond, regT1, regT0);
+
+    Jump isTrue = branch32(Equal, regT1, Imm32(JSValue::TrueTag));
+    addJump(branch32(Equal, regT1, Imm32(JSValue::FalseTag)), target);
+
+    Jump isNotInteger = branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag));
+    Jump isTrue2 = branch32(NotEqual, regT0, Imm32(0));
+    addJump(jump(), target);
+
+    if (supportsFloatingPoint()) {
+        isNotInteger.link(this);
+
+        addSlowCase(branch32(Above, regT1, Imm32(JSValue::LowestTag)));
+
+        zeroDouble(fpRegT0);
+        emitLoadDouble(cond, fpRegT1);
+        addJump(branchDouble(DoubleEqualOrUnordered, fpRegT0, fpRegT1), target);
+    } else
+        addSlowCase(isNotInteger);
+
+    isTrue.link(this);
+    isTrue2.link(this);
+}
+
+void JIT::emitSlow_op_loop_if_false(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+    unsigned cond = currentInstruction[1].u.operand;
+    unsigned target = currentInstruction[2].u.operand;
+
+    linkSlowCase(iter);
+
+    JITStubCall stubCall(this, cti_op_jtrue);
+    stubCall.addArgument(cond);
+    stubCall.call();
+    emitJumpSlowToHot(branchTest32(Zero, regT0), target);
+}
+
 void JIT::emit_op_resolve_base(Instruction* currentInstruction)
 {
     JITStubCall stubCall(this, cti_op_resolve_base);
diff --git a/JavaScriptCore/jit/JITStubs.cpp b/JavaScriptCore/jit/JITStubs.cpp
index 0316a86..adedf5b 100644
--- a/JavaScriptCore/jit/JITStubs.cpp
+++ b/JavaScriptCore/jit/JITStubs.cpp
@@ -1119,19 +1119,6 @@ DEFINE_STUB_FUNCTION(void, register_file_check)
     throwStackOverflowError(oldCallFrame, stackFrame.globalData, ReturnAddressPtr(oldCallFrame->returnPC()), STUB_RETURN_ADDRESS);
 }
 
-DEFINE_STUB_FUNCTION(int, op_loop_if_less)
-{
-    STUB_INIT_STACK_FRAME(stackFrame);
-
-    JSValue src1 = stackFrame.args[0].jsValue();
-    JSValue src2 = stackFrame.args[1].jsValue();
-    CallFrame* callFrame = stackFrame.callFrame;
-
-    bool result = jsLess(callFrame, src1, src2);
-    CHECK_FOR_EXCEPTION_AT_END();
-    return result;
-}
-
 DEFINE_STUB_FUNCTION(int, op_loop_if_lesseq)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
@@ -2097,19 +2084,6 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_lesseq)
     return JSValue::encode(result);
 }
 
-DEFINE_STUB_FUNCTION(int, op_loop_if_true)
-{
-    STUB_INIT_STACK_FRAME(stackFrame);
-
-    JSValue src1 = stackFrame.args[0].jsValue();
-
-    CallFrame* callFrame = stackFrame.callFrame;
-
-    bool result = src1.toBoolean(callFrame);
-    CHECK_FOR_EXCEPTION_AT_END();
-    return result;
-}
-    
 DEFINE_STUB_FUNCTION(int, op_load_varargs)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
diff --git a/JavaScriptCore/jit/JITStubs.h b/JavaScriptCore/jit/JITStubs.h
index a8ea127..f71dc9a 100644
--- a/JavaScriptCore/jit/JITStubs.h
+++ b/JavaScriptCore/jit/JITStubs.h
@@ -335,9 +335,7 @@ extern "C" {
     int JIT_STUB cti_op_jlesseq(STUB_ARGS_DECLARATION);
     int JIT_STUB cti_op_jtrue(STUB_ARGS_DECLARATION);
     int JIT_STUB cti_op_load_varargs(STUB_ARGS_DECLARATION);
-    int JIT_STUB cti_op_loop_if_less(STUB_ARGS_DECLARATION);
     int JIT_STUB cti_op_loop_if_lesseq(STUB_ARGS_DECLARATION);
-    int JIT_STUB cti_op_loop_if_true(STUB_ARGS_DECLARATION);
     int JIT_STUB cti_timeout_check(STUB_ARGS_DECLARATION);
     int JIT_STUB cti_has_property(STUB_ARGS_DECLARATION);
     void JIT_STUB cti_op_create_arguments(STUB_ARGS_DECLARATION);
diff --git a/JavaScriptCore/parser/Nodes.cpp b/JavaScriptCore/parser/Nodes.cpp
index 45009dc..bad6b0d 100644
--- a/JavaScriptCore/parser/Nodes.cpp
+++ b/JavaScriptCore/parser/Nodes.cpp
@@ -811,6 +811,18 @@ RegisterID* UnaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID*
     return generator.emitUnaryOp(opcodeID(), generator.finalDestination(dst), src);
 }
 
+
+// ------------------------------ LogicalNotNode -----------------------------------
+
+void LogicalNotNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, bool fallThroughMeansTrue)
+{
+    ASSERT(expr()->hasConditionContextCodegen());
+
+    // reverse the true and false targets
+    generator.emitNodeInConditionContext(expr(), falseTarget, trueTarget, !fallThroughMeansTrue);
+}
+
+
 // ------------------------------ Binary Operation Nodes -----------------------------------
 
 // BinaryOpNode::emitStrcat:
@@ -1017,6 +1029,34 @@ RegisterID* LogicalOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID
     return generator.moveToDestinationIfNeeded(dst, temp.get());
 }
 
+void LogicalOpNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, bool fallThroughMeansTrue)
+{
+    if (m_expr1->hasConditionContextCodegen()) {
+        RefPtr<Label> afterExpr1 = generator.newLabel();
+        if (m_operator == OpLogicalAnd)
+            generator.emitNodeInConditionContext(m_expr1, afterExpr1.get(), falseTarget, true);
+        else 
+            generator.emitNodeInConditionContext(m_expr1, trueTarget, afterExpr1.get(), false);
+        generator.emitLabel(afterExpr1.get());
+    } else {
+        RegisterID* temp = generator.emitNode(m_expr1);
+        if (m_operator == OpLogicalAnd)
+            generator.emitJumpIfFalse(temp, falseTarget);
+        else
+            generator.emitJumpIfTrue(temp, trueTarget);
+    }
+
+    if (m_expr2->hasConditionContextCodegen())
+        generator.emitNodeInConditionContext(m_expr2, trueTarget, falseTarget, fallThroughMeansTrue);
+    else {
+        RegisterID* temp = generator.emitNode(m_expr2);
+        if (fallThroughMeansTrue)
+            generator.emitJumpIfFalse(temp, falseTarget);
+        else
+            generator.emitJumpIfTrue(temp, trueTarget);
+    }
+}
+
 // ------------------------------ ConditionalNode ------------------------------
 
 RegisterID* ConditionalNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
@@ -1025,8 +1065,14 @@ RegisterID* ConditionalNode::emitBytecode(BytecodeGenerator& generator, Register
     RefPtr<Label> beforeElse = generator.newLabel();
     RefPtr<Label> afterElse = generator.newLabel();
 
-    RegisterID* cond = generator.emitNode(m_logical);
-    generator.emitJumpIfFalse(cond, beforeElse.get());
+    if (m_logical->hasConditionContextCodegen()) {
+        RefPtr<Label> beforeThen = generator.newLabel();
+        generator.emitNodeInConditionContext(m_logical, beforeThen.get(), beforeElse.get(), true);
+        generator.emitLabel(beforeThen.get());
+    } else {
+        RegisterID* cond = generator.emitNode(m_logical);
+        generator.emitJumpIfFalse(cond, beforeElse.get());
+    }
 
     generator.emitNode(newDst.get(), m_expr1);
     generator.emitJump(afterElse.get());
@@ -1343,8 +1389,14 @@ RegisterID* IfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
     
     RefPtr<Label> afterThen = generator.newLabel();
 
-    RegisterID* cond = generator.emitNode(m_condition);
-    generator.emitJumpIfFalse(cond, afterThen.get());
+    if (m_condition->hasConditionContextCodegen()) {
+        RefPtr<Label> beforeThen = generator.newLabel();
+        generator.emitNodeInConditionContext(m_condition, beforeThen.get(), afterThen.get(), true);
+        generator.emitLabel(beforeThen.get());
+    } else {
+        RegisterID* cond = generator.emitNode(m_condition);
+        generator.emitJumpIfFalse(cond, afterThen.get());
+    }
 
     generator.emitNode(dst, m_ifBlock);
     generator.emitLabel(afterThen.get());
@@ -1362,8 +1414,14 @@ RegisterID* IfElseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* d
     RefPtr<Label> beforeElse = generator.newLabel();
     RefPtr<Label> afterElse = generator.newLabel();
 
-    RegisterID* cond = generator.emitNode(m_condition);
-    generator.emitJumpIfFalse(cond, beforeElse.get());
+    if (m_condition->hasConditionContextCodegen()) {
+        RefPtr<Label> beforeThen = generator.newLabel();
+        generator.emitNodeInConditionContext(m_condition, beforeThen.get(), beforeElse.get(), true);
+        generator.emitLabel(beforeThen.get());
+    } else {
+        RegisterID* cond = generator.emitNode(m_condition);
+        generator.emitJumpIfFalse(cond, beforeElse.get());
+    }
 
     generator.emitNode(dst, m_ifBlock);
     generator.emitJump(afterElse.get());
@@ -1393,8 +1451,12 @@ RegisterID* DoWhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID*
 
     generator.emitLabel(scope->continueTarget());
     generator.emitDebugHook(WillExecuteStatement, m_expr->lineNo(), m_expr->lineNo());
-    RegisterID* cond = generator.emitNode(m_expr);
-    generator.emitJumpIfTrue(cond, topOfLoop.get());
+    if (m_expr->hasConditionContextCodegen())
+        generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), false);
+    else {
+        RegisterID* cond = generator.emitNode(m_expr);
+        generator.emitJumpIfTrue(cond, topOfLoop.get());
+    }
 
     generator.emitLabel(scope->breakTarget());
     return result.get();
@@ -1415,8 +1477,13 @@ RegisterID* WhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds
 
     generator.emitLabel(scope->continueTarget());
     generator.emitDebugHook(WillExecuteStatement, m_expr->lineNo(), m_expr->lineNo());
-    RegisterID* cond = generator.emitNode(m_expr);
-    generator.emitJumpIfTrue(cond, topOfLoop.get());
+
+    if (m_expr->hasConditionContextCodegen())
+        generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), false);
+    else {
+        RegisterID* cond = generator.emitNode(m_expr);
+        generator.emitJumpIfTrue(cond, topOfLoop.get());
+    }
 
     generator.emitLabel(scope->breakTarget());
     
@@ -1450,8 +1517,12 @@ RegisterID* ForNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
 
     generator.emitLabel(condition.get());
     if (m_expr2) {
-        RegisterID* cond = generator.emitNode(m_expr2);
-        generator.emitJumpIfTrue(cond, topOfLoop.get());
+        if (m_expr2->hasConditionContextCodegen())
+            generator.emitNodeInConditionContext(m_expr2, topOfLoop.get(), scope->breakTarget(), false);
+        else {
+            RegisterID* cond = generator.emitNode(m_expr2);
+            generator.emitJumpIfTrue(cond, topOfLoop.get());
+        }
     } else
         generator.emitJump(topOfLoop.get());
 
diff --git a/JavaScriptCore/parser/Nodes.h b/JavaScriptCore/parser/Nodes.h
index be84c4a..c216ea8 100644
--- a/JavaScriptCore/parser/Nodes.h
+++ b/JavaScriptCore/parser/Nodes.h
@@ -40,6 +40,7 @@ namespace JSC {
     class ArgumentListNode;
     class BytecodeGenerator;
     class FunctionBodyNode;
+    class Label;
     class PropertyListNode;
     class ReadModifyResolveNode;
     class RegisterID;
@@ -151,6 +152,9 @@ namespace JSC {
         virtual bool isCommaNode() const { return false; }
         virtual bool isSimpleArray() const { return false; }
         virtual bool isAdd() const { return false; }
+        virtual bool hasConditionContextCodegen() const { return false; }
+
+        virtual void emitBytecodeInConditionContext(BytecodeGenerator&, Label*, Label*, bool) { ASSERT_NOT_REACHED(); }
 
         virtual ExpressionNode* stripUnaryPlus() { return this; }
 
@@ -757,6 +761,7 @@ namespace JSC {
 
     protected:
         ExpressionNode* expr() { return m_expr; }
+        const ExpressionNode* expr() const { return m_expr; }
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
@@ -788,6 +793,9 @@ namespace JSC {
     class LogicalNotNode : public UnaryOpNode {
     public:
         LogicalNotNode(JSGlobalData*, ExpressionNode*);
+    private:
+        void emitBytecodeInConditionContext(BytecodeGenerator&, Label* trueTarget, Label* falseTarget, bool fallThroughMeansTrue);
+        virtual bool hasConditionContextCodegen() const { return expr()->hasConditionContextCodegen(); }
     };
 
     class BinaryOpNode : public ExpressionNode {
@@ -952,6 +960,8 @@ namespace JSC {
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+        void emitBytecodeInConditionContext(BytecodeGenerator&, Label* trueTarget, Label* falseTarget, bool fallThroughMeansTrue);
+        virtual bool hasConditionContextCodegen() const { return true; }
 
         ExpressionNode* m_expr1;
         ExpressionNode* m_expr2;
diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index 8fb56df..ebb2ec0 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,14 @@
+2009-12-05  Maciej Stachowiak  <mjs at apple.com>
+
+        Reviewed by Oliver Hunt.
+
+        conway benchmark spends half it's time in op_less (jump fusion fails)
+        https://bugs.webkit.org/show_bug.cgi?id=32190
+
+        * fast/js/codegen-loops-logical-nodes-expected.txt:
+        * fast/js/script-tests/codegen-loops-logical-nodes.js: Update to test some newly
+        sensitive cases of codegen that were not already covered.
+
 2009-12-05  Philippe Normand  <pnormand at igalia.com>
 
         Reviewed by Gustavo Noronha.
diff --git a/LayoutTests/fast/js/codegen-loops-logical-nodes-expected.txt b/LayoutTests/fast/js/codegen-loops-logical-nodes-expected.txt
index f38497a..641b77a 100644
--- a/LayoutTests/fast/js/codegen-loops-logical-nodes-expected.txt
+++ b/LayoutTests/fast/js/codegen-loops-logical-nodes-expected.txt
@@ -27,6 +27,77 @@ PASS dowhile_and_eq() is true
 PASS dowhile_and_neq() is true
 PASS dowhile_and_less() is true
 PASS dowhile_and_lesseq() is true
+PASS while_not_or_eq() is false
+PASS while_not_or_neq() is false
+PASS while_not_or_less() is false
+PASS while_not_or_lesseq() is false
+PASS while_not_and_eq() is false
+PASS while_not_and_neq() is false
+PASS while_not_and_less() is false
+PASS while_not_and_lesseq() is false
+PASS for_not_or_eq() is false
+PASS for_not_or_neq() is false
+PASS for_not_or_less() is false
+PASS for_not_or_lesseq() is false
+PASS for_not_and_eq() is false
+PASS for_not_and_neq() is false
+PASS for_not_and_less() is false
+PASS for_not_and_lesseq() is false
+PASS dowhile_not_or_eq() is false
+PASS dowhile_not_or_neq() is false
+PASS dowhile_not_or_less() is false
+PASS dowhile_not_or_lesseq() is false
+PASS dowhile_not_and_eq() is false
+PASS dowhile_not_and_neq() is false
+PASS dowhile_not_and_less() is false
+PASS dowhile_not_and_lesseq() is false
+PASS float_while_or_eq() is true
+PASS float_while_or_neq() is true
+PASS float_while_or_less() is true
+PASS float_while_or_lesseq() is true
+PASS float_while_and_eq() is true
+PASS float_while_and_neq() is true
+PASS float_while_and_less() is true
+PASS float_while_and_lesseq() is true
+PASS float_for_or_eq() is true
+PASS float_for_or_neq() is true
+PASS float_for_or_less() is true
+PASS float_for_or_lesseq() is true
+PASS float_for_and_eq() is true
+PASS float_for_and_neq() is true
+PASS float_for_and_less() is true
+PASS float_for_and_lesseq() is true
+PASS float_dowhile_or_eq() is true
+PASS float_dowhile_or_neq() is true
+PASS float_dowhile_or_less() is true
+PASS float_dowhile_or_lesseq() is true
+PASS float_dowhile_and_eq() is true
+PASS float_dowhile_and_neq() is true
+PASS float_dowhile_and_less() is true
+PASS float_dowhile_and_lesseq() is true
+PASS float_while_not_or_eq() is false
+PASS float_while_not_or_neq() is false
+PASS float_while_not_or_less() is false
+PASS float_while_not_or_lesseq() is false
+PASS float_while_not_and_eq() is false
+PASS float_while_not_and_neq() is false
+PASS float_while_not_and_less() is false
+PASS float_while_not_and_lesseq() is false
+PASS float_for_not_or_eq() is false
+PASS float_for_not_or_neq() is false
+PASS float_for_not_or_less() is false
+PASS float_for_not_or_lesseq() is false
+PASS float_for_not_and_eq() is false
+PASS float_for_not_and_neq() is false
+PASS float_for_not_and_less() is false
+PASS float_for_not_and_lesseq() is false
+PASS float_dowhile_not_or_eq() is false
+PASS float_dowhile_not_or_neq() is false
+PASS float_dowhile_not_or_less() is false
+PASS float_dowhile_not_or_lesseq() is false
+PASS float_dowhile_not_and_eq() is false
+PASS float_dowhile_not_and_neq() is false
+PASS float_dowhile_not_and_less() is false
 PASS successfullyParsed is true
 
 TEST COMPLETE
diff --git a/LayoutTests/fast/js/script-tests/codegen-loops-logical-nodes.js b/LayoutTests/fast/js/script-tests/codegen-loops-logical-nodes.js
index 4d255e2..2f8a3e0 100644
--- a/LayoutTests/fast/js/script-tests/codegen-loops-logical-nodes.js
+++ b/LayoutTests/fast/js/script-tests/codegen-loops-logical-nodes.js
@@ -266,4 +266,794 @@ function dowhile_and_lesseq()
 
 shouldBeTrue("dowhile_and_lesseq()");
 
+function while_not_or_eq()
+{
+    var a = 0;
+    while (!(a == 0 || a == 0))
+        return true;
+    return false;
+}
+
+shouldBeFalse("while_not_or_eq()");
+
+function while_not_or_neq()
+{
+    var a = 0;
+    while (!(a != 1 || a != 1))
+        return true;
+    return false;
+}
+
+shouldBeFalse("while_not_or_neq()");
+
+function while_not_or_less()
+{
+    var a = 0;
+    while (!(a < 1 || a < 1))
+        return true;
+    return false;
+}
+
+shouldBeFalse("while_not_or_less()");
+
+function while_not_or_lesseq()
+{
+    var a = 0;
+    while (!(a <= 1 || a <= 1))
+        return true;
+    return false;
+}
+
+shouldBeFalse("while_not_or_lesseq()");
+
+function while_not_and_eq()
+{
+    var a = 0;
+    while (!(a == 0 && a == 0))
+        return true;
+    return false;
+}
+
+shouldBeFalse("while_not_and_eq()");
+
+function while_not_and_neq()
+{
+    var a = 0;
+    while (!(a != 1 && a != 1))
+        return true;
+    return false;
+}
+
+shouldBeFalse("while_not_and_neq()");
+
+function while_not_and_less()
+{
+    var a = 0;
+    while (!(a < 1 && a < 1))
+        return true;
+    return false;
+}
+
+shouldBeFalse("while_not_and_less()");
+
+function while_not_and_lesseq()
+{
+    var a = 0;
+    while (!(a <= 1 && a <= 1))
+        return true;
+    return false;
+}
+
+shouldBeFalse("while_not_and_lesseq()");
+
+function for_not_or_eq()
+{
+    for (var a = 0; !(a == 0 || a == 0); )
+        return true;
+    return false;
+}
+
+shouldBeFalse("for_not_or_eq()");
+
+function for_not_or_neq()
+{
+    for (var a = 0; !(a != 1 || a != 1); )
+        return true;
+    return false;
+}
+
+shouldBeFalse("for_not_or_neq()");
+
+function for_not_or_less()
+{
+    for (var a = 0; !(a < 1 || a < 1); )
+        return true;
+    return false;
+}
+
+shouldBeFalse("for_not_or_less()");
+
+function for_not_or_lesseq()
+{
+    for (var a = 0; !(a <= 1 || a <= 1); )
+        return true;
+    return false;
+}
+
+shouldBeFalse("for_not_or_lesseq()");
+
+function for_not_and_eq()
+{
+    for (var a = 0; !(a == 0 && a == 0); )
+        return true;
+    return false;
+}
+
+shouldBeFalse("for_not_and_eq()");
+
+function for_not_and_neq()
+{
+    for (var a = 0; !(a != 1 && a != 1); )
+        return true;
+    return false;
+}
+
+shouldBeFalse("for_not_and_neq()");
+
+function for_not_and_less()
+{
+    for (var a = 0; !(a < 1 && a < 1); )
+        return true;
+    return false;
+}
+
+shouldBeFalse("for_not_and_less()");
+
+function for_not_and_lesseq()
+{
+    for (var a = 0; !(a <= 1 && a <= 1); )
+        return true;
+    return false;
+}
+
+shouldBeFalse("for_not_and_lesseq()");
+
+function dowhile_not_or_eq()
+{
+    var a = 0;
+    var i = 0;
+    do {
+        if (i > 0)
+            return true;
+        i++;
+    } while (!(a == 0 || a == 0))
+    return false;
+}
+
+shouldBeFalse("dowhile_not_or_eq()");
+
+function dowhile_not_or_neq()
+{
+    var a = 0;
+    var i = 0;
+    do {
+        if (i > 0)
+            return true;
+        i++;
+    } while (!(a != 1 || a != 1))
+    return false;
+}
+
+shouldBeFalse("dowhile_not_or_neq()");
+
+function dowhile_not_or_less()
+{
+    var a = 0;
+    var i = 0;
+    do {
+        if (i > 0)
+            return true;
+        i++;
+    } while (!(a < 1 || a < 1))
+    return false;
+}
+
+shouldBeFalse("dowhile_not_or_less()");
+
+function dowhile_not_or_lesseq()
+{
+    var a = 0;
+    var i = 0;
+    do {
+        if (i > 0)
+            return true;
+        i++;
+    } while (!(a <= 1 || a <= 1))
+    return false;
+}
+
+shouldBeFalse("dowhile_not_or_lesseq()");
+
+function dowhile_not_and_eq()
+{
+    var a = 0;
+    var i = 0;
+    do {
+        if (i > 0)
+            return true;
+        i++;
+    } while (!(a == 0 && a == 0))
+    return false;
+}
+
+shouldBeFalse("dowhile_not_and_eq()");
+
+function dowhile_not_and_neq()
+{
+    var a = 0;
+    var i = 0;
+    do {
+        if (i > 0)
+            return true;
+        i++;
+    } while (!(a != 1 && a != 1))
+    return false;
+}
+
+shouldBeFalse("dowhile_not_and_neq()");
+
+function dowhile_not_and_less()
+{
+    var a = 0;
+    var i = 0;
+    do {
+        if (i > 0)
+            return true;
+        i++;
+    } while (!(a < 1 && a < 1))
+    return false;
+}
+
+shouldBeFalse("dowhile_not_and_less()");
+
+function dowhile_not_and_lesseq()
+{
+    var a = 0;
+    var i = 0;
+    do {
+        if (i > 0)
+            return true;
+        i++;
+    } while (!(a <= 1 && a <= 1))
+    return false;
+}
+
+shouldBeFalse("dowhile_not_and_lesseq()");
+
+function float_while_or_eq()
+{
+    var a = 0.1;
+    while (a == 0.1 || a == 0.1)
+        return true;
+    return false;
+}
+
+shouldBeTrue("float_while_or_eq()");
+
+function float_while_or_neq()
+{
+    var a = 0.1;
+    while (a != 1.1 || a != 1.1)
+        return true;
+    return false;
+}
+
+shouldBeTrue("float_while_or_neq()");
+
+function float_while_or_less()
+{
+    var a = 0.1;
+    while (a < 1.1 || a < 1.1)
+        return true;
+    return false;
+}
+
+shouldBeTrue("float_while_or_less()");
+
+function float_while_or_lesseq()
+{
+    var a = 0.1;
+    while (a <= 1.1 || a <= 1.1)
+        return true;
+    return false;
+}
+
+shouldBeTrue("float_while_or_lesseq()");
+
+function float_while_and_eq()
+{
+    var a = 0.1;
+    while (a == 0.1 && a == 0.1)
+        return true;
+    return false;
+}
+
+shouldBeTrue("float_while_and_eq()");
+
+function float_while_and_neq()
+{
+    var a = 0.1;
+    while (a != 1.1 && a != 1.1)
+        return true;
+    return false;
+}
+
+shouldBeTrue("float_while_and_neq()");
+
+function float_while_and_less()
+{
+    var a = 0.1;
+    while (a < 1.1 && a < 1.1)
+        return true;
+    return false;
+}
+
+shouldBeTrue("float_while_and_less()");
+
+function float_while_and_lesseq()
+{
+    var a = 0.1;
+    while (a <= 1.1 && a <= 1.1)
+        return true;
+    return false;
+}
+
+shouldBeTrue("float_while_and_lesseq()");
+
+function float_for_or_eq()
+{
+    for (var a = 0.1; a == 0.1 || a == 0.1; )
+        return true;
+    return false;
+}
+
+shouldBeTrue("float_for_or_eq()");
+
+function float_for_or_neq()
+{
+    for (var a = 0.1; a != 1.1 || a != 1.1; )
+        return true;
+    return false;
+}
+
+shouldBeTrue("float_for_or_neq()");
+
+function float_for_or_less()
+{
+    for (var a = 0.1; a < 1.1 || a < 1.1; )
+        return true;
+    return false;
+}
+
+shouldBeTrue("float_for_or_less()");
+
+function float_for_or_lesseq()
+{
+    for (var a = 0.1; a <= 1.1 || a <= 1.1; )
+        return true;
+    return false;
+}
+
+shouldBeTrue("float_for_or_lesseq()");
+
+function float_for_and_eq()
+{
+    for (var a = 0.1; a == 0.1 && a == 0.1; )
+        return true;
+    return false;
+}
+
+shouldBeTrue("float_for_and_eq()");
+
+function float_for_and_neq()
+{
+    for (var a = 0.1; a != 1.1 && a != 1.1; )
+        return true;
+    return false;
+}
+
+shouldBeTrue("float_for_and_neq()");
+
+function float_for_and_less()
+{
+    for (var a = 0.1; a < 1.1 && a < 1.1; )
+        return true;
+    return false;
+}
+
+shouldBeTrue("float_for_and_less()");
+
+function float_for_and_lesseq()
+{
+    for (var a = 0.1; a <= 1.1 && a <= 1.1; )
+        return true;
+    return false;
+}
+
+shouldBeTrue("float_for_and_lesseq()");
+
+function float_dowhile_or_eq()
+{
+    var a = 0.1;
+    var i = 0.1;
+    do {
+        if (i > 0.1)
+            return true;
+        i++;
+    } while (a == 0.1 || a == 0.1)
+    return false;
+}
+
+shouldBeTrue("float_dowhile_or_eq()");
+
+function float_dowhile_or_neq()
+{
+    var a = 0.1;
+    var i = 0.1;
+    do {
+        if (i > 0.1)
+            return true;
+        i++;
+    } while (a != 1.1 || a != 1.1)
+    return false;
+}
+
+shouldBeTrue("float_dowhile_or_neq()");
+
+function float_dowhile_or_less()
+{
+    var a = 0.1;
+    var i = 0.1;
+    do {
+        if (i > 0.1)
+            return true;
+        i++;
+    } while (a < 1.1 || a < 1.1)
+    return false;
+}
+
+shouldBeTrue("float_dowhile_or_less()");
+
+function float_dowhile_or_lesseq()
+{
+    var a = 0.1;
+    var i = 0.1;
+    do {
+        if (i > 0.1)
+            return true;
+        i++;
+    } while (a <= 1.1 || a <= 1.1)
+    return false;
+}
+
+shouldBeTrue("float_dowhile_or_lesseq()");
+
+function float_dowhile_and_eq()
+{
+    var a = 0.1;
+    var i = 0.1;
+    do {
+        if (i > 0.1)
+            return true;
+        i++;
+    } while (a == 0.1 && a == 0.1)
+    return false;
+}
+
+shouldBeTrue("float_dowhile_and_eq()");
+
+function float_dowhile_and_neq()
+{
+    var a = 0.1;
+    var i = 0.1;
+    do {
+        if (i > 0.1)
+            return true;
+        i++;
+    } while (a != 1.1 && a != 1.1)
+    return false;
+}
+
+shouldBeTrue("float_dowhile_and_neq()");
+
+function float_dowhile_and_less()
+{
+    var a = 0.1;
+    var i = 0.1;
+    do {
+        if (i > 0.1)
+            return true;
+        i++;
+    } while (a < 1.1 && a < 1.1)
+    return false;
+}
+
+shouldBeTrue("float_dowhile_and_less()");
+
+function float_dowhile_and_lesseq()
+{
+    var a = 0.1;
+    var i = 0.1;
+    do {
+        if (i > 0.1)
+            return true;
+        i++;
+    } while (a <= 1.1 && a <= 1.1)
+    return false;
+}
+
+shouldBeTrue("float_dowhile_and_lesseq()");
+
+function float_while_not_or_eq()
+{
+    var a = 0.1;
+    while (!(a == 0.1 || a == 0.1))
+        return true;
+    return false;
+}
+
+shouldBeFalse("float_while_not_or_eq()");
+
+function float_while_not_or_neq()
+{
+    var a = 0.1;
+    while (!(a != 1.1 || a != 1.1))
+        return true;
+    return false;
+}
+
+shouldBeFalse("float_while_not_or_neq()");
+
+function float_while_not_or_less()
+{
+    var a = 0.1;
+    while (!(a < 1.1 || a < 1.1))
+        return true;
+    return false;
+}
+
+shouldBeFalse("float_while_not_or_less()");
+
+function float_while_not_or_lesseq()
+{
+    var a = 0.1;
+    while (!(a <= 1.1 || a <= 1.1))
+        return true;
+    return false;
+}
+
+shouldBeFalse("float_while_not_or_lesseq()");
+
+function float_while_not_and_eq()
+{
+    var a = 0.1;
+    while (!(a == 0.1 && a == 0.1))
+        return true;
+    return false;
+}
+
+shouldBeFalse("float_while_not_and_eq()");
+
+function float_while_not_and_neq()
+{
+    var a = 0.1;
+    while (!(a != 1.1 && a != 1.1))
+        return true;
+    return false;
+}
+
+shouldBeFalse("float_while_not_and_neq()");
+
+function float_while_not_and_less()
+{
+    var a = 0.1;
+    while (!(a < 1.1 && a < 1.1))
+        return true;
+    return false;
+}
+
+shouldBeFalse("float_while_not_and_less()");
+
+function float_while_not_and_lesseq()
+{
+    var a = 0.1;
+    while (!(a <= 1.1 && a <= 1.1))
+        return true;
+    return false;
+}
+
+shouldBeFalse("float_while_not_and_lesseq()");
+
+function float_for_not_or_eq()
+{
+    for (var a = 0.1; !(a == 0.1 || a == 0.1); )
+        return true;
+    return false;
+}
+
+shouldBeFalse("float_for_not_or_eq()");
+
+function float_for_not_or_neq()
+{
+    for (var a = 0.1; !(a != 1.1 || a != 1.1); )
+        return true;
+    return false;
+}
+
+shouldBeFalse("float_for_not_or_neq()");
+
+function float_for_not_or_less()
+{
+    for (var a = 0.1; !(a < 1.1 || a < 1.1); )
+        return true;
+    return false;
+}
+
+shouldBeFalse("float_for_not_or_less()");
+
+function float_for_not_or_lesseq()
+{
+    for (var a = 0.1; !(a <= 1.1 || a <= 1.1); )
+        return true;
+    return false;
+}
+
+shouldBeFalse("float_for_not_or_lesseq()");
+
+function float_for_not_and_eq()
+{
+    for (var a = 0.1; !(a == 0.1 && a == 0.1); )
+        return true;
+    return false;
+}
+
+shouldBeFalse("float_for_not_and_eq()");
+
+function float_for_not_and_neq()
+{
+    for (var a = 0.1; !(a != 1.1 && a != 1.1); )
+        return true;
+    return false;
+}
+
+shouldBeFalse("float_for_not_and_neq()");
+
+function float_for_not_and_less()
+{
+    for (var a = 0.1; !(a < 1.1 && a < 1.1); )
+        return true;
+    return false;
+}
+
+shouldBeFalse("float_for_not_and_less()");
+
+function float_for_not_and_lesseq()
+{
+    for (var a = 0.1; !(a <= 1.1 && a <= 1.1); )
+        return true;
+    return false;
+}
+
+shouldBeFalse("float_for_not_and_lesseq()");
+
+function float_dowhile_not_or_eq()
+{
+    var a = 0.1;
+    var i = 0.1;
+    do {
+        if (i > 0.1)
+            return true;
+        i++;
+    } while (!(a == 0.1 || a == 0.1))
+    return false;
+}
+
+shouldBeFalse("float_dowhile_not_or_eq()");
+
+function float_dowhile_not_or_neq()
+{
+    var a = 0.1;
+    var i = 0.1;
+    do {
+        if (i > 0.1)
+            return true;
+        i++;
+    } while (!(a != 1.1 || a != 1.1))
+    return false;
+}
+
+shouldBeFalse("float_dowhile_not_or_neq()");
+
+function float_dowhile_not_or_less()
+{
+    var a = 0.1;
+    var i = 0.1;
+    do {
+        if (i > 0.1)
+            return true;
+        i++;
+    } while (!(a < 1.1 || a < 1.1))
+    return false;
+}
+
+shouldBeFalse("float_dowhile_not_or_less()");
+
+function float_dowhile_not_or_lesseq()
+{
+    var a = 0.1;
+    var i = 0.1;
+    do {
+        if (i > 0.1)
+            return true;
+        i++;
+    } while (!(a <= 1.1 || a <= 1.1))
+    return false;
+}
+
+shouldBeFalse("float_dowhile_not_or_lesseq()");
+
+function float_dowhile_not_and_eq()
+{
+    var a = 0.1;
+    var i = 0.1;
+    do {
+        if (i > 0.1)
+            return true;
+        i++;
+    } while (!(a == 0.1 && a == 0.1))
+    return false;
+}
+
+shouldBeFalse("float_dowhile_not_and_eq()");
+
+function float_dowhile_not_and_neq()
+{
+    var a = 0.1;
+    var i = 0.1;
+    do {
+        if (i > 0.1)
+            return true;
+        i++;
+    } while (!(a != 1.1 && a != 1.1))
+    return false;
+}
+
+shouldBeFalse("float_dowhile_not_and_neq()");
+
+function float_dowhile_not_and_less()
+{
+    var a = 0.1;
+    var i = 0.1;
+    do {
+        if (i > 0.1)
+            return true;
+        i++;
+    } while (!(a < 1.1 && a < 1.1))
+    return false;
+}
+
+shouldBeFalse("float_dowhile_not_and_less()");
+
+function float_dowhile_not_and_lesseq()
+{
+    var a = 0.1;
+    var i = 0.1;
+    do {
+        if (i > 0.1)
+            return true;
+        i++;
+    } while (!(a <= 1.1 && a <= 1.1))
+    return false;
+}
+
 var successfullyParsed = true;

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list