Title: [147234] trunk/Source/_javascript_Core
Revision
147234
Author
gga...@apple.com
Date
2013-03-29 12:12:18 -0700 (Fri, 29 Mar 2013)

Log Message

Simplified bytecode generation by unforking "condition context" codegen
https://bugs.webkit.org/show_bug.cgi?id=113554

Reviewed by Mark Hahnenberg.

Now, a node that establishes a condition context can always ask its child
nodes to generate into that context.

This has a few advantages:

(*) Removes a bunch of code;

(*) Optimizes a few missed cases like "if (!(x < 2))", "if (!!x)", and
"if (!x || !y)";

(*) Paves the way to removing more opcodes.

* bytecode/Opcode.h:
(JSC): Separated out the branching opcodes for clarity.
* bytecompiler/NodesCodegen.cpp:
(JSC::ExpressionNode::emitBytecodeInConditionContext): All expressions
can be emitted in a condition context now -- the default behavior is
to branch based on the _expression_'s value.

(JSC::LogicalNotNode::emitBytecodeInConditionContext):
(JSC::LogicalOpNode::emitBytecodeInConditionContext):
(JSC::ConditionalNode::emitBytecode):
(JSC::IfNode::emitBytecode):
(JSC::IfElseNode::emitBytecode):
(JSC::DoWhileNode::emitBytecode):
(JSC::WhileNode::emitBytecode):
(JSC::ForNode::emitBytecode):
* parser/Nodes.h:
(JSC::ExpressionNode::isSubtract):
(ExpressionNode):
(LogicalNotNode):
(LogicalOpNode): Removed lots of code for handling expressions
that couldn't generate into a condition context because all expressions
can now.

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (147233 => 147234)


--- trunk/Source/_javascript_Core/ChangeLog	2013-03-29 19:12:04 UTC (rev 147233)
+++ trunk/Source/_javascript_Core/ChangeLog	2013-03-29 19:12:18 UTC (rev 147234)
@@ -1,3 +1,45 @@
+2013-03-29  Geoffrey Garen  <gga...@apple.com>
+
+        Simplified bytecode generation by unforking "condition context" codegen
+        https://bugs.webkit.org/show_bug.cgi?id=113554
+
+        Reviewed by Mark Hahnenberg.
+
+        Now, a node that establishes a condition context can always ask its child
+        nodes to generate into that context.
+
+        This has a few advantages:
+
+        (*) Removes a bunch of code;
+
+        (*) Optimizes a few missed cases like "if (!(x < 2))", "if (!!x)", and
+        "if (!x || !y)";
+
+        (*) Paves the way to removing more opcodes.
+
+        * bytecode/Opcode.h:
+        (JSC): Separated out the branching opcodes for clarity.
+        * bytecompiler/NodesCodegen.cpp:
+        (JSC::ExpressionNode::emitBytecodeInConditionContext): All expressions
+        can be emitted in a condition context now -- the default behavior is
+        to branch based on the _expression_'s value.
+
+        (JSC::LogicalNotNode::emitBytecodeInConditionContext):
+        (JSC::LogicalOpNode::emitBytecodeInConditionContext):
+        (JSC::ConditionalNode::emitBytecode):
+        (JSC::IfNode::emitBytecode):
+        (JSC::IfElseNode::emitBytecode):
+        (JSC::DoWhileNode::emitBytecode):
+        (JSC::WhileNode::emitBytecode):
+        (JSC::ForNode::emitBytecode):
+        * parser/Nodes.h:
+        (JSC::ExpressionNode::isSubtract):
+        (ExpressionNode):
+        (LogicalNotNode):
+        (LogicalOpNode): Removed lots of code for handling expressions
+        that couldn't generate into a condition context because all expressions
+        can now.
+
 2013-03-28  Geoffrey Garen  <gga...@apple.com>
 
         Simplified the bytecode by removing op_loop and op_loop_if_*

Modified: trunk/Source/_javascript_Core/bytecode/Opcode.h (147233 => 147234)


--- trunk/Source/_javascript_Core/bytecode/Opcode.h	2013-03-29 19:12:04 UTC (rev 147233)
+++ trunk/Source/_javascript_Core/bytecode/Opcode.h	2013-03-29 19:12:18 UTC (rev 147234)
@@ -172,7 +172,9 @@
     macro(op_jnlesseq, 4) \
     macro(op_jngreater, 4) \
     macro(op_jngreatereq, 4) \
+    \
     macro(op_loop_hint, 1) \
+    \
     macro(op_switch_imm, 4) \
     macro(op_switch_char, 4) \
     macro(op_switch_string, 4) \

Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h (147233 => 147234)


--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h	2013-03-29 19:12:04 UTC (rev 147233)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h	2013-03-29 19:12:18 UTC (rev 147234)
@@ -354,11 +354,11 @@
             return emitNode(0, n);
         }
 
