OLD | NEW |
---|---|
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 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 398 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
409 property_dictionary()->ValueAtPut(result->GetDictionaryEntry(), value); | 409 property_dictionary()->ValueAtPut(result->GetDictionaryEntry(), value); |
410 } | 410 } |
411 return value; | 411 return value; |
412 } | 412 } |
413 | 413 |
414 | 414 |
415 Object* JSObject::SetNormalizedProperty(String* name, | 415 Object* JSObject::SetNormalizedProperty(String* name, |
416 Object* value, | 416 Object* value, |
417 PropertyDetails details) { | 417 PropertyDetails details) { |
418 ASSERT(!HasFastProperties()); | 418 ASSERT(!HasFastProperties()); |
419 // Optimization for packer.js. We make short keys into symbols to avoid | |
420 // constantly reallocating them. | |
Søren Thygesen Gjesse
2009/11/19 21:42:57
This code is duplicated below, please refactor.
Erik Corry
2009/11/20 10:12:46
Instead I removed this occurrence since it is very
| |
421 if (!name->IsSymbol() && name->length() <= 2) { | |
422 Object* symbol_version = Heap::LookupSymbol(name); | |
423 if (!symbol_version->IsFailure()) name = String::cast(symbol_version); | |
424 } | |
419 int entry = property_dictionary()->FindEntry(name); | 425 int entry = property_dictionary()->FindEntry(name); |
420 if (entry == StringDictionary::kNotFound) { | 426 if (entry == StringDictionary::kNotFound) { |
421 Object* store_value = value; | 427 Object* store_value = value; |
422 if (IsGlobalObject()) { | 428 if (IsGlobalObject()) { |
423 store_value = Heap::AllocateJSGlobalPropertyCell(value); | 429 store_value = Heap::AllocateJSGlobalPropertyCell(value); |
424 if (store_value->IsFailure()) return store_value; | 430 if (store_value->IsFailure()) return store_value; |
425 } | 431 } |
426 Object* dict = property_dictionary()->Add(name, store_value, details); | 432 Object* dict = property_dictionary()->Add(name, store_value, details); |
427 if (dict->IsFailure()) return dict; | 433 if (dict->IsFailure()) return dict; |
428 set_properties(StringDictionary::cast(dict)); | 434 set_properties(StringDictionary::cast(dict)); |
(...skipping 1027 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1456 // Check local property, ignore interceptor. | 1462 // Check local property, ignore interceptor. |
1457 LookupResult result; | 1463 LookupResult result; |
1458 LocalLookupRealNamedProperty(name, &result); | 1464 LocalLookupRealNamedProperty(name, &result); |
1459 if (result.IsValid()) return SetProperty(&result, name, value, attributes); | 1465 if (result.IsValid()) return SetProperty(&result, name, value, attributes); |
1460 // Add real property. | 1466 // Add real property. |
1461 return AddProperty(name, value, attributes); | 1467 return AddProperty(name, value, attributes); |
1462 } | 1468 } |
1463 | 1469 |
1464 | 1470 |
1465 Object* JSObject::ReplaceSlowProperty(String* name, | 1471 Object* JSObject::ReplaceSlowProperty(String* name, |
1466 Object* value, | 1472 Object* value, |
1467 PropertyAttributes attributes) { | 1473 PropertyAttributes attributes) { |
1468 StringDictionary* dictionary = property_dictionary(); | 1474 StringDictionary* dictionary = property_dictionary(); |
1469 int old_index = dictionary->FindEntry(name); | 1475 int old_index = dictionary->FindEntry(name); |
1470 int new_enumeration_index = 0; // 0 means "Use the next available index." | 1476 int new_enumeration_index = 0; // 0 means "Use the next available index." |
1471 if (old_index != -1) { | 1477 if (old_index != -1) { |
1472 // All calls to ReplaceSlowProperty have had all transitions removed. | 1478 // All calls to ReplaceSlowProperty have had all transitions removed. |
1473 ASSERT(!dictionary->DetailsAt(old_index).IsTransition()); | 1479 ASSERT(!dictionary->DetailsAt(old_index).IsTransition()); |
1474 new_enumeration_index = dictionary->DetailsAt(old_index).index(); | 1480 new_enumeration_index = dictionary->DetailsAt(old_index).index(); |
1475 } | 1481 } |
1476 | 1482 |
1477 PropertyDetails new_details(attributes, NORMAL, new_enumeration_index); | 1483 PropertyDetails new_details(attributes, NORMAL, new_enumeration_index); |
1478 return SetNormalizedProperty(name, value, new_details); | 1484 return SetNormalizedProperty(name, value, new_details); |
1479 } | 1485 } |
1480 | 1486 |
1487 | |
1481 Object* JSObject::ConvertDescriptorToFieldAndMapTransition( | 1488 Object* JSObject::ConvertDescriptorToFieldAndMapTransition( |
1482 String* name, | 1489 String* name, |
1483 Object* new_value, | 1490 Object* new_value, |
1484 PropertyAttributes attributes) { | 1491 PropertyAttributes attributes) { |
1485 Map* old_map = map(); | 1492 Map* old_map = map(); |
1486 Object* result = ConvertDescriptorToField(name, new_value, attributes); | 1493 Object* result = ConvertDescriptorToField(name, new_value, attributes); |
1487 if (result->IsFailure()) return result; | 1494 if (result->IsFailure()) return result; |
1488 // If we get to this point we have succeeded - do not return failure | 1495 // If we get to this point we have succeeded - do not return failure |
1489 // after this point. Later stuff is optional. | 1496 // after this point. Later stuff is optional. |
1490 if (!HasFastProperties()) { | 1497 if (!HasFastProperties()) { |
(...skipping 371 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1862 | 1869 |
1863 | 1870 |
1864 Object* JSObject::SetProperty(LookupResult* result, | 1871 Object* JSObject::SetProperty(LookupResult* result, |
1865 String* name, | 1872 String* name, |
1866 Object* value, | 1873 Object* value, |
1867 PropertyAttributes attributes) { | 1874 PropertyAttributes attributes) { |
1868 // Make sure that the top context does not change when doing callbacks or | 1875 // Make sure that the top context does not change when doing callbacks or |
1869 // interceptor calls. | 1876 // interceptor calls. |
1870 AssertNoContextChange ncc; | 1877 AssertNoContextChange ncc; |
1871 | 1878 |
1879 // Optimization for packer.js. We make short keys into symbols to avoid | |
1880 // constantly reallocating them. | |
1881 if (!name->IsSymbol() && name->length() <= 2) { | |
1882 Object* symbol_version = Heap::LookupSymbol(name); | |
1883 if (!symbol_version->IsFailure()) name = String::cast(symbol_version); | |
1884 } | |
1885 | |
1872 // Check access rights if needed. | 1886 // Check access rights if needed. |
1873 if (IsAccessCheckNeeded() | 1887 if (IsAccessCheckNeeded() |
1874 && !Top::MayNamedAccess(this, name, v8::ACCESS_SET)) { | 1888 && !Top::MayNamedAccess(this, name, v8::ACCESS_SET)) { |
1875 return SetPropertyWithFailedAccessCheck(result, name, value); | 1889 return SetPropertyWithFailedAccessCheck(result, name, value); |
1876 } | 1890 } |
1877 | 1891 |
1878 if (IsJSGlobalProxy()) { | 1892 if (IsJSGlobalProxy()) { |
1879 Object* proto = GetPrototype(); | 1893 Object* proto = GetPrototype(); |
1880 if (proto->IsNull()) return value; | 1894 if (proto->IsNull()) return value; |
1881 ASSERT(proto->IsJSGlobalObject()); | 1895 ASSERT(proto->IsJSGlobalObject()); |
(...skipping 3351 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5233 } | 5247 } |
5234 set_elements(new_elements); | 5248 set_elements(new_elements); |
5235 return this; | 5249 return this; |
5236 } | 5250 } |
5237 | 5251 |
5238 | 5252 |
5239 void JSArray::Expand(int required_size) { | 5253 void JSArray::Expand(int required_size) { |
5240 Handle<JSArray> self(this); | 5254 Handle<JSArray> self(this); |
5241 Handle<FixedArray> old_backing(FixedArray::cast(elements())); | 5255 Handle<FixedArray> old_backing(FixedArray::cast(elements())); |
5242 int old_size = old_backing->length(); | 5256 int old_size = old_backing->length(); |
5243 // Doubling in size would be overkill, but leave some slack to avoid | 5257 int new_size = required_size > old_size ? required_size : old_size; |
5244 // constantly growing. | |
5245 int new_size = required_size + (required_size >> 3); | |
5246 Handle<FixedArray> new_backing = Factory::NewFixedArray(new_size); | 5258 Handle<FixedArray> new_backing = Factory::NewFixedArray(new_size); |
5247 // Can't use this any more now because we may have had a GC! | 5259 // Can't use this any more now because we may have had a GC! |
5248 for (int i = 0; i < old_size; i++) new_backing->set(i, old_backing->get(i)); | 5260 for (int i = 0; i < old_size; i++) new_backing->set(i, old_backing->get(i)); |
5249 self->SetContent(*new_backing); | 5261 self->SetContent(*new_backing); |
5250 } | 5262 } |
5251 | 5263 |
5252 | 5264 |
5253 // Computes the new capacity when expanding the elements of a JSObject. | 5265 // Computes the new capacity when expanding the elements of a JSObject. |
5254 static int NewElementsCapacity(int old_capacity) { | 5266 static int NewElementsCapacity(int old_capacity) { |
5255 // (old_capacity + 50%) + 16 | 5267 // (old_capacity + 50%) + 16 |
(...skipping 2064 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
7320 } | 7332 } |
7321 } | 7333 } |
7322 | 7334 |
7323 | 7335 |
7324 Object* SymbolTable::LookupString(String* string, Object** s) { | 7336 Object* SymbolTable::LookupString(String* string, Object** s) { |
7325 SymbolKey key(string); | 7337 SymbolKey key(string); |
7326 return LookupKey(&key, s); | 7338 return LookupKey(&key, s); |
7327 } | 7339 } |
7328 | 7340 |
7329 | 7341 |
7342 // This class is used for looking up two character strings in the symbol table. | |
7343 // If we don't have a hit we don't want to waste much time so we unroll the | |
7344 // string hash calculation loop here for speed. Doesn't work if the two | |
7345 // characters form a decimal integer, since such strings have a different hash | |
7346 // algorithm. | |
7347 class TwoCharHashTableKey : public HashTableKey { | |
7348 public: | |
7349 TwoCharHashTableKey(uint32_t c1, uint32_t c2) | |
7350 : c1_(c1), c2_(c2) { | |
Søren Thygesen Gjesse
2009/11/19 21:42:57
How about ASSERT(c1 > '9' || c2 > '9') here? I see
Erik Corry
2009/11/20 10:12:46
Added a comment to the ASSERT_EQ below instead.
| |
7351 // Char 1. | |
7352 uint32_t hash = c1 + (c1 << 10); | |
7353 hash ^= hash >> 6; | |
7354 // Char 2. | |
7355 hash += c2; | |
7356 hash += hash << 10; | |
7357 hash ^= hash >> 6; | |
7358 // GetHash. | |
7359 hash += hash << 3; | |
7360 hash ^= hash >> 11; | |
7361 hash += hash << 15; | |
7362 if (hash == 0) hash = 27; | |
7363 #ifdef DEBUG | |
7364 StringHasher hasher(2); | |
7365 hasher.AddCharacter(c1); | |
7366 hasher.AddCharacter(c2); | |
7367 ASSERT_EQ((int)hasher.GetHash(), (int)hash); | |
7368 #endif | |
7369 hash_ = hash; | |
7370 } | |
7371 | |
7372 bool IsMatch(Object* o) { | |
7373 if (!o->IsString()) return false; | |
7374 String* other = String::cast(o); | |
7375 if (other->length() != 2) return false; | |
7376 if (other->Get(0) != c1_) return false; | |
7377 return other->Get(1) == c2_; | |
7378 } | |
7379 | |
7380 uint32_t Hash() { return hash_; } | |
7381 uint32_t HashForObject(Object* key) { | |
7382 if (!key->IsString()) return 0; | |
7383 return String::cast(key)->Hash(); | |
7384 } | |
7385 | |
7386 Object* AsObject() { | |
7387 // The TwoCharHashTableKey is only used for looking in the symbol | |
7388 // table, not for adding to it. | |
7389 UNREACHABLE(); | |
7390 return NULL; | |
7391 } | |
7392 private: | |
7393 uint32_t c1_; | |
7394 uint32_t c2_; | |
7395 uint32_t hash_; | |
7396 }; | |
7397 | |
7398 | |
7330 bool SymbolTable::LookupSymbolIfExists(String* string, String** symbol) { | 7399 bool SymbolTable::LookupSymbolIfExists(String* string, String** symbol) { |
7331 SymbolKey key(string); | 7400 SymbolKey key(string); |
7332 int entry = FindEntry(&key); | 7401 int entry = FindEntry(&key); |
7333 if (entry == kNotFound) { | 7402 if (entry == kNotFound) { |
7334 return false; | 7403 return false; |
7335 } else { | 7404 } else { |
7336 String* result = String::cast(KeyAt(entry)); | 7405 String* result = String::cast(KeyAt(entry)); |
7337 ASSERT(StringShape(result).IsSymbol()); | 7406 ASSERT(StringShape(result).IsSymbol()); |
7338 *symbol = result; | 7407 *symbol = result; |
7339 return true; | 7408 return true; |
7340 } | 7409 } |
7341 } | 7410 } |
7342 | 7411 |
7343 | 7412 |
7413 bool SymbolTable::LookupTwoCharsIfExists(uint32_t c1, | |
7414 uint32_t c2, | |
7415 String** symbol) { | |
7416 TwoCharHashTableKey key(c1, c2); | |
7417 int entry = FindEntry(&key); | |
7418 if (entry == kNotFound) { | |
7419 return false; | |
7420 } else { | |
7421 String* result = String::cast(KeyAt(entry)); | |
7422 ASSERT(StringShape(result).IsSymbol()); | |
7423 *symbol = result; | |
7424 return true; | |
7425 } | |
7426 } | |
7427 | |
7428 | |
7344 Object* SymbolTable::LookupSymbol(Vector<const char> str, Object** s) { | 7429 Object* SymbolTable::LookupSymbol(Vector<const char> str, Object** s) { |
7345 Utf8SymbolKey key(str); | 7430 Utf8SymbolKey key(str); |
7346 return LookupKey(&key, s); | 7431 return LookupKey(&key, s); |
7347 } | 7432 } |
7348 | 7433 |
7349 | 7434 |
7350 Object* SymbolTable::LookupKey(HashTableKey* key, Object** s) { | 7435 Object* SymbolTable::LookupKey(HashTableKey* key, Object** s) { |
7351 int entry = FindEntry(key); | 7436 int entry = FindEntry(key); |
7352 | 7437 |
7353 // Symbol already in table. | 7438 // Symbol already in table. |
(...skipping 850 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
8204 if (break_point_objects()->IsUndefined()) return 0; | 8289 if (break_point_objects()->IsUndefined()) return 0; |
8205 // Single beak point. | 8290 // Single beak point. |
8206 if (!break_point_objects()->IsFixedArray()) return 1; | 8291 if (!break_point_objects()->IsFixedArray()) return 1; |
8207 // Multiple break points. | 8292 // Multiple break points. |
8208 return FixedArray::cast(break_point_objects())->length(); | 8293 return FixedArray::cast(break_point_objects())->length(); |
8209 } | 8294 } |
8210 #endif | 8295 #endif |
8211 | 8296 |
8212 | 8297 |
8213 } } // namespace v8::internal | 8298 } } // namespace v8::internal |
OLD | NEW |