author | Luke Wagner <luke@mozilla.com> |
Fri, 24 Oct 2014 12:32:10 -0500 | |
changeset 212298 | fcd719ea99902352255b7f18188b2853fb6716d9 |
parent 212297 | 1090f3645eb3c17beeddfc22ee2a441ba781c93b |
child 212299 | 7d515b995286c76af531e62ee20fae7274afa5a0 |
push id | 27704 |
push user | kwierso@gmail.com |
push date | Sat, 25 Oct 2014 01:25:30 +0000 |
treeherder | mozilla-central@e37231060eb4 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | bbouvier |
bugs | 1088328 |
milestone | 36.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
js/src/asmjs/AsmJSValidate.cpp | file | annotate | diff | comparison | revisions | |
js/src/jit-test/tests/asm.js/testBasic.js | file | annotate | diff | comparison | revisions |
--- a/js/src/asmjs/AsmJSValidate.cpp +++ b/js/src/asmjs/AsmJSValidate.cpp @@ -324,16 +324,31 @@ MaybeDefinitionInitializer(ParseNode *pn static inline bool IsUseOfName(ParseNode *pn, PropertyName *name) { return pn->isKind(PNK_NAME) && pn->name() == name; } static inline bool +IsIgnoredDirectiveName(ExclusiveContext *cx, JSAtom *atom) +{ + return atom != cx->names().useStrict; +} + +static inline bool +IsIgnoredDirective(ExclusiveContext *cx, ParseNode *pn) +{ + return pn->isKind(PNK_SEMI) && + UnaryKid(pn) && + UnaryKid(pn)->isKind(PNK_STRING) && + IsIgnoredDirectiveName(cx, UnaryKid(pn)->pn_atom); +} + +static inline bool IsEmptyStatement(ParseNode *pn) { return pn->isKind(PNK_SEMI) && !UnaryKid(pn); } static inline ParseNode * SkipEmptyStatements(ParseNode *pn) { @@ -3507,18 +3522,21 @@ CheckModuleArguments(ModuleCompiler &m, return true; } static bool CheckPrecedingStatements(ModuleCompiler &m, ParseNode *stmtList) { MOZ_ASSERT(stmtList->isKind(PNK_STATEMENTLIST)); - if (ListLength(stmtList) != 0) - return m.fail(ListHead(stmtList), "invalid asm.js statement"); + ParseNode *stmt = ListHead(stmtList); + for (unsigned i = 0, n = ListLength(stmtList); i < n; i++) { + if (!IsIgnoredDirective(m.cx(), stmt)) + return m.fail(stmt, "invalid asm.js statement"); + } return true; } static bool CheckGlobalVariableInitConstant(ModuleCompiler &m, PropertyName *varName, ParseNode *initNode, bool isConst) { @@ -3836,16 +3854,32 @@ CheckModuleGlobal(ModuleCompiler &m, Par if (initNode->isKind(PNK_DOT)) return CheckGlobalDotImport(m, var->name(), initNode); return m.fail(initNode, "unsupported import expression"); } static bool +CheckModuleProcessingDirectives(ModuleCompiler &m) +{ + TokenStream &ts = m.parser().tokenStream; + while (true) { + if (!ts.matchToken(TOK_STRING)) + return true; + + if (!IsIgnoredDirectiveName(m.cx(), ts.currentToken().atom())) + return m.fail(nullptr, "unsupported processing directive"); + + if (!ts.matchToken(TOK_SEMI)) + return m.fail(nullptr, "expected semicolon after string literal"); + } +} + +static bool CheckModuleGlobals(ModuleCompiler &m) { while (true) { ParseNode *varStmt; if (!ParseVarOrConstStatement(m.parser(), &varStmt)) return false; if (!varStmt) break; @@ -3889,16 +3923,28 @@ CheckArgumentType(FunctionCompiler &f, P if (!IsUseOfName(coercedExpr, name)) return ArgFail(f, name, stmt); *type = VarType(coercion); return true; } static bool +CheckProcessingDirectives(ModuleCompiler &m, ParseNode **stmtIter) +{ + ParseNode *stmt = *stmtIter; + + while (stmt && IsIgnoredDirective(m.cx(), stmt)) + stmt = NextNode(stmt); + + *stmtIter = stmt; + return true; +} + +static bool CheckArguments(FunctionCompiler &f, ParseNode **stmtIter, VarTypeVector *argTypes) { ParseNode *stmt = *stmtIter; unsigned numFormals; ParseNode *argpn = FunctionArgsList(f.fn(), &numFormals); for (unsigned i = 0; i < numFormals; i++, argpn = NextNode(argpn), stmt = NextNode(stmt)) { @@ -6897,16 +6943,19 @@ CheckFunction(ModuleCompiler &m, LifoAll } FunctionCompiler f(m, fn, lifo); if (!f.init()) return false; ParseNode *stmtIter = ListHead(FunctionStatementList(fn)); + if (!CheckProcessingDirectives(m, &stmtIter)) + return false; + VarTypeVector argTypes(m.lifo()); if (!CheckArguments(f, &stmtIter, &argTypes)) return false; if (!CheckVariables(f, &stmtIter)) return false; if (!f.prepareToEmitMIR(argTypes)) @@ -8500,16 +8549,19 @@ CheckModule(ExclusiveContext *cx, AsmJSP return false; if (!CheckModuleArguments(m, m.moduleFunctionNode())) return false; if (!CheckPrecedingStatements(m, stmtList)) return false; + if (!CheckModuleProcessingDirectives(m)) + return false; + if (!CheckModuleGlobals(m)) return false; m.startFunctionBodies(); if (!CheckFunctions(m)) return false;
--- a/js/src/jit-test/tests/asm.js/testBasic.js +++ b/js/src/jit-test/tests/asm.js/testBasic.js @@ -14,17 +14,28 @@ assertAsmTypeFail(USE_ASM + 'var f = f;' assertAsmTypeFail(USE_ASM + 'var f=0; function f(){} return f'); assertAsmTypeFail(USE_ASM + 'var f=glob.Math.imul; return {}'); assertAsmTypeFail('glob', USE_ASM + 'var f=glob.Math.imul; function f(){} return f'); assertAsmTypeFail('glob','foreign', USE_ASM + 'var f=foreign.foo; function f(){} return f'); assertAsmTypeFail(USE_ASM + 'function f(){} var f=[f,f]; return f'); assertAsmTypeFail(USE_ASM + 'function f() 0; return f'); assertAsmTypeFail('"use strict";' + USE_ASM + 'function f() {} return f'); assertAsmTypeFail(USE_ASM + '"use strict"; function f() {} return f'); +assertAsmTypeFail(USE_ASM + '"use foopy" + 1; function f() {} return f'); assertAsmTypeFail(USE_ASM + 'function f() { "use strict"; } return f'); +assertEq(asmLink(asmCompile(USE_ASM + '"use asm"; function f() {} return f'))(), undefined); +assertEq(asmLink(asmCompile(USE_ASM + '"use foopy"; function f() {} return f'))(), undefined); +assertEq(asmLink(asmCompile(USE_ASM + '"use foopy"; "use blarg"; function f() {} return f'))(), undefined); +assertEq(asmLink(asmCompile(USE_ASM + 'function f() { "use asm"; } return f'))(), undefined); +assertEq(asmLink(asmCompile(USE_ASM + 'function f() { "use foopy"; } return f'))(), undefined); +assertEq(asmLink(asmCompile(USE_ASM + 'function f() { "use foopy"; "use blarg"; } return f'))(), undefined); +assertEq(asmLink(asmCompile(USE_ASM + 'function f(i) { "use foopy"; i=i|0; } return f'))(), undefined); +assertEq(asmLink(asmCompile(USE_ASM + 'function f(i) { "use foopy"; "use asm"; i=i|0; } return f'))(), undefined); +assertEq(asmLink(asmCompile(USE_ASM + '"use warm"; function f(i) { "use cold"; i=i|0 } function g() { "use hot"; return 0 } return f'))(), undefined); +assertEq(asmLink(asmCompile(USE_ASM + '"use warm"; function f(i) { "use cold"; i=i|0 } function g() { "use asm"; return 0 } return f'))(), undefined); assertEq(asmLink(asmCompile(USE_ASM + 'function f(){} return f'))(), undefined); assertEq(asmLink(asmCompile(USE_ASM + 'function f(){;} return f'))(), undefined); assertAsmTypeFail(USE_ASM + 'function f(i,j){;} return f'); assertEq(asmLink(asmCompile('"use asm";; function f(){};;; return f;;'))(), undefined); assertAsmTypeFail(USE_ASM + 'function f(x){} return f'); assertAsmTypeFail(USE_ASM + 'function f(){return; return 1} return f'); assertEq(asmLink(asmCompile(USE_ASM + 'function f(x){x=x|0} return f'))(42), undefined); assertEq(asmLink(asmCompile(USE_ASM + 'function f(x){x=x|0; return x|0} return f'))(42), 42);