Bug 1516697 - Make AsmJSParser a template typedef and {Module,Function}Validator template classes. r=arai

This commit is contained in:
Jeff Walden 2018-12-28 21:00:57 -06:00
parent ea1a7af6af
commit fcdd8f5160
2 changed files with 196 additions and 100 deletions

View File

@ -204,6 +204,7 @@ class AsmJSGlobal {
CacheableChars field_;
friend class ModuleValidatorShared;
template <typename Unit>
friend class ModuleValidator;
public:
@ -645,7 +646,8 @@ static inline ParseNode* NextNonEmptyStatement(ParseNode* pn) {
return SkipEmptyStatements(pn->pn_next);
}
static bool GetToken(AsmJSParser& parser, TokenKind* tkp) {
template <typename Unit>
static bool GetToken(AsmJSParser<Unit>& parser, TokenKind* tkp) {
auto& ts = parser.tokenStream;
TokenKind tk;
while (true) {
@ -660,7 +662,8 @@ static bool GetToken(AsmJSParser& parser, TokenKind* tkp) {
return true;
}
static bool PeekToken(AsmJSParser& parser, TokenKind* tkp) {
template <typename Unit>
static bool PeekToken(AsmJSParser<Unit>& parser, TokenKind* tkp) {
auto& ts = parser.tokenStream;
TokenKind tk;
while (true) {
@ -676,7 +679,9 @@ static bool PeekToken(AsmJSParser& parser, TokenKind* tkp) {
return true;
}
static bool ParseVarOrConstStatement(AsmJSParser& parser, ParseNode** var) {
template <typename Unit>
static bool ParseVarOrConstStatement(AsmJSParser<Unit>& parser,
ParseNode** var) {
TokenKind tk;
if (!PeekToken(parser, &tk)) {
return false;
@ -1196,6 +1201,7 @@ class MOZ_STACK_CLASS JS_HAZ_ROOTED ModuleValidatorShared {
} u;
friend class ModuleValidatorShared;
template <typename Unit>
friend class ModuleValidator;
friend class js::LifoAlloc;
@ -1876,13 +1882,14 @@ class MOZ_STACK_CLASS JS_HAZ_ROOTED ModuleValidatorShared {
//
// ModuleValidator is marked as rooted in the rooting analysis. Don't add
// non-JSAtom pointers, or this will break!
template <typename Unit>
class MOZ_STACK_CLASS JS_HAZ_ROOTED ModuleValidator
: public ModuleValidatorShared {
private:
AsmJSParser& parser_;
AsmJSParser<Unit>& parser_;
public:
ModuleValidator(JSContext* cx, AsmJSParser& parser,
ModuleValidator(JSContext* cx, AsmJSParser<Unit>& parser,
CodeNode* moduleFunctionNode)
: ModuleValidatorShared(cx, moduleFunctionNode), parser_(parser) {}
@ -1972,7 +1979,7 @@ class MOZ_STACK_CLASS JS_HAZ_ROOTED ModuleValidator
return true;
}
AsmJSParser& parser() const { return parser_; }
AsmJSParser<Unit>& parser() const { return parser_; }
auto tokenStream() const -> decltype(parser_.tokenStream)& {
return parser_.tokenStream;
@ -2349,7 +2356,7 @@ class MOZ_STACK_CLASS FunctionValidatorShared {
using LocalMap = HashMap<PropertyName*, Local>;
using LabelMap = HashMap<PropertyName*, uint32_t>;
// This is also a ModuleValidator& after the appropriate static_cast<>.
// This is also a ModuleValidator<Unit>& after the appropriate static_cast<>.
ModuleValidatorShared& m_;
ParseNode* fn_;
@ -2382,7 +2389,9 @@ class MOZ_STACK_CLASS FunctionValidatorShared {
ret_(ExprType::Limit) {}
protected:
FunctionValidatorShared(ModuleValidator& m, ParseNode* fn, JSContext* cx)
template <typename Unit>
FunctionValidatorShared(ModuleValidator<Unit>& m, ParseNode* fn,
JSContext* cx)
: FunctionValidatorShared(static_cast<ModuleValidatorShared&>(m), fn,
cx) {}
@ -2614,14 +2623,15 @@ class MOZ_STACK_CLASS FunctionValidatorShared {
// Encapsulates the building of an asm bytecode function from an asm.js function
// source code, packing the asm.js code into the asm bytecode form that can
// be decoded and compiled with a FunctionCompiler.
template <typename Unit>
class MOZ_STACK_CLASS FunctionValidator : public FunctionValidatorShared {
public:
FunctionValidator(ModuleValidator& m, ParseNode* fn)
FunctionValidator(ModuleValidator<Unit>& m, ParseNode* fn)
: FunctionValidatorShared(m, fn, m.cx()) {}
public:
ModuleValidator& m() const {
return static_cast<ModuleValidator&>(FunctionValidatorShared::m());
ModuleValidator<Unit>& m() const {
return static_cast<ModuleValidator<Unit>&>(FunctionValidatorShared::m());
}
MOZ_MUST_USE bool writeCall(ParseNode* pn, Op op) {
@ -3078,7 +3088,8 @@ static bool CheckModuleGlobal(ModuleValidatorShared& m, ParseNode* var,
return m.fail(initNode, "unsupported import expression");
}
static bool CheckModuleProcessingDirectives(ModuleValidator& m) {
template <typename Unit>
static bool CheckModuleProcessingDirectives(ModuleValidator<Unit>& m) {
auto& ts = m.parser().tokenStream;
while (true) {
bool matched;
@ -3105,7 +3116,8 @@ static bool CheckModuleProcessingDirectives(ModuleValidator& m) {
}
}
static bool CheckModuleGlobals(ModuleValidator& m) {
template <typename Unit>
static bool CheckModuleGlobals(ModuleValidator<Unit>& m) {
while (true) {
ParseNode* varStmt;
if (!ParseVarOrConstStatement(m.parser(), &varStmt)) {
@ -3331,9 +3343,11 @@ static bool CheckVariables(FunctionValidatorShared& f, ParseNode** stmtIter) {
return true;
}
static bool CheckExpr(FunctionValidator& f, ParseNode* op, Type* type);
template <typename Unit>
static bool CheckExpr(FunctionValidator<Unit>& f, ParseNode* op, Type* type);
static bool CheckNumericLiteral(FunctionValidator& f, ParseNode* num,
template <typename Unit>
static bool CheckNumericLiteral(FunctionValidator<Unit>& f, ParseNode* num,
Type* type) {
NumLit lit = ExtractNumericLiteral(f.m(), num);
if (!lit.valid()) {
@ -3397,7 +3411,8 @@ static inline bool IsLiteralOrConstInt(FunctionValidatorShared& f,
static const int32_t NoMask = -1;
static bool CheckArrayAccess(FunctionValidator& f, ParseNode* viewName,
template <typename Unit>
static bool CheckArrayAccess(FunctionValidator<Unit>& f, ParseNode* viewName,
ParseNode* indexExpr, Scalar::Type* viewType) {
if (!viewName->isKind(ParseNodeKind::Name)) {
return f.fail(viewName,
@ -3502,7 +3517,9 @@ static bool WriteArrayAccessFlags(FunctionValidatorShared& f,
return true;
}
static bool CheckLoadArray(FunctionValidator& f, ParseNode* elem, Type* type) {
template <typename Unit>
static bool CheckLoadArray(FunctionValidator<Unit>& f, ParseNode* elem,
Type* type) {
Scalar::Type viewType;
if (!CheckArrayAccess(f, ElemBase(elem), ElemIndex(elem), &viewType)) {
@ -3562,7 +3579,8 @@ static bool CheckLoadArray(FunctionValidator& f, ParseNode* elem, Type* type) {
return true;
}
static bool CheckStoreArray(FunctionValidator& f, ParseNode* lhs,
template <typename Unit>
static bool CheckStoreArray(FunctionValidator<Unit>& f, ParseNode* lhs,
ParseNode* rhs, Type* type) {
Scalar::Type viewType;
if (!CheckArrayAccess(f, ElemBase(lhs), ElemIndex(lhs), &viewType)) {
@ -3654,7 +3672,8 @@ static bool CheckStoreArray(FunctionValidator& f, ParseNode* lhs,
return true;
}
static bool CheckAssignName(FunctionValidator& f, ParseNode* lhs,
template <typename Unit>
static bool CheckAssignName(FunctionValidator<Unit>& f, ParseNode* lhs,
ParseNode* rhs, Type* type) {
RootedPropertyName name(f.cx(), lhs->as<NameNode>().name());
@ -3709,7 +3728,9 @@ static bool CheckAssignName(FunctionValidator& f, ParseNode* lhs,
name);
}
static bool CheckAssign(FunctionValidator& f, ParseNode* assign, Type* type) {
template <typename Unit>
static bool CheckAssign(FunctionValidator<Unit>& f, ParseNode* assign,
Type* type) {
MOZ_ASSERT(assign->isKind(ParseNodeKind::AssignExpr));
ParseNode* lhs = BinaryLeft(assign);
@ -3728,7 +3749,9 @@ static bool CheckAssign(FunctionValidator& f, ParseNode* assign, Type* type) {
"left-hand side of assignment must be a variable or array access");
}
static bool CheckMathIMul(FunctionValidator& f, ParseNode* call, Type* type) {
template <typename Unit>
static bool CheckMathIMul(FunctionValidator<Unit>& f, ParseNode* call,
Type* type) {
if (CallArgListLength(call) != 2) {
return f.fail(call, "Math.imul must be passed 2 arguments");
}
@ -3757,7 +3780,9 @@ static bool CheckMathIMul(FunctionValidator& f, ParseNode* call, Type* type) {
return f.encoder().writeOp(Op::I32Mul);
}
static bool CheckMathClz32(FunctionValidator& f, ParseNode* call, Type* type) {
template <typename Unit>
static bool CheckMathClz32(FunctionValidator<Unit>& f, ParseNode* call,
Type* type) {
if (CallArgListLength(call) != 1) {
return f.fail(call, "Math.clz32 must be passed 1 argument");
}
@ -3777,7 +3802,9 @@ static bool CheckMathClz32(FunctionValidator& f, ParseNode* call, Type* type) {
return f.encoder().writeOp(Op::I32Clz);
}
static bool CheckMathAbs(FunctionValidator& f, ParseNode* call, Type* type) {
template <typename Unit>
static bool CheckMathAbs(FunctionValidator<Unit>& f, ParseNode* call,
Type* type) {
if (CallArgListLength(call) != 1) {
return f.fail(call, "Math.abs must be passed 1 argument");
}
@ -3808,7 +3835,9 @@ static bool CheckMathAbs(FunctionValidator& f, ParseNode* call, Type* type) {
argType.toChars());
}
static bool CheckMathSqrt(FunctionValidator& f, ParseNode* call, Type* type) {
template <typename Unit>
static bool CheckMathSqrt(FunctionValidator<Unit>& f, ParseNode* call,
Type* type) {
if (CallArgListLength(call) != 1) {
return f.fail(call, "Math.sqrt must be passed 1 argument");
}
@ -3834,7 +3863,8 @@ static bool CheckMathSqrt(FunctionValidator& f, ParseNode* call, Type* type) {
argType.toChars());
}
static bool CheckMathMinMax(FunctionValidator& f, ParseNode* callNode,
template <typename Unit>
static bool CheckMathMinMax(FunctionValidator<Unit>& f, ParseNode* callNode,
bool isMax, Type* type) {
if (CallArgListLength(callNode) < 2) {
return f.fail(callNode, "Math.min/max must be passed at least 2 arguments");
@ -3894,8 +3924,8 @@ static bool CheckMathMinMax(FunctionValidator& f, ParseNode* callNode,
using CheckArgType = bool (*)(FunctionValidatorShared& f, ParseNode* argNode,
Type type);
template <CheckArgType checkArg>
static bool CheckCallArgs(FunctionValidator& f, ParseNode* callNode,
template <CheckArgType checkArg, typename Unit>
static bool CheckCallArgs(FunctionValidator<Unit>& f, ParseNode* callNode,
ValTypeVector* args) {
ParseNode* argNode = CallArgList(callNode);
for (unsigned i = 0; i < CallArgListLength(callNode);
@ -3943,7 +3973,8 @@ static bool CheckSignatureAgainstExisting(ModuleValidatorShared& m,
return true;
}
static bool CheckFunctionSignature(ModuleValidator& m, ParseNode* usepn,
template <typename Unit>
static bool CheckFunctionSignature(ModuleValidator<Unit>& m, ParseNode* usepn,
FuncType&& sig, PropertyName* name,
ModuleValidatorShared::Func** func) {
if (sig.args().length() > MaxParams) {
@ -3978,7 +4009,8 @@ static bool CheckIsArgType(FunctionValidatorShared& f, ParseNode* argNode,
return true;
}
static bool CheckInternalCall(FunctionValidator& f, ParseNode* callNode,
template <typename Unit>
static bool CheckInternalCall(FunctionValidator<Unit>& f, ParseNode* callNode,
PropertyName* calleeName, Type ret, Type* type) {
MOZ_ASSERT(ret.isCanonical());
@ -4007,7 +4039,8 @@ static bool CheckInternalCall(FunctionValidator& f, ParseNode* callNode,
return true;
}
static bool CheckFuncPtrTableAgainstExisting(ModuleValidator& m,
template <typename Unit>
static bool CheckFuncPtrTableAgainstExisting(ModuleValidator<Unit>& m,
ParseNode* usepn,
PropertyName* name, FuncType&& sig,
unsigned mask,
@ -4044,7 +4077,8 @@ static bool CheckFuncPtrTableAgainstExisting(ModuleValidator& m,
return true;
}
static bool CheckFuncPtrCall(FunctionValidator& f, ParseNode* callNode,
template <typename Unit>
static bool CheckFuncPtrCall(FunctionValidator<Unit>& f, ParseNode* callNode,
Type ret, Type* type) {
MOZ_ASSERT(ret.isCanonical());
@ -4124,7 +4158,8 @@ static bool CheckIsExternType(FunctionValidatorShared& f, ParseNode* argNode,
return true;
}
static bool CheckFFICall(FunctionValidator& f, ParseNode* callNode,
template <typename Unit>
static bool CheckFFICall(FunctionValidator<Unit>& f, ParseNode* callNode,
unsigned ffiIndex, Type ret, Type* type) {
MOZ_ASSERT(ret.isCanonical());
@ -4179,10 +4214,12 @@ static bool CheckFloatCoercionArg(FunctionValidatorShared& f,
inputType.toChars());
}
static bool CheckCoercedCall(FunctionValidator& f, ParseNode* call, Type ret,
Type* type);
template <typename Unit>
static bool CheckCoercedCall(FunctionValidator<Unit>& f, ParseNode* call,
Type ret, Type* type);
static bool CheckCoercionArg(FunctionValidator& f, ParseNode* arg,
template <typename Unit>
static bool CheckCoercionArg(FunctionValidator<Unit>& f, ParseNode* arg,
Type expected, Type* type) {
MOZ_ASSERT(expected.isCanonicalValType());
@ -4207,7 +4244,8 @@ static bool CheckCoercionArg(FunctionValidator& f, ParseNode* arg,
return true;
}
static bool CheckMathFRound(FunctionValidator& f, ParseNode* callNode,
template <typename Unit>
static bool CheckMathFRound(FunctionValidator<Unit>& f, ParseNode* callNode,
Type* type) {
if (CallArgListLength(callNode) != 1) {
return f.fail(callNode, "Math.fround must be passed 1 argument");
@ -4224,7 +4262,9 @@ static bool CheckMathFRound(FunctionValidator& f, ParseNode* callNode,
return true;
}
static bool CheckMathBuiltinCall(FunctionValidator& f, ParseNode* callNode,
template <typename Unit>
static bool CheckMathBuiltinCall(FunctionValidator<Unit>& f,
ParseNode* callNode,
AsmJSMathBuiltinFunction func, Type* type) {
unsigned arity = 0;
Op f32 = Op::Limit;
@ -4375,7 +4415,8 @@ static bool CheckMathBuiltinCall(FunctionValidator& f, ParseNode* callNode,
return true;
}
static bool CheckUncoercedCall(FunctionValidator& f, ParseNode* expr,
template <typename Unit>
static bool CheckUncoercedCall(FunctionValidator<Unit>& f, ParseNode* expr,
Type* type) {
MOZ_ASSERT(expr->isKind(ParseNodeKind::CallExpr));
@ -4444,7 +4485,8 @@ static bool CoerceResult(FunctionValidatorShared& f, ParseNode* expr,
return true;
}
static bool CheckCoercedMathBuiltinCall(FunctionValidator& f,
template <typename Unit>
static bool CheckCoercedMathBuiltinCall(FunctionValidator<Unit>& f,
ParseNode* callNode,
AsmJSMathBuiltinFunction func, Type ret,
Type* type) {
@ -4455,8 +4497,9 @@ static bool CheckCoercedMathBuiltinCall(FunctionValidator& f,
return CoerceResult(f, callNode, ret, actual, type);
}
static bool CheckCoercedCall(FunctionValidator& f, ParseNode* call, Type ret,
Type* type) {
template <typename Unit>
static bool CheckCoercedCall(FunctionValidator<Unit>& f, ParseNode* call,
Type ret, Type* type) {
MOZ_ASSERT(ret.isCanonical());
if (!CheckRecursionLimitDontReport(f.cx())) {
@ -4506,7 +4549,8 @@ static bool CheckCoercedCall(FunctionValidator& f, ParseNode* call, Type ret,
return CheckInternalCall(f, call, calleeName, ret, type);
}
static bool CheckPos(FunctionValidator& f, ParseNode* pos, Type* type) {
template <typename Unit>
static bool CheckPos(FunctionValidator<Unit>& f, ParseNode* pos, Type* type) {
MOZ_ASSERT(pos->isKind(ParseNodeKind::PosExpr));
ParseNode* operand = UnaryKid(pos);
@ -4522,7 +4566,8 @@ static bool CheckPos(FunctionValidator& f, ParseNode* pos, Type* type) {
return CoerceResult(f, operand, Type::Double, actual, type);
}
static bool CheckNot(FunctionValidator& f, ParseNode* expr, Type* type) {
template <typename Unit>
static bool CheckNot(FunctionValidator<Unit>& f, ParseNode* expr, Type* type) {
MOZ_ASSERT(expr->isKind(ParseNodeKind::NotExpr));
ParseNode* operand = UnaryKid(expr);
@ -4540,7 +4585,8 @@ static bool CheckNot(FunctionValidator& f, ParseNode* expr, Type* type) {
return f.encoder().writeOp(Op::I32Eqz);
}
static bool CheckNeg(FunctionValidator& f, ParseNode* expr, Type* type) {
template <typename Unit>
static bool CheckNeg(FunctionValidator<Unit>& f, ParseNode* expr, Type* type) {
MOZ_ASSERT(expr->isKind(ParseNodeKind::NegExpr));
ParseNode* operand = UnaryKid(expr);
@ -4568,7 +4614,8 @@ static bool CheckNeg(FunctionValidator& f, ParseNode* expr, Type* type) {
operandType.toChars());
}
static bool CheckCoerceToInt(FunctionValidator& f, ParseNode* expr,
template <typename Unit>
static bool CheckCoerceToInt(FunctionValidator<Unit>& f, ParseNode* expr,
Type* type) {
MOZ_ASSERT(expr->isKind(ParseNodeKind::BitNotExpr));
ParseNode* operand = UnaryKid(expr);
@ -4594,7 +4641,9 @@ static bool CheckCoerceToInt(FunctionValidator& f, ParseNode* expr,
return true;
}
static bool CheckBitNot(FunctionValidator& f, ParseNode* neg, Type* type) {
template <typename Unit>
static bool CheckBitNot(FunctionValidator<Unit>& f, ParseNode* neg,
Type* type) {
MOZ_ASSERT(neg->isKind(ParseNodeKind::BitNotExpr));
ParseNode* operand = UnaryKid(neg);
@ -4620,9 +4669,13 @@ static bool CheckBitNot(FunctionValidator& f, ParseNode* neg, Type* type) {
return true;
}
static bool CheckAsExprStatement(FunctionValidator& f, ParseNode* exprStmt);
template <typename Unit>
static bool CheckAsExprStatement(FunctionValidator<Unit>& f,
ParseNode* exprStmt);
static bool CheckComma(FunctionValidator& f, ParseNode* comma, Type* type) {
template <typename Unit>
static bool CheckComma(FunctionValidator<Unit>& f, ParseNode* comma,
Type* type) {
MOZ_ASSERT(comma->isKind(ParseNodeKind::CommaExpr));
ParseNode* operands = ListHead(comma);
@ -4654,7 +4707,8 @@ static bool CheckComma(FunctionValidator& f, ParseNode* comma, Type* type) {
return f.encoder().writeOp(Op::End);
}
static bool CheckConditional(FunctionValidator& f, ParseNode* ternary,
template <typename Unit>
static bool CheckConditional(FunctionValidator<Unit>& f, ParseNode* ternary,
Type* type) {
MOZ_ASSERT(ternary->isKind(ParseNodeKind::ConditionalExpr));
@ -4711,7 +4765,9 @@ static bool CheckConditional(FunctionValidator& f, ParseNode* ternary,
return true;
}
static bool IsValidIntMultiplyConstant(ModuleValidator& m, ParseNode* expr) {
template <typename Unit>
static bool IsValidIntMultiplyConstant(ModuleValidator<Unit>& m,
ParseNode* expr) {
if (!IsNumericLiteral(m, expr)) {
return false;
}
@ -4734,7 +4790,9 @@ static bool IsValidIntMultiplyConstant(ModuleValidator& m, ParseNode* expr) {
MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE("Bad literal");
}
static bool CheckMultiply(FunctionValidator& f, ParseNode* star, Type* type) {
template <typename Unit>
static bool CheckMultiply(FunctionValidator<Unit>& f, ParseNode* star,
Type* type) {
MOZ_ASSERT(star->isKind(ParseNodeKind::MulExpr));
ParseNode* lhs = MultiplyLeft(star);
ParseNode* rhs = MultiplyRight(star);
@ -4774,8 +4832,9 @@ static bool CheckMultiply(FunctionValidator& f, ParseNode* star, Type* type) {
star, "multiply operands must be both int, both double? or both float?");
}
static bool CheckAddOrSub(FunctionValidator& f, ParseNode* expr, Type* type,
unsigned* numAddOrSubOut = nullptr) {
template <typename Unit>
static bool CheckAddOrSub(FunctionValidator<Unit>& f, ParseNode* expr,
Type* type, unsigned* numAddOrSubOut = nullptr) {
if (!CheckRecursionLimitDontReport(f.cx())) {
return f.m().failOverRecursed();
}
@ -4854,7 +4913,9 @@ static bool CheckAddOrSub(FunctionValidator& f, ParseNode* expr, Type* type,
return true;
}
static bool CheckDivOrMod(FunctionValidator& f, ParseNode* expr, Type* type) {
template <typename Unit>
static bool CheckDivOrMod(FunctionValidator<Unit>& f, ParseNode* expr,
Type* type) {
MOZ_ASSERT(expr->isKind(ParseNodeKind::DivExpr) ||
expr->isKind(ParseNodeKind::ModExpr));
@ -4905,7 +4966,9 @@ static bool CheckDivOrMod(FunctionValidator& f, ParseNode* expr, Type* type) {
lhsType.toChars(), rhsType.toChars());
}
static bool CheckComparison(FunctionValidator& f, ParseNode* comp, Type* type) {
template <typename Unit>
static bool CheckComparison(FunctionValidator<Unit>& f, ParseNode* comp,
Type* type) {
MOZ_ASSERT(comp->isKind(ParseNodeKind::LtExpr) ||
comp->isKind(ParseNodeKind::LeExpr) ||
comp->isKind(ParseNodeKind::GtExpr) ||
@ -5036,7 +5099,9 @@ static bool CheckComparison(FunctionValidator& f, ParseNode* comp, Type* type) {
return f.encoder().writeOp(stmt);
}
static bool CheckBitwise(FunctionValidator& f, ParseNode* bitwise, Type* type) {
template <typename Unit>
static bool CheckBitwise(FunctionValidator<Unit>& f, ParseNode* bitwise,
Type* type) {
ParseNode* lhs = BitwiseLeft(bitwise);
ParseNode* rhs = BitwiseRight(bitwise);
@ -5151,7 +5216,8 @@ static bool CheckBitwise(FunctionValidator& f, ParseNode* bitwise, Type* type) {
return true;
}
static bool CheckExpr(FunctionValidator& f, ParseNode* expr, Type* type) {
template <typename Unit>
static bool CheckExpr(FunctionValidator<Unit>& f, ParseNode* expr, Type* type) {
if (!CheckRecursionLimitDontReport(f.cx())) {
return f.m().failOverRecursed();
}
@ -5214,9 +5280,11 @@ static bool CheckExpr(FunctionValidator& f, ParseNode* expr, Type* type) {
return f.fail(expr, "unsupported expression");
}
static bool CheckStatement(FunctionValidator& f, ParseNode* stmt);
template <typename Unit>
static bool CheckStatement(FunctionValidator<Unit>& f, ParseNode* stmt);
static bool CheckAsExprStatement(FunctionValidator& f, ParseNode* expr) {
template <typename Unit>
static bool CheckAsExprStatement(FunctionValidator<Unit>& f, ParseNode* expr) {
if (expr->isKind(ParseNodeKind::CallExpr)) {
Type ignored;
return CheckCoercedCall(f, expr, Type::Void, &ignored);
@ -5236,12 +5304,16 @@ static bool CheckAsExprStatement(FunctionValidator& f, ParseNode* expr) {
return true;
}
static bool CheckExprStatement(FunctionValidator& f, ParseNode* exprStmt) {
template <typename Unit>
static bool CheckExprStatement(FunctionValidator<Unit>& f,
ParseNode* exprStmt) {
MOZ_ASSERT(exprStmt->isKind(ParseNodeKind::ExpressionStmt));
return CheckAsExprStatement(f, UnaryKid(exprStmt));
}
static bool CheckLoopConditionOnEntry(FunctionValidator& f, ParseNode* cond) {
template <typename Unit>
static bool CheckLoopConditionOnEntry(FunctionValidator<Unit>& f,
ParseNode* cond) {
uint32_t maybeLit;
if (IsLiteralInt(f.m(), cond, &maybeLit) && maybeLit) {
return true;
@ -5267,7 +5339,8 @@ static bool CheckLoopConditionOnEntry(FunctionValidator& f, ParseNode* cond) {
return true;
}
static bool CheckWhile(FunctionValidator& f, ParseNode* whileStmt,
template <typename Unit>
static bool CheckWhile(FunctionValidator<Unit>& f, ParseNode* whileStmt,
const LabelVector* labels = nullptr) {
MOZ_ASSERT(whileStmt->isKind(ParseNodeKind::WhileStmt));
ParseNode* cond = BinaryLeft(whileStmt);
@ -5308,7 +5381,8 @@ static bool CheckWhile(FunctionValidator& f, ParseNode* whileStmt,
return true;
}
static bool CheckFor(FunctionValidator& f, ParseNode* forStmt,
template <typename Unit>
static bool CheckFor(FunctionValidator<Unit>& f, ParseNode* forStmt,
const LabelVector* labels = nullptr) {
MOZ_ASSERT(forStmt->isKind(ParseNodeKind::ForStmt));
ParseNode* forHead = BinaryLeft(forStmt);
@ -5393,7 +5467,8 @@ static bool CheckFor(FunctionValidator& f, ParseNode* forStmt,
return true;
}
static bool CheckDoWhile(FunctionValidator& f, ParseNode* whileStmt,
template <typename Unit>
static bool CheckDoWhile(FunctionValidator<Unit>& f, ParseNode* whileStmt,
const LabelVector* labels = nullptr) {
MOZ_ASSERT(whileStmt->isKind(ParseNodeKind::DoWhileStmt));
ParseNode* body = BinaryLeft(whileStmt);
@ -5450,10 +5525,12 @@ static bool CheckDoWhile(FunctionValidator& f, ParseNode* whileStmt,
return true;
}
static bool CheckStatementList(FunctionValidator& f, ParseNode*,
template <typename Unit>
static bool CheckStatementList(FunctionValidator<Unit>& f, ParseNode*,
const LabelVector* = nullptr);
static bool CheckLabel(FunctionValidator& f, ParseNode* labeledStmt) {
template <typename Unit>
static bool CheckLabel(FunctionValidator<Unit>& f, ParseNode* labeledStmt) {
MOZ_ASSERT(labeledStmt->isKind(ParseNodeKind::LabelStmt));
LabelVector labels;
@ -5492,7 +5569,8 @@ static bool CheckLabel(FunctionValidator& f, ParseNode* labeledStmt) {
return true;
}
static bool CheckIf(FunctionValidator& f, ParseNode* ifStmt) {
template <typename Unit>
static bool CheckIf(FunctionValidator<Unit>& f, ParseNode* ifStmt) {
uint32_t numIfEnd = 1;
recurse:
@ -5622,7 +5700,8 @@ static bool CheckSwitchRange(FunctionValidatorShared& f, ParseNode* stmt,
return true;
}
static bool CheckSwitchExpr(FunctionValidator& f, ParseNode* switchExpr) {
template <typename Unit>
static bool CheckSwitchExpr(FunctionValidator<Unit>& f, ParseNode* switchExpr) {
Type exprType;
if (!CheckExpr(f, switchExpr, &exprType)) {
return false;
@ -5646,7 +5725,8 @@ static bool CheckSwitchExpr(FunctionValidator& f, ParseNode* switchExpr) {
// matches the sequential order of cases.
// - one block for the br_table, so that the first break goes to the first
// case's block.
static bool CheckSwitch(FunctionValidator& f, ParseNode* switchStmt) {
template <typename Unit>
static bool CheckSwitch(FunctionValidator<Unit>& f, ParseNode* switchStmt) {
MOZ_ASSERT(switchStmt->isKind(ParseNodeKind::SwitchStmt));
ParseNode* switchExpr = BinaryLeft(switchStmt);
@ -5808,7 +5888,8 @@ static bool CheckReturnType(FunctionValidatorShared& f, ParseNode* usepn,
return true;
}
static bool CheckReturn(FunctionValidator& f, ParseNode* returnStmt) {
template <typename Unit>
static bool CheckReturn(FunctionValidator<Unit>& f, ParseNode* returnStmt) {
ParseNode* expr = ReturnExpr(returnStmt);
if (!expr) {
@ -5837,7 +5918,8 @@ static bool CheckReturn(FunctionValidator& f, ParseNode* returnStmt) {
return true;
}
static bool CheckStatementList(FunctionValidator& f, ParseNode* stmtList,
template <typename Unit>
static bool CheckStatementList(FunctionValidator<Unit>& f, ParseNode* stmtList,
const LabelVector* labels /*= nullptr */) {
MOZ_ASSERT(stmtList->isKind(ParseNodeKind::StatementList));
@ -5857,7 +5939,8 @@ static bool CheckStatementList(FunctionValidator& f, ParseNode* stmtList,
return true;
}
static bool CheckLexicalScope(FunctionValidator& f, ParseNode* node) {
template <typename Unit>
static bool CheckLexicalScope(FunctionValidator<Unit>& f, ParseNode* node) {
LexicalScopeNode* lexicalScope = &node->as<LexicalScopeNode>();
if (!lexicalScope->isEmptyScope()) {
return f.fail(lexicalScope, "cannot have 'let' or 'const' declarations");
@ -5874,7 +5957,8 @@ static bool CheckBreakOrContinue(FunctionValidatorShared& f, bool isBreak,
return f.writeUnlabeledBreakOrContinue(isBreak);
}
static bool CheckStatement(FunctionValidator& f, ParseNode* stmt) {
template <typename Unit>
static bool CheckStatement(FunctionValidator<Unit>& f, ParseNode* stmt) {
if (!CheckRecursionLimitDontReport(f.cx())) {
return f.m().failOverRecursed();
}
@ -5912,7 +5996,8 @@ static bool CheckStatement(FunctionValidator& f, ParseNode* stmt) {
return f.fail(stmt, "unexpected statement kind");
}
static bool ParseFunction(ModuleValidator& m, CodeNode** funNodeOut,
template <typename Unit>
static bool ParseFunction(ModuleValidator<Unit>& m, CodeNode** funNodeOut,
unsigned* line) {
auto& tokenStream = m.tokenStream();
@ -5981,11 +6066,12 @@ static bool ParseFunction(ModuleValidator& m, CodeNode** funNodeOut,
return true;
}
static bool CheckFunction(ModuleValidator& m) {
template <typename Unit>
static bool CheckFunction(ModuleValidator<Unit>& m) {
// asm.js modules can be quite large when represented as parse trees so pop
// the backing LifoAlloc after parsing/compiling each function. Release the
// parser's lifo memory after the last use of a parse node.
AsmJSParser::Mark mark = m.parser().mark();
frontend::ParserBase::Mark mark = m.parser().mark();
auto releaseMark =
mozilla::MakeScopeExit([&m, &mark] { m.parser().release(mark); });
@ -5999,7 +6085,7 @@ static bool CheckFunction(ModuleValidator& m) {
return false;
}
FunctionValidator f(m, funNode);
FunctionValidator<Unit> f(m, funNode);
ParseNode* stmtIter = ListHead(FunctionStatementList(funNode));
@ -6057,7 +6143,8 @@ static bool CheckAllFunctionsDefined(ModuleValidatorShared& m) {
return true;
}
static bool CheckFunctions(ModuleValidator& m) {
template <typename Unit>
static bool CheckFunctions(ModuleValidator<Unit>& m) {
while (true) {
TokenKind tk;
if (!PeekToken(m.parser(), &tk)) {
@ -6076,7 +6163,8 @@ static bool CheckFunctions(ModuleValidator& m) {
return CheckAllFunctionsDefined(m);
}
static bool CheckFuncPtrTable(ModuleValidator& m, ParseNode* var) {
template <typename Unit>
static bool CheckFuncPtrTable(ModuleValidator<Unit>& m, ParseNode* var) {
if (!var->isKind(ParseNodeKind::Name)) {
return m.fail(var, "function-pointer table name is not a plain name");
}
@ -6144,7 +6232,8 @@ static bool CheckFuncPtrTable(ModuleValidator& m, ParseNode* var) {
return true;
}
static bool CheckFuncPtrTables(ModuleValidator& m) {
template <typename Unit>
static bool CheckFuncPtrTables(ModuleValidator<Unit>& m) {
while (true) {
ParseNode* varStmt;
if (!ParseVarOrConstStatement(m.parser(), &varStmt)) {
@ -6215,7 +6304,8 @@ static bool CheckModuleExportObject(ModuleValidatorShared& m,
return true;
}
static bool CheckModuleReturn(ModuleValidator& m) {
template <typename Unit>
static bool CheckModuleReturn(ModuleValidator<Unit>& m) {
TokenKind tk;
if (!GetToken(m.parser(), &tk)) {
return false;
@ -6252,7 +6342,8 @@ static bool CheckModuleReturn(ModuleValidator& m) {
return true;
}
static bool CheckModuleEnd(ModuleValidator& m) {
template <typename Unit>
static bool CheckModuleEnd(ModuleValidator<Unit>& m) {
TokenKind tk;
if (!GetToken(m.parser(), &tk)) {
return false;
@ -6267,14 +6358,15 @@ static bool CheckModuleEnd(ModuleValidator& m) {
return true;
}
static SharedModule CheckModule(JSContext* cx, AsmJSParser& parser,
template <typename Unit>
static SharedModule CheckModule(JSContext* cx, AsmJSParser<Unit>& parser,
ParseNode* stmtList, UniqueLinkData* linkData,
unsigned* time) {
int64_t before = PRMJ_Now();
CodeNode* moduleFunctionNode = parser.pc->functionBox()->functionNode;
ModuleValidator m(cx, parser, moduleFunctionNode);
ModuleValidator<Unit> m(cx, parser, moduleFunctionNode);
if (!m.init()) {
return nullptr;
}
@ -7031,11 +7123,11 @@ class ModuleChars {
Vector<CacheableChars, 0, SystemAllocPolicy> funCtorArgs_;
public:
static uint32_t beginOffset(AsmJSParser& parser) {
static uint32_t beginOffset(AsmJSParser<char16_t>& parser) {
return parser.pc->functionBox()->functionNode->pn_pos.begin;
}
static uint32_t endOffset(AsmJSParser& parser) {
static uint32_t endOffset(AsmJSParser<char16_t>& parser) {
TokenPos pos(0, 0); // initialize to silence GCC warning
MOZ_ALWAYS_TRUE(
parser.tokenStream.peekTokenPos(&pos, TokenStreamShared::Operand));
@ -7049,7 +7141,7 @@ class ModuleCharsForStore : ModuleChars {
Vector<char, 0, SystemAllocPolicy> compressedBuffer_;
public:
bool init(AsmJSParser& parser) {
bool init(AsmJSParser<char16_t>& parser) {
MOZ_ASSERT(beginOffset(parser) < endOffset(parser));
uncompressedSize_ =
@ -7152,7 +7244,7 @@ class ModuleCharsForLookup : ModuleChars {
return cursor;
}
bool match(AsmJSParser& parser) const {
bool match(AsmJSParser<char16_t>& parser) const {
const char16_t* parseBegin =
parser.tokenStream.codeUnitPtrAt(beginOffset(parser));
const char16_t* parseLimit = parser.tokenStream.rawLimit();
@ -7229,10 +7321,9 @@ struct ScopedCacheEntryOpenedForRead {
} // unnamed namespace
static JS::AsmJSCacheResult StoreAsmJSModuleInCache(AsmJSParser& parser,
const Module& module,
const LinkData& linkData,
JSContext* cx) {
static JS::AsmJSCacheResult StoreAsmJSModuleInCache(
AsmJSParser<char16_t>& parser, const Module& module,
const LinkData& linkData, JSContext* cx) {
ModuleCharsForStore moduleChars;
if (!moduleChars.init(parser)) {
return JS::AsmJSCache_InternalError;
@ -7283,7 +7374,8 @@ static JS::AsmJSCacheResult StoreAsmJSModuleInCache(AsmJSParser& parser,
return JS::AsmJSCache_Success;
}
static bool LookupAsmJSModuleInCache(JSContext* cx, AsmJSParser& parser,
static bool LookupAsmJSModuleInCache(JSContext* cx,
AsmJSParser<char16_t>& parser,
bool* loadedFromCache,
SharedModule* module,
UniqueChars* compilationTimeReport) {
@ -7385,11 +7477,12 @@ static bool NoExceptionPending(JSContext* cx) {
return cx->helperThread() || !cx->isExceptionPending();
}
static bool SuccessfulValidation(AsmJSParser& parser, UniqueChars str) {
static bool SuccessfulValidation(frontend::ParserBase& parser,
UniqueChars str) {
return parser.warningNoOffset(JSMSG_USE_ASM_TYPE_OK, str.get());
}
static bool TypeFailureWarning(AsmJSParser& parser, const char* str) {
static bool TypeFailureWarning(frontend::ParserBase& parser, const char* str) {
if (parser.options().throwOnAsmJSValidationFailureOption) {
parser.errorNoOffset(JSMSG_USE_ASM_TYPE_FAIL, str ? str : "");
return false;
@ -7402,7 +7495,8 @@ static bool TypeFailureWarning(AsmJSParser& parser, const char* str) {
return false;
}
static bool EstablishPreconditions(JSContext* cx, AsmJSParser& parser) {
static bool EstablishPreconditions(JSContext* cx,
frontend::ParserBase& parser) {
// asm.js requires Ion.
if (!HasCompilerSupport(cx) || !IonCanCompile()) {
return TypeFailureWarning(parser, "Disabled by lack of compiler support");
@ -7489,8 +7583,8 @@ static UniqueChars BuildConsoleMessage(unsigned time,
#endif
}
bool js::CompileAsmJS(JSContext* cx, AsmJSParser& parser, ParseNode* stmtList,
bool* validated) {
bool js::CompileAsmJS(JSContext* cx, AsmJSParser<char16_t>& parser,
ParseNode* stmtList, bool* validated) {
*validated = false;
// Various conditions disable asm.js optimizations.

View File

@ -50,7 +50,8 @@ class FullParseHandler;
} // namespace frontend
using AsmJSParser = frontend::Parser<frontend::FullParseHandler, char16_t>;
template <typename Unit>
using AsmJSParser = frontend::Parser<frontend::FullParseHandler, Unit>;
// This function takes over parsing of a function starting with "use asm". The
// return value indicates whether an error was reported which the caller should
@ -59,7 +60,8 @@ using AsmJSParser = frontend::Parser<frontend::FullParseHandler, char16_t>;
// indeterminate amount and the entire function should be reparsed from the
// beginning.
extern MOZ_MUST_USE bool CompileAsmJS(JSContext* cx, AsmJSParser& parser,
extern MOZ_MUST_USE bool CompileAsmJS(JSContext* cx,
AsmJSParser<char16_t>& parser,
frontend::ParseNode* stmtList,
bool* validated);