| Index: src/objects.cc
|
| ===================================================================
|
| --- src/objects.cc (revision 1540)
|
| +++ src/objects.cc (working copy)
|
| @@ -3236,8 +3236,12 @@
|
|
|
|
|
| int DescriptorArray::LinearSearch(String* name, int len) {
|
| + uint32_t hash = name->Hash();
|
| for (int number = 0; number < len; number++) {
|
| - if (name->Equals(GetKey(number)) && !is_null_descriptor(number)) {
|
| + String* entry = GetKey(number);
|
| + if ((entry->Hash() == hash) &&
|
| + name->Equals(entry) &&
|
| + !is_null_descriptor(number)) {
|
| return number;
|
| }
|
| }
|
| @@ -4281,7 +4285,7 @@
|
|
|
|
|
| uint32_t String::ComputeAndSetHash() {
|
| - // Should only be call if hash code has not yet been computed.
|
| + // Should only be called if hash code has not yet been computed.
|
| ASSERT(!(length_field() & kHashComputedMask));
|
|
|
| // Compute the hash code.
|
| @@ -4293,7 +4297,9 @@
|
|
|
| // Check the hash code is there.
|
| ASSERT(length_field() & kHashComputedMask);
|
| - return field >> kHashShift;
|
| + uint32_t result = field >> kHashShift;
|
| + ASSERT(result != 0); // Ensure that the hash value of 0 is never computed.
|
| + return result;
|
| }
|
|
|
|
|
| @@ -5171,6 +5177,45 @@
|
| }
|
|
|
|
|
| +Object* JSObject::GetHiddenProperties(bool create_if_needed) {
|
| + String* key = Heap::hidden_symbol();
|
| + if (this->HasFastProperties()) {
|
| + // If the object has fast properties, check whether the first slot in the
|
| + // descriptor array matches the hidden symbol. Since the hidden symbols
|
| + // hash code is zero it will always occupy the first entry if present.
|
| + DescriptorArray* descriptors = this->map()->instance_descriptors();
|
| + if (descriptors->number_of_descriptors() > 0) {
|
| + if (descriptors->GetKey(0) == key) {
|
| +#ifdef DEBUG
|
| + PropertyDetails details(descriptors->GetDetails(0));
|
| + ASSERT(details.type() == FIELD);
|
| +#endif // DEBUG
|
| + Object* value = descriptors->GetValue(0);
|
| + return FastPropertyAt(Descriptor::IndexFromValue(value));
|
| + }
|
| + }
|
| + }
|
| +
|
| + // Only attempt to find the hidden properties in the local object and not
|
| + // in the prototype chain.
|
| + if (!this->HasLocalProperty(key)) {
|
| + // Hidden properties object not found. Allocate a new hidden properties
|
| + // object if requested. Otherwise return the undefined value.
|
| + if (create_if_needed) {
|
| + Object* obj = Heap::AllocateJSObject(
|
| + Top::context()->global_context()->object_function());
|
| + if (obj->IsFailure()) {
|
| + return obj;
|
| + }
|
| + return this->SetProperty(key, obj, DONT_ENUM);
|
| + } else {
|
| + return Heap::undefined_value();
|
| + }
|
| + }
|
| + return this->GetProperty(key);
|
| +}
|
| +
|
| +
|
| bool JSObject::HasElementWithReceiver(JSObject* receiver, uint32_t index) {
|
| // Check access rights if needed.
|
| if (IsAccessCheckNeeded() &&
|
| @@ -6065,13 +6110,20 @@
|
| // StringKey simply carries a string object as key.
|
| class StringKey : public HashTableKey {
|
| public:
|
| - explicit StringKey(String* string) : string_(string) { }
|
| + explicit StringKey(String* string) :
|
| + string_(string),
|
| + hash_(StringHash(string)) { }
|
|
|
| bool IsMatch(Object* string) {
|
| + // We know that all entries in a hash table had their hash keys created.
|
| + // Use that knowledge to have fast failure.
|
| + if (hash_ != StringHash(string)) {
|
| + return false;
|
| + }
|
| return string_->Equals(String::cast(string));
|
| }
|
|
|
| - uint32_t Hash() { return StringHash(string_); }
|
| + uint32_t Hash() { return hash_; }
|
|
|
| HashFunction GetHashFunction() { return StringHash; }
|
|
|
| @@ -6084,6 +6136,7 @@
|
| bool IsStringKey() { return true; }
|
|
|
| String* string_;
|
| + uint32_t hash_;
|
| };
|
|
|
|
|
| @@ -6210,7 +6263,9 @@
|
| static_cast<unsigned>(string_.length()));
|
| chars_ = buffer.Length();
|
| length_field_ = String::ComputeLengthAndHashField(&buffer, chars_);
|
| - return length_field_ >> String::kHashShift;
|
| + uint32_t result = length_field_ >> String::kHashShift;
|
| + ASSERT(result != 0); // Ensure that the hash value of 0 is never computed.
|
| + return result;
|
| }
|
|
|
| Object* GetObject() {
|
|
|