OLD | NEW |
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 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 3218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3229 for (; (mid <= high) && (GetKey(mid)->Hash() == hash); mid++) { | 3229 for (; (mid <= high) && (GetKey(mid)->Hash() == hash); mid++) { |
3230 if (GetKey(mid)->Equals(name) && !is_null_descriptor(mid)) return mid; | 3230 if (GetKey(mid)->Equals(name) && !is_null_descriptor(mid)) return mid; |
3231 } | 3231 } |
3232 break; | 3232 break; |
3233 } | 3233 } |
3234 return kNotFound; | 3234 return kNotFound; |
3235 } | 3235 } |
3236 | 3236 |
3237 | 3237 |
3238 int DescriptorArray::LinearSearch(String* name, int len) { | 3238 int DescriptorArray::LinearSearch(String* name, int len) { |
| 3239 uint32_t hash = name->Hash(); |
3239 for (int number = 0; number < len; number++) { | 3240 for (int number = 0; number < len; number++) { |
3240 if (name->Equals(GetKey(number)) && !is_null_descriptor(number)) { | 3241 String* entry = GetKey(number); |
| 3242 if ((entry->Hash() == hash) && |
| 3243 name->Equals(entry) && |
| 3244 !is_null_descriptor(number)) { |
3241 return number; | 3245 return number; |
3242 } | 3246 } |
3243 } | 3247 } |
3244 return kNotFound; | 3248 return kNotFound; |
3245 } | 3249 } |
3246 | 3250 |
3247 | 3251 |
3248 #ifdef DEBUG | 3252 #ifdef DEBUG |
3249 bool DescriptorArray::IsEqualTo(DescriptorArray* other) { | 3253 bool DescriptorArray::IsEqualTo(DescriptorArray* other) { |
3250 if (IsEmpty()) return other->IsEmpty(); | 3254 if (IsEmpty()) return other->IsEmpty(); |
(...skipping 1023 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4274 int i; | 4278 int i; |
4275 for (i = 0; i < slen && decoder->has_more(); i++) { | 4279 for (i = 0; i < slen && decoder->has_more(); i++) { |
4276 uc32 r = decoder->GetNext(); | 4280 uc32 r = decoder->GetNext(); |
4277 if (Get(i) != r) return false; | 4281 if (Get(i) != r) return false; |
4278 } | 4282 } |
4279 return i == slen && !decoder->has_more(); | 4283 return i == slen && !decoder->has_more(); |
4280 } | 4284 } |
4281 | 4285 |
4282 | 4286 |
4283 uint32_t String::ComputeAndSetHash() { | 4287 uint32_t String::ComputeAndSetHash() { |
4284 // Should only be call if hash code has not yet been computed. | 4288 // Should only be called if hash code has not yet been computed. |
4285 ASSERT(!(length_field() & kHashComputedMask)); | 4289 ASSERT(!(length_field() & kHashComputedMask)); |
4286 | 4290 |
4287 // Compute the hash code. | 4291 // Compute the hash code. |
4288 StringInputBuffer buffer(this); | 4292 StringInputBuffer buffer(this); |
4289 uint32_t field = ComputeLengthAndHashField(&buffer, length()); | 4293 uint32_t field = ComputeLengthAndHashField(&buffer, length()); |
4290 | 4294 |
4291 // Store the hash code in the object. | 4295 // Store the hash code in the object. |
4292 set_length_field(field); | 4296 set_length_field(field); |
4293 | 4297 |
4294 // Check the hash code is there. | 4298 // Check the hash code is there. |
4295 ASSERT(length_field() & kHashComputedMask); | 4299 ASSERT(length_field() & kHashComputedMask); |
4296 return field >> kHashShift; | 4300 uint32_t result = field >> kHashShift; |
| 4301 ASSERT(result != 0); // Ensure that the hash value of 0 is never computed. |
| 4302 return result; |
4297 } | 4303 } |
4298 | 4304 |
4299 | 4305 |
4300 bool String::ComputeArrayIndex(unibrow::CharacterStream* buffer, | 4306 bool String::ComputeArrayIndex(unibrow::CharacterStream* buffer, |
4301 uint32_t* index, | 4307 uint32_t* index, |
4302 int length) { | 4308 int length) { |
4303 if (length == 0 || length > kMaxArrayIndexSize) return false; | 4309 if (length == 0 || length > kMaxArrayIndexSize) return false; |
4304 uc32 ch = buffer->GetNext(); | 4310 uc32 ch = buffer->GetNext(); |
4305 | 4311 |
4306 // If the string begins with a '0' character, it must only consist | 4312 // If the string begins with a '0' character, it must only consist |
(...skipping 857 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5164 Smi::cast(JSArray::cast(this)->length())->value()) : | 5170 Smi::cast(JSArray::cast(this)->length())->value()) : |
5165 static_cast<uint32_t>(FixedArray::cast(elements())->length()); | 5171 static_cast<uint32_t>(FixedArray::cast(elements())->length()); |
5166 return (index < length) && | 5172 return (index < length) && |
5167 !FixedArray::cast(elements())->get(index)->IsTheHole(); | 5173 !FixedArray::cast(elements())->get(index)->IsTheHole(); |
5168 } else { | 5174 } else { |
5169 return element_dictionary()->FindNumberEntry(index) != -1; | 5175 return element_dictionary()->FindNumberEntry(index) != -1; |
5170 } | 5176 } |
5171 } | 5177 } |
5172 | 5178 |
5173 | 5179 |
| 5180 Object* JSObject::GetHiddenProperties(bool create_if_needed) { |
| 5181 String* key = Heap::hidden_symbol(); |
| 5182 if (this->HasFastProperties()) { |
| 5183 // If the object has fast properties, check whether the first slot in the |
| 5184 // descriptor array matches the hidden symbol. Since the hidden symbols |
| 5185 // hash code is zero it will always occupy the first entry if present. |
| 5186 DescriptorArray* descriptors = this->map()->instance_descriptors(); |
| 5187 if (descriptors->number_of_descriptors() > 0) { |
| 5188 if (descriptors->GetKey(0) == key) { |
| 5189 #ifdef DEBUG |
| 5190 PropertyDetails details(descriptors->GetDetails(0)); |
| 5191 ASSERT(details.type() == FIELD); |
| 5192 #endif // DEBUG |
| 5193 Object* value = descriptors->GetValue(0); |
| 5194 return FastPropertyAt(Descriptor::IndexFromValue(value)); |
| 5195 } |
| 5196 } |
| 5197 } |
| 5198 |
| 5199 // Only attempt to find the hidden properties in the local object and not |
| 5200 // in the prototype chain. |
| 5201 if (!this->HasLocalProperty(key)) { |
| 5202 // Hidden properties object not found. Allocate a new hidden properties |
| 5203 // object if requested. Otherwise return the undefined value. |
| 5204 if (create_if_needed) { |
| 5205 Object* obj = Heap::AllocateJSObject( |
| 5206 Top::context()->global_context()->object_function()); |
| 5207 if (obj->IsFailure()) { |
| 5208 return obj; |
| 5209 } |
| 5210 return this->SetProperty(key, obj, DONT_ENUM); |
| 5211 } else { |
| 5212 return Heap::undefined_value(); |
| 5213 } |
| 5214 } |
| 5215 return this->GetProperty(key); |
| 5216 } |
| 5217 |
| 5218 |
5174 bool JSObject::HasElementWithReceiver(JSObject* receiver, uint32_t index) { | 5219 bool JSObject::HasElementWithReceiver(JSObject* receiver, uint32_t index) { |
5175 // Check access rights if needed. | 5220 // Check access rights if needed. |
5176 if (IsAccessCheckNeeded() && | 5221 if (IsAccessCheckNeeded() && |
5177 !Top::MayIndexedAccess(this, index, v8::ACCESS_HAS)) { | 5222 !Top::MayIndexedAccess(this, index, v8::ACCESS_HAS)) { |
5178 Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS); | 5223 Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS); |
5179 return false; | 5224 return false; |
5180 } | 5225 } |
5181 | 5226 |
5182 // Check for lookup interceptor | 5227 // Check for lookup interceptor |
5183 if (HasIndexedInterceptor()) { | 5228 if (HasIndexedInterceptor()) { |
(...skipping 874 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6058 return static_cast<uint32_t>(obj->Number()); | 6103 return static_cast<uint32_t>(obj->Number()); |
6059 } | 6104 } |
6060 | 6105 |
6061 uint32_t number_; | 6106 uint32_t number_; |
6062 }; | 6107 }; |
6063 | 6108 |
6064 | 6109 |
6065 // StringKey simply carries a string object as key. | 6110 // StringKey simply carries a string object as key. |
6066 class StringKey : public HashTableKey { | 6111 class StringKey : public HashTableKey { |
6067 public: | 6112 public: |
6068 explicit StringKey(String* string) : string_(string) { } | 6113 explicit StringKey(String* string) : |
| 6114 string_(string), |
| 6115 hash_(StringHash(string)) { } |
6069 | 6116 |
6070 bool IsMatch(Object* string) { | 6117 bool IsMatch(Object* string) { |
| 6118 // We know that all entries in a hash table had their hash keys created. |
| 6119 // Use that knowledge to have fast failure. |
| 6120 if (hash_ != StringHash(string)) { |
| 6121 return false; |
| 6122 } |
6071 return string_->Equals(String::cast(string)); | 6123 return string_->Equals(String::cast(string)); |
6072 } | 6124 } |
6073 | 6125 |
6074 uint32_t Hash() { return StringHash(string_); } | 6126 uint32_t Hash() { return hash_; } |
6075 | 6127 |
6076 HashFunction GetHashFunction() { return StringHash; } | 6128 HashFunction GetHashFunction() { return StringHash; } |
6077 | 6129 |
6078 Object* GetObject() { return string_; } | 6130 Object* GetObject() { return string_; } |
6079 | 6131 |
6080 static uint32_t StringHash(Object* obj) { | 6132 static uint32_t StringHash(Object* obj) { |
6081 return String::cast(obj)->Hash(); | 6133 return String::cast(obj)->Hash(); |
6082 } | 6134 } |
6083 | 6135 |
6084 bool IsStringKey() { return true; } | 6136 bool IsStringKey() { return true; } |
6085 | 6137 |
6086 String* string_; | 6138 String* string_; |
| 6139 uint32_t hash_; |
6087 }; | 6140 }; |
6088 | 6141 |
6089 | 6142 |
6090 // StringSharedKeys are used as keys in the eval cache. | 6143 // StringSharedKeys are used as keys in the eval cache. |
6091 class StringSharedKey : public HashTableKey { | 6144 class StringSharedKey : public HashTableKey { |
6092 public: | 6145 public: |
6093 StringSharedKey(String* source, SharedFunctionInfo* shared) | 6146 StringSharedKey(String* source, SharedFunctionInfo* shared) |
6094 : source_(source), shared_(shared) { } | 6147 : source_(source), shared_(shared) { } |
6095 | 6148 |
6096 bool IsMatch(Object* other) { | 6149 bool IsMatch(Object* other) { |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6203 HashFunction GetHashFunction() { | 6256 HashFunction GetHashFunction() { |
6204 return StringHash; | 6257 return StringHash; |
6205 } | 6258 } |
6206 | 6259 |
6207 uint32_t Hash() { | 6260 uint32_t Hash() { |
6208 if (length_field_ != 0) return length_field_ >> String::kHashShift; | 6261 if (length_field_ != 0) return length_field_ >> String::kHashShift; |
6209 unibrow::Utf8InputBuffer<> buffer(string_.start(), | 6262 unibrow::Utf8InputBuffer<> buffer(string_.start(), |
6210 static_cast<unsigned>(string_.length())); | 6263 static_cast<unsigned>(string_.length())); |
6211 chars_ = buffer.Length(); | 6264 chars_ = buffer.Length(); |
6212 length_field_ = String::ComputeLengthAndHashField(&buffer, chars_); | 6265 length_field_ = String::ComputeLengthAndHashField(&buffer, chars_); |
6213 return length_field_ >> String::kHashShift; | 6266 uint32_t result = length_field_ >> String::kHashShift; |
| 6267 ASSERT(result != 0); // Ensure that the hash value of 0 is never computed. |
| 6268 return result; |
6214 } | 6269 } |
6215 | 6270 |
6216 Object* GetObject() { | 6271 Object* GetObject() { |
6217 if (length_field_ == 0) Hash(); | 6272 if (length_field_ == 0) Hash(); |
6218 return Heap::AllocateSymbol(string_, chars_, length_field_); | 6273 return Heap::AllocateSymbol(string_, chars_, length_field_); |
6219 } | 6274 } |
6220 | 6275 |
6221 static uint32_t StringHash(Object* obj) { | 6276 static uint32_t StringHash(Object* obj) { |
6222 return String::cast(obj)->Hash(); | 6277 return String::cast(obj)->Hash(); |
6223 } | 6278 } |
(...skipping 1140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7364 // No break point. | 7419 // No break point. |
7365 if (break_point_objects()->IsUndefined()) return 0; | 7420 if (break_point_objects()->IsUndefined()) return 0; |
7366 // Single beak point. | 7421 // Single beak point. |
7367 if (!break_point_objects()->IsFixedArray()) return 1; | 7422 if (!break_point_objects()->IsFixedArray()) return 1; |
7368 // Multiple break points. | 7423 // Multiple break points. |
7369 return FixedArray::cast(break_point_objects())->length(); | 7424 return FixedArray::cast(break_point_objects())->length(); |
7370 } | 7425 } |
7371 | 7426 |
7372 | 7427 |
7373 } } // namespace v8::internal | 7428 } } // namespace v8::internal |
OLD | NEW |