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

Side by Side Diff: src/preparser.cc

Issue 26375004: Unify and fix checkers for duplicate object literal properties. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Fix check for illegal getter/setter name. Created 7 years, 2 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/scanner.h » ('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
(...skipping 1213 matching lines...) Expand 10 before | Expand all | Expand 10 after
1224 if (peek() != i::Token::RBRACK) { 1224 if (peek() != i::Token::RBRACK) {
1225 Expect(i::Token::COMMA, CHECK_OK); 1225 Expect(i::Token::COMMA, CHECK_OK);
1226 } 1226 }
1227 } 1227 }
1228 Expect(i::Token::RBRACK, CHECK_OK); 1228 Expect(i::Token::RBRACK, CHECK_OK);
1229 1229
1230 scope_->NextMaterializedLiteralIndex(); 1230 scope_->NextMaterializedLiteralIndex();
1231 return Expression::Default(); 1231 return Expression::Default();
1232 } 1232 }
1233 1233
1234 void PreParser::CheckDuplicate(DuplicateFinder* finder,
1235 i::Token::Value property,
1236 int type,
1237 bool* ok) {
1238 int old_type;
1239 if (property == i::Token::NUMBER) {
1240 old_type = finder->AddNumber(scanner_->literal_ascii_string(), type);
1241 } else if (scanner_->is_literal_ascii()) {
1242 old_type = finder->AddAsciiSymbol(scanner_->literal_ascii_string(),
1243 type);
1244 } else {
1245 old_type = finder->AddUtf16Symbol(scanner_->literal_utf16_string(), type);
1246 }
1247 if (HasConflict(old_type, type)) {
1248 if (IsDataDataConflict(old_type, type)) {
1249 // Both are data properties.
1250 if (is_classic_mode()) return;
1251 ReportMessageAt(scanner_->location(),
1252 "strict_duplicate_property", NULL);
1253 } else if (IsDataAccessorConflict(old_type, type)) {
1254 // Both a data and an accessor property with the same name.
1255 ReportMessageAt(scanner_->location(),
1256 "accessor_data_property", NULL);
1257 } else {
1258 ASSERT(IsAccessorAccessorConflict(old_type, type));
1259 // Both accessors of the same type.
1260 ReportMessageAt(scanner_->location(),
1261 "accessor_get_set", NULL);
1262 }
1263 *ok = false;
1264 }
1265 }
1266
1267 1234
1268 PreParser::Expression PreParser::ParseObjectLiteral(bool* ok) { 1235 PreParser::Expression PreParser::ParseObjectLiteral(bool* ok) {
1269 // ObjectLiteral :: 1236 // ObjectLiteral ::
1270 // '{' ( 1237 // '{' (
1271 // ((IdentifierName | String | Number) ':' AssignmentExpression) 1238 // ((IdentifierName | String | Number) ':' AssignmentExpression)
1272 // | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral) 1239 // | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral)
1273 // )*[','] '}' 1240 // )*[','] '}'
1274 1241
1242 i::ObjectLiteralChecker<PreParser> checker(this, scanner_, language_mode());
1243
1275 Expect(i::Token::LBRACE, CHECK_OK); 1244 Expect(i::Token::LBRACE, CHECK_OK);
1276 DuplicateFinder duplicate_finder(scanner_->unicode_cache());
1277 while (peek() != i::Token::RBRACE) { 1245 while (peek() != i::Token::RBRACE) {
1278 i::Token::Value next = peek(); 1246 i::Token::Value next = peek();
1279 switch (next) { 1247 switch (next) {
1280 case i::Token::IDENTIFIER: 1248 case i::Token::IDENTIFIER:
1281 case i::Token::FUTURE_RESERVED_WORD: 1249 case i::Token::FUTURE_RESERVED_WORD:
1282 case i::Token::FUTURE_STRICT_RESERVED_WORD: { 1250 case i::Token::FUTURE_STRICT_RESERVED_WORD: {
1283 bool is_getter = false; 1251 bool is_getter = false;
1284 bool is_setter = false; 1252 bool is_setter = false;
1285 ParseIdentifierNameOrGetOrSet(&is_getter, &is_setter, CHECK_OK); 1253 ParseIdentifierNameOrGetOrSet(&is_getter, &is_setter, CHECK_OK);
1286 if ((is_getter || is_setter) && peek() != i::Token::COLON) { 1254 if ((is_getter || is_setter) && peek() != i::Token::COLON) {
1287 i::Token::Value name = Next(); 1255 i::Token::Value name = Next();
1288 bool is_keyword = i::Token::IsKeyword(name); 1256 bool is_keyword = i::Token::IsKeyword(name);
1289 if (name != i::Token::IDENTIFIER && 1257 if (name != i::Token::IDENTIFIER &&
1290 name != i::Token::FUTURE_RESERVED_WORD && 1258 name != i::Token::FUTURE_RESERVED_WORD &&
1291 name != i::Token::FUTURE_STRICT_RESERVED_WORD && 1259 name != i::Token::FUTURE_STRICT_RESERVED_WORD &&
1292 name != i::Token::NUMBER && 1260 name != i::Token::NUMBER &&
1293 name != i::Token::STRING && 1261 name != i::Token::STRING &&
1294 !is_keyword) { 1262 !is_keyword) {
1295 *ok = false; 1263 *ok = false;
1296 return Expression::Default(); 1264 return Expression::Default();
1297 } 1265 }
1298 if (!is_keyword) { 1266 if (!is_keyword) {
1299 LogSymbol(); 1267 LogSymbol();
1300 } 1268 }
1301 PropertyType type = is_getter ? kGetterProperty : kSetterProperty; 1269 i::PropertyKind type = is_getter ? i::kGetterProperty
1302 CheckDuplicate(&duplicate_finder, name, type, CHECK_OK); 1270 : i::kSetterProperty;
1271 checker.CheckProperty(name, type, CHECK_OK);
1303 ParseFunctionLiteral(false, CHECK_OK); 1272 ParseFunctionLiteral(false, CHECK_OK);
1304 if (peek() != i::Token::RBRACE) { 1273 if (peek() != i::Token::RBRACE) {
1305 Expect(i::Token::COMMA, CHECK_OK); 1274 Expect(i::Token::COMMA, CHECK_OK);
1306 } 1275 }
1307 continue; // restart the while 1276 continue; // restart the while
1308 } 1277 }
1309 CheckDuplicate(&duplicate_finder, next, kValueProperty, CHECK_OK); 1278 checker.CheckProperty(next, i::kValueProperty, CHECK_OK);
1310 break; 1279 break;
1311 } 1280 }
1312 case i::Token::STRING: 1281 case i::Token::STRING:
1313 Consume(next); 1282 Consume(next);
1314 CheckDuplicate(&duplicate_finder, next, kValueProperty, CHECK_OK); 1283 checker.CheckProperty(next, i::kValueProperty, CHECK_OK);
1315 GetStringSymbol(); 1284 GetStringSymbol();
1316 break; 1285 break;
1317 case i::Token::NUMBER: 1286 case i::Token::NUMBER:
1318 Consume(next); 1287 Consume(next);
1319 CheckDuplicate(&duplicate_finder, next, kValueProperty, CHECK_OK); 1288 checker.CheckProperty(next, i::kValueProperty, CHECK_OK);
1320 break; 1289 break;
1321 default: 1290 default:
1322 if (i::Token::IsKeyword(next)) { 1291 if (i::Token::IsKeyword(next)) {
1323 Consume(next); 1292 Consume(next);
1324 CheckDuplicate(&duplicate_finder, next, kValueProperty, CHECK_OK); 1293 checker.CheckProperty(next, i::kValueProperty, CHECK_OK);
1325 } else { 1294 } else {
1326 // Unexpected token. 1295 // Unexpected token.
1327 *ok = false; 1296 *ok = false;
1328 return Expression::Default(); 1297 return Expression::Default();
1329 } 1298 }
1330 } 1299 }
1331 1300
1332 Expect(i::Token::COLON, CHECK_OK); 1301 Expect(i::Token::COLON, CHECK_OK);
1333 ParseAssignmentExpression(true, CHECK_OK); 1302 ParseAssignmentExpression(true, CHECK_OK);
1334 1303
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
1395 // Parse function body. 1364 // Parse function body.
1396 ScopeType outer_scope_type = scope_->type(); 1365 ScopeType outer_scope_type = scope_->type();
1397 bool inside_with = scope_->IsInsideWith(); 1366 bool inside_with = scope_->IsInsideWith();
1398 Scope function_scope(&scope_, kFunctionScope); 1367 Scope function_scope(&scope_, kFunctionScope);
1399 function_scope.set_is_generator(is_generator); 1368 function_scope.set_is_generator(is_generator);
1400 // FormalParameterList :: 1369 // FormalParameterList ::
1401 // '(' (Identifier)*[','] ')' 1370 // '(' (Identifier)*[','] ')'
1402 Expect(i::Token::LPAREN, CHECK_OK); 1371 Expect(i::Token::LPAREN, CHECK_OK);
1403 int start_position = scanner_->location().beg_pos; 1372 int start_position = scanner_->location().beg_pos;
1404 bool done = (peek() == i::Token::RPAREN); 1373 bool done = (peek() == i::Token::RPAREN);
1405 DuplicateFinder duplicate_finder(scanner_->unicode_cache()); 1374 i::DuplicateFinder duplicate_finder(scanner_->unicode_cache());
1406 while (!done) { 1375 while (!done) {
1407 Identifier id = ParseIdentifier(CHECK_OK); 1376 Identifier id = ParseIdentifier(CHECK_OK);
1408 if (!id.IsValidStrictVariable()) { 1377 if (!id.IsValidStrictVariable()) {
1409 StrictModeIdentifierViolation(scanner_->location(), 1378 StrictModeIdentifierViolation(scanner_->location(),
1410 "strict_param_name", 1379 "strict_param_name",
1411 id, 1380 id,
1412 CHECK_OK); 1381 CHECK_OK);
1413 } 1382 }
1414 int prev_value; 1383 int prev_value;
1415 if (scanner_->is_literal_ascii()) { 1384 if (scanner_->is_literal_ascii()) {
(...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after
1687 1656
1688 1657
1689 bool PreParser::peek_any_identifier() { 1658 bool PreParser::peek_any_identifier() {
1690 i::Token::Value next = peek(); 1659 i::Token::Value next = peek();
1691 return next == i::Token::IDENTIFIER || 1660 return next == i::Token::IDENTIFIER ||
1692 next == i::Token::FUTURE_RESERVED_WORD || 1661 next == i::Token::FUTURE_RESERVED_WORD ||
1693 next == i::Token::FUTURE_STRICT_RESERVED_WORD || 1662 next == i::Token::FUTURE_STRICT_RESERVED_WORD ||
1694 next == i::Token::YIELD; 1663 next == i::Token::YIELD;
1695 } 1664 }
1696 1665
1697
1698 int DuplicateFinder::AddAsciiSymbol(i::Vector<const char> key, int value) {
1699 return AddSymbol(i::Vector<const byte>::cast(key), true, value);
1700 }
1701
1702
1703 int DuplicateFinder::AddUtf16Symbol(i::Vector<const uint16_t> key, int value) {
1704 return AddSymbol(i::Vector<const byte>::cast(key), false, value);
1705 }
1706
1707 int DuplicateFinder::AddSymbol(i::Vector<const byte> key,
1708 bool is_ascii,
1709 int value) {
1710 uint32_t hash = Hash(key, is_ascii);
1711 byte* encoding = BackupKey(key, is_ascii);
1712 i::HashMap::Entry* entry = map_.Lookup(encoding, hash, true);
1713 int old_value = static_cast<int>(reinterpret_cast<intptr_t>(entry->value));
1714 entry->value =
1715 reinterpret_cast<void*>(static_cast<intptr_t>(value | old_value));
1716 return old_value;
1717 }
1718
1719
1720 int DuplicateFinder::AddNumber(i::Vector<const char> key, int value) {
1721 ASSERT(key.length() > 0);
1722 // Quick check for already being in canonical form.
1723 if (IsNumberCanonical(key)) {
1724 return AddAsciiSymbol(key, value);
1725 }
1726
1727 int flags = i::ALLOW_HEX | i::ALLOW_OCTAL | i::ALLOW_IMPLICIT_OCTAL |
1728 i::ALLOW_BINARY;
1729 double double_value = StringToDouble(unicode_constants_, key, flags, 0.0);
1730 int length;
1731 const char* string;
1732 if (!std::isfinite(double_value)) {
1733 string = "Infinity";
1734 length = 8; // strlen("Infinity");
1735 } else {
1736 string = DoubleToCString(double_value,
1737 i::Vector<char>(number_buffer_, kBufferSize));
1738 length = i::StrLength(string);
1739 }
1740 return AddSymbol(i::Vector<const byte>(reinterpret_cast<const byte*>(string),
1741 length), true, value);
1742 }
1743
1744
1745 bool DuplicateFinder::IsNumberCanonical(i::Vector<const char> number) {
1746 // Test for a safe approximation of number literals that are already
1747 // in canonical form: max 15 digits, no leading zeroes, except an
1748 // integer part that is a single zero, and no trailing zeros below
1749 // the decimal point.
1750 int pos = 0;
1751 int length = number.length();
1752 if (number.length() > 15) return false;
1753 if (number[pos] == '0') {
1754 pos++;
1755 } else {
1756 while (pos < length &&
1757 static_cast<unsigned>(number[pos] - '0') <= ('9' - '0')) pos++;
1758 }
1759 if (length == pos) return true;
1760 if (number[pos] != '.') return false;
1761 pos++;
1762 bool invalid_last_digit = true;
1763 while (pos < length) {
1764 byte digit = number[pos] - '0';
1765 if (digit > '9' - '0') return false;
1766 invalid_last_digit = (digit == 0);
1767 pos++;
1768 }
1769 return !invalid_last_digit;
1770 }
1771
1772
1773 uint32_t DuplicateFinder::Hash(i::Vector<const byte> key, bool is_ascii) {
1774 // Primitive hash function, almost identical to the one used
1775 // for strings (except that it's seeded by the length and ASCII-ness).
1776 int length = key.length();
1777 uint32_t hash = (length << 1) | (is_ascii ? 1 : 0) ;
1778 for (int i = 0; i < length; i++) {
1779 uint32_t c = key[i];
1780 hash = (hash + c) * 1025;
1781 hash ^= (hash >> 6);
1782 }
1783 return hash;
1784 }
1785
1786
1787 bool DuplicateFinder::Match(void* first, void* second) {
1788 // Decode lengths.
1789 // Length + ASCII-bit is encoded as base 128, most significant heptet first,
1790 // with a 8th bit being non-zero while there are more heptets.
1791 // The value encodes the number of bytes following, and whether the original
1792 // was ASCII.
1793 byte* s1 = reinterpret_cast<byte*>(first);
1794 byte* s2 = reinterpret_cast<byte*>(second);
1795 uint32_t length_ascii_field = 0;
1796 byte c1;
1797 do {
1798 c1 = *s1;
1799 if (c1 != *s2) return false;
1800 length_ascii_field = (length_ascii_field << 7) | (c1 & 0x7f);
1801 s1++;
1802 s2++;
1803 } while ((c1 & 0x80) != 0);
1804 int length = static_cast<int>(length_ascii_field >> 1);
1805 return memcmp(s1, s2, length) == 0;
1806 }
1807
1808
1809 byte* DuplicateFinder::BackupKey(i::Vector<const byte> bytes,
1810 bool is_ascii) {
1811 uint32_t ascii_length = (bytes.length() << 1) | (is_ascii ? 1 : 0);
1812 backing_store_.StartSequence();
1813 // Emit ascii_length as base-128 encoded number, with the 7th bit set
1814 // on the byte of every heptet except the last, least significant, one.
1815 if (ascii_length >= (1 << 7)) {
1816 if (ascii_length >= (1 << 14)) {
1817 if (ascii_length >= (1 << 21)) {
1818 if (ascii_length >= (1 << 28)) {
1819 backing_store_.Add(static_cast<byte>((ascii_length >> 28) | 0x80));
1820 }
1821 backing_store_.Add(static_cast<byte>((ascii_length >> 21) | 0x80u));
1822 }
1823 backing_store_.Add(static_cast<byte>((ascii_length >> 14) | 0x80u));
1824 }
1825 backing_store_.Add(static_cast<byte>((ascii_length >> 7) | 0x80u));
1826 }
1827 backing_store_.Add(static_cast<byte>(ascii_length & 0x7f));
1828
1829 backing_store_.AddBlock(bytes);
1830 return backing_store_.EndSequence().start();
1831 }
1832 } } // v8::preparser 1666 } } // v8::preparser
OLDNEW
« no previous file with comments | « src/preparser.h ('k') | src/scanner.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698