Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(273)

Side by Side Diff: src/preparser.cc

Issue 7782023: Reintroduce duplicate identifier detection in preparser. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Removed dependency on platform.h in conversions-inl.h Created 9 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution. 11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its 12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived 13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission. 14 // from this software without specific prior written permission.
15 // 15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 #include <math.h>
29
28 #include "../include/v8stdint.h" 30 #include "../include/v8stdint.h"
29 #include "unicode.h" 31 #include "unicode.h"
30 #include "globals.h" 32 #include "globals.h"
31 #include "checks.h" 33 #include "checks.h"
32 #include "allocation.h" 34 #include "allocation.h"
33 #include "utils.h" 35 #include "utils.h"
34 #include "list.h" 36 #include "list.h"
37 #include "conversions.h"
38 #include "hashmap.h"
35 39
36 #include "scanner-base.h" 40 #include "scanner-base.h"
37 #include "preparse-data-format.h" 41 #include "preparse-data-format.h"
38 #include "preparse-data.h" 42 #include "preparse-data.h"
39 #include "preparser.h" 43 #include "preparser.h"
40 44
41 #include "conversions-inl.h" 45 #include "conversions-inl.h"
42 46
43 namespace v8 { 47 namespace v8 {
48
49 #ifdef _MSC_VER
50 // Usually defined in math.h, but not in MSVC.
51 // Abstracted to work
52 int isfinite(double value);
53 #endif
54
44 namespace preparser { 55 namespace preparser {
45 56
46 // Preparsing checks a JavaScript program and emits preparse-data that helps 57 // Preparsing checks a JavaScript program and emits preparse-data that helps
47 // a later parsing to be faster. 58 // a later parsing to be faster.
48 // See preparser-data.h for the data. 59 // See preparser-data.h for the data.
49 60
50 // The PreParser checks that the syntax follows the grammar for JavaScript, 61 // The PreParser checks that the syntax follows the grammar for JavaScript,
51 // and collects some information about the program along the way. 62 // and collects some information about the program along the way.
52 // The grammar check is only performed in order to understand the program 63 // The grammar check is only performed in order to understand the program
53 // sufficiently to deduce some information about it, that can be used 64 // sufficiently to deduce some information about it, that can be used
54 // to speed up later parsing. Finding errors is not the goal of pre-parsing, 65 // to speed up later parsing. Finding errors is not the goal of pre-parsing,
55 // rather it is to speed up properly written and correct programs. 66 // rather it is to speed up properly written and correct programs.
56 // That means that contextual checks (like a label being declared where 67 // That means that contextual checks (like a label being declared where
57 // it is used) are generally omitted. 68 // it is used) are generally omitted.
58 69
59 void PreParser::ReportUnexpectedToken(i::Token::Value token) { 70 void PreParser::ReportUnexpectedToken(i::Token::Value token) {
60 // We don't report stack overflows here, to avoid increasing the 71 // We don't report stack overflows here, to avoid increasing the
61 // stack depth even further. Instead we report it after parsing is 72 // stack depth even further. Instead we report it after parsing is
62 // over, in ParseProgram. 73 // over, in ParseProgram.
63 if (token == i::Token::ILLEGAL && stack_overflow_) { 74 if (token == i::Token::ILLEGAL && stack_overflow_) {
64 return; 75 return;
65 } 76 }
66 i::JavaScriptScanner::Location source_location = scanner_->location(); 77 i::JavaScriptScanner::Location source_location = scanner_->location();
67 78
68 // Four of the tokens are treated specially 79 // Four of the tokens are treated specially
69 switch (token) { 80 switch (token) {
70 case i::Token::EOS: 81 case i::Token::EOS:
71 return ReportMessageAt(source_location.beg_pos, source_location.end_pos, 82 return ReportMessageAt(source_location, "unexpected_eos", NULL);
72 "unexpected_eos", NULL);
73 case i::Token::NUMBER: 83 case i::Token::NUMBER:
74 return ReportMessageAt(source_location.beg_pos, source_location.end_pos, 84 return ReportMessageAt(source_location, "unexpected_token_number", NULL);
75 "unexpected_token_number", NULL);
76 case i::Token::STRING: 85 case i::Token::STRING:
77 return ReportMessageAt(source_location.beg_pos, source_location.end_pos, 86 return ReportMessageAt(source_location, "unexpected_token_string", NULL);
78 "unexpected_token_string", NULL);
79 case i::Token::IDENTIFIER: 87 case i::Token::IDENTIFIER:
80 return ReportMessageAt(source_location.beg_pos, source_location.end_pos, 88 return ReportMessageAt(source_location,
81 "unexpected_token_identifier", NULL); 89 "unexpected_token_identifier", NULL);
82 case i::Token::FUTURE_RESERVED_WORD: 90 case i::Token::FUTURE_RESERVED_WORD:
83 return ReportMessageAt(source_location.beg_pos, source_location.end_pos, 91 return ReportMessageAt(source_location, "unexpected_reserved", NULL);
84 "unexpected_reserved", NULL);
85 case i::Token::FUTURE_STRICT_RESERVED_WORD: 92 case i::Token::FUTURE_STRICT_RESERVED_WORD:
86 return ReportMessageAt(source_location.beg_pos, source_location.end_pos, 93 return ReportMessageAt(source_location,
87 "unexpected_strict_reserved", NULL); 94 "unexpected_strict_reserved", NULL);
88 default: 95 default:
89 const char* name = i::Token::String(token); 96 const char* name = i::Token::String(token);
90 ReportMessageAt(source_location.beg_pos, source_location.end_pos, 97 ReportMessageAt(source_location, "unexpected_token", name);
91 "unexpected_token", name);
92 } 98 }
93 } 99 }
94 100
95 101
96 // Checks whether octal literal last seen is between beg_pos and end_pos. 102 // Checks whether octal literal last seen is between beg_pos and end_pos.
97 // If so, reports an error. 103 // If so, reports an error.
98 void PreParser::CheckOctalLiteral(int beg_pos, int end_pos, bool* ok) { 104 void PreParser::CheckOctalLiteral(int beg_pos, int end_pos, bool* ok) {
99 i::Scanner::Location octal = scanner_->octal_position(); 105 i::Scanner::Location octal = scanner_->octal_position();
100 if (beg_pos <= octal.beg_pos && octal.end_pos <= end_pos) { 106 if (beg_pos <= octal.beg_pos && octal.end_pos <= end_pos) {
101 ReportMessageAt(octal.beg_pos, octal.end_pos, "strict_octal_literal", NULL); 107 ReportMessageAt(octal, "strict_octal_literal", NULL);
102 scanner_->clear_octal_position(); 108 scanner_->clear_octal_position();
103 *ok = false; 109 *ok = false;
104 } 110 }
105 } 111 }
106 112
107 113
108 #define CHECK_OK ok); \ 114 #define CHECK_OK ok); \
109 if (!*ok) return kUnknownSourceElements; \ 115 if (!*ok) return kUnknownSourceElements; \
110 ((void)0 116 ((void)0
111 #define DUMMY ) // to make indentation work 117 #define DUMMY ) // to make indentation work
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
244 Expression function_value = ParseFunctionLiteral(CHECK_OK); 250 Expression function_value = ParseFunctionLiteral(CHECK_OK);
245 251
246 if (function_value.IsStrictFunction() && 252 if (function_value.IsStrictFunction() &&
247 !identifier.IsValidStrictVariable()) { 253 !identifier.IsValidStrictVariable()) {
248 // Strict mode violation, using either reserved word or eval/arguments 254 // Strict mode violation, using either reserved word or eval/arguments
249 // as name of strict function. 255 // as name of strict function.
250 const char* type = "strict_function_name"; 256 const char* type = "strict_function_name";
251 if (identifier.IsFutureStrictReserved()) { 257 if (identifier.IsFutureStrictReserved()) {
252 type = "strict_reserved_word"; 258 type = "strict_reserved_word";
253 } 259 }
254 ReportMessageAt(location.beg_pos, location.end_pos, type, NULL); 260 ReportMessageAt(location, type, NULL);
255 *ok = false; 261 *ok = false;
256 } 262 }
257 return Statement::FunctionDeclaration(); 263 return Statement::FunctionDeclaration();
258 } 264 }
259 265
260 266
261 PreParser::Statement PreParser::ParseBlock(bool* ok) { 267 PreParser::Statement PreParser::ParseBlock(bool* ok) {
262 // Block :: 268 // Block ::
263 // '{' Statement* '}' 269 // '{' Statement* '}'
264 270
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
306 int* num_decl, 312 int* num_decl,
307 bool* ok) { 313 bool* ok) {
308 // VariableDeclarations :: 314 // VariableDeclarations ::
309 // ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[','] 315 // ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[',']
310 316
311 if (peek() == i::Token::VAR) { 317 if (peek() == i::Token::VAR) {
312 Consume(i::Token::VAR); 318 Consume(i::Token::VAR);
313 } else if (peek() == i::Token::CONST) { 319 } else if (peek() == i::Token::CONST) {
314 if (strict_mode()) { 320 if (strict_mode()) {
315 i::Scanner::Location location = scanner_->peek_location(); 321 i::Scanner::Location location = scanner_->peek_location();
316 ReportMessageAt(location.beg_pos, location.end_pos, 322 ReportMessageAt(location, "strict_const", NULL);
317 "strict_const", NULL);
318 *ok = false; 323 *ok = false;
319 return Statement::Default(); 324 return Statement::Default();
320 } 325 }
321 Consume(i::Token::CONST); 326 Consume(i::Token::CONST);
322 } else if (peek() == i::Token::LET) { 327 } else if (peek() == i::Token::LET) {
323 if (var_context != kSourceElement && 328 if (var_context != kSourceElement &&
324 var_context != kForStatement) { 329 var_context != kForStatement) {
325 i::Scanner::Location location = scanner_->peek_location(); 330 i::Scanner::Location location = scanner_->peek_location();
326 ReportMessageAt(location.beg_pos, location.end_pos, 331 ReportMessageAt(location.beg_pos, location.end_pos,
327 "unprotected_let", NULL); 332 "unprotected_let", NULL);
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
468 return Statement::Default(); 473 return Statement::Default();
469 } 474 }
470 475
471 476
472 PreParser::Statement PreParser::ParseWithStatement(bool* ok) { 477 PreParser::Statement PreParser::ParseWithStatement(bool* ok) {
473 // WithStatement :: 478 // WithStatement ::
474 // 'with' '(' Expression ')' Statement 479 // 'with' '(' Expression ')' Statement
475 Expect(i::Token::WITH, CHECK_OK); 480 Expect(i::Token::WITH, CHECK_OK);
476 if (strict_mode()) { 481 if (strict_mode()) {
477 i::Scanner::Location location = scanner_->location(); 482 i::Scanner::Location location = scanner_->location();
478 ReportMessageAt(location.beg_pos, location.end_pos, 483 ReportMessageAt(location, "strict_mode_with", NULL);
479 "strict_mode_with", NULL);
480 *ok = false; 484 *ok = false;
481 return Statement::Default(); 485 return Statement::Default();
482 } 486 }
483 Expect(i::Token::LPAREN, CHECK_OK); 487 Expect(i::Token::LPAREN, CHECK_OK);
484 ParseExpression(true, CHECK_OK); 488 ParseExpression(true, CHECK_OK);
485 Expect(i::Token::RPAREN, CHECK_OK); 489 Expect(i::Token::RPAREN, CHECK_OK);
486 490
487 scope_->EnterWith(); 491 scope_->EnterWith();
488 ParseStatement(CHECK_OK); 492 ParseStatement(CHECK_OK);
489 scope_->LeaveWith(); 493 scope_->LeaveWith();
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
605 } 609 }
606 610
607 611
608 PreParser::Statement PreParser::ParseThrowStatement(bool* ok) { 612 PreParser::Statement PreParser::ParseThrowStatement(bool* ok) {
609 // ThrowStatement :: 613 // ThrowStatement ::
610 // 'throw' [no line terminator] Expression ';' 614 // 'throw' [no line terminator] Expression ';'
611 615
612 Expect(i::Token::THROW, CHECK_OK); 616 Expect(i::Token::THROW, CHECK_OK);
613 if (scanner_->HasAnyLineTerminatorBeforeNext()) { 617 if (scanner_->HasAnyLineTerminatorBeforeNext()) {
614 i::JavaScriptScanner::Location pos = scanner_->location(); 618 i::JavaScriptScanner::Location pos = scanner_->location();
615 ReportMessageAt(pos.beg_pos, pos.end_pos, 619 ReportMessageAt(pos, "newline_after_throw", NULL);
616 "newline_after_throw", NULL);
617 *ok = false; 620 *ok = false;
618 return Statement::Default(); 621 return Statement::Default();
619 } 622 }
620 ParseExpression(true, CHECK_OK); 623 ParseExpression(true, CHECK_OK);
621 ExpectSemicolon(ok); 624 ExpectSemicolon(ok);
622 return Statement::Default(); 625 return Statement::Default();
623 } 626 }
624 627
625 628
626 PreParser::Statement PreParser::ParseTryStatement(bool* ok) { 629 PreParser::Statement PreParser::ParseTryStatement(bool* ok) {
(...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after
1018 ReportMessageAt(location.beg_pos, location.end_pos, 1021 ReportMessageAt(location.beg_pos, location.end_pos,
1019 "reserved_word", NULL); 1022 "reserved_word", NULL);
1020 *ok = false; 1023 *ok = false;
1021 return Expression::Default(); 1024 return Expression::Default();
1022 } 1025 }
1023 1026
1024 case i::Token::FUTURE_STRICT_RESERVED_WORD: 1027 case i::Token::FUTURE_STRICT_RESERVED_WORD:
1025 if (strict_mode()) { 1028 if (strict_mode()) {
1026 Next(); 1029 Next();
1027 i::Scanner::Location location = scanner_->location(); 1030 i::Scanner::Location location = scanner_->location();
1028 ReportMessageAt(location.beg_pos, location.end_pos, 1031 ReportMessageAt(location, "strict_reserved_word", NULL);
1029 "strict_reserved_word", NULL);
1030 *ok = false; 1032 *ok = false;
1031 return Expression::Default(); 1033 return Expression::Default();
1032 } 1034 }
1033 // FALLTHROUGH 1035 // FALLTHROUGH
1034 case i::Token::IDENTIFIER: { 1036 case i::Token::IDENTIFIER: {
1035 Identifier id = ParseIdentifier(CHECK_OK); 1037 Identifier id = ParseIdentifier(CHECK_OK);
1036 result = Expression::FromIdentifier(id); 1038 result = Expression::FromIdentifier(id);
1037 break; 1039 break;
1038 } 1040 }
1039 1041
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
1100 if (peek() != i::Token::RBRACK) { 1102 if (peek() != i::Token::RBRACK) {
1101 Expect(i::Token::COMMA, CHECK_OK); 1103 Expect(i::Token::COMMA, CHECK_OK);
1102 } 1104 }
1103 } 1105 }
1104 Expect(i::Token::RBRACK, CHECK_OK); 1106 Expect(i::Token::RBRACK, CHECK_OK);
1105 1107
1106 scope_->NextMaterializedLiteralIndex(); 1108 scope_->NextMaterializedLiteralIndex();
1107 return Expression::Default(); 1109 return Expression::Default();
1108 } 1110 }
1109 1111
1112 void PreParser::CheckDuplicate(DuplicateFinder* finder,
1113 i::Token::Value property,
1114 int type,
1115 bool* ok) {
1116 int old_type;
1117 if (property == i::Token::NUMBER) {
1118 old_type = finder->AddNumber(scanner_->literal_ascii_string(), type);
1119 } else if (scanner_->is_literal_ascii()) {
1120 old_type = finder->AddAsciiSymbol(scanner_->literal_ascii_string(),
1121 type);
1122 } else {
1123 old_type = finder->AddUC16Symbol(scanner_->literal_uc16_string(), type);
1124 }
1125 if (HasConflict(old_type, type)) {
1126 if (IsDataDataConflict(old_type, type)) {
1127 // Both are data properties.
1128 if (!strict_mode()) return;
1129 ReportMessageAt(scanner_->location(),
1130 "strict_duplicate_property", NULL);
1131 } else if (IsDataAccessorConflict(old_type, type)) {
1132 // Both a data and an accessor property with the same name.
1133 ReportMessageAt(scanner_->location(),
1134 "accessor_data_property", NULL);
1135 } else {
1136 ASSERT(IsAccessorAccessorConflict(old_type, type));
1137 // Both accessors of the same type.
1138 ReportMessageAt(scanner_->location(),
1139 "accessor_get_set", NULL);
1140 }
1141 *ok = false;
1142 }
1143 }
1144
1110 1145
1111 PreParser::Expression PreParser::ParseObjectLiteral(bool* ok) { 1146 PreParser::Expression PreParser::ParseObjectLiteral(bool* ok) {
1112 // ObjectLiteral :: 1147 // ObjectLiteral ::
1113 // '{' ( 1148 // '{' (
1114 // ((IdentifierName | String | Number) ':' AssignmentExpression) 1149 // ((IdentifierName | String | Number) ':' AssignmentExpression)
1115 // | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral) 1150 // | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral)
1116 // )*[','] '}' 1151 // )*[','] '}'
1117 1152
1118 Expect(i::Token::LBRACE, CHECK_OK); 1153 Expect(i::Token::LBRACE, CHECK_OK);
1154 DuplicateFinder duplicate_finder(scanner_->unicode_cache());
1119 while (peek() != i::Token::RBRACE) { 1155 while (peek() != i::Token::RBRACE) {
1120 i::Token::Value next = peek(); 1156 i::Token::Value next = peek();
1121 switch (next) { 1157 switch (next) {
1122 case i::Token::IDENTIFIER: 1158 case i::Token::IDENTIFIER:
1123 case i::Token::FUTURE_RESERVED_WORD: 1159 case i::Token::FUTURE_RESERVED_WORD:
1124 case i::Token::FUTURE_STRICT_RESERVED_WORD: { 1160 case i::Token::FUTURE_STRICT_RESERVED_WORD: {
1125 bool is_getter = false; 1161 bool is_getter = false;
1126 bool is_setter = false; 1162 bool is_setter = false;
1127 ParseIdentifierNameOrGetOrSet(&is_getter, &is_setter, CHECK_OK); 1163 ParseIdentifierNameOrGetOrSet(&is_getter, &is_setter, CHECK_OK);
1128 if ((is_getter || is_setter) && peek() != i::Token::COLON) { 1164 if ((is_getter || is_setter) && peek() != i::Token::COLON) {
1129 i::Token::Value name = Next(); 1165 i::Token::Value name = Next();
1130 bool is_keyword = i::Token::IsKeyword(name); 1166 bool is_keyword = i::Token::IsKeyword(name);
1131 if (name != i::Token::IDENTIFIER && 1167 if (name != i::Token::IDENTIFIER &&
1132 name != i::Token::FUTURE_RESERVED_WORD && 1168 name != i::Token::FUTURE_RESERVED_WORD &&
1133 name != i::Token::FUTURE_STRICT_RESERVED_WORD && 1169 name != i::Token::FUTURE_STRICT_RESERVED_WORD &&
1134 name != i::Token::NUMBER && 1170 name != i::Token::NUMBER &&
1135 name != i::Token::STRING && 1171 name != i::Token::STRING &&
1136 !is_keyword) { 1172 !is_keyword) {
1137 *ok = false; 1173 *ok = false;
1138 return Expression::Default(); 1174 return Expression::Default();
1139 } 1175 }
1140 if (!is_keyword) { 1176 if (!is_keyword) {
1141 LogSymbol(); 1177 LogSymbol();
1142 } 1178 }
1179 PropertyType type = is_getter ? kGetterProperty : kSetterProperty;
1180 CheckDuplicate(&duplicate_finder, name, type, CHECK_OK);
1143 ParseFunctionLiteral(CHECK_OK); 1181 ParseFunctionLiteral(CHECK_OK);
1144 if (peek() != i::Token::RBRACE) { 1182 if (peek() != i::Token::RBRACE) {
1145 Expect(i::Token::COMMA, CHECK_OK); 1183 Expect(i::Token::COMMA, CHECK_OK);
1146 } 1184 }
1147 continue; // restart the while 1185 continue; // restart the while
1148 } 1186 }
1187 CheckDuplicate(&duplicate_finder, next, kValueProperty, CHECK_OK);
1149 break; 1188 break;
1150 } 1189 }
1151 case i::Token::STRING: 1190 case i::Token::STRING:
1152 Consume(next); 1191 Consume(next);
1192 CheckDuplicate(&duplicate_finder, next, kValueProperty, CHECK_OK);
1153 GetStringSymbol(); 1193 GetStringSymbol();
1154 break; 1194 break;
1155 case i::Token::NUMBER: 1195 case i::Token::NUMBER:
1156 Consume(next); 1196 Consume(next);
1197 CheckDuplicate(&duplicate_finder, next, kValueProperty, CHECK_OK);
1157 break; 1198 break;
1158 default: 1199 default:
1159 if (i::Token::IsKeyword(next)) { 1200 if (i::Token::IsKeyword(next)) {
1160 Consume(next); 1201 Consume(next);
1202 CheckDuplicate(&duplicate_finder, next, kValueProperty, CHECK_OK);
1161 } else { 1203 } else {
1162 // Unexpected token. 1204 // Unexpected token.
1163 *ok = false; 1205 *ok = false;
1164 return Expression::Default(); 1206 return Expression::Default();
1165 } 1207 }
1166 } 1208 }
1167 1209
1168 Expect(i::Token::COLON, CHECK_OK); 1210 Expect(i::Token::COLON, CHECK_OK);
1169 ParseAssignmentExpression(true, CHECK_OK); 1211 ParseAssignmentExpression(true, CHECK_OK);
1170 1212
1171 // TODO(1240767): Consider allowing trailing comma. 1213 // TODO(1240767): Consider allowing trailing comma.
1172 if (peek() != i::Token::RBRACE) Expect(i::Token::COMMA, CHECK_OK); 1214 if (peek() != i::Token::RBRACE) Expect(i::Token::COMMA, CHECK_OK);
1173 } 1215 }
1174 Expect(i::Token::RBRACE, CHECK_OK); 1216 Expect(i::Token::RBRACE, CHECK_OK);
1175 1217
1176 scope_->NextMaterializedLiteralIndex(); 1218 scope_->NextMaterializedLiteralIndex();
1177 return Expression::Default(); 1219 return Expression::Default();
1178 } 1220 }
1179 1221
1180 1222
1181 PreParser::Expression PreParser::ParseRegExpLiteral(bool seen_equal, 1223 PreParser::Expression PreParser::ParseRegExpLiteral(bool seen_equal,
1182 bool* ok) { 1224 bool* ok) {
1183 if (!scanner_->ScanRegExpPattern(seen_equal)) { 1225 if (!scanner_->ScanRegExpPattern(seen_equal)) {
1184 Next(); 1226 Next();
1185 i::JavaScriptScanner::Location location = scanner_->location(); 1227 ReportMessageAt(scanner_->location(), "unterminated_regexp", NULL);
1186 ReportMessageAt(location.beg_pos, location.end_pos,
1187 "unterminated_regexp", NULL);
1188 *ok = false; 1228 *ok = false;
1189 return Expression::Default(); 1229 return Expression::Default();
1190 } 1230 }
1191 1231
1192 scope_->NextMaterializedLiteralIndex(); 1232 scope_->NextMaterializedLiteralIndex();
1193 1233
1194 if (!scanner_->ScanRegExpFlags()) { 1234 if (!scanner_->ScanRegExpFlags()) {
1195 Next(); 1235 Next();
1196 i::JavaScriptScanner::Location location = scanner_->location(); 1236 ReportMessageAt(scanner_->location(), "invalid_regexp_flags", NULL);
1197 ReportMessageAt(location.beg_pos, location.end_pos,
1198 "invalid_regexp_flags", NULL);
1199 *ok = false; 1237 *ok = false;
1200 return Expression::Default(); 1238 return Expression::Default();
1201 } 1239 }
1202 Next(); 1240 Next();
1203 return Expression::Default(); 1241 return Expression::Default();
1204 } 1242 }
1205 1243
1206 1244
1207 PreParser::Arguments PreParser::ParseArguments(bool* ok) { 1245 PreParser::Arguments PreParser::ParseArguments(bool* ok) {
1208 // Arguments :: 1246 // Arguments ::
(...skipping 24 matching lines...) Expand all
1233 1271
1234 // Parse function body. 1272 // Parse function body.
1235 ScopeType outer_scope_type = scope_->type(); 1273 ScopeType outer_scope_type = scope_->type();
1236 bool inside_with = scope_->IsInsideWith(); 1274 bool inside_with = scope_->IsInsideWith();
1237 Scope function_scope(&scope_, kFunctionScope); 1275 Scope function_scope(&scope_, kFunctionScope);
1238 // FormalParameterList :: 1276 // FormalParameterList ::
1239 // '(' (Identifier)*[','] ')' 1277 // '(' (Identifier)*[','] ')'
1240 Expect(i::Token::LPAREN, CHECK_OK); 1278 Expect(i::Token::LPAREN, CHECK_OK);
1241 int start_position = scanner_->location().beg_pos; 1279 int start_position = scanner_->location().beg_pos;
1242 bool done = (peek() == i::Token::RPAREN); 1280 bool done = (peek() == i::Token::RPAREN);
1281 DuplicateFinder duplicate_finder(scanner_->unicode_cache());
1243 while (!done) { 1282 while (!done) {
1244 Identifier id = ParseIdentifier(CHECK_OK); 1283 Identifier id = ParseIdentifier(CHECK_OK);
1245 if (!id.IsValidStrictVariable()) { 1284 if (!id.IsValidStrictVariable()) {
1246 StrictModeIdentifierViolation(scanner_->location(), 1285 StrictModeIdentifierViolation(scanner_->location(),
1247 "strict_param_name", 1286 "strict_param_name",
1248 id, 1287 id,
1249 CHECK_OK); 1288 CHECK_OK);
1250 } 1289 }
1290 int prev_value;
1291 if (scanner_->is_literal_ascii()) {
1292 prev_value =
1293 duplicate_finder.AddAsciiSymbol(scanner_->literal_ascii_string(), 1);
1294 } else {
1295 prev_value =
1296 duplicate_finder.AddUC16Symbol(scanner_->literal_uc16_string(), 1);
1297 }
1298
1299 if (prev_value != 0) {
1300 SetStrictModeViolation(scanner_->location(),
1301 "strict_param_dupe",
1302 CHECK_OK);
1303 }
1251 done = (peek() == i::Token::RPAREN); 1304 done = (peek() == i::Token::RPAREN);
1252 if (!done) { 1305 if (!done) {
1253 Expect(i::Token::COMMA, CHECK_OK); 1306 Expect(i::Token::COMMA, CHECK_OK);
1254 } 1307 }
1255 } 1308 }
1256 Expect(i::Token::RPAREN, CHECK_OK); 1309 Expect(i::Token::RPAREN, CHECK_OK);
1257 1310
1258 Expect(i::Token::LBRACE, CHECK_OK); 1311 Expect(i::Token::LBRACE, CHECK_OK);
1259 int function_block_pos = scanner_->location().beg_pos; 1312 int function_block_pos = scanner_->location().beg_pos;
1260 1313
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
1392 *ok = false; 1445 *ok = false;
1393 return Identifier::Default(); 1446 return Identifier::Default();
1394 } 1447 }
1395 } 1448 }
1396 1449
1397 1450
1398 void PreParser::SetStrictModeViolation(i::Scanner::Location location, 1451 void PreParser::SetStrictModeViolation(i::Scanner::Location location,
1399 const char* type, 1452 const char* type,
1400 bool* ok) { 1453 bool* ok) {
1401 if (strict_mode()) { 1454 if (strict_mode()) {
1402 ReportMessageAt(location.beg_pos, location.end_pos, type, NULL); 1455 ReportMessageAt(location, type, NULL);
1403 *ok = false; 1456 *ok = false;
1404 return; 1457 return;
1405 } 1458 }
1406 // Delay report in case this later turns out to be strict code 1459 // Delay report in case this later turns out to be strict code
1407 // (i.e., for function names and parameters prior to a "use strict" 1460 // (i.e., for function names and parameters prior to a "use strict"
1408 // directive). 1461 // directive).
1462 // It's safe to overwrite an existing violation.
1463 // It's either from a function that turned out to be non-strict,
1464 // or it's in the current function (and we just need to report
1465 // one error), or it's in a unclosed nesting function that wasn't
1466 // strict (otherwise we would already be in strict mode).
1409 strict_mode_violation_location_ = location; 1467 strict_mode_violation_location_ = location;
1410 strict_mode_violation_type_ = type; 1468 strict_mode_violation_type_ = type;
1411 } 1469 }
1412 1470
1413 1471
1414 void PreParser::CheckDelayedStrictModeViolation(int beg_pos, 1472 void PreParser::CheckDelayedStrictModeViolation(int beg_pos,
1415 int end_pos, 1473 int end_pos,
1416 bool* ok) { 1474 bool* ok) {
1417 i::Scanner::Location location = strict_mode_violation_location_; 1475 i::Scanner::Location location = strict_mode_violation_location_;
1418 if (location.IsValid() && 1476 if (location.IsValid() &&
1419 location.beg_pos > beg_pos && location.end_pos < end_pos) { 1477 location.beg_pos > beg_pos && location.end_pos < end_pos) {
1420 ReportMessageAt(location.beg_pos, location.end_pos, 1478 ReportMessageAt(location, strict_mode_violation_type_, NULL);
1421 strict_mode_violation_type_, NULL);
1422 *ok = false; 1479 *ok = false;
1423 } 1480 }
1424 strict_mode_violation_location_ = i::Scanner::Location::invalid();
1425 } 1481 }
1426 1482
1427 1483
1428 void PreParser::StrictModeIdentifierViolation(i::Scanner::Location location, 1484 void PreParser::StrictModeIdentifierViolation(i::Scanner::Location location,
1429 const char* eval_args_type, 1485 const char* eval_args_type,
1430 Identifier identifier, 1486 Identifier identifier,
1431 bool* ok) { 1487 bool* ok) {
1432 const char* type = eval_args_type; 1488 const char* type = eval_args_type;
1433 if (identifier.IsFutureReserved()) { 1489 if (identifier.IsFutureReserved()) {
1434 type = "reserved_word"; 1490 type = "reserved_word";
1435 } else if (identifier.IsFutureStrictReserved()) { 1491 } else if (identifier.IsFutureStrictReserved()) {
1436 type = "strict_reserved_word"; 1492 type = "strict_reserved_word";
1437 } 1493 }
1438 if (strict_mode()) { 1494 if (strict_mode()) {
1439 ReportMessageAt(location.beg_pos, location.end_pos, type, NULL); 1495 ReportMessageAt(location, type, NULL);
1440 *ok = false; 1496 *ok = false;
1441 return; 1497 return;
1442 } 1498 }
1443 strict_mode_violation_location_ = location; 1499 strict_mode_violation_location_ = location;
1444 strict_mode_violation_type_ = type; 1500 strict_mode_violation_type_ = type;
1445 } 1501 }
1446 1502
1447 1503
1448 PreParser::Identifier PreParser::ParseIdentifierName(bool* ok) { 1504 PreParser::Identifier PreParser::ParseIdentifierName(bool* ok) {
1449 i::Token::Value next = Next(); 1505 i::Token::Value next = Next();
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1481 } 1537 }
1482 return result; 1538 return result;
1483 } 1539 }
1484 1540
1485 bool PreParser::peek_any_identifier() { 1541 bool PreParser::peek_any_identifier() {
1486 i::Token::Value next = peek(); 1542 i::Token::Value next = peek();
1487 return next == i::Token::IDENTIFIER || 1543 return next == i::Token::IDENTIFIER ||
1488 next == i::Token::FUTURE_RESERVED_WORD || 1544 next == i::Token::FUTURE_RESERVED_WORD ||
1489 next == i::Token::FUTURE_STRICT_RESERVED_WORD; 1545 next == i::Token::FUTURE_STRICT_RESERVED_WORD;
1490 } 1546 }
1547
1548
1549 int DuplicateFinder::AddAsciiSymbol(i::Vector<const char> key, int value) {
1550 return AddSymbol(i::Vector<const byte>::cast(key), true, value);
1551 }
1552
1553 int DuplicateFinder::AddUC16Symbol(i::Vector<const uint16_t> key, int value) {
1554 return AddSymbol(i::Vector<const byte>::cast(key), false, value);
1555 }
1556
1557 int DuplicateFinder::AddSymbol(i::Vector<const byte> key,
1558 bool is_ascii,
1559 int value) {
1560 uint32_t hash = Hash(key, is_ascii);
1561 byte* encoding = BackupKey(key, is_ascii);
1562 i::HashMap::Entry* entry = map_->Lookup(encoding, hash, true);
1563 int old_value = static_cast<int>(reinterpret_cast<intptr_t>(entry->value));
1564 entry->value =
1565 reinterpret_cast<void*>(static_cast<intptr_t>(value | old_value));
1566 return old_value;
1567 }
1568
1569
1570 int DuplicateFinder::AddNumber(i::Vector<const char> key, int value) {
1571 ASSERT(key.length() > 0);
1572 // Quick check for already being in canonical form.
1573 if (IsNumberCanonical(key)) {
1574 return AddAsciiSymbol(key, value);
1575 }
1576
1577 int flags = i::ALLOW_HEX | i::ALLOW_OCTALS;
1578 double double_value = StringToDouble(unicode_constants_, key, flags, 0.0);
1579 int length;
1580 const char* string;
1581 if (!isfinite(double_value)) {
1582 string = "Infinity";
1583 length = 8; // strlen("Infinity");
1584 } else {
1585 string = DoubleToCString(double_value,
1586 i::Vector<char>(number_buffer_, kBufferSize));
1587 length = i::StrLength(string);
1588 }
1589 return AddAsciiSymbol(i::Vector<const char>(string, length), value);
1590 }
1591
1592
1593 bool DuplicateFinder::IsNumberCanonical(i::Vector<const char> number) {
1594 // Test for a safe approximation of number literals that are already
1595 // in canonical form: max 15 digits, no leading zeroes, except an
1596 // integer part that is a single zero, and no trailing zeros below
1597 // the decimal point.
1598 int pos = 0;
1599 int length = number.length();
1600 if (number.length() > 15) return false;
1601 if (number[pos] == '0') {
1602 pos++;
1603 } else {
1604 while (pos < length &&
1605 static_cast<unsigned>(number[pos] - '0') <= ('9' - '0')) pos++;
1606 }
1607 if (length == pos) return true;
1608 if (number[pos] != '.') return false;
1609 pos++;
1610 bool invalid_last_digit = true;
1611 while (pos < length) {
1612 byte digit = number[pos] - '0';
1613 if (digit > '9' - '0') return false;
1614 invalid_last_digit = (digit == 0);
1615 pos++;
1616 }
1617 return !invalid_last_digit;
1618 }
1619
1620
1621 uint32_t DuplicateFinder::Hash(i::Vector<const byte> key, bool is_ascii) {
1622 // Primitive hash function, almost identical to the one used
1623 // for strings (except that it's seeded by the length and ASCII-ness).
1624 int length = key.length();
1625 uint32_t hash = (length << 1) | (is_ascii ? 1 : 0) ;
1626 for (int i = 0; i < length; i++) {
1627 uint32_t c = key[i];
1628 hash = (hash + c) * 1025;
1629 hash ^= (hash >> 6);
1630 }
1631 return hash;
1632 }
1633
1634
1635 bool DuplicateFinder::Match(void* first, void* second) {
1636 // Decode lengths.
1637 // Length + ASCII-bit is encoded as base 128, most significant heptet first,
1638 // with a 8th bit being non-zero while there are more heptets.
1639 // The value encodes the number of bytes following, and whether the original
1640 // was ASCII.
1641 byte* s1 = reinterpret_cast<byte*>(first);
1642 byte* s2 = reinterpret_cast<byte*>(second);
1643 uint32_t length_ascii_field = 0;
1644 byte c1;
1645 do {
1646 c1 = *s1;
1647 if (c1 != *s2) return false;
1648 length_ascii_field = (length_ascii_field << 7) | (c1 & 0x7f);
1649 s1++;
1650 s2++;
1651 } while ((c1 & 0x80) != 0);
1652 int length = static_cast<int>(length_ascii_field >> 1);
1653 return memcmp(s1, s2, length) == 0;
1654 }
1655
1656
1657 byte* DuplicateFinder::BackupKey(i::Vector<const byte> bytes,
1658 bool is_ascii) {
1659 uint32_t ascii_length = (bytes.length() << 1) | (is_ascii ? 1 : 0);
1660 backing_store_.StartSequence();
1661 // Emit ascii_length as base-128 encoded number, with the 7th bit set
1662 // on the byte of every heptet except the last, least significant, one.
1663 if (ascii_length >= (1 << 7)) {
1664 if (ascii_length >= (1 << 14)) {
1665 if (ascii_length >= (1 << 21)) {
1666 if (ascii_length >= (1 << 28)) {
1667 backing_store_.Add(static_cast<byte>((ascii_length >> 28) | 0x80));
1668 }
1669 backing_store_.Add(static_cast<byte>((ascii_length >> 21) | 0x80u));
1670 }
1671 backing_store_.Add(static_cast<byte>((ascii_length >> 14) | 0x80u));
1672 }
1673 backing_store_.Add(static_cast<byte>((ascii_length >> 7) | 0x80u));
1674 }
1675 backing_store_.Add(static_cast<byte>(ascii_length & 0x7f));
1676
1677 backing_store_.AddBlock(bytes);
1678 return backing_store_.EndSequence().start();
1679 }
1491 } } // v8::preparser 1680 } } // v8::preparser
OLDNEW
« src/globals.h ('K') | « src/preparser.h ('k') | src/preparser-api.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698