Issue #2173 - Add TryNode

This is adjusted from upstream to follow our data structure with PNK_CATCHLIST

Based-on: m-c 1479659/8
This commit is contained in:
Martok 2023-04-02 01:29:38 +02:00 committed by roytam1
commit d4103253dd
7 changed files with 64 additions and 37 deletions

View file

@ -1825,7 +1825,7 @@ class ASTSerializer
bool blockStatement(ListNode* node, MutableHandleValue dst);
bool switchStatement(SwitchStatement* switchStmt, MutableHandleValue dst);
bool switchCase(CaseClause* caseClause, MutableHandleValue dst);
bool tryStatement(TernaryNode* tryNode, MutableHandleValue dst);
bool tryStatement(TryNode* tryNode, MutableHandleValue dst);
bool catchClause(TernaryNode* clauseNode, bool* isGuarded, MutableHandleValue dst);
bool optExpression(ParseNode* pn, MutableHandleValue dst) {
@ -2358,15 +2358,15 @@ ASTSerializer::catchClause(TernaryNode* clauseNode, bool* isGuarded, MutableHand
}
bool
ASTSerializer::tryStatement(TernaryNode* tryNode, MutableHandleValue dst)
ASTSerializer::tryStatement(TryNode* tryNode, MutableHandleValue dst)
{
ParseNode* bodyNode = tryNode->kid1();
ParseNode* bodyNode = tryNode->body();
MOZ_ASSERT(tryNode->pn_pos.encloses(bodyNode->pn_pos));
ParseNode* catchNode = tryNode->kid2();
MOZ_ASSERT_IF(catchNode, tryNode->pn_pos.encloses(catchNode->pn_pos));
ListNode* catchList = tryNode->catchList();
MOZ_ASSERT_IF(catchList, tryNode->pn_pos.encloses(catchList->pn_pos));
ParseNode* finallyNode = tryNode->kid3();
ParseNode* finallyNode = tryNode->finallyBlock();
MOZ_ASSERT_IF(finallyNode, tryNode->pn_pos.encloses(finallyNode->pn_pos));
RootedValue body(cx);
@ -2376,7 +2376,7 @@ ASTSerializer::tryStatement(TernaryNode* tryNode, MutableHandleValue dst)
NodeVector guarded(cx);
RootedValue unguarded(cx, NullValue());
if (ListNode* catchList = &catchNode->as<ListNode>()) {
if (catchList) {
if (!guarded.reserve(catchList->count()))
return false;
@ -2513,7 +2513,7 @@ ASTSerializer::statement(ParseNode* pn, MutableHandleValue dst)
return switchStatement(&pn->as<SwitchStatement>(), dst);
case PNK_TRY:
return tryStatement(&pn->as<TernaryNode>(), dst);
return tryStatement(&pn->as<TryNode>(), dst);
case PNK_WITH:
case PNK_WHILE:

View file

@ -1438,19 +1438,18 @@ BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer)
case PNK_TRY:
{
TernaryNode* tryNode = &pn->as<TernaryNode>();
if (!checkSideEffects(tryNode->kid1(), answer))
TryNode* tryNode = &pn->as<TryNode>();
if (!checkSideEffects(tryNode->body(), answer))
return false;
if (*answer)
return true;
if (ParseNode* catchList = tryNode->kid2()) {
MOZ_ASSERT(catchList->isKind(PNK_CATCHLIST));
if (ListNode* catchList = tryNode->catchList()) {
if (!checkSideEffects(catchList, answer))
return false;
if (*answer)
return true;
}
if (ParseNode* finallyBlock = tryNode->kid3()) {
if (ParseNode* finallyBlock = tryNode->finallyBlock()) {
if (!checkSideEffects(finallyBlock, answer))
return false;
}
@ -4220,10 +4219,10 @@ BytecodeEmitter::emitCatch(TernaryNode* catchNode)
// Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See the
// comment on EmitSwitch.
MOZ_NEVER_INLINE bool
BytecodeEmitter::emitTry(TernaryNode* tryNode)
BytecodeEmitter::emitTry(TryNode* tryNode)
{
ParseNode* catchList = tryNode->kid2();
ParseNode* finallyNode = tryNode->kid3();
ListNode* catchList = tryNode->catchList();
ParseNode* finallyNode = tryNode->finallyBlock();
TryEmitter::Kind kind;
if (catchList) {
@ -4240,13 +4239,11 @@ BytecodeEmitter::emitTry(TernaryNode* tryNode)
if (!tryCatch.emitTry())
return false;
if (!emitTree(tryNode->kid1()))
if (!emitTree(tryNode->body()))
return false;
// If this try has a catch block, emit it.
if (catchList) {
MOZ_ASSERT(catchList->isKind(PNK_CATCHLIST));
// The emitted code for a catch block looks like:
//
// [pushlexicalenv] only if any local aliased
@ -4272,7 +4269,7 @@ BytecodeEmitter::emitTry(TernaryNode* tryNode)
// code if appropriate, and is also used for the catch-all trynote for
// capturing exceptions thrown from catch{} blocks.
//
for (ParseNode* scopeNode : catchList->as<ListNode>().contents()) {
for (ParseNode* scopeNode : catchList->contents()) {
LexicalScopeNode* catchScope = &scopeNode->as<LexicalScopeNode>();
if (!tryCatch.emitCatch())
return false;
@ -8703,7 +8700,7 @@ BytecodeEmitter::emitTree(ParseNode* pn, ValueUsage valueUsage /* = ValueUsage::
break;
case PNK_TRY:
if (!emitTry(&pn->as<TernaryNode>()))
if (!emitTry(&pn->as<TryNode>()))
return false;
break;

View file

@ -592,7 +592,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter
MOZ_MUST_USE bool emitLexicalScopeBody(ParseNode* body,
EmitLineNumberNote emitLineNote = EMIT_LINENOTE);
MOZ_NEVER_INLINE MOZ_MUST_USE bool emitSwitch(SwitchStatement* switchStmt);
MOZ_NEVER_INLINE MOZ_MUST_USE bool emitTry(TernaryNode* tryNode);
MOZ_NEVER_INLINE MOZ_MUST_USE bool emitTry(TryNode* tryNode);
enum DestructuringFlavor {
// Destructuring into a declaration.

View file

@ -1230,10 +1230,9 @@ FoldReturn(ExclusiveContext* cx, UnaryNode* node, Parser<FullParseHandler>& pars
}
static bool
FoldTry(ExclusiveContext* cx, TernaryNode* node, Parser<FullParseHandler>& parser,
FoldTry(ExclusiveContext* cx, TryNode* node, Parser<FullParseHandler>& parser,
bool inGenexpLambda)
{
MOZ_ASSERT(node->isKind(PNK_TRY));
ParseNode** statements = node->unsafeKid1Reference();
if (!Fold(cx, statements, parser, inGenexpLambda))
return false;
@ -1845,7 +1844,7 @@ Fold(ExclusiveContext* cx, ParseNode** pnp, Parser<FullParseHandler>& parser, bo
return FoldReturn(cx, &pn->as<UnaryNode>(), parser, inGenexpLambda);
case PNK_TRY:
return FoldTry(cx, &pn->as<TernaryNode>(), parser, inGenexpLambda);
return FoldTry(cx, &pn->as<TryNode>(), parser, inGenexpLambda);
case PNK_CATCH:
return FoldCatch(cx, &pn->as<TernaryNode>(), parser, inGenexpLambda);

View file

@ -686,8 +686,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)
TernaryNodeType newTryStatement(uint32_t begin, Node body, ListNodeType catchList,
Node finallyBlock) {
TokenPos pos(begin, (finallyBlock ? finallyBlock : catchList)->pn_pos.end);
return new_<TernaryNode>(PNK_TRY, JSOP_NOP, body, catchList, finallyBlock, pos);
return new_<TryNode>(begin, body, catchList, finallyBlock);
}
DebuggerStatementType newDebuggerStatement(const TokenPos& pos) {

View file

@ -668,16 +668,15 @@ class NameResolver
// and finally block are optional (but at least one or the other must
// be present).
case PNK_TRY: {
TernaryNode* tryNode = &cur->as<TernaryNode>();
if (!resolve(tryNode->kid1(), prefix))
TryNode* tryNode = &cur->as<TryNode>();
if (!resolve(tryNode->body(), prefix))
return false;
MOZ_ASSERT(tryNode->kid2() || tryNode->kid3());
if (ParseNode* catchList = tryNode->kid2()) {
MOZ_ASSERT(catchList->isKind(PNK_CATCHLIST));
MOZ_ASSERT(tryNode->catchList() || tryNode->finallyBlock());
if (ListNode* catchList = tryNode->catchList()) {
if (!resolve(catchList, prefix))
return false;
}
if (ParseNode* finallyBlock = tryNode->kid3()) {
if (ParseNode* finallyBlock = tryNode->finallyBlock()) {
if (!resolve(finallyBlock, prefix))
return false;
}

View file

@ -308,10 +308,10 @@ IsTypeofKind(ParseNodeKind kind)
* kid3: update expr after second ';' or nullptr
* PNK_THROW (UnaryNode)
* kid: thrown exception
* PNK_TRY (TernaryNode)
* kid1: try block
* kid2: null or PNK_CATCHLIST list
* kid3: null or finally block
* PNK_TRY (TryNode)
* body: try block
* catchList: null or PNK_CATCHLIST list
* finallyBlock: null or finally block
* PNK_CATCHLIST (ListNode)
* head: list of PNK_LEXICALSCOPE nodes, one per catch-block,
* each with scopeBody pointing to a PNK_CATCH node
@ -593,6 +593,8 @@ enum ParseNodeArity
macro(TernaryNode, TernaryNodeType, asTernary) \
macro(ClassNode, ClassNodeType, asClass) \
macro(ConditionalExpression, ConditionalExpressionType, asConditionalExpression) \
macro(TryNode, TryNodeType, asTry) \
\
macro(UnaryNode, UnaryNodeType, asUnary) \
macro(ThisLiteral, ThisLiteralType, asThisLiteral)
@ -1711,6 +1713,37 @@ class ConditionalExpression : public TernaryNode
}
};
class TryNode : public TernaryNode
{
public:
TryNode(uint32_t begin, ParseNode* body, ListNode* catchList, ParseNode* finallyBlock)
: TernaryNode(PNK_TRY, JSOP_NOP, body, catchList, finallyBlock,
TokenPos(begin, (finallyBlock ? finallyBlock : catchList)->pn_pos.end))
{
MOZ_ASSERT(body);
MOZ_ASSERT(catchList || finallyBlock);
MOZ_ASSERT_IF(catchList, catchList->isKind(PNK_CATCHLIST));
}
static bool test(const ParseNode& node) {
bool match = node.isKind(PNK_TRY);
MOZ_ASSERT_IF(match, node.is<TernaryNode>());
return match;
}
ParseNode* body() const {
return kid1();
}
ListNode* catchList() const {
return kid2() ? &kid2()->as<ListNode>() : nullptr;
}
ParseNode* finallyBlock() const {
return kid3();
}
};
class ThisLiteral : public UnaryNode
{
public: