зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1660055 - Convert FoldConstants to use ParserAtoms. r=tcampbell
Differential Revision: https://phabricator.services.mozilla.com/D87643
This commit is contained in:
Родитель
7f624e0a5e
Коммит
0afd0b76f9
|
@ -29,6 +29,13 @@ using mozilla::IsNegative;
|
|||
using mozilla::NegativeInfinity;
|
||||
using mozilla::PositiveInfinity;
|
||||
|
||||
struct FoldInfo {
|
||||
CompilationInfo& compilationInfo;
|
||||
FullParseHandler* handler;
|
||||
|
||||
JSContext* cx() { return compilationInfo.cx; }
|
||||
};
|
||||
|
||||
// Don't use ReplaceNode directly, because we want the constant folder to keep
|
||||
// the attributes isInParens and isDirectRHSAnonFunction of the old node being
|
||||
// replaced.
|
||||
|
@ -448,19 +455,18 @@ restart:
|
|||
* Fold from one constant type to another.
|
||||
* XXX handles only strings and numbers for now
|
||||
*/
|
||||
static bool FoldType(JSContext* cx, FullParseHandler* handler, ParseNode** pnp,
|
||||
ParseNodeKind kind) {
|
||||
static bool FoldType(FoldInfo info, ParseNode** pnp, ParseNodeKind kind) {
|
||||
const ParseNode* pn = *pnp;
|
||||
if (!pn->isKind(kind)) {
|
||||
switch (kind) {
|
||||
case ParseNodeKind::NumberExpr:
|
||||
if (pn->isKind(ParseNodeKind::StringExpr)) {
|
||||
double d;
|
||||
if (!StringToNumber(cx, pn->as<NameNode>().atom(), &d)) {
|
||||
if (!StringToNumber(info.cx(), pn->as<NameNode>().atom(), &d)) {
|
||||
return false;
|
||||
}
|
||||
if (!TryReplaceNode(pnp,
|
||||
handler->newNumber(d, NoDecimal, pn->pn_pos))) {
|
||||
if (!TryReplaceNode(
|
||||
pnp, info.handler->newNumber(d, NoDecimal, pn->pn_pos))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -468,12 +474,12 @@ static bool FoldType(JSContext* cx, FullParseHandler* handler, ParseNode** pnp,
|
|||
|
||||
case ParseNodeKind::StringExpr:
|
||||
if (pn->isKind(ParseNodeKind::NumberExpr)) {
|
||||
JSAtom* atom = pn->as<NumericLiteral>().toAtom(cx);
|
||||
JSAtom* atom = pn->as<NumericLiteral>().toAtom(info.cx());
|
||||
if (!atom) {
|
||||
return false;
|
||||
}
|
||||
if (!TryReplaceNode(pnp,
|
||||
handler->newStringLiteral(atom, pn->pn_pos))) {
|
||||
if (!TryReplaceNode(
|
||||
pnp, info.handler->newStringLiteral(atom, pn->pn_pos))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -543,8 +549,7 @@ static Truthiness Boolish(ParseNode* pn) {
|
|||
}
|
||||
}
|
||||
|
||||
static bool SimplifyCondition(JSContext* cx, FullParseHandler* handler,
|
||||
ParseNode** nodePtr) {
|
||||
static bool SimplifyCondition(FoldInfo info, ParseNode** nodePtr) {
|
||||
// Conditions fold like any other expression, but then they sometimes can be
|
||||
// further folded to constants. *nodePtr should already have been
|
||||
// constant-folded.
|
||||
|
@ -556,8 +561,8 @@ static bool SimplifyCondition(JSContext* cx, FullParseHandler* handler,
|
|||
// that appears on a method list corrupts the method list. However,
|
||||
// methods are M's in statements of the form 'this.foo = M;', which we
|
||||
// never fold, so we're okay.
|
||||
if (!TryReplaceNode(
|
||||
nodePtr, handler->newBooleanLiteral(t == Truthy, node->pn_pos))) {
|
||||
if (!TryReplaceNode(nodePtr, info.handler->newBooleanLiteral(
|
||||
t == Truthy, node->pn_pos))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -565,33 +570,32 @@ static bool SimplifyCondition(JSContext* cx, FullParseHandler* handler,
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool FoldTypeOfExpr(JSContext* cx, FullParseHandler* handler,
|
||||
ParseNode** nodePtr) {
|
||||
static bool FoldTypeOfExpr(FoldInfo info, ParseNode** nodePtr) {
|
||||
UnaryNode* node = &(*nodePtr)->as<UnaryNode>();
|
||||
MOZ_ASSERT(node->isKind(ParseNodeKind::TypeOfExpr));
|
||||
ParseNode* expr = node->kid();
|
||||
|
||||
// Constant-fold the entire |typeof| if given a constant with known type.
|
||||
RootedPropertyName result(cx);
|
||||
RootedPropertyName result(info.cx());
|
||||
if (expr->isKind(ParseNodeKind::StringExpr) ||
|
||||
expr->isKind(ParseNodeKind::TemplateStringExpr)) {
|
||||
result = cx->names().string;
|
||||
result = info.cx()->names().string;
|
||||
} else if (expr->isKind(ParseNodeKind::NumberExpr)) {
|
||||
result = cx->names().number;
|
||||
result = info.cx()->names().number;
|
||||
} else if (expr->isKind(ParseNodeKind::BigIntExpr)) {
|
||||
result = cx->names().bigint;
|
||||
result = info.cx()->names().bigint;
|
||||
} else if (expr->isKind(ParseNodeKind::NullExpr)) {
|
||||
result = cx->names().object;
|
||||
result = info.cx()->names().object;
|
||||
} else if (expr->isKind(ParseNodeKind::TrueExpr) ||
|
||||
expr->isKind(ParseNodeKind::FalseExpr)) {
|
||||
result = cx->names().boolean;
|
||||
result = info.cx()->names().boolean;
|
||||
} else if (expr->is<FunctionNode>()) {
|
||||
result = cx->names().function;
|
||||
result = info.cx()->names().function;
|
||||
}
|
||||
|
||||
if (result) {
|
||||
if (!TryReplaceNode(nodePtr,
|
||||
handler->newStringLiteral(result, node->pn_pos))) {
|
||||
info.handler->newStringLiteral(result, node->pn_pos))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -599,8 +603,7 @@ static bool FoldTypeOfExpr(JSContext* cx, FullParseHandler* handler,
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool FoldDeleteExpr(JSContext* cx, FullParseHandler* handler,
|
||||
ParseNode** nodePtr) {
|
||||
static bool FoldDeleteExpr(FoldInfo info, ParseNode** nodePtr) {
|
||||
UnaryNode* node = &(*nodePtr)->as<UnaryNode>();
|
||||
|
||||
MOZ_ASSERT(node->isKind(ParseNodeKind::DeleteExpr));
|
||||
|
@ -610,7 +613,7 @@ static bool FoldDeleteExpr(JSContext* cx, FullParseHandler* handler,
|
|||
// For effectless expressions, eliminate the expression evaluation.
|
||||
if (IsEffectless(expr)) {
|
||||
if (!TryReplaceNode(nodePtr,
|
||||
handler->newBooleanLiteral(true, node->pn_pos))) {
|
||||
info.handler->newBooleanLiteral(true, node->pn_pos))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -618,8 +621,7 @@ static bool FoldDeleteExpr(JSContext* cx, FullParseHandler* handler,
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool FoldDeleteElement(JSContext* cx, FullParseHandler* handler,
|
||||
ParseNode** nodePtr) {
|
||||
static bool FoldDeleteElement(FoldInfo info, ParseNode** nodePtr) {
|
||||
UnaryNode* node = &(*nodePtr)->as<UnaryNode>();
|
||||
MOZ_ASSERT(node->isKind(ParseNodeKind::DeleteElemExpr));
|
||||
ParseNode* expr = node->kid();
|
||||
|
@ -635,7 +637,7 @@ static bool FoldDeleteElement(JSContext* cx, FullParseHandler* handler,
|
|||
if (expr->isKind(ParseNodeKind::DotExpr)) {
|
||||
// newDelete will detect and use DeletePropExpr
|
||||
if (!TryReplaceNode(nodePtr,
|
||||
handler->newDelete(node->pn_pos.begin, expr))) {
|
||||
info.handler->newDelete(node->pn_pos.begin, expr))) {
|
||||
return false;
|
||||
}
|
||||
MOZ_ASSERT((*nodePtr)->getKind() == ParseNodeKind::DeletePropExpr);
|
||||
|
@ -644,12 +646,11 @@ static bool FoldDeleteElement(JSContext* cx, FullParseHandler* handler,
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool FoldNot(JSContext* cx, FullParseHandler* handler,
|
||||
ParseNode** nodePtr) {
|
||||
static bool FoldNot(FoldInfo info, ParseNode** nodePtr) {
|
||||
UnaryNode* node = &(*nodePtr)->as<UnaryNode>();
|
||||
MOZ_ASSERT(node->isKind(ParseNodeKind::NotExpr));
|
||||
|
||||
if (!SimplifyCondition(cx, handler, node->unsafeKidReference())) {
|
||||
if (!SimplifyCondition(info, node->unsafeKidReference())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -659,8 +660,8 @@ static bool FoldNot(JSContext* cx, FullParseHandler* handler,
|
|||
expr->isKind(ParseNodeKind::FalseExpr)) {
|
||||
bool newval = !expr->isKind(ParseNodeKind::TrueExpr);
|
||||
|
||||
if (!TryReplaceNode(nodePtr,
|
||||
handler->newBooleanLiteral(newval, node->pn_pos))) {
|
||||
if (!TryReplaceNode(
|
||||
nodePtr, info.handler->newBooleanLiteral(newval, node->pn_pos))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -668,8 +669,7 @@ static bool FoldNot(JSContext* cx, FullParseHandler* handler,
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool FoldUnaryArithmetic(JSContext* cx, FullParseHandler* handler,
|
||||
ParseNode** nodePtr) {
|
||||
static bool FoldUnaryArithmetic(FoldInfo info, ParseNode** nodePtr) {
|
||||
UnaryNode* node = &(*nodePtr)->as<UnaryNode>();
|
||||
MOZ_ASSERT(node->isKind(ParseNodeKind::BitNotExpr) ||
|
||||
node->isKind(ParseNodeKind::PosExpr) ||
|
||||
|
@ -694,7 +694,7 @@ static bool FoldUnaryArithmetic(JSContext* cx, FullParseHandler* handler,
|
|||
}
|
||||
|
||||
if (!TryReplaceNode(nodePtr,
|
||||
handler->newNumber(d, NoDecimal, node->pn_pos))) {
|
||||
info.handler->newNumber(d, NoDecimal, node->pn_pos))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -702,7 +702,7 @@ static bool FoldUnaryArithmetic(JSContext* cx, FullParseHandler* handler,
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool FoldAndOrCoalesce(JSContext* cx, ParseNode** nodePtr) {
|
||||
static bool FoldAndOrCoalesce(FoldInfo info, ParseNode** nodePtr) {
|
||||
ListNode* node = &(*nodePtr)->as<ListNode>();
|
||||
|
||||
MOZ_ASSERT(node->isKind(ParseNodeKind::AndExpr) ||
|
||||
|
@ -779,10 +779,9 @@ static bool FoldAndOrCoalesce(JSContext* cx, ParseNode** nodePtr) {
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool Fold(JSContext* cx, FullParseHandler* handler, ParseNode** pnp);
|
||||
static bool Fold(FoldInfo info, ParseNode** pnp);
|
||||
|
||||
static bool FoldConditional(JSContext* cx, FullParseHandler* handler,
|
||||
ParseNode** nodePtr) {
|
||||
static bool FoldConditional(FoldInfo info, ParseNode** nodePtr) {
|
||||
ParseNode** nextNode = nodePtr;
|
||||
|
||||
do {
|
||||
|
@ -796,15 +795,15 @@ static bool FoldConditional(JSContext* cx, FullParseHandler* handler,
|
|||
MOZ_ASSERT(node->isKind(ParseNodeKind::ConditionalExpr));
|
||||
|
||||
ParseNode** expr = node->unsafeKid1Reference();
|
||||
if (!Fold(cx, handler, expr)) {
|
||||
if (!Fold(info, expr)) {
|
||||
return false;
|
||||
}
|
||||
if (!SimplifyCondition(cx, handler, expr)) {
|
||||
if (!SimplifyCondition(info, expr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ParseNode** ifTruthy = node->unsafeKid2Reference();
|
||||
if (!Fold(cx, handler, ifTruthy)) {
|
||||
if (!Fold(info, ifTruthy)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -821,7 +820,7 @@ static bool FoldConditional(JSContext* cx, FullParseHandler* handler,
|
|||
MOZ_ASSERT((*ifFalsy)->is<TernaryNode>());
|
||||
nextNode = ifFalsy;
|
||||
} else {
|
||||
if (!Fold(cx, handler, ifFalsy)) {
|
||||
if (!Fold(info, ifFalsy)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -847,8 +846,7 @@ static bool FoldConditional(JSContext* cx, FullParseHandler* handler,
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool FoldIf(JSContext* cx, FullParseHandler* handler,
|
||||
ParseNode** nodePtr) {
|
||||
static bool FoldIf(FoldInfo info, ParseNode** nodePtr) {
|
||||
ParseNode** nextNode = nodePtr;
|
||||
|
||||
do {
|
||||
|
@ -861,15 +859,15 @@ static bool FoldIf(JSContext* cx, FullParseHandler* handler,
|
|||
MOZ_ASSERT(node->isKind(ParseNodeKind::IfStmt));
|
||||
|
||||
ParseNode** expr = node->unsafeKid1Reference();
|
||||
if (!Fold(cx, handler, expr)) {
|
||||
if (!Fold(info, expr)) {
|
||||
return false;
|
||||
}
|
||||
if (!SimplifyCondition(cx, handler, expr)) {
|
||||
if (!SimplifyCondition(info, expr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ParseNode** consequent = node->unsafeKid2Reference();
|
||||
if (!Fold(cx, handler, consequent)) {
|
||||
if (!Fold(info, consequent)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -884,7 +882,7 @@ static bool FoldIf(JSContext* cx, FullParseHandler* handler,
|
|||
MOZ_ASSERT((*alternative)->is<TernaryNode>());
|
||||
nextNode = alternative;
|
||||
} else {
|
||||
if (!Fold(cx, handler, alternative)) {
|
||||
if (!Fold(info, alternative)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -914,7 +912,8 @@ static bool FoldIf(JSContext* cx, FullParseHandler* handler,
|
|||
// A declaration that hoists outside the discarded arm prevents the
|
||||
// |if| from being folded away.
|
||||
bool containsHoistedDecls;
|
||||
if (!ContainsHoistedDeclaration(cx, discarded, &containsHoistedDecls)) {
|
||||
if (!ContainsHoistedDeclaration(info.cx(), discarded,
|
||||
&containsHoistedDecls)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -929,7 +928,8 @@ static bool FoldIf(JSContext* cx, FullParseHandler* handler,
|
|||
// If there's no replacement node, we have a constantly-false |if|
|
||||
// with no |else|. Replace the entire thing with an empty
|
||||
// statement list.
|
||||
if (!TryReplaceNode(nodePtr, handler->newStatementList(node->pn_pos))) {
|
||||
if (!TryReplaceNode(nodePtr,
|
||||
info.handler->newStatementList(node->pn_pos))) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
|
@ -978,8 +978,7 @@ static double ComputeBinary(ParseNodeKind kind, double left, double right) {
|
|||
return int32_t((kind == ParseNodeKind::LshExpr) ? uint32_t(i) << j : i >> j);
|
||||
}
|
||||
|
||||
static bool FoldBinaryArithmetic(JSContext* cx, FullParseHandler* handler,
|
||||
ParseNode** nodePtr) {
|
||||
static bool FoldBinaryArithmetic(FoldInfo info, ParseNode** nodePtr) {
|
||||
ListNode* node = &(*nodePtr)->as<ListNode>();
|
||||
MOZ_ASSERT(node->isKind(ParseNodeKind::SubExpr) ||
|
||||
node->isKind(ParseNodeKind::MulExpr) ||
|
||||
|
@ -993,7 +992,7 @@ static bool FoldBinaryArithmetic(JSContext* cx, FullParseHandler* handler,
|
|||
// Fold each operand to a number if possible.
|
||||
ParseNode** listp = node->unsafeHeadReference();
|
||||
for (; *listp; listp = &(*listp)->pn_next) {
|
||||
if (!FoldType(cx, handler, listp, ParseNodeKind::NumberExpr)) {
|
||||
if (!FoldType(info, listp, ParseNodeKind::NumberExpr)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -1017,7 +1016,7 @@ static bool FoldBinaryArithmetic(JSContext* cx, FullParseHandler* handler,
|
|||
(*next)->as<NumericLiteral>().value());
|
||||
|
||||
TokenPos pos((*elem)->pn_pos.begin, (*next)->pn_pos.end);
|
||||
if (!TryReplaceNode(elem, handler->newNumber(d, NoDecimal, pos))) {
|
||||
if (!TryReplaceNode(elem, info.handler->newNumber(d, NoDecimal, pos))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1039,8 +1038,7 @@ static bool FoldBinaryArithmetic(JSContext* cx, FullParseHandler* handler,
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool FoldExponentiation(JSContext* cx, FullParseHandler* handler,
|
||||
ParseNode** nodePtr) {
|
||||
static bool FoldExponentiation(FoldInfo info, ParseNode** nodePtr) {
|
||||
ListNode* node = &(*nodePtr)->as<ListNode>();
|
||||
MOZ_ASSERT(node->isKind(ParseNodeKind::PowExpr));
|
||||
MOZ_ASSERT(node->count() >= 2);
|
||||
|
@ -1048,7 +1046,7 @@ static bool FoldExponentiation(JSContext* cx, FullParseHandler* handler,
|
|||
// Fold each operand, ideally into a number.
|
||||
ParseNode** listp = node->unsafeHeadReference();
|
||||
for (; *listp; listp = &(*listp)->pn_next) {
|
||||
if (!FoldType(cx, handler, listp, ParseNodeKind::NumberExpr)) {
|
||||
if (!FoldType(info, listp, ParseNodeKind::NumberExpr)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -1074,12 +1072,11 @@ static bool FoldExponentiation(JSContext* cx, FullParseHandler* handler,
|
|||
double d1 = base->as<NumericLiteral>().value();
|
||||
double d2 = exponent->as<NumericLiteral>().value();
|
||||
|
||||
return TryReplaceNode(
|
||||
nodePtr, handler->newNumber(ecmaPow(d1, d2), NoDecimal, node->pn_pos));
|
||||
return TryReplaceNode(nodePtr, info.handler->newNumber(
|
||||
ecmaPow(d1, d2), NoDecimal, node->pn_pos));
|
||||
}
|
||||
|
||||
static bool FoldElement(JSContext* cx, FullParseHandler* handler,
|
||||
ParseNode** nodePtr) {
|
||||
static bool FoldElement(FoldInfo info, ParseNode** nodePtr) {
|
||||
PropertyByValue* elem = &(*nodePtr)->as<PropertyByValue>();
|
||||
|
||||
ParseNode* expr = &elem->expression();
|
||||
|
@ -1092,8 +1089,9 @@ static bool FoldElement(JSContext* cx, FullParseHandler* handler,
|
|||
if (atom->isIndex(&index)) {
|
||||
// Optimization 1: We have something like expr["100"]. This is
|
||||
// equivalent to expr[100] which is faster.
|
||||
if (!TryReplaceNode(elem->unsafeRightReference(),
|
||||
handler->newNumber(index, NoDecimal, key->pn_pos))) {
|
||||
if (!TryReplaceNode(
|
||||
elem->unsafeRightReference(),
|
||||
info.handler->newNumber(index, NoDecimal, key->pn_pos))) {
|
||||
return false;
|
||||
}
|
||||
key = &elem->key();
|
||||
|
@ -1107,7 +1105,7 @@ static bool FoldElement(JSContext* cx, FullParseHandler* handler,
|
|||
// Optimization 2: We have something like expr[3.14]. The number
|
||||
// isn't an array index, so it converts to a string ("3.14"),
|
||||
// enabling optimization 3 below.
|
||||
JSAtom* atom = numeric->toAtom(cx);
|
||||
JSAtom* atom = numeric->toAtom(info.cx());
|
||||
if (!atom) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1123,20 +1121,19 @@ static bool FoldElement(JSContext* cx, FullParseHandler* handler,
|
|||
// Optimization 3: We have expr["foo"] where foo is not an index. Convert
|
||||
// to a property access (like expr.foo) that optimizes better downstream.
|
||||
|
||||
NameNode* propertyNameExpr = handler->newPropertyName(name, key->pn_pos);
|
||||
NameNode* propertyNameExpr = info.handler->newPropertyName(name, key->pn_pos);
|
||||
if (!propertyNameExpr) {
|
||||
return false;
|
||||
}
|
||||
if (!TryReplaceNode(nodePtr,
|
||||
handler->newPropertyAccess(expr, propertyNameExpr))) {
|
||||
if (!TryReplaceNode(
|
||||
nodePtr, info.handler->newPropertyAccess(expr, propertyNameExpr))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool FoldAdd(JSContext* cx, FullParseHandler* handler,
|
||||
ParseNode** nodePtr) {
|
||||
static bool FoldAdd(FoldInfo info, ParseNode** nodePtr) {
|
||||
ListNode* node = &(*nodePtr)->as<ListNode>();
|
||||
|
||||
MOZ_ASSERT(node->isKind(ParseNodeKind::AddExpr));
|
||||
|
@ -1160,8 +1157,8 @@ static bool FoldAdd(JSContext* cx, FullParseHandler* handler,
|
|||
double right = (*next)->as<NumericLiteral>().value();
|
||||
TokenPos pos((*current)->pn_pos.begin, (*next)->pn_pos.end);
|
||||
|
||||
if (!TryReplaceNode(current,
|
||||
handler->newNumber(left + right, NoDecimal, pos))) {
|
||||
if (!TryReplaceNode(
|
||||
current, info.handler->newNumber(left + right, NoDecimal, pos))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1183,7 +1180,7 @@ static bool FoldAdd(JSContext* cx, FullParseHandler* handler,
|
|||
// the list: (x + 1 + "2" !== x + "12") when x is a number.
|
||||
if ((*current)->isKind(ParseNodeKind::NumberExpr) &&
|
||||
(*next)->isKind(ParseNodeKind::StringExpr)) {
|
||||
if (!FoldType(cx, handler, current, ParseNodeKind::StringExpr)) {
|
||||
if (!FoldType(info, current, ParseNodeKind::StringExpr)) {
|
||||
return false;
|
||||
}
|
||||
next = &(*current)->pn_next;
|
||||
|
@ -1205,8 +1202,8 @@ static bool FoldAdd(JSContext* cx, FullParseHandler* handler,
|
|||
break;
|
||||
}
|
||||
|
||||
RootedString combination(cx);
|
||||
RootedString tmp(cx);
|
||||
RootedString combination(info.cx());
|
||||
RootedString tmp(info.cx());
|
||||
do {
|
||||
// Create a rope of the current string and all succeeding
|
||||
// constants that we can convert to strings, then atomize it
|
||||
|
@ -1217,7 +1214,7 @@ static bool FoldAdd(JSContext* cx, FullParseHandler* handler,
|
|||
|
||||
do {
|
||||
// Try folding the next operand to a string.
|
||||
if (!FoldType(cx, handler, next, ParseNodeKind::StringExpr)) {
|
||||
if (!FoldType(info, next, ParseNodeKind::StringExpr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1228,7 +1225,7 @@ static bool FoldAdd(JSContext* cx, FullParseHandler* handler,
|
|||
|
||||
// Add this string to the combination and remove the node.
|
||||
tmp = (*next)->as<NameNode>().atom();
|
||||
combination = ConcatStrings<CanGC>(cx, combination, tmp);
|
||||
combination = ConcatStrings<CanGC>(info.cx(), combination, tmp);
|
||||
if (!combination) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1241,7 +1238,7 @@ static bool FoldAdd(JSContext* cx, FullParseHandler* handler,
|
|||
|
||||
// Replace |current|'s string with the entire combination.
|
||||
MOZ_ASSERT((*current)->isKind(ParseNodeKind::StringExpr));
|
||||
combination = AtomizeString(cx, combination);
|
||||
combination = AtomizeString(info.cx(), combination);
|
||||
if (!combination) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1265,7 +1262,7 @@ static bool FoldAdd(JSContext* cx, FullParseHandler* handler,
|
|||
do {
|
||||
current = next;
|
||||
|
||||
if (!FoldType(cx, handler, current, ParseNodeKind::StringExpr)) {
|
||||
if (!FoldType(info, current, ParseNodeKind::StringExpr)) {
|
||||
return false;
|
||||
}
|
||||
next = &(*current)->pn_next;
|
||||
|
@ -1290,99 +1287,104 @@ static bool FoldAdd(JSContext* cx, FullParseHandler* handler,
|
|||
class FoldVisitor : public RewritingParseNodeVisitor<FoldVisitor> {
|
||||
using Base = RewritingParseNodeVisitor;
|
||||
|
||||
CompilationInfo& compilationInfo;
|
||||
FullParseHandler* handler;
|
||||
|
||||
FoldInfo info() const { return FoldInfo{compilationInfo, handler}; }
|
||||
|
||||
public:
|
||||
explicit FoldVisitor(JSContext* cx, FullParseHandler* handler)
|
||||
: RewritingParseNodeVisitor(cx), handler(handler) {}
|
||||
explicit FoldVisitor(JSContext* cx, CompilationInfo& compilationInfo,
|
||||
FullParseHandler* handler)
|
||||
: RewritingParseNodeVisitor(cx),
|
||||
compilationInfo(compilationInfo),
|
||||
handler(handler) {}
|
||||
|
||||
bool visitElemExpr(ParseNode*& pn) {
|
||||
return Base::visitElemExpr(pn) && FoldElement(cx_, handler, &pn);
|
||||
return Base::visitElemExpr(pn) && FoldElement(info(), &pn);
|
||||
}
|
||||
|
||||
bool visitTypeOfExpr(ParseNode*& pn) {
|
||||
return Base::visitTypeOfExpr(pn) && FoldTypeOfExpr(cx_, handler, &pn);
|
||||
return Base::visitTypeOfExpr(pn) && FoldTypeOfExpr(info(), &pn);
|
||||
}
|
||||
|
||||
bool visitDeleteExpr(ParseNode*& pn) {
|
||||
return Base::visitDeleteExpr(pn) && FoldDeleteExpr(cx_, handler, &pn);
|
||||
return Base::visitDeleteExpr(pn) && FoldDeleteExpr(info(), &pn);
|
||||
}
|
||||
|
||||
bool visitDeleteElemExpr(ParseNode*& pn) {
|
||||
return Base::visitDeleteElemExpr(pn) &&
|
||||
FoldDeleteElement(cx_, handler, &pn);
|
||||
return Base::visitDeleteElemExpr(pn) && FoldDeleteElement(info(), &pn);
|
||||
}
|
||||
|
||||
bool visitNotExpr(ParseNode*& pn) {
|
||||
return Base::visitNotExpr(pn) && FoldNot(cx_, handler, &pn);
|
||||
return Base::visitNotExpr(pn) && FoldNot(info(), &pn);
|
||||
}
|
||||
|
||||
bool visitBitNotExpr(ParseNode*& pn) {
|
||||
return Base::visitBitNotExpr(pn) && FoldUnaryArithmetic(cx_, handler, &pn);
|
||||
return Base::visitBitNotExpr(pn) && FoldUnaryArithmetic(info(), &pn);
|
||||
}
|
||||
|
||||
bool visitPosExpr(ParseNode*& pn) {
|
||||
return Base::visitPosExpr(pn) && FoldUnaryArithmetic(cx_, handler, &pn);
|
||||
return Base::visitPosExpr(pn) && FoldUnaryArithmetic(info(), &pn);
|
||||
}
|
||||
|
||||
bool visitNegExpr(ParseNode*& pn) {
|
||||
return Base::visitNegExpr(pn) && FoldUnaryArithmetic(cx_, handler, &pn);
|
||||
return Base::visitNegExpr(pn) && FoldUnaryArithmetic(info(), &pn);
|
||||
}
|
||||
|
||||
bool visitPowExpr(ParseNode*& pn) {
|
||||
return Base::visitPowExpr(pn) && FoldExponentiation(cx_, handler, &pn);
|
||||
return Base::visitPowExpr(pn) && FoldExponentiation(info(), &pn);
|
||||
}
|
||||
|
||||
bool visitMulExpr(ParseNode*& pn) {
|
||||
return Base::visitMulExpr(pn) && FoldBinaryArithmetic(cx_, handler, &pn);
|
||||
return Base::visitMulExpr(pn) && FoldBinaryArithmetic(info(), &pn);
|
||||
}
|
||||
|
||||
bool visitDivExpr(ParseNode*& pn) {
|
||||
return Base::visitDivExpr(pn) && FoldBinaryArithmetic(cx_, handler, &pn);
|
||||
return Base::visitDivExpr(pn) && FoldBinaryArithmetic(info(), &pn);
|
||||
}
|
||||
|
||||
bool visitModExpr(ParseNode*& pn) {
|
||||
return Base::visitModExpr(pn) && FoldBinaryArithmetic(cx_, handler, &pn);
|
||||
return Base::visitModExpr(pn) && FoldBinaryArithmetic(info(), &pn);
|
||||
}
|
||||
|
||||
bool visitAddExpr(ParseNode*& pn) {
|
||||
return Base::visitAddExpr(pn) && FoldAdd(cx_, handler, &pn);
|
||||
return Base::visitAddExpr(pn) && FoldAdd(info(), &pn);
|
||||
}
|
||||
|
||||
bool visitSubExpr(ParseNode*& pn) {
|
||||
return Base::visitSubExpr(pn) && FoldBinaryArithmetic(cx_, handler, &pn);
|
||||
return Base::visitSubExpr(pn) && FoldBinaryArithmetic(info(), &pn);
|
||||
}
|
||||
|
||||
bool visitLshExpr(ParseNode*& pn) {
|
||||
return Base::visitLshExpr(pn) && FoldBinaryArithmetic(cx_, handler, &pn);
|
||||
return Base::visitLshExpr(pn) && FoldBinaryArithmetic(info(), &pn);
|
||||
}
|
||||
|
||||
bool visitRshExpr(ParseNode*& pn) {
|
||||
return Base::visitRshExpr(pn) && FoldBinaryArithmetic(cx_, handler, &pn);
|
||||
return Base::visitRshExpr(pn) && FoldBinaryArithmetic(info(), &pn);
|
||||
}
|
||||
|
||||
bool visitUrshExpr(ParseNode*& pn) {
|
||||
return Base::visitUrshExpr(pn) && FoldBinaryArithmetic(cx_, handler, &pn);
|
||||
return Base::visitUrshExpr(pn) && FoldBinaryArithmetic(info(), &pn);
|
||||
}
|
||||
|
||||
bool visitAndExpr(ParseNode*& pn) {
|
||||
// Note that this does result in the unfortunate fact that dead arms of this
|
||||
// node get constant folded. The same goes for visitOr and visitCoalesce.
|
||||
return Base::visitAndExpr(pn) && FoldAndOrCoalesce(cx_, &pn);
|
||||
return Base::visitAndExpr(pn) && FoldAndOrCoalesce(info(), &pn);
|
||||
}
|
||||
|
||||
bool visitOrExpr(ParseNode*& pn) {
|
||||
return Base::visitOrExpr(pn) && FoldAndOrCoalesce(cx_, &pn);
|
||||
return Base::visitOrExpr(pn) && FoldAndOrCoalesce(info(), &pn);
|
||||
}
|
||||
|
||||
bool visitCoalesceExpr(ParseNode*& pn) {
|
||||
return Base::visitCoalesceExpr(pn) && FoldAndOrCoalesce(cx_, &pn);
|
||||
return Base::visitCoalesceExpr(pn) && FoldAndOrCoalesce(info(), &pn);
|
||||
}
|
||||
|
||||
bool visitConditionalExpr(ParseNode*& pn) {
|
||||
// Don't call base-class visitConditional because FoldConditional processes
|
||||
// pn's child nodes specially to save stack space.
|
||||
return FoldConditional(cx_, handler, &pn);
|
||||
return FoldConditional(info(), &pn);
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -1447,7 +1449,7 @@ class FoldVisitor : public RewritingParseNodeVisitor<FoldVisitor> {
|
|||
bool visitIfStmt(ParseNode*& pn) {
|
||||
// Don't call base-class visitIf because FoldIf processes pn's child nodes
|
||||
// specially to save stack space.
|
||||
return FoldIf(cx_, handler, &pn);
|
||||
return FoldIf(info(), &pn);
|
||||
}
|
||||
|
||||
bool visitForStmt(ParseNode*& pn) {
|
||||
|
@ -1460,7 +1462,7 @@ class FoldVisitor : public RewritingParseNodeVisitor<FoldVisitor> {
|
|||
TernaryNode& head = stmt.left()->as<TernaryNode>();
|
||||
ParseNode** test = head.unsafeKid2Reference();
|
||||
if (*test) {
|
||||
if (!SimplifyCondition(cx_, handler, test)) {
|
||||
if (!SimplifyCondition(info(), test)) {
|
||||
return false;
|
||||
}
|
||||
if ((*test)->isKind(ParseNodeKind::TrueExpr)) {
|
||||
|
@ -1475,13 +1477,13 @@ class FoldVisitor : public RewritingParseNodeVisitor<FoldVisitor> {
|
|||
bool visitWhileStmt(ParseNode*& pn) {
|
||||
BinaryNode& node = pn->as<BinaryNode>();
|
||||
return Base::visitWhileStmt(pn) &&
|
||||
SimplifyCondition(cx_, handler, node.unsafeLeftReference());
|
||||
SimplifyCondition(info(), node.unsafeLeftReference());
|
||||
}
|
||||
|
||||
bool visitDoWhileStmt(ParseNode*& pn) {
|
||||
BinaryNode& node = pn->as<BinaryNode>();
|
||||
return Base::visitDoWhileStmt(pn) &&
|
||||
SimplifyCondition(cx_, handler, node.unsafeRightReference());
|
||||
SimplifyCondition(info(), node.unsafeRightReference());
|
||||
}
|
||||
|
||||
bool visitFunction(ParseNode*& pn) {
|
||||
|
@ -1540,15 +1542,19 @@ class FoldVisitor : public RewritingParseNodeVisitor<FoldVisitor> {
|
|||
}
|
||||
};
|
||||
|
||||
bool Fold(JSContext* cx, FullParseHandler* handler, ParseNode** pnp) {
|
||||
FoldVisitor visitor(cx, handler);
|
||||
static bool Fold(JSContext* cx, CompilationInfo& compilationInfo,
|
||||
FullParseHandler* handler, ParseNode** pnp) {
|
||||
FoldVisitor visitor(cx, compilationInfo, handler);
|
||||
return visitor.visit(*pnp);
|
||||
}
|
||||
static bool Fold(FoldInfo info, ParseNode** pnp) {
|
||||
return Fold(info.cx(), info.compilationInfo, info.handler, pnp);
|
||||
}
|
||||
|
||||
bool frontend::FoldConstants(JSContext* cx, ParseNode** pnp,
|
||||
FullParseHandler* handler) {
|
||||
bool frontend::FoldConstants(JSContext* cx, CompilationInfo& compilationInfo,
|
||||
ParseNode** pnp, FullParseHandler* handler) {
|
||||
AutoTraceLog traceLog(TraceLoggerForCurrentThread(cx),
|
||||
TraceLogger_BytecodeFoldConstants);
|
||||
|
||||
return Fold(cx, handler, pnp);
|
||||
return Fold(cx, compilationInfo, handler, pnp);
|
||||
}
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
namespace js {
|
||||
namespace frontend {
|
||||
|
||||
struct CompilationInfo;
|
||||
|
||||
class FullParseHandler;
|
||||
template <class ParseHandler>
|
||||
class PerHandlerParser;
|
||||
|
@ -31,12 +33,15 @@ class PerHandlerParser;
|
|||
// if (!FoldConstants(cx, &pn, parser)) {
|
||||
// return false;
|
||||
// }
|
||||
extern MOZ_MUST_USE bool FoldConstants(JSContext* cx, ParseNode** pnp,
|
||||
FullParseHandler* parser);
|
||||
extern MOZ_MUST_USE bool FoldConstants(JSContext* cx,
|
||||
CompilationInfo& compilationInfo,
|
||||
ParseNode** pnp,
|
||||
FullParseHandler* handler);
|
||||
|
||||
inline MOZ_MUST_USE bool FoldConstants(JSContext* cx,
|
||||
CompilationInfo& compilationInfo,
|
||||
typename SyntaxParseHandler::Node* pnp,
|
||||
SyntaxParseHandler* parser) {
|
||||
SyntaxParseHandler* handler) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -384,7 +384,7 @@ typename ParseHandler::ListNodeType GeneralParser<ParseHandler, Unit>::parse() {
|
|||
// Don't constant-fold inside "use asm" code, as this could create a parse
|
||||
// tree that doesn't type-check as asm.js.
|
||||
if (!pc_->useAsmOrInsideUseAsm()) {
|
||||
if (!FoldConstants(cx_, &node, &handler_)) {
|
||||
if (!FoldConstants(cx_, this->getCompilationInfo(), &node, &handler_)) {
|
||||
return null();
|
||||
}
|
||||
}
|
||||
|
@ -1561,7 +1561,7 @@ LexicalScopeNode* Parser<FullParseHandler, Unit>::evalBody(
|
|||
// Don't constant-fold inside "use asm" code, as this could create a parse
|
||||
// tree that doesn't type-check as asm.js.
|
||||
if (!pc_->useAsmOrInsideUseAsm()) {
|
||||
if (!FoldConstants(cx_, &node, &handler_)) {
|
||||
if (!FoldConstants(cx_, this->getCompilationInfo(), &node, &handler_)) {
|
||||
return null();
|
||||
}
|
||||
}
|
||||
|
@ -1621,7 +1621,7 @@ ListNode* Parser<FullParseHandler, Unit>::globalBody(
|
|||
// Don't constant-fold inside "use asm" code, as this could create a parse
|
||||
// tree that doesn't type-check as asm.js.
|
||||
if (!pc_->useAsmOrInsideUseAsm()) {
|
||||
if (!FoldConstants(cx_, &node, &handler_)) {
|
||||
if (!FoldConstants(cx_, this->getCompilationInfo(), &node, &handler_)) {
|
||||
return null();
|
||||
}
|
||||
}
|
||||
|
@ -1732,7 +1732,7 @@ ModuleNode* Parser<FullParseHandler, Unit>::moduleBody(
|
|||
// Don't constant-fold inside "use asm" code, as this could create a parse
|
||||
// tree that doesn't type-check as asm.js.
|
||||
if (!pc_->useAsmOrInsideUseAsm()) {
|
||||
if (!FoldConstants(cx_, &node, &handler_)) {
|
||||
if (!FoldConstants(cx_, this->getCompilationInfo(), &node, &handler_)) {
|
||||
return null();
|
||||
}
|
||||
}
|
||||
|
@ -2121,7 +2121,7 @@ FunctionNode* Parser<FullParseHandler, Unit>::standaloneFunction(
|
|||
// Don't constant-fold inside "use asm" code, as this could create a parse
|
||||
// tree that doesn't type-check as asm.js.
|
||||
if (!pc_->useAsmOrInsideUseAsm()) {
|
||||
if (!FoldConstants(cx_, &node, &handler_)) {
|
||||
if (!FoldConstants(cx_, this->getCompilationInfo(), &node, &handler_)) {
|
||||
return null();
|
||||
}
|
||||
}
|
||||
|
@ -3195,7 +3195,7 @@ FunctionNode* Parser<FullParseHandler, Unit>::standaloneLazyFunction(
|
|||
// Don't constant-fold inside "use asm" code, as this could create a parse
|
||||
// tree that doesn't type-check as asm.js.
|
||||
if (!pc_->useAsmOrInsideUseAsm()) {
|
||||
if (!FoldConstants(cx_, &node, &handler_)) {
|
||||
if (!FoldConstants(cx_, this->getCompilationInfo(), &node, &handler_)) {
|
||||
return null();
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче