| 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 |