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

Side by Side Diff: src/preparser.cc

Issue 7168016: Add duplicate parameter detection to preparser. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Update to tip of bleeding_edge Created 9 years, 5 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
« no previous file with comments | « src/preparser.h ('k') | src/preparser-api.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 <errno.h>
29 #include <math.h>
30
28 #include "../include/v8stdint.h" 31 #include "../include/v8stdint.h"
29 #include "unicode.h" 32 #include "unicode.h"
30 #include "globals.h" 33 #include "globals.h"
31 #include "checks.h" 34 #include "checks.h"
32 #include "allocation.h" 35 #include "allocation.h"
33 #include "utils.h" 36 #include "utils.h"
34 #include "list.h" 37 #include "list.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 namespace v8 { 45 namespace v8 {
42 namespace preparser { 46 namespace preparser {
43 47
44 // Preparsing checks a JavaScript program and emits preparse-data that helps 48 // Preparsing checks a JavaScript program and emits preparse-data that helps
(...skipping 16 matching lines...) Expand all
61 // stack depth even further. Instead we report it after parsing is 65 // stack depth even further. Instead we report it after parsing is
62 // over, in ParseProgram. 66 // over, in ParseProgram.
63 if (token == i::Token::ILLEGAL && stack_overflow_) { 67 if (token == i::Token::ILLEGAL && stack_overflow_) {
64 return; 68 return;
65 } 69 }
66 i::JavaScriptScanner::Location source_location = scanner_->location(); 70 i::JavaScriptScanner::Location source_location = scanner_->location();
67 71
68 // Four of the tokens are treated specially 72 // Four of the tokens are treated specially
69 switch (token) { 73 switch (token) {
70 case i::Token::EOS: 74 case i::Token::EOS:
71 return ReportMessageAt(source_location.beg_pos, source_location.end_pos, 75 return ReportMessageAt(source_location, "unexpected_eos", NULL);
72 "unexpected_eos", NULL);
73 case i::Token::NUMBER: 76 case i::Token::NUMBER:
74 return ReportMessageAt(source_location.beg_pos, source_location.end_pos, 77 return ReportMessageAt(source_location, "unexpected_token_number", NULL);
75 "unexpected_token_number", NULL);
76 case i::Token::STRING: 78 case i::Token::STRING:
77 return ReportMessageAt(source_location.beg_pos, source_location.end_pos, 79 return ReportMessageAt(source_location, "unexpected_token_string", NULL);
78 "unexpected_token_string", NULL);
79 case i::Token::IDENTIFIER: 80 case i::Token::IDENTIFIER:
80 return ReportMessageAt(source_location.beg_pos, source_location.end_pos, 81 return ReportMessageAt(source_location,
81 "unexpected_token_identifier", NULL); 82 "unexpected_token_identifier", NULL);
82 case i::Token::FUTURE_RESERVED_WORD: 83 case i::Token::FUTURE_RESERVED_WORD:
83 return ReportMessageAt(source_location.beg_pos, source_location.end_pos, 84 return ReportMessageAt(source_location, "unexpected_reserved", NULL);
84 "unexpected_reserved", NULL);
85 case i::Token::FUTURE_STRICT_RESERVED_WORD: 85 case i::Token::FUTURE_STRICT_RESERVED_WORD:
86 return ReportMessageAt(source_location.beg_pos, source_location.end_pos, 86 return ReportMessageAt(source_location,
87 "unexpected_strict_reserved", NULL); 87 "unexpected_strict_reserved", NULL);
88 default: 88 default:
89 const char* name = i::Token::String(token); 89 const char* name = i::Token::String(token);
90 ReportMessageAt(source_location.beg_pos, source_location.end_pos, 90 ReportMessageAt(source_location, "unexpected_token", name);
91 "unexpected_token", name);
92 } 91 }
93 } 92 }
94 93
95 94
96 // Checks whether octal literal last seen is between beg_pos and end_pos. 95 // Checks whether octal literal last seen is between beg_pos and end_pos.
97 // If so, reports an error. 96 // If so, reports an error.
98 void PreParser::CheckOctalLiteral(int beg_pos, int end_pos, bool* ok) { 97 void PreParser::CheckOctalLiteral(int beg_pos, int end_pos, bool* ok) {
99 i::Scanner::Location octal = scanner_->octal_position(); 98 i::Scanner::Location octal = scanner_->octal_position();
100 if (beg_pos <= octal.beg_pos && octal.end_pos <= end_pos) { 99 if (beg_pos <= octal.beg_pos && octal.end_pos <= end_pos) {
101 ReportMessageAt(octal.beg_pos, octal.end_pos, "strict_octal_literal", NULL); 100 ReportMessageAt(octal, "strict_octal_literal", NULL);
102 scanner_->clear_octal_position(); 101 scanner_->clear_octal_position();
103 *ok = false; 102 *ok = false;
104 } 103 }
105 } 104 }
106 105
107 106
108 #define CHECK_OK ok); \ 107 #define CHECK_OK ok); \
109 if (!*ok) return kUnknownSourceElements; \ 108 if (!*ok) return kUnknownSourceElements; \
110 ((void)0 109 ((void)0
111 #define DUMMY ) // to make indentation work 110 #define DUMMY ) // to make indentation work
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
234 Expression function_value = ParseFunctionLiteral(CHECK_OK); 233 Expression function_value = ParseFunctionLiteral(CHECK_OK);
235 234
236 if (function_value.IsStrictFunction() && 235 if (function_value.IsStrictFunction() &&
237 !identifier.IsValidStrictVariable()) { 236 !identifier.IsValidStrictVariable()) {
238 // Strict mode violation, using either reserved word or eval/arguments 237 // Strict mode violation, using either reserved word or eval/arguments
239 // as name of strict function. 238 // as name of strict function.
240 const char* type = "strict_function_name"; 239 const char* type = "strict_function_name";
241 if (identifier.IsFutureStrictReserved()) { 240 if (identifier.IsFutureStrictReserved()) {
242 type = "strict_reserved_word"; 241 type = "strict_reserved_word";
243 } 242 }
244 ReportMessageAt(location.beg_pos, location.end_pos, type, NULL); 243 ReportMessageAt(location, type, NULL);
245 *ok = false; 244 *ok = false;
246 } 245 }
247 return Statement::FunctionDeclaration(); 246 return Statement::FunctionDeclaration();
248 } 247 }
249 248
250 249
251 PreParser::Statement PreParser::ParseBlock(bool* ok) { 250 PreParser::Statement PreParser::ParseBlock(bool* ok) {
252 // Block :: 251 // Block ::
253 // '{' Statement* '}' 252 // '{' Statement* '}'
254 253
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
291 int* num_decl, 290 int* num_decl,
292 bool* ok) { 291 bool* ok) {
293 // VariableDeclarations :: 292 // VariableDeclarations ::
294 // ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[','] 293 // ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[',']
295 294
296 if (peek() == i::Token::VAR) { 295 if (peek() == i::Token::VAR) {
297 Consume(i::Token::VAR); 296 Consume(i::Token::VAR);
298 } else if (peek() == i::Token::CONST) { 297 } else if (peek() == i::Token::CONST) {
299 if (strict_mode()) { 298 if (strict_mode()) {
300 i::Scanner::Location location = scanner_->peek_location(); 299 i::Scanner::Location location = scanner_->peek_location();
301 ReportMessageAt(location.beg_pos, location.end_pos, 300 ReportMessageAt(location, "strict_const", NULL);
302 "strict_const", NULL);
303 *ok = false; 301 *ok = false;
304 return Statement::Default(); 302 return Statement::Default();
305 } 303 }
306 Consume(i::Token::CONST); 304 Consume(i::Token::CONST);
307 } else { 305 } else {
308 *ok = false; 306 *ok = false;
309 return Statement::Default(); 307 return Statement::Default();
310 } 308 }
311 309
312 // The scope of a variable/const declared anywhere inside a function 310 // The scope of a variable/const declared anywhere inside a function
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
441 return Statement::Default(); 439 return Statement::Default();
442 } 440 }
443 441
444 442
445 PreParser::Statement PreParser::ParseWithStatement(bool* ok) { 443 PreParser::Statement PreParser::ParseWithStatement(bool* ok) {
446 // WithStatement :: 444 // WithStatement ::
447 // 'with' '(' Expression ')' Statement 445 // 'with' '(' Expression ')' Statement
448 Expect(i::Token::WITH, CHECK_OK); 446 Expect(i::Token::WITH, CHECK_OK);
449 if (strict_mode()) { 447 if (strict_mode()) {
450 i::Scanner::Location location = scanner_->location(); 448 i::Scanner::Location location = scanner_->location();
451 ReportMessageAt(location.beg_pos, location.end_pos, 449 ReportMessageAt(location, "strict_mode_with", NULL);
452 "strict_mode_with", NULL);
453 *ok = false; 450 *ok = false;
454 return Statement::Default(); 451 return Statement::Default();
455 } 452 }
456 Expect(i::Token::LPAREN, CHECK_OK); 453 Expect(i::Token::LPAREN, CHECK_OK);
457 ParseExpression(true, CHECK_OK); 454 ParseExpression(true, CHECK_OK);
458 Expect(i::Token::RPAREN, CHECK_OK); 455 Expect(i::Token::RPAREN, CHECK_OK);
459 456
460 scope_->EnterWith(); 457 scope_->EnterWith();
461 ParseStatement(CHECK_OK); 458 ParseStatement(CHECK_OK);
462 scope_->LeaveWith(); 459 scope_->LeaveWith();
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
577 } 574 }
578 575
579 576
580 PreParser::Statement PreParser::ParseThrowStatement(bool* ok) { 577 PreParser::Statement PreParser::ParseThrowStatement(bool* ok) {
581 // ThrowStatement :: 578 // ThrowStatement ::
582 // 'throw' [no line terminator] Expression ';' 579 // 'throw' [no line terminator] Expression ';'
583 580
584 Expect(i::Token::THROW, CHECK_OK); 581 Expect(i::Token::THROW, CHECK_OK);
585 if (scanner_->HasAnyLineTerminatorBeforeNext()) { 582 if (scanner_->HasAnyLineTerminatorBeforeNext()) {
586 i::JavaScriptScanner::Location pos = scanner_->location(); 583 i::JavaScriptScanner::Location pos = scanner_->location();
587 ReportMessageAt(pos.beg_pos, pos.end_pos, 584 ReportMessageAt(pos, "newline_after_throw", NULL);
588 "newline_after_throw", NULL);
589 *ok = false; 585 *ok = false;
590 return Statement::Default(); 586 return Statement::Default();
591 } 587 }
592 ParseExpression(true, CHECK_OK); 588 ParseExpression(true, CHECK_OK);
593 ExpectSemicolon(ok); 589 ExpectSemicolon(ok);
594 return Statement::Default(); 590 return Statement::Default();
595 } 591 }
596 592
597 593
598 PreParser::Statement PreParser::ParseTryStatement(bool* ok) { 594 PreParser::Statement PreParser::ParseTryStatement(bool* ok) {
(...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after
990 ReportMessageAt(location.beg_pos, location.end_pos, 986 ReportMessageAt(location.beg_pos, location.end_pos,
991 "reserved_word", NULL); 987 "reserved_word", NULL);
992 *ok = false; 988 *ok = false;
993 return Expression::Default(); 989 return Expression::Default();
994 } 990 }
995 991
996 case i::Token::FUTURE_STRICT_RESERVED_WORD: 992 case i::Token::FUTURE_STRICT_RESERVED_WORD:
997 if (strict_mode()) { 993 if (strict_mode()) {
998 Next(); 994 Next();
999 i::Scanner::Location location = scanner_->location(); 995 i::Scanner::Location location = scanner_->location();
1000 ReportMessageAt(location.beg_pos, location.end_pos, 996 ReportMessageAt(location, "strict_reserved_word", NULL);
1001 "strict_reserved_word", NULL);
1002 *ok = false; 997 *ok = false;
1003 return Expression::Default(); 998 return Expression::Default();
1004 } 999 }
1005 // FALLTHROUGH 1000 // FALLTHROUGH
1006 case i::Token::IDENTIFIER: { 1001 case i::Token::IDENTIFIER: {
1007 Identifier id = ParseIdentifier(CHECK_OK); 1002 Identifier id = ParseIdentifier(CHECK_OK);
1008 result = Expression::FromIdentifier(id); 1003 result = Expression::FromIdentifier(id);
1009 break; 1004 break;
1010 } 1005 }
1011 1006
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
1072 if (peek() != i::Token::RBRACK) { 1067 if (peek() != i::Token::RBRACK) {
1073 Expect(i::Token::COMMA, CHECK_OK); 1068 Expect(i::Token::COMMA, CHECK_OK);
1074 } 1069 }
1075 } 1070 }
1076 Expect(i::Token::RBRACK, CHECK_OK); 1071 Expect(i::Token::RBRACK, CHECK_OK);
1077 1072
1078 scope_->NextMaterializedLiteralIndex(); 1073 scope_->NextMaterializedLiteralIndex();
1079 return Expression::Default(); 1074 return Expression::Default();
1080 } 1075 }
1081 1076
1077 void PreParser::CheckDuplicate(DuplicateFinder* finder,
1078 i::Token::Value property,
1079 int type,
1080 bool* ok) {
1081 int old_value;
1082 if (property == i::Token::NUMBER) {
1083 old_value = finder->AddNumber(scanner_->literal_ascii_string(), type);
1084 } else if (scanner_->is_literal_ascii()) {
1085 old_value = finder->AddAsciiSymbol(scanner_->literal_ascii_string(),
1086 type);
1087 } else {
1088 old_value = finder->AddUC16Symbol(scanner_->literal_uc16_string(), type);
1089 }
1090 int intersect = old_value & type;
1091 if (intersect != 0) {
1092 if ((intersect & kValueFlag) != 0) {
1093 // Both are data properties.
1094 if (!strict_mode()) return;
1095 ReportMessageAt(scanner_->location(),
1096 "strict_duplicate_property", NULL);
1097 } else if (((old_value ^ type) & kValueFlag) != 0) {
1098 // Both a data and an accessor property with the same name.
1099 ReportMessageAt(scanner_->location(),
1100 "accessor_data_property", NULL);
1101 } else {
1102 // Both accessors of the same type.
1103 ReportMessageAt(scanner_->location(),
1104 "accessor_get_set", NULL);
1105 }
1106 *ok = false;
1107 }
1108 }
1109
1082 1110
1083 PreParser::Expression PreParser::ParseObjectLiteral(bool* ok) { 1111 PreParser::Expression PreParser::ParseObjectLiteral(bool* ok) {
1084 // ObjectLiteral :: 1112 // ObjectLiteral ::
1085 // '{' ( 1113 // '{' (
1086 // ((IdentifierName | String | Number) ':' AssignmentExpression) 1114 // ((IdentifierName | String | Number) ':' AssignmentExpression)
1087 // | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral) 1115 // | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral)
1088 // )*[','] '}' 1116 // )*[','] '}'
1089 1117
1090 Expect(i::Token::LBRACE, CHECK_OK); 1118 Expect(i::Token::LBRACE, CHECK_OK);
1119 DuplicateFinder duplicate_finder;
1091 while (peek() != i::Token::RBRACE) { 1120 while (peek() != i::Token::RBRACE) {
1092 i::Token::Value next = peek(); 1121 i::Token::Value next = peek();
1093 switch (next) { 1122 switch (next) {
1094 case i::Token::IDENTIFIER: 1123 case i::Token::IDENTIFIER:
1095 case i::Token::FUTURE_RESERVED_WORD: 1124 case i::Token::FUTURE_RESERVED_WORD:
1096 case i::Token::FUTURE_STRICT_RESERVED_WORD: { 1125 case i::Token::FUTURE_STRICT_RESERVED_WORD: {
1097 bool is_getter = false; 1126 bool is_getter = false;
1098 bool is_setter = false; 1127 bool is_setter = false;
1099 ParseIdentifierNameOrGetOrSet(&is_getter, &is_setter, CHECK_OK); 1128 ParseIdentifierNameOrGetOrSet(&is_getter, &is_setter, CHECK_OK);
1100 if ((is_getter || is_setter) && peek() != i::Token::COLON) { 1129 if ((is_getter || is_setter) && peek() != i::Token::COLON) {
1101 i::Token::Value name = Next(); 1130 i::Token::Value name = Next();
1102 bool is_keyword = i::Token::IsKeyword(name); 1131 bool is_keyword = i::Token::IsKeyword(name);
1103 if (name != i::Token::IDENTIFIER && 1132 if (name != i::Token::IDENTIFIER &&
1104 name != i::Token::FUTURE_RESERVED_WORD && 1133 name != i::Token::FUTURE_RESERVED_WORD &&
1105 name != i::Token::FUTURE_STRICT_RESERVED_WORD && 1134 name != i::Token::FUTURE_STRICT_RESERVED_WORD &&
1106 name != i::Token::NUMBER && 1135 name != i::Token::NUMBER &&
1107 name != i::Token::STRING && 1136 name != i::Token::STRING &&
1108 !is_keyword) { 1137 !is_keyword) {
1109 *ok = false; 1138 *ok = false;
1110 return Expression::Default(); 1139 return Expression::Default();
1111 } 1140 }
1112 if (!is_keyword) { 1141 if (!is_keyword) {
1113 LogSymbol(); 1142 LogSymbol();
1114 } 1143 }
1144 int type = is_getter ? kGetterProperty : kSetterProperty;
1145 CheckDuplicate(&duplicate_finder, name, type, CHECK_OK);
1115 ParseFunctionLiteral(CHECK_OK); 1146 ParseFunctionLiteral(CHECK_OK);
1116 if (peek() != i::Token::RBRACE) { 1147 if (peek() != i::Token::RBRACE) {
1117 Expect(i::Token::COMMA, CHECK_OK); 1148 Expect(i::Token::COMMA, CHECK_OK);
1118 } 1149 }
1119 continue; // restart the while 1150 continue; // restart the while
1120 } 1151 }
1152 CheckDuplicate(&duplicate_finder, next, kValueProperty, CHECK_OK);
1121 break; 1153 break;
1122 } 1154 }
1123 case i::Token::STRING: 1155 case i::Token::STRING:
1124 Consume(next); 1156 Consume(next);
1157 CheckDuplicate(&duplicate_finder, next, kValueProperty, CHECK_OK);
1125 GetStringSymbol(); 1158 GetStringSymbol();
1126 break; 1159 break;
1127 case i::Token::NUMBER: 1160 case i::Token::NUMBER:
1128 Consume(next); 1161 Consume(next);
1162 CheckDuplicate(&duplicate_finder, next, kValueProperty, CHECK_OK);
1129 break; 1163 break;
1130 default: 1164 default:
1131 if (i::Token::IsKeyword(next)) { 1165 if (i::Token::IsKeyword(next)) {
1132 Consume(next); 1166 Consume(next);
1167 CheckDuplicate(&duplicate_finder, next, kValueProperty, CHECK_OK);
1133 } else { 1168 } else {
1134 // Unexpected token. 1169 // Unexpected token.
1135 *ok = false; 1170 *ok = false;
1136 return Expression::Default(); 1171 return Expression::Default();
1137 } 1172 }
1138 } 1173 }
1139 1174
1140 Expect(i::Token::COLON, CHECK_OK); 1175 Expect(i::Token::COLON, CHECK_OK);
1141 ParseAssignmentExpression(true, CHECK_OK); 1176 ParseAssignmentExpression(true, CHECK_OK);
1142 1177
1143 // TODO(1240767): Consider allowing trailing comma. 1178 // TODO(1240767): Consider allowing trailing comma.
1144 if (peek() != i::Token::RBRACE) Expect(i::Token::COMMA, CHECK_OK); 1179 if (peek() != i::Token::RBRACE) Expect(i::Token::COMMA, CHECK_OK);
1145 } 1180 }
1146 Expect(i::Token::RBRACE, CHECK_OK); 1181 Expect(i::Token::RBRACE, CHECK_OK);
1147 1182
1148 scope_->NextMaterializedLiteralIndex(); 1183 scope_->NextMaterializedLiteralIndex();
1149 return Expression::Default(); 1184 return Expression::Default();
1150 } 1185 }
1151 1186
1152 1187
1153 PreParser::Expression PreParser::ParseRegExpLiteral(bool seen_equal, 1188 PreParser::Expression PreParser::ParseRegExpLiteral(bool seen_equal,
1154 bool* ok) { 1189 bool* ok) {
1155 if (!scanner_->ScanRegExpPattern(seen_equal)) { 1190 if (!scanner_->ScanRegExpPattern(seen_equal)) {
1156 Next(); 1191 Next();
1157 i::JavaScriptScanner::Location location = scanner_->location(); 1192 ReportMessageAt(scanner_->location(), "unterminated_regexp", NULL);
1158 ReportMessageAt(location.beg_pos, location.end_pos,
1159 "unterminated_regexp", NULL);
1160 *ok = false; 1193 *ok = false;
1161 return Expression::Default(); 1194 return Expression::Default();
1162 } 1195 }
1163 1196
1164 scope_->NextMaterializedLiteralIndex(); 1197 scope_->NextMaterializedLiteralIndex();
1165 1198
1166 if (!scanner_->ScanRegExpFlags()) { 1199 if (!scanner_->ScanRegExpFlags()) {
1167 Next(); 1200 Next();
1168 i::JavaScriptScanner::Location location = scanner_->location(); 1201 ReportMessageAt(scanner_->location(), "invalid_regexp_flags", NULL);
1169 ReportMessageAt(location.beg_pos, location.end_pos,
1170 "invalid_regexp_flags", NULL);
1171 *ok = false; 1202 *ok = false;
1172 return Expression::Default(); 1203 return Expression::Default();
1173 } 1204 }
1174 Next(); 1205 Next();
1175 return Expression::Default(); 1206 return Expression::Default();
1176 } 1207 }
1177 1208
1178 1209
1179 PreParser::Arguments PreParser::ParseArguments(bool* ok) { 1210 PreParser::Arguments PreParser::ParseArguments(bool* ok) {
1180 // Arguments :: 1211 // Arguments ::
(...skipping 24 matching lines...) Expand all
1205 1236
1206 // Parse function body. 1237 // Parse function body.
1207 ScopeType outer_scope_type = scope_->type(); 1238 ScopeType outer_scope_type = scope_->type();
1208 bool inside_with = scope_->IsInsideWith(); 1239 bool inside_with = scope_->IsInsideWith();
1209 Scope function_scope(&scope_, kFunctionScope); 1240 Scope function_scope(&scope_, kFunctionScope);
1210 // FormalParameterList :: 1241 // FormalParameterList ::
1211 // '(' (Identifier)*[','] ')' 1242 // '(' (Identifier)*[','] ')'
1212 Expect(i::Token::LPAREN, CHECK_OK); 1243 Expect(i::Token::LPAREN, CHECK_OK);
1213 int start_position = scanner_->location().beg_pos; 1244 int start_position = scanner_->location().beg_pos;
1214 bool done = (peek() == i::Token::RPAREN); 1245 bool done = (peek() == i::Token::RPAREN);
1246 DuplicateFinder duplicate_finder;
1215 while (!done) { 1247 while (!done) {
1216 Identifier id = ParseIdentifier(CHECK_OK); 1248 Identifier id = ParseIdentifier(CHECK_OK);
1217 if (!id.IsValidStrictVariable()) { 1249 if (!id.IsValidStrictVariable()) {
1218 StrictModeIdentifierViolation(scanner_->location(), 1250 StrictModeIdentifierViolation(scanner_->location(),
1219 "strict_param_name", 1251 "strict_param_name",
1220 id, 1252 id,
1221 CHECK_OK); 1253 CHECK_OK);
1222 } 1254 }
1255 int prev_value;
1256 if (scanner_->is_literal_ascii()) {
1257 prev_value =
1258 duplicate_finder.AddAsciiSymbol(scanner_->literal_ascii_string(), 1);
1259 } else {
1260 prev_value =
1261 duplicate_finder.AddUC16Symbol(scanner_->literal_uc16_string(), 1);
1262 }
1263
1264 if (prev_value != 0) {
1265 SetStrictModeViolation(scanner_->location(),
1266 "strict_param_dupe",
1267 CHECK_OK);
1268 }
1223 done = (peek() == i::Token::RPAREN); 1269 done = (peek() == i::Token::RPAREN);
1224 if (!done) { 1270 if (!done) {
1225 Expect(i::Token::COMMA, CHECK_OK); 1271 Expect(i::Token::COMMA, CHECK_OK);
1226 } 1272 }
1227 } 1273 }
1228 Expect(i::Token::RPAREN, CHECK_OK); 1274 Expect(i::Token::RPAREN, CHECK_OK);
1229 1275
1230 Expect(i::Token::LBRACE, CHECK_OK); 1276 Expect(i::Token::LBRACE, CHECK_OK);
1231 int function_block_pos = scanner_->location().beg_pos; 1277 int function_block_pos = scanner_->location().beg_pos;
1232 1278
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
1364 *ok = false; 1410 *ok = false;
1365 return Identifier::Default(); 1411 return Identifier::Default();
1366 } 1412 }
1367 } 1413 }
1368 1414
1369 1415
1370 void PreParser::SetStrictModeViolation(i::Scanner::Location location, 1416 void PreParser::SetStrictModeViolation(i::Scanner::Location location,
1371 const char* type, 1417 const char* type,
1372 bool* ok) { 1418 bool* ok) {
1373 if (strict_mode()) { 1419 if (strict_mode()) {
1374 ReportMessageAt(location.beg_pos, location.end_pos, type, NULL); 1420 ReportMessageAt(location, type, NULL);
1375 *ok = false; 1421 *ok = false;
1376 return; 1422 return;
1377 } 1423 }
1378 // Delay report in case this later turns out to be strict code 1424 // Delay report in case this later turns out to be strict code
1379 // (i.e., for function names and parameters prior to a "use strict" 1425 // (i.e., for function names and parameters prior to a "use strict"
1380 // directive). 1426 // directive).
1427 // It's safe to overwrite an existing violation.
1428 // It's either from a function that turned out to be non-strict,
1429 // or it's in the current function (and we just need to report
1430 // one error), or it's in a unclosed nesting function that wasn't
1431 // strict (otherwise we would already be in strict mode).
1381 strict_mode_violation_location_ = location; 1432 strict_mode_violation_location_ = location;
1382 strict_mode_violation_type_ = type; 1433 strict_mode_violation_type_ = type;
1383 } 1434 }
1384 1435
1385 1436
1386 void PreParser::CheckDelayedStrictModeViolation(int beg_pos, 1437 void PreParser::CheckDelayedStrictModeViolation(int beg_pos,
1387 int end_pos, 1438 int end_pos,
1388 bool* ok) { 1439 bool* ok) {
1389 i::Scanner::Location location = strict_mode_violation_location_; 1440 i::Scanner::Location location = strict_mode_violation_location_;
1390 if (location.IsValid() && 1441 if (location.IsValid() &&
1391 location.beg_pos > beg_pos && location.end_pos < end_pos) { 1442 location.beg_pos > beg_pos && location.end_pos < end_pos) {
1392 ReportMessageAt(location.beg_pos, location.end_pos, 1443 ReportMessageAt(location, strict_mode_violation_type_, NULL);
1393 strict_mode_violation_type_, NULL);
1394 *ok = false; 1444 *ok = false;
1395 } 1445 }
1396 strict_mode_violation_location_ = i::Scanner::Location::invalid();
1397 } 1446 }
1398 1447
1399 1448
1400 void PreParser::StrictModeIdentifierViolation(i::Scanner::Location location, 1449 void PreParser::StrictModeIdentifierViolation(i::Scanner::Location location,
1401 const char* eval_args_type, 1450 const char* eval_args_type,
1402 Identifier identifier, 1451 Identifier identifier,
1403 bool* ok) { 1452 bool* ok) {
1404 const char* type = eval_args_type; 1453 const char* type = eval_args_type;
1405 if (identifier.IsFutureReserved()) { 1454 if (identifier.IsFutureReserved()) {
1406 type = "reserved_word"; 1455 type = "reserved_word";
1407 } else if (identifier.IsFutureStrictReserved()) { 1456 } else if (identifier.IsFutureStrictReserved()) {
1408 type = "strict_reserved_word"; 1457 type = "strict_reserved_word";
1409 } 1458 }
1410 if (strict_mode()) { 1459 if (strict_mode()) {
1411 ReportMessageAt(location.beg_pos, location.end_pos, type, NULL); 1460 ReportMessageAt(location, type, NULL);
1412 *ok = false; 1461 *ok = false;
1413 return; 1462 return;
1414 } 1463 }
1415 strict_mode_violation_location_ = location; 1464 strict_mode_violation_location_ = location;
1416 strict_mode_violation_type_ = type; 1465 strict_mode_violation_type_ = type;
1417 } 1466 }
1418 1467
1419 1468
1420 PreParser::Identifier PreParser::ParseIdentifierName(bool* ok) { 1469 PreParser::Identifier PreParser::ParseIdentifierName(bool* ok) {
1421 i::Token::Value next = Next(); 1470 i::Token::Value next = Next();
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1453 } 1502 }
1454 return result; 1503 return result;
1455 } 1504 }
1456 1505
1457 bool PreParser::peek_any_identifier() { 1506 bool PreParser::peek_any_identifier() {
1458 i::Token::Value next = peek(); 1507 i::Token::Value next = peek();
1459 return next == i::Token::IDENTIFIER || 1508 return next == i::Token::IDENTIFIER ||
1460 next == i::Token::FUTURE_RESERVED_WORD || 1509 next == i::Token::FUTURE_RESERVED_WORD ||
1461 next == i::Token::FUTURE_STRICT_RESERVED_WORD; 1510 next == i::Token::FUTURE_STRICT_RESERVED_WORD;
1462 } 1511 }
1512
1513
1514 int DuplicateFinder::AddAsciiSymbol(i::Vector<const char> key, int value) {
1515 return AddSymbol(i::Vector<const byte>::cast(key), true, value);
1516 }
1517
1518 int DuplicateFinder::AddUC16Symbol(i::Vector<const uint16_t> key, int value) {
1519 return AddSymbol(i::Vector<const byte>::cast(key), false, value);
1520 }
1521
1522 int DuplicateFinder::AddSymbol(i::Vector<const byte> key,
1523 bool is_ascii,
1524 int value) {
1525 uint32_t hash = Hash(key, is_ascii);
1526 byte* encoding = BackupKey(key, is_ascii);
1527 i::HashMap::Entry* entry = map_->Lookup(encoding, hash, true);
1528 int old_value = static_cast<int>(reinterpret_cast<intptr_t>(entry->value));
1529 entry->value =
1530 reinterpret_cast<void*>(static_cast<intptr_t>(value | old_value));
1531 return old_value;
1532 }
1533
1534
1535 int DuplicateFinder::AddNumber(i::Vector<const char> key, int value) {
1536 // Quick check for already being in canonical form.
1537 if (IsNumberCanonical(key)) {
1538 return AddAsciiSymbol(key, value);
1539 }
1540
1541 // TODO(lrn): Use correct string->number->string conversions that
1542 // generate the same string as v8's ToString(ToNumber(literal)).
1543 // Current solution doesn't handle octal, and probably doesn't
1544 // generate the same string in edge cases.
1545 double double_value = 0.0;
1546 double_value = strtod(key.start(), NULL);
1547 int length;
1548 if (errno == ERANGE && double_value == HUGE_VAL) {
1549 // Overflow.
1550 // Negative overflow (-HUGE_VAL) cannit happen as number literals
1551 // don't have signs.
1552 // Underflow is handled by the default code, since it returns 0.
1553 length = 8; // strlen("Infinity");
1554 memcpy(number_buffer_, "Infinity", length);
1555 } else {
1556 length = snprintf(number_buffer_, kBufferSize, "%g", double_value);
1557 }
1558 return AddAsciiSymbol(i::Vector<const char>(number_buffer_, length), value);
1559 }
1560
1561
1562 bool DuplicateFinder::IsNumberCanonical(i::Vector<const char> number) {
1563 // Test for a safe approximation of number literals that are already
1564 // in canonical form: max 15 digits, no leading zeroes, except an
1565 // integer part that is a single zero, and no trailing zeros below
1566 // the decimal point.
1567 int pos = 0;
1568 int length = number.length();
1569 if (number.length() > 15) return false;
1570 if (number[pos] == '0') {
1571 pos++;
1572 } else {
1573 while (pos < length &&
1574 static_cast<unsigned>(number[pos] - '0') <= ('9' - '0')) pos++;
1575 }
1576 if (length == pos) return true;
1577 if (number[pos] != '.') return false;
1578 pos++;
1579 bool invalid_last_digit = true;
1580 while (pos < length) {
1581 byte digit = number[pos] - '0';
1582 if (digit > '9' - '0') return false;
1583 invalid_last_digit = (digit == 0);
1584 pos++;
1585 }
1586 return !invalid_last_digit;
1587 }
1588
1589
1590 uint32_t DuplicateFinder::Hash(i::Vector<const byte> key, bool is_ascii) {
1591 // Primitive hash function, almost identical to the one used
1592 // for strings (except that it's seeded by the length and ASCII-ness).
1593 int length = key.length();
1594 uint32_t hash = (length << 1) | (is_ascii ? 1 : 0) ;
1595 for (int i = 0; i < length; i++) {
1596 uint32_t c = key[i];
1597 hash = (hash + c) * 1025;
1598 hash ^= (hash >> 6);
1599 }
1600 return hash;
1601 }
1602
1603
1604 bool DuplicateFinder::Match(void* first, void* second) {
1605 // Decode lengths.
1606 // Length + ASCII-bit is encoded as base 128, most significant heptet first,
1607 // with a 8th bit being non-zero while there are more heptets.
1608 // The value encodes the number of bytes following, and whether the original
1609 // was ASCII.
1610 byte* s1 = reinterpret_cast<byte*>(first);
1611 byte* s2 = reinterpret_cast<byte*>(second);
1612 uint32_t length_ascii_field = 0;
1613 byte c1;
1614 do {
1615 c1 = *s1;
1616 if (c1 != *s2) return false;
1617 length_ascii_field = (length_ascii_field << 7) | (c1 & 0x7f);
1618 s1++;
1619 s2++;
1620 } while ((c1 & 0x80) != 0);
1621 int length = static_cast<int>(length_ascii_field >> 1);
1622 return memcmp(s1, s2, length) == 0;
1623 }
1624
1625
1626 byte* DuplicateFinder::BackupKey(i::Vector<const byte> bytes,
1627 bool is_ascii) {
1628 uint32_t ascii_length = (bytes.length() << 1) | (is_ascii ? 1 : 0);
1629 backing_store_.StartSequence();
1630 // Emit ascii_length as base-128 encoded number, with the 7th bit set
1631 // on the byte of every heptet except the last, least significant, one.
1632 if (ascii_length >= (1 << 7)) {
1633 if (ascii_length >= (1 << 14)) {
1634 if (ascii_length >= (1 << 21)) {
1635 if (ascii_length >= (1 << 28)) {
1636 backing_store_.Add(static_cast<byte>((ascii_length >> 28) | 0x80));
1637 }
1638 backing_store_.Add(static_cast<byte>((ascii_length >> 21) | 0x80u));
1639 }
1640 backing_store_.Add(static_cast<byte>((ascii_length >> 14) | 0x80u));
1641 }
1642 backing_store_.Add(static_cast<byte>((ascii_length >> 7) | 0x80u));
1643 }
1644 backing_store_.Add(static_cast<byte>(ascii_length & 0x7f));
1645
1646 backing_store_.AddBlock(bytes);
1647 return backing_store_.EndSequence().start();
1648 }
1463 } } // v8::preparser 1649 } } // v8::preparser
OLDNEW
« no previous file with comments | « src/preparser.h ('k') | src/preparser-api.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698