Index: src/preparser.h |
diff --git a/src/preparser.h b/src/preparser.h |
index 44bd85c85e2d01070068afa4bb39fe4b972477dd..9358d6bd18957e21fbf6334b70ce09186dd9e0a6 100644 |
--- a/src/preparser.h |
+++ b/src/preparser.h |
@@ -35,98 +35,9 @@ |
namespace v8 { |
namespace internal { |
- |
-// Used to detect duplicates in object literals. Each of the values |
-// kGetterProperty, kSetterProperty and kValueProperty represents |
-// a type of object literal property. When parsing a property, its |
-// type value is stored in the DuplicateFinder for the property name. |
-// Values are chosen so that having intersection bits means the there is |
-// an incompatibility. |
-// I.e., you can add a getter to a property that already has a setter, since |
-// kGetterProperty and kSetterProperty doesn't intersect, but not if it |
-// already has a getter or a value. Adding the getter to an existing |
-// setter will store the value (kGetterProperty | kSetterProperty), which |
-// is incompatible with adding any further properties. |
-enum PropertyKind { |
- kNone = 0, |
- // Bit patterns representing different object literal property types. |
- kGetterProperty = 1, |
- kSetterProperty = 2, |
- kValueProperty = 7, |
- // Helper constants. |
- kValueFlag = 4 |
-}; |
- |
- |
-// Validation per 11.1.5 Object Initialiser |
-template<typename P> |
-class ObjectLiteralChecker { |
- public: |
- ObjectLiteralChecker(P* parser, Scanner* scanner, LanguageMode mode) |
- : parser_(parser), |
- scanner_(scanner), |
- finder_(scanner->unicode_cache()), |
- language_mode_(mode) { } |
- |
- void CheckProperty(Token::Value property, PropertyKind type, bool* ok); |
- |
- private: |
- // Checks the type of conflict based on values coming from PropertyType. |
- bool HasConflict(PropertyKind type1, PropertyKind type2) { |
- return (type1 & type2) != 0; |
- } |
- bool IsDataDataConflict(PropertyKind type1, PropertyKind type2) { |
- return ((type1 & type2) & kValueFlag) != 0; |
- } |
- bool IsDataAccessorConflict(PropertyKind type1, PropertyKind type2) { |
- return ((type1 ^ type2) & kValueFlag) != 0; |
- } |
- bool IsAccessorAccessorConflict(PropertyKind type1, PropertyKind type2) { |
- return ((type1 | type2) & kValueFlag) == 0; |
- } |
- |
- P* parser_; |
- Scanner* scanner_; |
- DuplicateFinder finder_; |
- LanguageMode language_mode_; |
-}; |
- |
- |
-template<typename P> |
-void ObjectLiteralChecker<P>::CheckProperty(Token::Value property, |
- PropertyKind type, |
- bool* ok) { |
- int old; |
- if (property == Token::NUMBER) { |
- old = finder_.AddNumber(scanner_->literal_ascii_string(), type); |
- } else if (scanner_->is_literal_ascii()) { |
- old = finder_.AddAsciiSymbol(scanner_->literal_ascii_string(), type); |
- } else { |
- old = finder_.AddUtf16Symbol(scanner_->literal_utf16_string(), type); |
- } |
- PropertyKind old_type = static_cast<PropertyKind>(old); |
- if (HasConflict(old_type, type)) { |
- if (IsDataDataConflict(old_type, type)) { |
- // Both are data properties. |
- if (language_mode_ == CLASSIC_MODE) return; |
- parser_->ReportMessageAt(scanner_->location(), |
- "strict_duplicate_property"); |
- } else if (IsDataAccessorConflict(old_type, type)) { |
- // Both a data and an accessor property with the same name. |
- parser_->ReportMessageAt(scanner_->location(), |
- "accessor_data_property"); |
- } else { |
- ASSERT(IsAccessorAccessorConflict(old_type, type)); |
- // Both accessors of the same type. |
- parser_->ReportMessageAt(scanner_->location(), |
- "accessor_get_set"); |
- } |
- *ok = false; |
- } |
+class UnicodeCache; |
} |
-} // v8::internal |
- |
namespace preparser { |
typedef uint8_t byte; |
@@ -146,6 +57,53 @@ typedef uint8_t byte; |
namespace i = v8::internal; |
+class DuplicateFinder { |
+ public: |
+ explicit DuplicateFinder(i::UnicodeCache* constants) |
+ : unicode_constants_(constants), |
+ backing_store_(16), |
+ map_(&Match) { } |
+ |
+ int AddAsciiSymbol(i::Vector<const char> key, int value); |
+ int AddUtf16Symbol(i::Vector<const uint16_t> key, int value); |
+ // Add a a number literal by converting it (if necessary) |
+ // to the string that ToString(ToNumber(literal)) would generate. |
+ // and then adding that string with AddAsciiSymbol. |
+ // This string is the actual value used as key in an object literal, |
+ // and the one that must be different from the other keys. |
+ int AddNumber(i::Vector<const char> key, int value); |
+ |
+ private: |
+ int AddSymbol(i::Vector<const byte> key, bool is_ascii, int value); |
+ // Backs up the key and its length in the backing store. |
+ // The backup is stored with a base 127 encoding of the |
+ // length (plus a bit saying whether the string is ASCII), |
+ // followed by the bytes of the key. |
+ byte* BackupKey(i::Vector<const byte> key, bool is_ascii); |
+ |
+ // Compare two encoded keys (both pointing into the backing store) |
+ // for having the same base-127 encoded lengths and ASCII-ness, |
+ // and then having the same 'length' bytes following. |
+ static bool Match(void* first, void* second); |
+ // Creates a hash from a sequence of bytes. |
+ static uint32_t Hash(i::Vector<const byte> key, bool is_ascii); |
+ // Checks whether a string containing a JS number is its canonical |
+ // form. |
+ static bool IsNumberCanonical(i::Vector<const char> key); |
+ |
+ // Size of buffer. Sufficient for using it to call DoubleToCString in |
+ // from conversions.h. |
+ static const int kBufferSize = 100; |
+ |
+ i::UnicodeCache* unicode_constants_; |
+ // Backing store used to store strings used as hashmap keys. |
+ i::SequenceCollector<unsigned char> backing_store_; |
+ i::HashMap map_; |
+ // Buffer used for string->number->canonical string conversions. |
+ char number_buffer_[kBufferSize]; |
+}; |
+ |
+ |
class PreParser { |
public: |
enum PreParseResult { |
@@ -225,6 +183,45 @@ class PreParser { |
i::ParserRecorder* log); |
private: |
+ // Used to detect duplicates in object literals. Each of the values |
+ // kGetterProperty, kSetterProperty and kValueProperty represents |
+ // a type of object literal property. When parsing a property, its |
+ // type value is stored in the DuplicateFinder for the property name. |
+ // Values are chosen so that having intersection bits means the there is |
+ // an incompatibility. |
+ // I.e., you can add a getter to a property that already has a setter, since |
+ // kGetterProperty and kSetterProperty doesn't intersect, but not if it |
+ // already has a getter or a value. Adding the getter to an existing |
+ // setter will store the value (kGetterProperty | kSetterProperty), which |
+ // is incompatible with adding any further properties. |
+ enum PropertyType { |
+ kNone = 0, |
+ // Bit patterns representing different object literal property types. |
+ kGetterProperty = 1, |
+ kSetterProperty = 2, |
+ kValueProperty = 7, |
+ // Helper constants. |
+ kValueFlag = 4 |
+ }; |
+ |
+ // Checks the type of conflict based on values coming from PropertyType. |
+ bool HasConflict(int type1, int type2) { return (type1 & type2) != 0; } |
+ bool IsDataDataConflict(int type1, int type2) { |
+ return ((type1 & type2) & kValueFlag) != 0; |
+ } |
+ bool IsDataAccessorConflict(int type1, int type2) { |
+ return ((type1 ^ type2) & kValueFlag) != 0; |
+ } |
+ bool IsAccessorAccessorConflict(int type1, int type2) { |
+ return ((type1 | type2) & kValueFlag) == 0; |
+ } |
+ |
+ |
+ void CheckDuplicate(DuplicateFinder* finder, |
+ i::Token::Value property, |
+ int type, |
+ bool* ok); |
+ |
// These types form an algebra over syntactic categories that is just |
// rich enough to let us recognize and propagate the constructs that |
// are either being counted in the preparser data, or is important |
@@ -534,7 +531,7 @@ class PreParser { |
void ReportUnexpectedToken(i::Token::Value token); |
void ReportMessageAt(i::Scanner::Location location, |
const char* type, |
- const char* name_opt = NULL) { |
+ const char* name_opt) { |
log_->LogMessage(location.beg_pos, location.end_pos, type, name_opt); |
} |
void ReportMessageAt(int start_pos, |
@@ -689,10 +686,7 @@ class PreParser { |
bool allow_generators_; |
bool allow_for_of_; |
bool parenthesized_function_; |
- |
- friend class i::ObjectLiteralChecker<PreParser>; |
}; |
- |
} } // v8::preparser |
#endif // V8_PREPARSER_H |