Bug 1351913 - Reduce calls to FindReservedWord when checking for forbidden identifiers during parsing. r=shu

--HG--
extra : rebase_source : 70a24f7c32f062f195167504722891c6df51ee4c
This commit is contained in:
André Bargull 2017-04-18 05:48:51 -07:00
Родитель 92a16eae93
Коммит 0129caa07f
4 изменённых файлов: 113 добавлений и 100 удалений

Просмотреть файл

@ -1014,12 +1014,15 @@ Parser<ParseHandler>::parse()
bool
ParserBase::isValidStrictBinding(PropertyName* name)
{
return name != context->names().eval &&
name != context->names().arguments &&
name != context->names().let &&
name != context->names().static_ &&
name != context->names().yield &&
!IsStrictReservedWord(name);
TokenKind tt = ReservedWordTokenKind(name);
if (tt == TOK_NAME) {
return name != context->names().eval &&
name != context->names().arguments;
}
return tt != TOK_LET &&
tt != TOK_STATIC &&
tt != TOK_YIELD &&
!TokenKindIsStrictReservedWord(tt);
}
/*
@ -9086,75 +9089,80 @@ Parser<ParseHandler>::newName(PropertyName* name, TokenPos pos)
template <typename ParseHandler>
bool
Parser<ParseHandler>::checkLabelOrIdentifierReference(HandlePropertyName ident,
Parser<ParseHandler>::checkLabelOrIdentifierReference(PropertyName* ident,
uint32_t offset,
YieldHandling yieldHandling)
YieldHandling yieldHandling,
TokenKind hint /* = TOK_LIMIT */)
{
if (ident == context->names().yield) {
if (yieldHandling == YieldIsKeyword ||
versionNumber() >= JSVERSION_1_7)
{
errorAt(offset, JSMSG_RESERVED_ID, "yield");
return false;
TokenKind tt;
if (hint == TOK_LIMIT) {
tt = ReservedWordTokenKind(ident);
} else {
MOZ_ASSERT(hint == ReservedWordTokenKind(ident), "hint doesn't match actual token kind");
tt = hint;
}
if (tt == TOK_NAME)
return true;
if (TokenKindIsContextualKeyword(tt)) {
if (tt == TOK_YIELD) {
if (yieldHandling == YieldIsKeyword || versionNumber() >= JSVERSION_1_7) {
errorAt(offset, JSMSG_RESERVED_ID, "yield");
return false;
}
if (pc->sc()->needStrictChecks()) {
if (!strictModeErrorAt(offset, JSMSG_RESERVED_ID, "yield"))
return false;
}
return true;
}
if (tt == TOK_AWAIT) {
if (awaitIsKeyword()) {
errorAt(offset, JSMSG_RESERVED_ID, "await");
return false;
}
return true;
}
if (pc->sc()->needStrictChecks()) {
if (!strictModeErrorAt(offset, JSMSG_RESERVED_ID, "yield"))
return false;
}
return true;
}
if (ident == context->names().await) {
if (awaitIsKeyword()) {
errorAt(offset, JSMSG_RESERVED_ID, "await");
return false;
if (tt == TOK_LET) {
if (!strictModeErrorAt(offset, JSMSG_RESERVED_ID, "let"))
return false;
return true;
}
if (tt == TOK_STATIC) {
if (!strictModeErrorAt(offset, JSMSG_RESERVED_ID, "static"))
return false;
return true;
}
}
return true;
}
if (IsKeyword(ident) || IsReservedWordLiteral(ident)) {
errorAt(offset, JSMSG_INVALID_ID, ReservedWordToCharZ(ident));
if (TokenKindIsStrictReservedWord(tt)) {
if (pc->sc()->needStrictChecks()) {
if (!strictModeErrorAt(offset, JSMSG_RESERVED_ID, ReservedWordToCharZ(tt)))
return false;
}
return true;
}
if (TokenKindIsKeyword(tt) || TokenKindIsReservedWordLiteral(tt)) {
errorAt(offset, JSMSG_INVALID_ID, ReservedWordToCharZ(tt));
return false;
}
if (IsFutureReservedWord(ident)) {
errorAt(offset, JSMSG_RESERVED_ID, ReservedWordToCharZ(ident));
if (TokenKindIsFutureReservedWord(tt)) {
errorAt(offset, JSMSG_RESERVED_ID, ReservedWordToCharZ(tt));
return false;
}
if (pc->sc()->needStrictChecks()) {
if (IsStrictReservedWord(ident)) {
if (!strictModeErrorAt(offset, JSMSG_RESERVED_ID, ReservedWordToCharZ(ident)))
return false;
return true;
}
if (ident == context->names().let) {
if (!strictModeErrorAt(offset, JSMSG_RESERVED_ID, "let"))
return false;
return true;
}
if (ident == context->names().static_) {
if (!strictModeErrorAt(offset, JSMSG_RESERVED_ID, "static"))
return false;
return true;
}
}
return true;
MOZ_ASSERT_UNREACHABLE("Unexpected reserved word kind.");
return false;
}
template <typename ParseHandler>
bool
Parser<ParseHandler>::checkBindingIdentifier(HandlePropertyName ident,
Parser<ParseHandler>::checkBindingIdentifier(PropertyName* ident,
uint32_t offset,
YieldHandling yieldHandling)
YieldHandling yieldHandling,
TokenKind hint /* = TOK_LIMIT */)
{
if (!checkLabelOrIdentifierReference(ident, offset, yieldHandling))
return false;
if (pc->sc()->needStrictChecks()) {
if (ident == context->names().arguments) {
if (!strictModeErrorAt(offset, JSMSG_BAD_STRICT_ASSIGN, "arguments"))
@ -9169,7 +9177,7 @@ Parser<ParseHandler>::checkBindingIdentifier(HandlePropertyName ident,
}
}
return true;
return checkLabelOrIdentifierReference(ident, offset, yieldHandling, hint);
}
template <typename ParseHandler>
@ -9183,8 +9191,13 @@ Parser<ParseHandler>::labelOrIdentifierReference(YieldHandling yieldHandling)
//
// Use PropertyName* instead of TokenKind to reflect the normalization.
// Unless the name contains escapes, we can reuse the current TokenKind
// to determine if the name is a restricted identifier.
TokenKind hint = !tokenStream.currentNameHasEscapes()
? tokenStream.currentToken().type
: TOK_LIMIT;
RootedPropertyName ident(context, tokenStream.currentName());
if (!checkLabelOrIdentifierReference(ident, pos().begin, yieldHandling))
if (!checkLabelOrIdentifierReference(ident, pos().begin, yieldHandling, hint))
return nullptr;
return ident;
}
@ -9193,8 +9206,11 @@ template <typename ParseHandler>
PropertyName*
Parser<ParseHandler>::bindingIdentifier(YieldHandling yieldHandling)
{
TokenKind hint = !tokenStream.currentNameHasEscapes()
? tokenStream.currentToken().type
: TOK_LIMIT;
RootedPropertyName ident(context, tokenStream.currentName());
if (!checkBindingIdentifier(ident, pos().begin, yieldHandling))
if (!checkBindingIdentifier(ident, pos().begin, yieldHandling, hint))
return nullptr;
return ident;
}

Просмотреть файл

@ -1416,17 +1416,19 @@ class Parser final : public ParserBase, private JS::AutoGCRooter
Node classDefinition(YieldHandling yieldHandling, ClassContext classContext,
DefaultHandling defaultHandling);
bool checkLabelOrIdentifierReference(HandlePropertyName ident,
bool checkLabelOrIdentifierReference(PropertyName* ident,
uint32_t offset,
YieldHandling yieldHandling);
YieldHandling yieldHandling,
TokenKind hint = TOK_LIMIT);
bool checkLocalExportName(HandlePropertyName ident, uint32_t offset) {
bool checkLocalExportName(PropertyName* ident, uint32_t offset) {
return checkLabelOrIdentifierReference(ident, offset, YieldIsName);
}
bool checkBindingIdentifier(HandlePropertyName ident,
bool checkBindingIdentifier(PropertyName* ident,
uint32_t offset,
YieldHandling yieldHandling);
YieldHandling yieldHandling,
TokenKind hint = TOK_LIMIT);
PropertyName* labelOrIdentifierReference(YieldHandling yieldHandling);

Просмотреть файл

@ -194,41 +194,29 @@ frontend::IsKeyword(JSLinearString* str)
return false;
}
bool
frontend::IsFutureReservedWord(JSLinearString* str)
TokenKind
frontend::ReservedWordTokenKind(PropertyName* str)
{
if (const ReservedWordInfo* rw = FindReservedWord(str))
return TokenKindIsFutureReservedWord(rw->tokentype);
return rw->tokentype;
return false;
}
bool
frontend::IsStrictReservedWord(JSLinearString* str)
{
if (const ReservedWordInfo* rw = FindReservedWord(str))
return TokenKindIsStrictReservedWord(rw->tokentype);
return false;
}
bool
frontend::IsReservedWordLiteral(JSLinearString* str)
{
if (const ReservedWordInfo* rw = FindReservedWord(str))
return TokenKindIsReservedWordLiteral(rw->tokentype);
return false;
return TOK_NAME;
}
const char*
frontend::ReservedWordToCharZ(PropertyName* str)
{
const ReservedWordInfo* rw = FindReservedWord(str);
if (rw == nullptr)
return nullptr;
if (const ReservedWordInfo* rw = FindReservedWord(str))
return ReservedWordToCharZ(rw->tokentype);
switch (rw->tokentype) {
return nullptr;
}
const char*
frontend::ReservedWordToCharZ(TokenKind tt)
{
MOZ_ASSERT(tt != TOK_NAME);
switch (tt) {
#define EMIT_CASE(word, name, type) case type: return js_##word##_str;
FOR_EACH_JAVASCRIPT_RESERVED_WORD(EMIT_CASE)
#undef EMIT_CASE

Просмотреть файл

@ -242,17 +242,14 @@ struct Token
}
};
extern TokenKind
ReservedWordTokenKind(PropertyName* str);
extern const char*
ReservedWordToCharZ(PropertyName* str);
extern MOZ_MUST_USE bool
IsFutureReservedWord(JSLinearString* str);
extern MOZ_MUST_USE bool
IsReservedWordLiteral(JSLinearString* str);
extern MOZ_MUST_USE bool
IsStrictReservedWord(JSLinearString* str);
extern const char*
ReservedWordToCharZ(TokenKind tt);
// Ideally, tokenizing would be entirely independent of context. But the
// strict mode flag, which is in SharedContext, affects tokenizing, and
@ -308,6 +305,16 @@ class TokenStreamBase
return reservedWordToPropertyName(currentToken().type);
}
bool currentNameHasEscapes() const {
if (isCurrentTokenType(TOK_NAME)) {
TokenPos pos = currentToken().pos;
return (pos.end - pos.begin) != currentToken().name()->length();
}
MOZ_ASSERT(TokenKindIsPossibleIdentifierName(currentToken().type));
return false;
}
PropertyName* nextName() const {
if (nextToken().type != TOK_NAME)
return nextToken().name();