-        void emitNodeInConditionContext(ExpressionNode* n, Label* trueTarget, Label* falseTarget, bool fallThroughMeansTrue)
+        void emitNodeInConditionContext(ExpressionNode* n, Label* trueTarget, Label* falseTarget, FallThroughMode fallThroughMode)
         {
             addLineInfo(n->lineNo());
             if (m_stack.isSafeToRecurse())
-                n->emitBytecodeInConditionContext(*this, trueTarget, falseTarget, fallThroughMeansTrue);
+                n->emitBytecodeInConditionContext(*this, trueTarget, falseTarget, fallThroughMode);
             else
                 emitThrowExpressionTooDeepException();
         }

Modified: trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp (147233 => 147234)


--- trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp	2013-03-29 19:12:04 UTC (rev 147233)
+++ trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp	2013-03-29 19:12:18 UTC (rev 147234)
@@ -74,6 +74,15 @@
     because the assignment node, "x =", passes r[x] as dst to the number node, "1".
 */
 
+void ExpressionNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, FallThroughMode fallThroughMode)
+{
+    RegisterID* result = generator.emitNode(this);
+    if (fallThroughMode == FallThroughMeansTrue)
+        generator.emitJumpIfFalse(result, falseTarget);
+    else
+        generator.emitJumpIfTrue(result, trueTarget);
+}
+
 // ------------------------------ ThrowableExpressionData --------------------------------
 
 RegisterID* ThrowableExpressionData::emitThrowReferenceError(BytecodeGenerator& generator, const String& message)
@@ -921,12 +930,10 @@
  
 // ------------------------------ LogicalNotNode -----------------------------------
 
-void LogicalNotNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, bool fallThroughMeansTrue)
+void LogicalNotNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, FallThroughMode fallThroughMode)
 {
-    ASSERT(expr()->hasConditionContextCodegen());
-
     // reverse the true and false targets
-    generator.emitNodeInConditionContext(expr(), falseTarget, trueTarget, !fallThroughMeansTrue);
+    generator.emitNodeInConditionContext(expr(), falseTarget, trueTarget, invert(fallThroughMode));
 }
 
 
@@ -1164,32 +1171,16 @@
     return generator.moveToDestinationIfNeeded(dst, temp.get());
 }
 
-void LogicalOpNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, bool fallThroughMeansTrue)
+void LogicalOpNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, FallThroughMode fallThroughMode)
 {
-    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);
-    }
+    RefPtr<Label> afterExpr1 = generator.newLabel();
+    if (m_operator == OpLogicalAnd)
+        generator.emitNodeInConditionContext(m_expr1, afterExpr1.get(), falseTarget, FallThroughMeansTrue);
+    else 
+        generator.emitNodeInConditionContext(m_expr1, trueTarget, afterExpr1.get(), FallThroughMeansFalse);
+    generator.emitLabel(afterExpr1.get());
 
-    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);
-    }
+    generator.emitNodeInConditionContext(m_expr2, trueTarget, falseTarget, fallThroughMode);
 }
 
 // ------------------------------ ConditionalNode ------------------------------
@@ -1200,14 +1191,9 @@
     RefPtr<Label> beforeElse = generator.newLabel();
     RefPtr<Label> afterElse = generator.newLabel();
 
-    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());
-    }
+    RefPtr<Label> beforeThen = generator.newLabel();
+    generator.emitNodeInConditionContext(m_logical, beforeThen.get(), beforeElse.get(), FallThroughMeansTrue);
+    generator.emitLabel(beforeThen.get());
 
     generator.emitNode(newDst.get(), m_expr1);
     generator.emitJump(afterElse.get());
@@ -1543,14 +1529,9 @@
     
     RefPtr<Label> afterThen = generator.newLabel();
 
-    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());
-    }
+    RefPtr<Label> beforeThen = generator.newLabel();
+    generator.emitNodeInConditionContext(m_condition, beforeThen.get(), afterThen.get(), FallThroughMeansTrue);
+    generator.emitLabel(beforeThen.get());
 
     generator.emitNode(dst, m_ifBlock);
     generator.emitLabel(afterThen.get());
@@ -1568,14 +1549,9 @@
     RefPtr<Label> beforeElse = generator.newLabel();
     RefPtr<Label> afterElse = generator.newLabel();
 
-    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());
-    }
+    RefPtr<Label> beforeThen = generator.newLabel();
+    generator.emitNodeInConditionContext(m_condition, beforeThen.get(), beforeElse.get(), FallThroughMeansTrue);
+    generator.emitLabel(beforeThen.get());
 
     generator.emitNode(dst, m_ifBlock);
     generator.emitJump(afterElse.get());
@@ -1605,12 +1581,7 @@
 
     generator.emitLabel(scope->continueTarget());
     generator.emitDebugHook(WillExecuteStatement, lastLine(), lastLine(), charPosition());
