| Index: src/preparser.h
 | 
| diff --git a/src/preparser.h b/src/preparser.h
 | 
| index cd0a530e8d0bba8b368510601e30ff566a00cb49..9dc36f18a3fbaca89ad4821ebedb76e8e9ebd08f 100644
 | 
| --- a/src/preparser.h
 | 
| +++ b/src/preparser.h
 | 
| @@ -31,6 +31,8 @@
 | 
|  namespace v8 {
 | 
|  namespace preparser {
 | 
|  
 | 
| +typedef uint8_t byte;
 | 
| +
 | 
|  // Preparsing checks a JavaScript program and emits preparse-data that helps
 | 
|  // a later parsing to be faster.
 | 
|  // See preparse-data-format.h for the data format.
 | 
| @@ -46,6 +48,57 @@ namespace preparser {
 | 
|  
 | 
|  namespace i = v8::internal;
 | 
|  
 | 
| +class DuplicateFinder {
 | 
| + public:
 | 
| +  explicit DuplicateFinder(i::UnicodeCache* constants)
 | 
| +      : unicode_constants_(constants),
 | 
| +        backing_store_(16),
 | 
| +        map_(new i::HashMap(&Match)) { }
 | 
| +
 | 
| +  ~DuplicateFinder() {
 | 
| +    delete map_;
 | 
| +  }
 | 
| +
 | 
| +  int AddAsciiSymbol(i::Vector<const char> key, int value);
 | 
| +  int AddUC16Symbol(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 {
 | 
| @@ -67,6 +120,45 @@ class PreParser {
 | 
|    }
 | 
|  
 | 
|   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
 | 
| @@ -371,6 +463,11 @@ class PreParser {
 | 
|  
 | 
|    // Report syntax error
 | 
|    void ReportUnexpectedToken(i::Token::Value token);
 | 
| +  void ReportMessageAt(i::Scanner::Location location,
 | 
| +                       const char* type,
 | 
| +                       const char* name_opt) {
 | 
| +    log_->LogMessage(location.beg_pos, location.end_pos, type, name_opt);
 | 
| +  }
 | 
|    void ReportMessageAt(int start_pos,
 | 
|                         int end_pos,
 | 
|                         const char* type,
 | 
| 
 |