| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |