Stop pretending that statements return a value
https://bugs.webkit.org/show_bug.cgi?id=113969
Reviewed by Oliver Hunt.
Expressions have an intrinsic value, which they return to their parent
in the AST.
Statements just execute for effect in sequence.
This patch moves emitBytecode into the ExpressionNode and StatementNode
subclasses, and changes the SatementNode subclass to return void. This
eliminates some cruft where we used to return 0, or try to save a bogus
register and return it, as if a statement had a consuming parent in the
AST.
* bytecompiler/BytecodeGenerator.h:
(JSC::BytecodeGenerator::emitNode):
(BytecodeGenerator):
(JSC::BytecodeGenerator::emitNodeInConditionContext):
* bytecompiler/NodesCodegen.cpp:
(JSC::ConstStatementNode::emitBytecode):
(JSC::BlockNode::emitBytecode):
(JSC::EmptyStatementNode::emitBytecode):
(JSC::DebuggerStatementNode::emitBytecode):
(JSC::ExprStatementNode::emitBytecode):
(JSC::VarStatementNode::emitBytecode):
(JSC::IfNode::emitBytecode):
(JSC::IfElseNode::emitBytecode):
(JSC::DoWhileNode::emitBytecode):
(JSC::WhileNode::emitBytecode):
(JSC::ForNode::emitBytecode):
(JSC::ForInNode::emitBytecode):
(JSC::ContinueNode::emitBytecode):
(JSC::BreakNode::emitBytecode):
(JSC::ReturnNode::emitBytecode):
(JSC::WithNode::emitBytecode):
(JSC::CaseClauseNode::emitBytecode):
(JSC::CaseBlockNode::emitBytecodeForBlock):
(JSC::SwitchNode::emitBytecode):
(JSC::LabelNode::emitBytecode):
(JSC::ThrowNode::emitBytecode):
(JSC::TryNode::emitBytecode):
(JSC::ScopeNode::emitStatementsBytecode):
(JSC::ProgramNode::emitBytecode):
(JSC::EvalNode::emitBytecode):
(JSC::FunctionBodyNode::emitBytecode):
(JSC::FuncDeclNode::emitBytecode):
* parser/NodeConstructors.h:
(JSC::PropertyListNode::PropertyListNode):
(JSC::ArgumentListNode::ArgumentListNode):
* parser/Nodes.h:
(Node):
(ExpressionNode):
(StatementNode):
(ConstStatementNode):
(BlockNode):
(EmptyStatementNode):
(DebuggerStatementNode):
(ExprStatementNode):
(VarStatementNode):
(IfNode):
(IfElseNode):
(DoWhileNode):
(WhileNode):
(ForNode):
(ForInNode):
(ContinueNode):
(BreakNode):
(ReturnNode):
(WithNode):
(LabelNode):
(ThrowNode):
(TryNode):
(ProgramNode):
(EvalNode):
(FunctionBodyNode):
(FuncDeclNode):
(CaseBlockNode):
(SwitchNode):
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@147677 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
index aaec47e..5d5c0e4 100644
--- a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
+++ b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
@@ -334,22 +334,34 @@
LabelScopePtr newLabelScope(LabelScope::Type, const Identifier* = 0);
PassRefPtr<Label> newLabel();
- // The emitNode functions are just syntactic sugar for calling
- // Node::emitCode. These functions accept a 0 for the register,
- // meaning that the node should allocate a register, or ignoredResult(),
- // meaning that the node need not put the result in a register.
- // Other emit functions do not accept 0 or ignoredResult().
- RegisterID* emitNode(RegisterID* dst, Node* n)
+ void emitNode(RegisterID* dst, StatementNode* n)
{
// Node::emitCode assumes that dst, if provided, is either a local or a referenced temporary.
ASSERT(!dst || dst == ignoredResult() || !dst->isTemporary() || dst->refCount());
addLineInfo(n->lineNo());
- return m_stack.isSafeToRecurse()
- ? n->emitBytecode(*this, dst)
- : emitThrowExpressionTooDeepException();
+ if (!m_stack.isSafeToRecurse()) {
+ emitThrowExpressionTooDeepException();
+ return;
+ }
+ n->emitBytecode(*this, dst);
}
- RegisterID* emitNode(Node* n)
+ void emitNode(StatementNode* n)
+ {
+ emitNode(0, n);
+ }
+
+ RegisterID* emitNode(RegisterID* dst, ExpressionNode* n)
+ {
+ // Node::emitCode assumes that dst, if provided, is either a local or a referenced temporary.
+ ASSERT(!dst || dst == ignoredResult() || !dst->isTemporary() || dst->refCount());
+ addLineInfo(n->lineNo());
+ if (!m_stack.isSafeToRecurse())
+ return emitThrowExpressionTooDeepException();
+ return n->emitBytecode(*this, dst);
+ }
+
+ RegisterID* emitNode(ExpressionNode* n)
{
return emitNode(0, n);
}
@@ -357,10 +369,12 @@
void emitNodeInConditionContext(ExpressionNode* n, Label* trueTarget, Label* falseTarget, FallThroughMode fallThroughMode)
{
addLineInfo(n->lineNo());
- if (m_stack.isSafeToRecurse())
- n->emitBytecodeInConditionContext(*this, trueTarget, falseTarget, fallThroughMode);
- else
+ if (!m_stack.isSafeToRecurse()) {
emitThrowExpressionTooDeepException();
+ return;
+ }
+
+ n->emitBytecodeInConditionContext(*this, trueTarget, falseTarget, fallThroughMode);
}
void emitExpressionInfo(unsigned divot, unsigned startOffset, unsigned endOffset)
diff --git a/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp b/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
index fb5811d..7398608 100644
--- a/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
+++ b/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
@@ -1431,10 +1431,10 @@
// ------------------------------ ConstStatementNode -----------------------------
-RegisterID* ConstStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
+void ConstStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
{
generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), charPosition());
- return generator.emitNode(m_next);
+ generator.emitNode(m_next);
}
// ------------------------------ SourceElements -------------------------------
@@ -1465,50 +1465,48 @@
return m_statements ? m_statements->singleStatement() : 0;
}
-RegisterID* BlockNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+void BlockNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
{
- if (m_statements)
- m_statements->emitBytecode(generator, dst);
- return 0;
+ if (!m_statements)
+ return;
+ m_statements->emitBytecode(generator, dst);
}
// ------------------------------ EmptyStatementNode ---------------------------
-RegisterID* EmptyStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+void EmptyStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
{
generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), charPosition());
- return dst;
}
// ------------------------------ DebuggerStatementNode ---------------------------
-RegisterID* DebuggerStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+void DebuggerStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
{
generator.emitDebugHook(DidReachBreakpoint, firstLine(), lastLine(), charPosition());
- return dst;
}
// ------------------------------ ExprStatementNode ----------------------------
-RegisterID* ExprStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+void ExprStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
{
ASSERT(m_expr);
generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), charPosition());
- return generator.emitNode(dst, m_expr);
+ generator.emitNode(dst, m_expr);
}
// ------------------------------ VarStatementNode ----------------------------
-RegisterID* VarStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
+void VarStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
{
ASSERT(m_expr);
generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), charPosition());
- return generator.emitNode(m_expr);
+ generator.emitNode(m_expr);
}
// ------------------------------ IfNode ---------------------------------------
-RegisterID* IfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+void IfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
{
generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), charPosition());
@@ -1520,14 +1518,11 @@
generator.emitNode(dst, m_ifBlock);
generator.emitLabel(afterThen.get());
-
- // FIXME: This should return the last statement executed so that it can be returned as a Completion.
- return 0;
}
// ------------------------------ IfElseNode ---------------------------------------
-RegisterID* IfElseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+void IfElseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
{
generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), charPosition());
@@ -1546,14 +1541,11 @@
generator.emitNode(dst, m_elseBlock);
generator.emitLabel(afterElse.get());
-
- // FIXME: This should return the last statement executed so that it can be returned as a Completion.
- return 0;
}
// ------------------------------ DoWhileNode ----------------------------------
-RegisterID* DoWhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+void DoWhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
{
LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
@@ -1562,19 +1554,18 @@
generator.emitLoopHint();
generator.emitDebugHook(WillExecuteStatement, lastLine(), lastLine(), charPosition());
- RefPtr<RegisterID> result = generator.emitNode(dst, m_statement);
+ generator.emitNode(dst, m_statement);
generator.emitLabel(scope->continueTarget());
generator.emitDebugHook(WillExecuteStatement, lastLine(), lastLine(), charPosition());
generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), FallThroughMeansFalse);
generator.emitLabel(scope->breakTarget());
- return result.get();
}
// ------------------------------ WhileNode ------------------------------------
-RegisterID* WhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+void WhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
{
LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
RefPtr<Label> topOfLoop = generator.newLabel();
@@ -1593,14 +1584,11 @@
generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), FallThroughMeansFalse);
generator.emitLabel(scope->breakTarget());
-
- // FIXME: This should return the last statement executed so that it can be returned as a Completion
- return 0;
}
// ------------------------------ ForNode --------------------------------------
-RegisterID* ForNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+void ForNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
{
LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
@@ -1616,7 +1604,7 @@
generator.emitLabel(topOfLoop.get());
generator.emitLoopHint();
- RefPtr<RegisterID> result = generator.emitNode(dst, m_statement);
+ generator.emitNode(dst, m_statement);
generator.emitLabel(scope->continueTarget());
generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), charPosition());
@@ -1629,17 +1617,18 @@
generator.emitJump(topOfLoop.get());
generator.emitLabel(scope->breakTarget());
- return result.get();
}
// ------------------------------ ForInNode ------------------------------------
-RegisterID* ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+void ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
{
LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
- if (!m_lexpr->isLocation())
- return emitThrowReferenceError(generator, "Left side of for-in statement is not a reference.");
+ if (!m_lexpr->isLocation()) {
+ emitThrowReferenceError(generator, "Left side of for-in statement is not a reference.");
+ return;
+ }
generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), charPosition());
@@ -1707,13 +1696,11 @@
generator.emitNextPropertyName(propertyName, base.get(), i.get(), size.get(), iter.get(), loopStart.get());
generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), charPosition());
generator.emitLabel(scope->breakTarget());
- return dst;
}
// ------------------------------ ContinueNode ---------------------------------
-// ECMA 12.7
-RegisterID* ContinueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+void ContinueNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
{
generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), charPosition());
@@ -1722,13 +1709,11 @@
generator.emitPopScopes(scope->scopeDepth());
generator.emitJump(scope->continueTarget());
- return dst;
}
// ------------------------------ BreakNode ------------------------------------
-// ECMA 12.8
-RegisterID* BreakNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+void BreakNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
{
generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), charPosition());
@@ -1737,12 +1722,11 @@
generator.emitPopScopes(scope->scopeDepth());
generator.emitJump(scope->breakTarget());
- return dst;
}
// ------------------------------ ReturnNode -----------------------------------
-RegisterID* ReturnNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+void ReturnNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
{
generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), charPosition());
ASSERT(generator.codeType() == FunctionCode);
@@ -1757,29 +1741,29 @@
}
generator.emitDebugHook(WillLeaveCallFrame, firstLine(), lastLine(), charPosition());
- return generator.emitReturn(returnRegister.get());
+ generator.emitReturn(returnRegister.get());
}
// ------------------------------ WithNode -------------------------------------
-RegisterID* WithNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+void WithNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
{
generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), charPosition());
RefPtr<RegisterID> scope = generator.emitNode(m_expr);
generator.emitExpressionInfo(m_divot, m_expressionLength, 0);
generator.emitPushWithScope(scope.get());
- RegisterID* result = generator.emitNode(dst, m_statement);
+ generator.emitNode(dst, m_statement);
generator.emitPopScope();
- return result;
}
// ------------------------------ CaseClauseNode --------------------------------
inline void CaseClauseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
{
- if (m_statements)
- m_statements->emitBytecode(generator, dst);
+ if (!m_statements)
+ return;
+ m_statements->emitBytecode(generator, dst);
}
// ------------------------------ CaseBlockNode --------------------------------
@@ -1873,7 +1857,7 @@
return SwitchInfo::SwitchString;
}
-RegisterID* CaseBlockNode::emitBytecodeForBlock(BytecodeGenerator& generator, RegisterID* switchExpression, RegisterID* dst)
+void CaseBlockNode::emitBytecodeForBlock(BytecodeGenerator& generator, RegisterID* switchExpression, RegisterID* dst)
{
RefPtr<Label> defaultLabel;
Vector<RefPtr<Label>, 8> labelVector;
@@ -1909,8 +1893,6 @@
generator.emitJump(defaultLabel.get());
}
- RegisterID* result = 0;
-
size_t i = 0;
for (ClauseListNode* list = m_list1; list; list = list->getNext()) {
generator.emitLabel(labelVector[i++].get());
@@ -1934,42 +1916,39 @@
ASSERT(labelVector.size() == literalVector.size());
generator.endSwitch(labelVector.size(), labelVector.data(), literalVector.data(), defaultLabel.get(), min_num, max_num);
}
- return result;
}
// ------------------------------ SwitchNode -----------------------------------
-RegisterID* SwitchNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+void SwitchNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
{
generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), charPosition());
LabelScopePtr scope = generator.newLabelScope(LabelScope::Switch);
RefPtr<RegisterID> r0 = generator.emitNode(m_expr);
- RegisterID* r1 = m_block->emitBytecodeForBlock(generator, r0.get(), dst);
+ m_block->emitBytecodeForBlock(generator, r0.get(), dst);
generator.emitLabel(scope->breakTarget());
- return r1;
}
// ------------------------------ LabelNode ------------------------------------
-RegisterID* LabelNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+void LabelNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
{
generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), charPosition());
ASSERT(!generator.breakTarget(m_name));
LabelScopePtr scope = generator.newLabelScope(LabelScope::NamedLabel, &m_name);
- RegisterID* r0 = generator.emitNode(dst, m_statement);
+ generator.emitNode(dst, m_statement);
generator.emitLabel(scope->breakTarget());
- return r0;
}
// ------------------------------ ThrowNode ------------------------------------
-RegisterID* ThrowNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+void ThrowNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
{
generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), charPosition());
@@ -1978,12 +1957,11 @@
RefPtr<RegisterID> expr = generator.emitNode(m_expr);
generator.emitExpressionInfo(divot(), startOffset(), endOffset());
generator.emitThrow(expr.get());
- return 0;
}
// ------------------------------ TryNode --------------------------------------
-RegisterID* TryNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+void TryNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
{
// NOTE: The catch and finally blocks must be labeled explicitly, so the
// optimizer knows they may be jumped to from anywhere.
@@ -2041,21 +2019,20 @@
generator.emitLabel(finallyEndLabel.get());
}
-
- return dst;
}
// ------------------------------ ScopeNode -----------------------------
inline void ScopeNode::emitStatementsBytecode(BytecodeGenerator& generator, RegisterID* dst)
{
- if (m_statements)
- m_statements->emitBytecode(generator, dst);
+ if (!m_statements)
+ return;
+ m_statements->emitBytecode(generator, dst);
}
// ------------------------------ ProgramNode -----------------------------
-RegisterID* ProgramNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
+void ProgramNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
{
generator.emitDebugHook(WillExecuteProgram, startLine(), startLine(), startCharPosition());
@@ -2065,12 +2042,11 @@
generator.emitDebugHook(DidExecuteProgram, lastLine(), lastLine(), charPosition() - 1);
generator.emitEnd(dstRegister.get());
- return 0;
}
// ------------------------------ EvalNode -----------------------------
-RegisterID* EvalNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
+void EvalNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
{
generator.emitDebugHook(WillExecuteProgram, startLine(), startLine(), startCharPosition());
@@ -2080,12 +2056,11 @@
generator.emitDebugHook(DidExecuteProgram, lastLine(), lastLine(), charPosition() - 1);
generator.emitEnd(dstRegister.get());
- return 0;
}
// ------------------------------ FunctionBodyNode -----------------------------
-RegisterID* FunctionBodyNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
+void FunctionBodyNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
{
generator.emitDebugHook(DidEnterCallFrame, startLine(), startLine(), startCharPosition());
emitStatementsBytecode(generator, generator.ignoredResult());
@@ -2106,7 +2081,7 @@
ASSERT((charPosition() - 1) >= 0);
generator.emitDebugHook(WillLeaveCallFrame, lastLine(), lastLine(), charPosition() - 1);
generator.emitReturn(r0);
- return 0;
+ return;
}
// If there is a return statment, and it is the only statement in the function, check if this is a numeric compare.
@@ -2124,17 +2099,12 @@
}
}
}
-
- return 0;
}
// ------------------------------ FuncDeclNode ---------------------------------
-RegisterID* FuncDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+void FuncDeclNode::emitBytecode(BytecodeGenerator&, RegisterID*)
{
- if (dst == generator.ignoredResult())
- dst = 0;
- return dst;
}
// ------------------------------ FuncExprNode ---------------------------------