Diff
Modified: trunk/LayoutTests/ChangeLog (149235 => 149236)
--- trunk/LayoutTests/ChangeLog 2013-04-27 06:33:34 UTC (rev 149235)
+++ trunk/LayoutTests/ChangeLog 2013-04-27 06:43:33 UTC (rev 149236)
@@ -1,3 +1,18 @@
+2013-04-26 Geoffrey Garen <[email protected]>
+
+ Re-landing <http://trac.webkit.org/changeset/148999>
+
+ Filled out more cases of branch folding in bytecode when emitting
+ expressions into a branching context
+ https://bugs.webkit.org/show_bug.cgi?id=115057
+
+ Reviewed by Phil Pizlo.
+
+ Added a more exhaustive correctness test.
+
+ * fast/js/branch-fold-correctness-expected.txt: Added.
+ * fast/js/branch-fold-correctness.html: Added.
+
2013-04-26 Jer Noble <[email protected]>
Video playback has corruption on the edges of the video
Added: trunk/LayoutTests/fast/js/branch-fold-correctness-expected.txt (0 => 149236)
--- trunk/LayoutTests/fast/js/branch-fold-correctness-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/js/branch-fold-correctness-expected.txt 2013-04-27 06:43:33 UTC (rev 149236)
@@ -0,0 +1,4 @@
+This page tests branches that might cause interesting forms of _expression_ folding in bytecode.
+
+tests completed: 32
+
Added: trunk/LayoutTests/fast/js/branch-fold-correctness.html (0 => 149236)
--- trunk/LayoutTests/fast/js/branch-fold-correctness.html (rev 0)
+++ trunk/LayoutTests/fast/js/branch-fold-correctness.html 2013-04-27 06:43:33 UTC (rev 149236)
@@ -0,0 +1,192 @@
+<p>This page tests branches that might cause interesting forms of _expression_ folding in bytecode.</p>
+<pre id="console"></pre>
+
+<script>
+if (window.testRunner)
+ testRunner.dumpAsText();
+
+function log(s)
+{
+ document.getElementById("console").appendChild(document.createTextNode(s + "\n"));
+}
+
+(function () {
+ var count = 0;
+ function fail()
+ {
+ log("FAIL on test " + count + ".");
+ }
+
+ var zero = 0;
+ var _one_ = 1;
+ var two = 2;
+
+ // bool vs bool
+ ++count;
+ if (true == (_one_ == one)) {
+ } else
+ fail();
+
+ ++count;
+ if (false == (one != one)) {
+ } else
+ fail();
+
+ ++count;
+ if (true != (one != one)) {
+ } else
+ fail();
+
+ ++count;
+ if (false != (_one_ == one)) {
+ } else
+ fail();
+
+ ++count;
+ if (true === (_one_ == one)) {
+ } else
+ fail();
+
+ ++count;
+ if (false === (one != one)) {
+ } else
+ fail();
+
+ ++count;
+ if (true !== (one != one)) {
+ } else
+ fail();
+
+ ++count;
+ if (false !== (_one_ == one)) {
+ } else
+ fail();
+
+
+ // int vs bool
+ ++count;
+ if (1 == (_one_ == one)) {
+ } else
+ fail();
+
+ ++count;
+ if (0 == (one != one)) {
+ } else
+ fail();
+
+ ++count;
+ if (2 != (one != one)) {
+ } else
+ fail();
+
+ ++count;
+ if (1 != (one != one)) {
+ } else
+ fail();
+
+ ++count;
+ if (0 != (_one_ == one)) {
+ } else
+ fail();
+
+ ++count;
+ if (2 != (_one_ == one)) {
+ } else
+ fail();
+
+ ++count;
+ if (1 !== (_one_ == one)) {
+ } else
+ fail();
+
+ ++count;
+ if (0 !== (one != one)) {
+ } else
+ fail();
+
+ ++count;
+ if (2 !== (one != one)) {
+ } else
+ fail();
+
+ ++count;
+ if (1 !== (one != one)) {
+ } else
+ fail();
+
+ ++count;
+ if (0 !== (_one_ == one)) {
+ } else
+ fail();
+
+ ++count;
+ if (2 !== (_one_ == one)) {
+ } else
+ fail();
+
+
+
+ // int vs int
+ ++count;
+ if (1 == (one | 0)) {
+ } else
+ fail();
+
+ ++count;
+ if (0 == (zero | 0)) {
+ } else
+ fail();
+
+ ++count;
+ if (2 != (one | 0)) {
+ } else
+ fail();
+
+ ++count;
+ if (1 != (zero | 0)) {
+ } else
+ fail();
+
+ ++count;
+ if (0 != (one | 0)) {
+ } else
+ fail();
+
+ ++count;
+ if (2 != (one | 0)) {
+ } else
+ fail();
+
+ ++count;
+ if (1 === (one | 0)) {
+ } else
+ fail();
+
+ ++count;
+ if (0 === (zero | 0)) {
+ } else
+ fail();
+
+ ++count;
+ if (2 !== (one | 0)) {
+ } else
+ fail();
+
+ ++count;
+ if (1 !== (two | 0)) {
+ } else
+ fail();
+
+ ++count;
+ if (0 !== (one | 0)) {
+ } else
+ fail();
+
+ ++count;
+ if (2 !== (one | 0)) {
+ } else
+ fail();
+
+ log("tests completed: " + count);
+})();
+</script>
Modified: trunk/Source/_javascript_Core/ChangeLog (149235 => 149236)
--- trunk/Source/_javascript_Core/ChangeLog 2013-04-27 06:33:34 UTC (rev 149235)
+++ trunk/Source/_javascript_Core/ChangeLog 2013-04-27 06:43:33 UTC (rev 149236)
@@ -1,3 +1,16 @@
+2013-04-26 Geoffrey Garen <[email protected]>
+
+ Re-landing <http://trac.webkit.org/changeset/148999>
+
+ Filled out more cases of branch folding in bytecode when emitting
+ expressions into a branching context
+ https://bugs.webkit.org/show_bug.cgi?id=115057
+
+ Reviewed by Phil Pizlo.
+
+ We can't fold the number == 1 case to boolean because all non-zero numbers
+ down-cast to true, but only 1 is == to true.
+
2013-04-26 Filip Pizlo <[email protected]>
Correct indentation of SymbolTable.h
Modified: trunk/Source/_javascript_Core/_javascript_Core.order (149235 => 149236)
--- trunk/Source/_javascript_Core/_javascript_Core.order 2013-04-27 06:33:34 UTC (rev 149235)
+++ trunk/Source/_javascript_Core/_javascript_Core.order 2013-04-27 06:43:33 UTC (rev 149236)
@@ -717,7 +717,6 @@
__ZNK3JSC14ExpressionNode21isBracketAccessorNodeEv
__ZN3JSC9CodeBlock25createRareDataIfNecessaryEv
__ZN3WTF6VectorIN3JSC8LineInfoELm0EE14expandCapacityEm
-__ZN3JSC6IfNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
__ZN3JSC17BytecodeGenerator8newLabelEv
__ZNK3JSC14ExpressionNode26hasConditionContextCodegenEv
__ZN3WTF6VectorIN3JSC19ExpressionRangeInfoELm0EE14expandCapacityEm
Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp (149235 => 149236)
--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp 2013-04-27 06:33:34 UTC (rev 149235)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp 2013-04-27 06:43:33 UTC (rev 149236)
@@ -1628,7 +1628,7 @@
bool hadVariableExpression = false;
if (length) {
for (ElementNode* n = elements; n; n = n->next()) {
- if (!n->value()->isNumber() && !n->value()->isString()) {
+ if (!n->value()->isConstant()) {
hadVariableExpression = true;
break;
}
@@ -1644,12 +1644,8 @@
JSValue* constantBuffer = m_codeBlock->constantBuffer(constantBufferIndex).data();
unsigned index = 0;
for (ElementNode* n = elements; index < length; n = n->next()) {
- if (n->value()->isNumber())
- constantBuffer[index++] = jsNumber(static_cast<NumberNode*>(n->value())->value());
- else {
- ASSERT(n->value()->isString());
- constantBuffer[index++] = addStringConstant(static_cast<StringNode*>(n->value())->value());
- }
+ ASSERT(n->value()->isConstant());
+ constantBuffer[index++] = static_cast<ConstantNode*>(n->value())->jsValue(*this);
}
emitOpcode(op_new_array_buffer);
instructions().append(dst->index());
@@ -2365,7 +2361,7 @@
void BytecodeGenerator::emitThrowReferenceError(const String& message)
{
emitOpcode(op_throw_static_error);
- instructions().append(addConstantValue(jsString(vm(), message))->index());
+ instructions().append(addConstantValue(addStringConstant(Identifier(m_vm, message)))->index());
instructions().append(true);
}
@@ -2523,7 +2519,7 @@
if (!isStrictMode())
return;
emitOpcode(op_throw_static_error);
- instructions().append(addConstantValue(jsString(vm(), StrictModeReadonlyPropertyWriteError))->index());
+ instructions().append(addConstantValue(addStringConstant(Identifier(m_vm, StrictModeReadonlyPropertyWriteError)))->index());
instructions().append(false);
}
Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h (149235 => 149236)
--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h 2013-04-27 06:33:34 UTC (rev 149235)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h 2013-04-27 06:43:33 UTC (rev 149236)
@@ -553,6 +553,7 @@
CodeType codeType() const { return m_codeType; }
bool shouldEmitProfileHooks() { return m_shouldEmitProfileHooks; }
+ bool shouldEmitDebugHooks() { return m_shouldEmitDebugHooks; }
bool isStrictMode() const { return m_codeBlock->isStrictMode(); }
@@ -646,8 +647,6 @@
return UnlinkedFunctionExecutable::create(m_vm, m_scopeNode->source(), body);
}
- JSString* addStringConstant(const Identifier&);
-
void addLineInfo(unsigned lineNo)
{
m_codeBlock->addLineInfo(instructions().size(), lineNo - m_scopeNode->firstLine());
@@ -656,6 +655,8 @@
RegisterID* emitInitLazyRegister(RegisterID*);
public:
+ JSString* addStringConstant(const Identifier&);
+
Vector<UnlinkedInstruction, 0, UnsafeVectorOverflow>& instructions() { return m_instructions; }
SharedSymbolTable& symbolTable() { return *m_symbolTable; }
Modified: trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp (149235 => 149236)
--- trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp 2013-04-27 06:33:34 UTC (rev 149235)
+++ trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp 2013-04-27 06:43:33 UTC (rev 149236)
@@ -92,40 +92,31 @@
return generator.newTemporary();
}
-// ------------------------------ NullNode -------------------------------------
+// ------------------------------ ConstantNode ----------------------------------
-RegisterID* NullNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+void ConstantNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, FallThroughMode fallThroughMode)
{
- if (dst == generator.ignoredResult())
- return 0;
- return generator.emitLoad(dst, jsNull());
-}
+ TriState value = jsValue(generator).pureToBoolean();
+ if (value == MixedTriState)
+ ExpressionNode::emitBytecodeInConditionContext(generator, trueTarget, falseTarget, fallThroughMode);
+ else if (value == TrueTriState && fallThroughMode == FallThroughMeansFalse)
+ generator.emitJump(trueTarget);
+ else if (value == FalseTriState && fallThroughMode == FallThroughMeansTrue)
+ generator.emitJump(falseTarget);
-// ------------------------------ BooleanNode ----------------------------------
-
-RegisterID* BooleanNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
-{
- if (dst == generator.ignoredResult())
- return 0;
- return generator.emitLoad(dst, m_value);
+ // All other cases are unconditional fall-throughs, like "if (true)".
}
-// ------------------------------ NumberNode -----------------------------------
-
-RegisterID* NumberNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+RegisterID* ConstantNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
{
if (dst == generator.ignoredResult())
return 0;
- return generator.emitLoad(dst, m_value);
+ return generator.emitLoad(dst, jsValue(generator));
}
-// ------------------------------ StringNode -----------------------------------
-
-RegisterID* StringNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+JSValue StringNode::jsValue(BytecodeGenerator& generator) const
{
- if (dst == generator.ignoredResult())
- return 0;
- return generator.emitLoad(dst, m_value);
+ return generator.addStringConstant(m_value);
}
// ------------------------------ RegExpNode -----------------------------------
@@ -1042,6 +1033,64 @@
return generator.emitStrcat(generator.finalDestination(dst, temporaryRegisters[0].get()), temporaryRegisters[0].get(), temporaryRegisters.size());
}
+void BinaryOpNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, FallThroughMode fallThroughMode)
+{
+ TriState branchCondition;
+ ExpressionNode* branchExpression;
+ tryFoldToBranch(generator, branchCondition, branchExpression);
+
+ if (branchCondition == MixedTriState)
+ ExpressionNode::emitBytecodeInConditionContext(generator, trueTarget, falseTarget, fallThroughMode);
+ else if (branchCondition == TrueTriState)
+ generator.emitNodeInConditionContext(branchExpression, trueTarget, falseTarget, fallThroughMode);
+ else
+ generator.emitNodeInConditionContext(branchExpression, falseTarget, trueTarget, invert(fallThroughMode));
+}
+
+static inline bool canFoldToBranch(OpcodeID opcodeID, ExpressionNode* branchExpression, JSValue constant)
+{
+ ResultType expressionType = branchExpression->resultDescriptor();
+
+ if (expressionType.definitelyIsBoolean() && constant.isBoolean())
+ return true;
+ else if (expressionType.definitelyIsBoolean() && constant.isInt32() && (constant.asInt32() == 0 || constant.asInt32() == 1))
+ return opcodeID == op_eq || opcodeID == op_neq; // Strict equality is false in the case of type mismatch.
+ else if (expressionType.isInt32() && constant.isInt32() && constant.asInt32() == 0)
+ return true;
+
+ return false;
+}
+
+void BinaryOpNode::tryFoldToBranch(BytecodeGenerator& generator, TriState& branchCondition, ExpressionNode*& branchExpression)
+{
+ branchCondition = MixedTriState;
+ branchExpression = 0;
+
+ ConstantNode* constant = 0;
+ if (m_expr1->isConstant()) {
+ constant = static_cast<ConstantNode*>(m_expr1);
+ branchExpression = m_expr2;
+ } else if (m_expr2->isConstant()) {
+ constant = static_cast<ConstantNode*>(m_expr2);
+ branchExpression = m_expr1;
+ }
+
+ if (!constant)
+ return;
+ ASSERT(branchExpression);
+
+ OpcodeID opcodeID = this->opcodeID();
+ JSValue value = constant->jsValue(generator);
+ bool canFoldToBranch = JSC::canFoldToBranch(opcodeID, branchExpression, value);
+ if (!canFoldToBranch)
+ return;
+
+ if (opcodeID == op_eq || opcodeID == op_stricteq)
+ branchCondition = triState(value.pureToBoolean());
+ else if (opcodeID == op_neq || opcodeID == op_nstricteq)
+ branchCondition = triState(!value.pureToBoolean());
+}
+
RegisterID* BinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
{
OpcodeID opcodeID = this->opcodeID();
@@ -1504,41 +1553,71 @@
generator.emitNode(m_expr);
}
-// ------------------------------ IfNode ---------------------------------------
+// ------------------------------ IfElseNode ---------------------------------------
-void IfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+static inline StatementNode* singleStatement(StatementNode* statementNode)
{
- generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), charPosition());
-
- RefPtr<Label> afterThen = generator.newLabel();
+ if (statementNode->isBlock())
+ return static_cast<BlockNode*>(statementNode)->singleStatement();
+ return statementNode;
+}
- RefPtr<Label> beforeThen = generator.newLabel();
- generator.emitNodeInConditionContext(m_condition, beforeThen.get(), afterThen.get(), FallThroughMeansTrue);
- generator.emitLabel(beforeThen.get());
+bool IfElseNode::tryFoldBreakAndContinue(BytecodeGenerator& generator, StatementNode* ifBlock,
+ Label*& trueTarget, FallThroughMode& fallThroughMode)
+{
+ StatementNode* singleStatement = JSC::singleStatement(ifBlock);
+ if (!singleStatement)
+ return false;
- generator.emitNode(dst, m_ifBlock);
- generator.emitLabel(afterThen.get());
+ if (singleStatement->isBreak()) {
+ BreakNode* breakNode = static_cast<BreakNode*>(singleStatement);
+ Label* target = breakNode->trivialTarget(generator);
+ if (!target)
+ return false;
+ trueTarget = target;
+ fallThroughMode = FallThroughMeansFalse;
+ return true;
+ }
+
+ if (singleStatement->isContinue()) {
+ ContinueNode* continueNode = static_cast<ContinueNode*>(singleStatement);
+ Label* target = continueNode->trivialTarget(generator);
+ if (!target)
+ return false;
+ trueTarget = target;
+ fallThroughMode = FallThroughMeansFalse;
+ return true;
+ }
+
+ return false;
}
-// ------------------------------ IfElseNode ---------------------------------------
-
void IfElseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
{
generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), charPosition());
+ RefPtr<Label> beforeThen = generator.newLabel();
RefPtr<Label> beforeElse = generator.newLabel();
RefPtr<Label> afterElse = generator.newLabel();
- RefPtr<Label> beforeThen = generator.newLabel();
- generator.emitNodeInConditionContext(m_condition, beforeThen.get(), beforeElse.get(), FallThroughMeansTrue);
+ Label* trueTarget = beforeThen.get();
+ Label* falseTarget = beforeElse.get();
+ FallThroughMode fallThroughMode = FallThroughMeansTrue;
+ bool didFoldIfBlock = tryFoldBreakAndContinue(generator, m_ifBlock, trueTarget, fallThroughMode);
+
+ generator.emitNodeInConditionContext(m_condition, trueTarget, falseTarget, fallThroughMode);
generator.emitLabel(beforeThen.get());
- generator.emitNode(dst, m_ifBlock);
- generator.emitJump(afterElse.get());
+ if (!didFoldIfBlock) {
+ generator.emitNode(dst, m_ifBlock);
+ if (m_elseBlock)
+ generator.emitJump(afterElse.get());
+ }
generator.emitLabel(beforeElse.get());
- generator.emitNode(dst, m_elseBlock);
+ if (m_elseBlock)
+ generator.emitNode(dst, m_elseBlock);
generator.emitLabel(afterElse.get());
}
@@ -1700,6 +1779,20 @@
// ------------------------------ ContinueNode ---------------------------------
+Label* ContinueNode::trivialTarget(BytecodeGenerator& generator)
+{
+ if (generator.shouldEmitDebugHooks())
+ return 0;
+
+ LabelScope* scope = generator.continueTarget(m_ident);
+ ASSERT(scope);
+
+ if (generator.scopeDepth() != scope->scopeDepth())
+ return 0;
+
+ return scope->continueTarget();
+}
+
void ContinueNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
{
generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), charPosition());
@@ -1713,6 +1806,20 @@
// ------------------------------ BreakNode ------------------------------------
+Label* BreakNode::trivialTarget(BytecodeGenerator& generator)
+{
+ if (generator.shouldEmitDebugHooks())
+ return 0;
+
+ LabelScope* scope = generator.breakTarget(m_ident);
+ ASSERT(scope);
+
+ if (generator.scopeDepth() != scope->scopeDepth())
+ return 0;
+
+ return scope->breakTarget();
+}
+
void BreakNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
{
generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), charPosition());
Modified: trunk/Source/_javascript_Core/parser/ASTBuilder.h (149235 => 149236)
--- trunk/Source/_javascript_Core/parser/ASTBuilder.h 2013-04-27 06:33:34 UTC (rev 149235)
+++ trunk/Source/_javascript_Core/parser/ASTBuilder.h 2013-04-27 06:43:33 UTC (rev 149236)
@@ -344,16 +344,9 @@
return result;
}
- StatementNode* createIfStatement(const JSTokenLocation& location, ExpressionNode* condition, StatementNode* trueBlock, int start, int end)
- {
- IfNode* result = new (m_vm) IfNode(location, condition, trueBlock);
- result->setLoc(start, end, location.charPosition);
- return result;
- }
-
StatementNode* createIfStatement(const JSTokenLocation& location, ExpressionNode* condition, StatementNode* trueBlock, StatementNode* falseBlock, int start, int end)
{
- IfNode* result = new (m_vm) IfElseNode(location, condition, trueBlock, falseBlock);
+ IfElseNode* result = new (m_vm) IfElseNode(location, condition, trueBlock, falseBlock);
result->setLoc(start, end, location.charPosition);
return result;
}
Modified: trunk/Source/_javascript_Core/parser/NodeConstructors.h (149235 => 149236)
--- trunk/Source/_javascript_Core/parser/NodeConstructors.h 2013-04-27 06:33:34 UTC (rev 149235)
+++ trunk/Source/_javascript_Core/parser/NodeConstructors.h 2013-04-27 06:43:33 UTC (rev 149236)
@@ -60,25 +60,30 @@
{
}
+ inline ConstantNode::ConstantNode(const JSTokenLocation& location, ResultType resultType)
+ : ExpressionNode(location, resultType)
+ {
+ }
+
inline NullNode::NullNode(const JSTokenLocation& location)
- : ExpressionNode(location, ResultType::nullType())
+ : ConstantNode(location, ResultType::nullType())
{
}
inline BooleanNode::BooleanNode(const JSTokenLocation& location, bool value)
- : ExpressionNode(location, ResultType::booleanType())
+ : ConstantNode(location, ResultType::booleanType())
, m_value(value)
{
}
inline NumberNode::NumberNode(const JSTokenLocation& location, double value)
- : ExpressionNode(location, ResultType::numberType())
+ : ConstantNode(location, JSValue(value).isInt32() ? ResultType::numberTypeIsInt32() : ResultType::numberType())
, m_value(value)
{
}
inline StringNode::StringNode(const JSTokenLocation& location, const Identifier& value)
- : ExpressionNode(location, ResultType::stringType())
+ : ConstantNode(location, ResultType::stringType())
, m_value(value)
{
}
@@ -631,15 +636,10 @@
{
}
- inline IfNode::IfNode(const JSTokenLocation& location, ExpressionNode* condition, StatementNode* ifBlock)
+ inline IfElseNode::IfElseNode(const JSTokenLocation& location, ExpressionNode* condition, StatementNode* ifBlock, StatementNode* elseBlock)
: StatementNode(location)
, m_condition(condition)
, m_ifBlock(ifBlock)
- {
- }
-
- inline IfElseNode::IfElseNode(const JSTokenLocation& location, ExpressionNode* condition, StatementNode* ifBlock, StatementNode* elseBlock)
- : IfNode(location, condition, ifBlock)
, m_elseBlock(elseBlock)
{
}
Modified: trunk/Source/_javascript_Core/parser/Nodes.h (149235 => 149236)
--- trunk/Source/_javascript_Core/parser/Nodes.h 2013-04-27 06:33:34 UTC (rev 149235)
+++ trunk/Source/_javascript_Core/parser/Nodes.h 2013-04-27 06:43:33 UTC (rev 149236)
@@ -149,6 +149,7 @@
virtual bool isString() const { return false; }
virtual bool isNull() const { return false; }
virtual bool isPure(BytecodeGenerator&) const { return false; }
+ virtual bool isConstant() const { return false; }
virtual bool isLocation() const { return false; }
virtual bool isResolveNode() const { return false; }
virtual bool isBracketAccessorNode() const { return false; }
@@ -158,6 +159,7 @@
virtual bool isSimpleArray() const { return false; }
virtual bool isAdd() const { return false; }
virtual bool isSubtract() const { return false; }
+ virtual bool isBoolean() const { return false; }
virtual void emitBytecodeInConditionContext(BytecodeGenerator&, Label*, Label*, FallThroughMode);
@@ -183,63 +185,67 @@
virtual bool isEmptyStatement() const { return false; }
virtual bool isReturnNode() const { return false; }
virtual bool isExprStatement() const { return false; }
-
+ virtual bool isBreak() const { return false; }
+ virtual bool isContinue() const { return false; }
virtual bool isBlock() const { return false; }
private:
int m_lastLine;
};
- class NullNode : public ExpressionNode {
+ class ConstantNode : public ExpressionNode {
public:
+ ConstantNode(const JSTokenLocation&, ResultType);
+ virtual bool isPure(BytecodeGenerator&) const { return true; }
+ virtual bool isConstant() const { return true; }
+ virtual JSValue jsValue(BytecodeGenerator&) const = 0;
+ private:
+ virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+ void emitBytecodeInConditionContext(BytecodeGenerator&, Label* trueTarget, Label* falseTarget, FallThroughMode);
+ };
+
+ class NullNode : public ConstantNode {
+ public:
NullNode(const JSTokenLocation&);
private:
- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
-
virtual bool isNull() const { return true; }
+ virtual JSValue jsValue(BytecodeGenerator&) const { return jsNull(); }
};
- class BooleanNode : public ExpressionNode {
+ class BooleanNode : public ConstantNode {
public:
BooleanNode(const JSTokenLocation&, bool value);
+ bool value() { return m_value; }
private:
- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+ virtual bool isBoolean() const { return true; }
+ virtual JSValue jsValue(BytecodeGenerator&) const { return jsBoolean(m_value); }
- virtual bool isPure(BytecodeGenerator&) const { return true; }
-
bool m_value;
};
- class NumberNode : public ExpressionNode {
+ class NumberNode : public ConstantNode {
public:
NumberNode(const JSTokenLocation&, double value);
-
- double value() const { return m_value; }
+ double value() { return m_value; }
void setValue(double value) { m_value = value; }
private:
- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
-
virtual bool isNumber() const { return true; }
- virtual bool isPure(BytecodeGenerator&) const { return true; }
+ virtual JSValue jsValue(BytecodeGenerator&) const { return jsNumber(m_value); }
double m_value;
};
- class StringNode : public ExpressionNode {
+ class StringNode : public ConstantNode {
public:
StringNode(const JSTokenLocation&, const Identifier&);
-
const Identifier& value() { return m_value; }
private:
- virtual bool isPure(BytecodeGenerator&) const { return true; }
-
- virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
-
virtual bool isString() const { return true; }
+ virtual JSValue jsValue(BytecodeGenerator&) const;
const Identifier& m_value;
};
@@ -745,11 +751,13 @@
BinaryOpNode(const JSTokenLocation&, ResultType, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments);
RegisterID* emitStrcat(BytecodeGenerator& generator, RegisterID* destination, RegisterID* lhs = 0, ReadModifyResolveNode* emitExpressionInfoForMe = 0);
+ void emitBytecodeInConditionContext(BytecodeGenerator&, Label* trueTarget, Label* falseTarget, FallThroughMode);
ExpressionNode* lhs() { return m_expr1; };
ExpressionNode* rhs() { return m_expr2; };
private:
+ void tryFoldToBranch(BytecodeGenerator&, TriState& branchCondition, ExpressionNode*& branchExpression);
virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
protected:
@@ -1124,24 +1132,17 @@
ExpressionNode* m_expr;
};
- class IfNode : public StatementNode {
+ class IfElseNode : public StatementNode {
public:
- IfNode(const JSTokenLocation&, ExpressionNode* condition, StatementNode* ifBlock);
+ IfElseNode(const JSTokenLocation&, ExpressionNode* condition, StatementNode* ifBlock, StatementNode* elseBlock);
- protected:
+ private:
virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0);
+ bool tryFoldBreakAndContinue(BytecodeGenerator&, StatementNode* ifBlock,
+ Label*& trueTarget, FallThroughMode&);
ExpressionNode* m_condition;
StatementNode* m_ifBlock;
- };
-
- class IfElseNode : public IfNode {
- public:
- IfElseNode(const JSTokenLocation&, ExpressionNode* condition, StatementNode* ifBlock, StatementNode* elseBlock);
-
- private:
- virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0);
-
StatementNode* m_elseBlock;
};
@@ -1198,8 +1199,10 @@
public:
ContinueNode(VM*, const JSTokenLocation&);
ContinueNode(const JSTokenLocation&, const Identifier&);
+ Label* trivialTarget(BytecodeGenerator&);
private:
+ virtual bool isContinue() const { return true; }
virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0);
const Identifier& m_ident;
@@ -1209,8 +1212,10 @@
public:
BreakNode(VM*, const JSTokenLocation&);
BreakNode(const JSTokenLocation&, const Identifier&);
+ Label* trivialTarget(BytecodeGenerator&);
private:
+ virtual bool isBreak() const { return true; }
virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0);
const Identifier& m_ident;
Modified: trunk/Source/_javascript_Core/parser/Parser.cpp (149235 => 149236)
--- trunk/Source/_javascript_Core/parser/Parser.cpp 2013-04-27 06:33:34 UTC (rev 149235)
+++ trunk/Source/_javascript_Core/parser/Parser.cpp 2013-04-27 06:43:33 UTC (rev 149236)
@@ -26,10 +26,11 @@
#include "ASTBuilder.h"
#include "CodeBlock.h"
#include "Debugger.h"
-#include "VM.h"
+#include "JSCJSValueInlines.h"
#include "Lexer.h"
#include "NodeInfo.h"
#include "SourceProvider.h"
+#include "VM.h"
#include <utility>
#include <wtf/HashFunctions.h>
#include <wtf/OwnPtr.h>
@@ -1011,7 +1012,7 @@
failIfFalse(trueBlock);
if (!match(ELSE))
- return context.createIfStatement(ifLocation, condition, trueBlock, start, end);
+ return context.createIfStatement(ifLocation, condition, trueBlock, 0, start, end);
Vector<TreeExpression> exprStack;
Vector<pair<int, int> > posStack;
@@ -1056,7 +1057,7 @@
posStack.removeLast();
JSTokenLocation elseLocation = tokenLocationStack.last();
tokenLocationStack.removeLast();
- statementStack.append(context.createIfStatement(elseLocation, condition, trueBlock, pos.first, pos.second));
+ statementStack.append(context.createIfStatement(elseLocation, condition, trueBlock, 0, pos.first, pos.second));
}
while (!exprStack.isEmpty()) {
Modified: trunk/Source/_javascript_Core/parser/ResultType.h (149235 => 149236)
--- trunk/Source/_javascript_Core/parser/ResultType.h 2013-04-27 06:33:34 UTC (rev 149235)
+++ trunk/Source/_javascript_Core/parser/ResultType.h 2013-04-27 06:43:33 UTC (rev 149236)
@@ -62,6 +62,11 @@
return (m_type & TypeBits) == TypeMaybeString;
}
+ bool definitelyIsBoolean()
+ {
+ return (m_type & TypeBits) == TypeMaybeBool;
+ }
+
bool mightBeNumber()
{
return m_type & TypeMaybeNumber;
Modified: trunk/Source/_javascript_Core/runtime/JSCJSValueInlines.h (149235 => 149236)
--- trunk/Source/_javascript_Core/runtime/JSCJSValueInlines.h 2013-04-27 06:33:34 UTC (rev 149235)
+++ trunk/Source/_javascript_Core/runtime/JSCJSValueInlines.h 2013-04-27 06:43:33 UTC (rev 149236)
@@ -800,7 +800,7 @@
if (isDouble())
return (asDouble() > 0.0 || asDouble() < 0.0) ? TrueTriState : FalseTriState; // false for NaN
if (isCell())
- return MixedTriState;
+ return asCell()->pureToBoolean();
return isTrue() ? TrueTriState : FalseTriState;
}
Modified: trunk/Source/_javascript_Core/runtime/JSCell.h (149235 => 149236)
--- trunk/Source/_javascript_Core/runtime/JSCell.h 2013-04-27 06:33:34 UTC (rev 149235)
+++ trunk/Source/_javascript_Core/runtime/JSCell.h 2013-04-27 06:43:33 UTC (rev 149236)
@@ -96,6 +96,7 @@
JS_EXPORT_PRIVATE JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const;
bool getPrimitiveNumber(ExecState*, double& number, JSValue&) const;
bool toBoolean(ExecState*) const;
+ TriState pureToBoolean() const;
JS_EXPORT_PRIVATE double toNumber(ExecState*) const;
JS_EXPORT_PRIVATE JSObject* toObject(ExecState*, JSGlobalObject*) const;
Modified: trunk/Source/_javascript_Core/runtime/JSCellInlines.h (149235 => 149236)
--- trunk/Source/_javascript_Core/runtime/JSCellInlines.h 2013-04-27 06:33:34 UTC (rev 149235)
+++ trunk/Source/_javascript_Core/runtime/JSCellInlines.h 2013-04-27 06:43:33 UTC (rev 149236)
@@ -192,6 +192,13 @@
return !structure()->masqueradesAsUndefined(exec->lexicalGlobalObject());
}
+inline TriState JSCell::pureToBoolean() const
+{
+ if (isString())
+ return static_cast<const JSString*>(this)->toBoolean() ? TrueTriState : FalseTriState;
+ return MixedTriState;
+}
+
} // namespace JSC
#endif // JSCellInlines_h
Modified: trunk/Source/WTF/ChangeLog (149235 => 149236)
--- trunk/Source/WTF/ChangeLog 2013-04-27 06:33:34 UTC (rev 149235)
+++ trunk/Source/WTF/ChangeLog 2013-04-27 06:43:33 UTC (rev 149236)
@@ -1,3 +1,17 @@
+2013-04-26 Geoffrey Garen <[email protected]>
+
+ Filled out more cases of branch folding in bytecode when emitting expressions into a branching context
+ https://bugs.webkit.org/show_bug.cgi?id=115057
+
+ Reviewed by Filip Pizlo.
+
+ Added a helper constructor for TriState so clients can make one without
+ branching or making assumptions about the integer values of TriStates.
+
+ * wtf/TriState.h:
+ (WTF::triState):
+ (WTF):
+
2013-04-26 Roger Fong <[email protected]>
Make Apple Windows VS2010 build results into and get dependencies from __32 suffixed folders.
Modified: trunk/Source/WTF/wtf/TriState.h (149235 => 149236)
--- trunk/Source/WTF/wtf/TriState.h 2013-04-27 06:33:34 UTC (rev 149235)
+++ trunk/Source/WTF/wtf/TriState.h 2013-04-27 06:43:33 UTC (rev 149236)
@@ -34,8 +34,13 @@
MixedTriState
};
+inline TriState triState(bool boolean)
+{
+ return static_cast<TriState>(boolean);
}
+}
+
using WTF::TriState;
using WTF::FalseTriState;
using WTF::TrueTriState;