-    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.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), FallThroughMeansFalse);
 
     generator.emitLabel(scope->breakTarget());
     return result.get();
@@ -1624,12 +1595,7 @@
     RefPtr<Label> topOfLoop = generator.newLabel();
 
     generator.emitDebugHook(WillExecuteStatement, m_expr->lineNo(), m_expr->lineNo(), m_expr->charPosition());
-    if (m_expr->hasConditionContextCodegen())
-        generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), true);
-    else {
-        RegisterID* cond = generator.emitNode(m_expr);
-        generator.emitJumpIfFalse(cond, scope->breakTarget());
-    }
+    generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), FallThroughMeansTrue);
 
     generator.emitLabel(topOfLoop.get());
     generator.emitLoopHint();
@@ -1639,12 +1605,7 @@
     generator.emitLabel(scope->continueTarget());
     generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), charPosition());
 
-    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.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), FallThroughMeansFalse);
 
     generator.emitLabel(scope->breakTarget());
     
@@ -1664,14 +1625,8 @@
         generator.emitNode(generator.ignoredResult(), m_expr1);
     
     RefPtr<Label> topOfLoop = generator.newLabel();
-    if (m_expr2) {
-        if (m_expr2->hasConditionContextCodegen())
-            generator.emitNodeInConditionContext(m_expr2, topOfLoop.get(), scope->breakTarget(), true);
-        else {
-            RegisterID* cond = generator.emitNode(m_expr2);
-            generator.emitJumpIfFalse(cond, scope->breakTarget());
-        }
-    }
+    if (m_expr2)
+        generator.emitNodeInConditionContext(m_expr2, topOfLoop.get(), scope->breakTarget(), FallThroughMeansTrue);
 
     generator.emitLabel(topOfLoop.get());
     generator.emitLoopHint();
@@ -1683,14 +1638,9 @@
     if (m_expr3)
         generator.emitNode(generator.ignoredResult(), m_expr3);
 
-    if (m_expr2) {
-        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
+    if (m_expr2)
+        generator.emitNodeInConditionContext(m_expr2, topOfLoop.get(), scope->breakTarget(), FallThroughMeansFalse);
+    else
         generator.emitJump(topOfLoop.get());
 
     generator.emitLabel(scope->breakTarget());

Modified: trunk/Source/_javascript_Core/parser/Nodes.h (147233 => 147234)


--- trunk/Source/_javascript_Core/parser/Nodes.h	2013-03-29 19:12:04 UTC (rev 147233)
+++ trunk/Source/_javascript_Core/parser/Nodes.h	2013-03-29 19:12:18 UTC (rev 147234)
@@ -70,6 +70,12 @@
         OpLogicalOr
     };
 
+    enum FallThroughMode {
+        FallThroughMeansTrue = 0,
+        FallThroughMeansFalse = 1
+    };
+    inline FallThroughMode invert(FallThroughMode fallThroughMode) { return static_cast<FallThroughMode>(!fallThroughMode); }
+
     typedef HashSet<RefPtr<StringImpl>, IdentifierRepHash> IdentifierSet;
 
     namespace DeclarationStacks {
@@ -152,9 +158,8 @@
         virtual bool isSimpleArray() const { return false; }
         virtual bool isAdd() const { return false; }
         virtual bool isSubtract() const { return false; }
-        virtual bool hasConditionContextCodegen() const { return false; }
 
-        virtual void emitBytecodeInConditionContext(BytecodeGenerator&, Label*, Label*, bool) { RELEASE_ASSERT_NOT_REACHED(); }
+        virtual void emitBytecodeInConditionContext(BytecodeGenerator&, Label*, Label*, FallThroughMode);
 
         virtual ExpressionNode* stripUnaryPlus() { return this; }
 
@@ -732,8 +737,7 @@
     public:
         LogicalNotNode(const JSTokenLocation&, ExpressionNode*);
     private:
-        void emitBytecodeInConditionContext(BytecodeGenerator&, Label* trueTarget, Label* falseTarget, bool fallThroughMeansTrue);
-        virtual bool hasConditionContextCodegen() const { return expr()->hasConditionContextCodegen(); }
+        void emitBytecodeInConditionContext(BytecodeGenerator&, Label* trueTarget, Label* falseTarget, FallThroughMode);
     };
 
     class BinaryOpNode : public ExpressionNode {
@@ -895,8 +899,7 @@
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
-        void emitBytecodeInConditionContext(BytecodeGenerator&, Label* trueTarget, Label* falseTarget, bool fallThroughMeansTrue);
-        virtual bool hasConditionContextCodegen() const { return true; }
+        void emitBytecodeInConditionContext(BytecodeGenerator&, Label* trueTarget, Label* falseTarget, FallThroughMode);
 
         ExpressionNode* m_expr1;
         ExpressionNode* m_expr2;
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to