| 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 23 matching lines...) Expand all Loading... |
| 34 #include "objects-inl.h" | 34 #include "objects-inl.h" |
| 35 #include "macro-assembler.h" | 35 #include "macro-assembler.h" |
| 36 #include "scanner.h" | 36 #include "scanner.h" |
| 37 #include "scopeinfo.h" | 37 #include "scopeinfo.h" |
| 38 #include "string-stream.h" | 38 #include "string-stream.h" |
| 39 | 39 |
| 40 #ifdef ENABLE_DISASSEMBLER | 40 #ifdef ENABLE_DISASSEMBLER |
| 41 #include "disassembler.h" | 41 #include "disassembler.h" |
| 42 #endif | 42 #endif |
| 43 | 43 |
| 44 |
| 44 namespace v8 { | 45 namespace v8 { |
| 45 namespace internal { | 46 namespace internal { |
| 46 | 47 |
| 47 // Getters and setters are stored in a fixed array property. These are | 48 // Getters and setters are stored in a fixed array property. These are |
| 48 // constants for their indices. | 49 // constants for their indices. |
| 49 const int kGetterIndex = 0; | 50 const int kGetterIndex = 0; |
| 50 const int kSetterIndex = 1; | 51 const int kSetterIndex = 1; |
| 51 | 52 |
| 52 bool Object::IsInstanceOf(FunctionTemplateInfo* expected) { | 53 bool Object::IsInstanceOf(FunctionTemplateInfo* expected) { |
| 53 // There is a constraint on the object; check | 54 // There is a constraint on the object; check |
| (...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 421 property_dictionary()->ValueAtPut(result->GetDictionaryEntry(), value); | 422 property_dictionary()->ValueAtPut(result->GetDictionaryEntry(), value); |
| 422 } | 423 } |
| 423 return value; | 424 return value; |
| 424 } | 425 } |
| 425 | 426 |
| 426 | 427 |
| 427 Object* JSObject::SetNormalizedProperty(String* name, | 428 Object* JSObject::SetNormalizedProperty(String* name, |
| 428 Object* value, | 429 Object* value, |
| 429 PropertyDetails details) { | 430 PropertyDetails details) { |
| 430 ASSERT(!HasFastProperties()); | 431 ASSERT(!HasFastProperties()); |
| 431 int entry = property_dictionary()->FindStringEntry(name); | 432 int entry = property_dictionary()->FindEntry(name); |
| 432 if (entry == Dictionary::kNotFound) { | 433 if (entry == StringDictionary::kNotFound) { |
| 433 Object* store_value = value; | 434 Object* store_value = value; |
| 434 if (IsGlobalObject()) { | 435 if (IsGlobalObject()) { |
| 435 store_value = Heap::AllocateJSGlobalPropertyCell(value); | 436 store_value = Heap::AllocateJSGlobalPropertyCell(value); |
| 436 if (store_value->IsFailure()) return store_value; | 437 if (store_value->IsFailure()) return store_value; |
| 437 } | 438 } |
| 438 Object* dict = | 439 Object* dict = |
| 439 property_dictionary()->AddStringEntry(name, store_value, details); | 440 property_dictionary()->Add(name, store_value, details); |
| 440 if (dict->IsFailure()) return dict; | 441 if (dict->IsFailure()) return dict; |
| 441 set_properties(Dictionary::cast(dict)); | 442 set_properties(StringDictionary::cast(dict)); |
| 442 return value; | 443 return value; |
| 443 } | 444 } |
| 444 // Preserve enumeration index. | 445 // Preserve enumeration index. |
| 445 details = PropertyDetails(details.attributes(), | 446 details = PropertyDetails(details.attributes(), |
| 446 details.type(), | 447 details.type(), |
| 447 property_dictionary()->DetailsAt(entry).index()); | 448 property_dictionary()->DetailsAt(entry).index()); |
| 448 if (IsGlobalObject()) { | 449 if (IsGlobalObject()) { |
| 449 JSGlobalPropertyCell* cell = | 450 JSGlobalPropertyCell* cell = |
| 450 JSGlobalPropertyCell::cast(property_dictionary()->ValueAt(entry)); | 451 JSGlobalPropertyCell::cast(property_dictionary()->ValueAt(entry)); |
| 451 cell->set_value(value); | 452 cell->set_value(value); |
| 452 // Please note we have to update the property details. | 453 // Please note we have to update the property details. |
| 453 property_dictionary()->DetailsAtPut(entry, details); | 454 property_dictionary()->DetailsAtPut(entry, details); |
| 454 } else { | 455 } else { |
| 455 property_dictionary()->SetStringEntry(entry, name, value, details); | 456 property_dictionary()->SetEntry(entry, name, value, details); |
| 456 } | 457 } |
| 457 return value; | 458 return value; |
| 458 } | 459 } |
| 459 | 460 |
| 460 | 461 |
| 461 Object* JSObject::DeleteNormalizedProperty(String* name, DeleteMode mode) { | 462 Object* JSObject::DeleteNormalizedProperty(String* name, DeleteMode mode) { |
| 462 ASSERT(!HasFastProperties()); | 463 ASSERT(!HasFastProperties()); |
| 463 Dictionary* dictionary = property_dictionary(); | 464 StringDictionary* dictionary = property_dictionary(); |
| 464 int entry = dictionary->FindStringEntry(name); | 465 int entry = dictionary->FindEntry(name); |
| 465 if (entry != Dictionary::kNotFound) { | 466 if (entry != StringDictionary::kNotFound) { |
| 466 // If we have a global object set the cell to the hole. | 467 // If we have a global object set the cell to the hole. |
| 467 if (IsGlobalObject()) { | 468 if (IsGlobalObject()) { |
| 468 PropertyDetails details = dictionary->DetailsAt(entry); | 469 PropertyDetails details = dictionary->DetailsAt(entry); |
| 469 if (details.IsDontDelete() && mode != FORCE_DELETION) { | 470 if (details.IsDontDelete() && mode != FORCE_DELETION) { |
| 470 return Heap::false_value(); | 471 return Heap::false_value(); |
| 471 } | 472 } |
| 472 JSGlobalPropertyCell* cell = | 473 JSGlobalPropertyCell* cell = |
| 473 JSGlobalPropertyCell::cast(dictionary->ValueAt(entry)); | 474 JSGlobalPropertyCell::cast(dictionary->ValueAt(entry)); |
| 474 cell->set_value(Heap::the_hole_value()); | 475 cell->set_value(Heap::the_hole_value()); |
| 475 dictionary->DetailsAtPut(entry, details.AsDeleted()); | 476 dictionary->DetailsAtPut(entry, details.AsDeleted()); |
| (...skipping 857 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1333 | 1334 |
| 1334 return function; | 1335 return function; |
| 1335 } | 1336 } |
| 1336 | 1337 |
| 1337 | 1338 |
| 1338 // Add property in slow mode | 1339 // Add property in slow mode |
| 1339 Object* JSObject::AddSlowProperty(String* name, | 1340 Object* JSObject::AddSlowProperty(String* name, |
| 1340 Object* value, | 1341 Object* value, |
| 1341 PropertyAttributes attributes) { | 1342 PropertyAttributes attributes) { |
| 1342 ASSERT(!HasFastProperties()); | 1343 ASSERT(!HasFastProperties()); |
| 1343 Dictionary* dict = property_dictionary(); | 1344 StringDictionary* dict = property_dictionary(); |
| 1344 Object* store_value = value; | 1345 Object* store_value = value; |
| 1345 if (IsGlobalObject()) { | 1346 if (IsGlobalObject()) { |
| 1346 // In case name is an orphaned property reuse the cell. | 1347 // In case name is an orphaned property reuse the cell. |
| 1347 int entry = dict->FindStringEntry(name); | 1348 int entry = dict->FindEntry(name); |
| 1348 if (entry != Dictionary::kNotFound) { | 1349 if (entry != StringDictionary::kNotFound) { |
| 1349 store_value = dict->ValueAt(entry); | 1350 store_value = dict->ValueAt(entry); |
| 1350 JSGlobalPropertyCell::cast(store_value)->set_value(value); | 1351 JSGlobalPropertyCell::cast(store_value)->set_value(value); |
| 1351 PropertyDetails details = PropertyDetails(attributes, NORMAL); | 1352 // Assign an enumeration index to the property and update |
| 1352 dict->SetStringEntry(entry, name, store_value, details); | 1353 // SetNextEnumerationIndex. |
| 1354 int index = dict->NextEnumerationIndex(); |
| 1355 PropertyDetails details = PropertyDetails(attributes, NORMAL, index); |
| 1356 dict->SetNextEnumerationIndex(index + 1); |
| 1357 dict->SetEntry(entry, name, store_value, details); |
| 1353 return value; | 1358 return value; |
| 1354 } | 1359 } |
| 1355 store_value = Heap::AllocateJSGlobalPropertyCell(value); | 1360 store_value = Heap::AllocateJSGlobalPropertyCell(value); |
| 1356 if (store_value->IsFailure()) return store_value; | 1361 if (store_value->IsFailure()) return store_value; |
| 1357 JSGlobalPropertyCell::cast(store_value)->set_value(value); | 1362 JSGlobalPropertyCell::cast(store_value)->set_value(value); |
| 1358 } | 1363 } |
| 1359 PropertyDetails details = PropertyDetails(attributes, NORMAL); | 1364 PropertyDetails details = PropertyDetails(attributes, NORMAL); |
| 1360 Object* result = dict->AddStringEntry(name, store_value, details); | 1365 Object* result = dict->Add(name, store_value, details); |
| 1361 if (result->IsFailure()) return result; | 1366 if (result->IsFailure()) return result; |
| 1362 if (dict != result) set_properties(Dictionary::cast(result)); | 1367 if (dict != result) set_properties(StringDictionary::cast(result)); |
| 1363 return value; | 1368 return value; |
| 1364 } | 1369 } |
| 1365 | 1370 |
| 1366 | 1371 |
| 1367 Object* JSObject::AddProperty(String* name, | 1372 Object* JSObject::AddProperty(String* name, |
| 1368 Object* value, | 1373 Object* value, |
| 1369 PropertyAttributes attributes) { | 1374 PropertyAttributes attributes) { |
| 1370 ASSERT(!IsJSGlobalProxy()); | 1375 ASSERT(!IsJSGlobalProxy()); |
| 1371 if (HasFastProperties()) { | 1376 if (HasFastProperties()) { |
| 1372 // Ensure the descriptor array does not get too big. | 1377 // Ensure the descriptor array does not get too big. |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1398 LocalLookupRealNamedProperty(name, &result); | 1403 LocalLookupRealNamedProperty(name, &result); |
| 1399 if (result.IsValid()) return SetProperty(&result, name, value, attributes); | 1404 if (result.IsValid()) return SetProperty(&result, name, value, attributes); |
| 1400 // Add real property. | 1405 // Add real property. |
| 1401 return AddProperty(name, value, attributes); | 1406 return AddProperty(name, value, attributes); |
| 1402 } | 1407 } |
| 1403 | 1408 |
| 1404 | 1409 |
| 1405 Object* JSObject::ReplaceSlowProperty(String* name, | 1410 Object* JSObject::ReplaceSlowProperty(String* name, |
| 1406 Object* value, | 1411 Object* value, |
| 1407 PropertyAttributes attributes) { | 1412 PropertyAttributes attributes) { |
| 1408 Dictionary* dictionary = property_dictionary(); | 1413 StringDictionary* dictionary = property_dictionary(); |
| 1409 int old_index = dictionary->FindStringEntry(name); | 1414 int old_index = dictionary->FindEntry(name); |
| 1410 int new_enumeration_index = 0; // 0 means "Use the next available index." | 1415 int new_enumeration_index = 0; // 0 means "Use the next available index." |
| 1411 if (old_index != -1) { | 1416 if (old_index != -1) { |
| 1412 // All calls to ReplaceSlowProperty have had all transitions removed. | 1417 // All calls to ReplaceSlowProperty have had all transitions removed. |
| 1413 ASSERT(!dictionary->DetailsAt(old_index).IsTransition()); | 1418 ASSERT(!dictionary->DetailsAt(old_index).IsTransition()); |
| 1414 new_enumeration_index = dictionary->DetailsAt(old_index).index(); | 1419 new_enumeration_index = dictionary->DetailsAt(old_index).index(); |
| 1415 } | 1420 } |
| 1416 | 1421 |
| 1417 PropertyDetails new_details(attributes, NORMAL, new_enumeration_index); | 1422 PropertyDetails new_details(attributes, NORMAL, new_enumeration_index); |
| 1418 return SetNormalizedProperty(name, value, new_details); | 1423 return SetNormalizedProperty(name, value, new_details); |
| 1419 } | 1424 } |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1639 } | 1644 } |
| 1640 result->NotFound(); | 1645 result->NotFound(); |
| 1641 } | 1646 } |
| 1642 | 1647 |
| 1643 | 1648 |
| 1644 Object* JSObject::LookupCallbackSetterInPrototypes(uint32_t index) { | 1649 Object* JSObject::LookupCallbackSetterInPrototypes(uint32_t index) { |
| 1645 for (Object* pt = GetPrototype(); | 1650 for (Object* pt = GetPrototype(); |
| 1646 pt != Heap::null_value(); | 1651 pt != Heap::null_value(); |
| 1647 pt = pt->GetPrototype()) { | 1652 pt = pt->GetPrototype()) { |
| 1648 if (JSObject::cast(pt)->HasFastElements()) continue; | 1653 if (JSObject::cast(pt)->HasFastElements()) continue; |
| 1649 Dictionary* dictionary = JSObject::cast(pt)->element_dictionary(); | 1654 NumberDictionary* dictionary = JSObject::cast(pt)->element_dictionary(); |
| 1650 int entry = dictionary->FindNumberEntry(index); | 1655 int entry = dictionary->FindEntry(index); |
| 1651 if (entry != Dictionary::kNotFound) { | 1656 if (entry != StringDictionary::kNotFound) { |
| 1652 Object* element = dictionary->ValueAt(entry); | 1657 Object* element = dictionary->ValueAt(entry); |
| 1653 PropertyDetails details = dictionary->DetailsAt(entry); | 1658 PropertyDetails details = dictionary->DetailsAt(entry); |
| 1654 if (details.type() == CALLBACKS) { | 1659 if (details.type() == CALLBACKS) { |
| 1655 // Only accessors allowed as elements. | 1660 // Only accessors allowed as elements. |
| 1656 return FixedArray::cast(element)->get(kSetterIndex); | 1661 return FixedArray::cast(element)->get(kSetterIndex); |
| 1657 } | 1662 } |
| 1658 } | 1663 } |
| 1659 } | 1664 } |
| 1660 return Heap::undefined_value(); | 1665 return Heap::undefined_value(); |
| 1661 } | 1666 } |
| (...skipping 29 matching lines...) Expand all Loading... |
| 1691 ASSERT(result->holder() == this && result->type() != NORMAL); | 1696 ASSERT(result->holder() == this && result->type() != NORMAL); |
| 1692 // Disallow caching for uninitialized constants. These can only | 1697 // Disallow caching for uninitialized constants. These can only |
| 1693 // occur as fields. | 1698 // occur as fields. |
| 1694 if (result->IsReadOnly() && result->type() == FIELD && | 1699 if (result->IsReadOnly() && result->type() == FIELD && |
| 1695 FastPropertyAt(result->GetFieldIndex())->IsTheHole()) { | 1700 FastPropertyAt(result->GetFieldIndex())->IsTheHole()) { |
| 1696 result->DisallowCaching(); | 1701 result->DisallowCaching(); |
| 1697 } | 1702 } |
| 1698 return; | 1703 return; |
| 1699 } | 1704 } |
| 1700 } else { | 1705 } else { |
| 1701 int entry = property_dictionary()->FindStringEntry(name); | 1706 int entry = property_dictionary()->FindEntry(name); |
| 1702 if (entry != Dictionary::kNotFound) { | 1707 if (entry != StringDictionary::kNotFound) { |
| 1703 // Make sure to disallow caching for uninitialized constants | 1708 // Make sure to disallow caching for uninitialized constants |
| 1704 // found in the dictionary-mode objects. | 1709 // found in the dictionary-mode objects. |
| 1705 Object* value = property_dictionary()->ValueAt(entry); | 1710 Object* value = property_dictionary()->ValueAt(entry); |
| 1706 if (IsGlobalObject()) { | 1711 if (IsGlobalObject()) { |
| 1707 PropertyDetails d = property_dictionary()->DetailsAt(entry); | 1712 PropertyDetails d = property_dictionary()->DetailsAt(entry); |
| 1708 if (d.IsDeleted()) { | 1713 if (d.IsDeleted()) { |
| 1709 result->NotFound(); | 1714 result->NotFound(); |
| 1710 return; | 1715 return; |
| 1711 } | 1716 } |
| 1712 value = JSGlobalPropertyCell::cast(value)->value(); | 1717 value = JSGlobalPropertyCell::cast(value)->value(); |
| (...skipping 381 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2094 LocalLookup(name, &result); | 2099 LocalLookup(name, &result); |
| 2095 return GetPropertyAttribute(this, &result, name, false); | 2100 return GetPropertyAttribute(this, &result, name, false); |
| 2096 } | 2101 } |
| 2097 | 2102 |
| 2098 | 2103 |
| 2099 Object* JSObject::NormalizeProperties(PropertyNormalizationMode mode) { | 2104 Object* JSObject::NormalizeProperties(PropertyNormalizationMode mode) { |
| 2100 if (!HasFastProperties()) return this; | 2105 if (!HasFastProperties()) return this; |
| 2101 | 2106 |
| 2102 // Allocate new content | 2107 // Allocate new content |
| 2103 Object* obj = | 2108 Object* obj = |
| 2104 Dictionary::Allocate(map()->NumberOfDescribedProperties() * 2 + 4); | 2109 StringDictionary::Allocate(map()->NumberOfDescribedProperties() * 2 + 4); |
| 2105 if (obj->IsFailure()) return obj; | 2110 if (obj->IsFailure()) return obj; |
| 2106 Dictionary* dictionary = Dictionary::cast(obj); | 2111 StringDictionary* dictionary = StringDictionary::cast(obj); |
| 2107 | 2112 |
| 2108 for (DescriptorReader r(map()->instance_descriptors()); | 2113 for (DescriptorReader r(map()->instance_descriptors()); |
| 2109 !r.eos(); | 2114 !r.eos(); |
| 2110 r.advance()) { | 2115 r.advance()) { |
| 2111 PropertyDetails details = r.GetDetails(); | 2116 PropertyDetails details = r.GetDetails(); |
| 2112 switch (details.type()) { | 2117 switch (details.type()) { |
| 2113 case CONSTANT_FUNCTION: { | 2118 case CONSTANT_FUNCTION: { |
| 2114 PropertyDetails d = | 2119 PropertyDetails d = |
| 2115 PropertyDetails(details.attributes(), NORMAL, details.index()); | 2120 PropertyDetails(details.attributes(), NORMAL, details.index()); |
| 2116 Object* value = r.GetConstantFunction(); | 2121 Object* value = r.GetConstantFunction(); |
| 2117 if (IsGlobalObject()) { | 2122 if (IsGlobalObject()) { |
| 2118 value = Heap::AllocateJSGlobalPropertyCell(value); | 2123 value = Heap::AllocateJSGlobalPropertyCell(value); |
| 2119 if (value->IsFailure()) return value; | 2124 if (value->IsFailure()) return value; |
| 2120 } | 2125 } |
| 2121 Object* result = dictionary->AddStringEntry(r.GetKey(), value, d); | 2126 Object* result = dictionary->Add(r.GetKey(), value, d); |
| 2122 if (result->IsFailure()) return result; | 2127 if (result->IsFailure()) return result; |
| 2123 dictionary = Dictionary::cast(result); | 2128 dictionary = StringDictionary::cast(result); |
| 2124 break; | 2129 break; |
| 2125 } | 2130 } |
| 2126 case FIELD: { | 2131 case FIELD: { |
| 2127 PropertyDetails d = | 2132 PropertyDetails d = |
| 2128 PropertyDetails(details.attributes(), NORMAL, details.index()); | 2133 PropertyDetails(details.attributes(), NORMAL, details.index()); |
| 2129 Object* value = FastPropertyAt(r.GetFieldIndex()); | 2134 Object* value = FastPropertyAt(r.GetFieldIndex()); |
| 2130 if (IsGlobalObject()) { | 2135 if (IsGlobalObject()) { |
| 2131 value = Heap::AllocateJSGlobalPropertyCell(value); | 2136 value = Heap::AllocateJSGlobalPropertyCell(value); |
| 2132 if (value->IsFailure()) return value; | 2137 if (value->IsFailure()) return value; |
| 2133 } | 2138 } |
| 2134 Object* result = dictionary->AddStringEntry(r.GetKey(), value, d); | 2139 Object* result = dictionary->Add(r.GetKey(), value, d); |
| 2135 if (result->IsFailure()) return result; | 2140 if (result->IsFailure()) return result; |
| 2136 dictionary = Dictionary::cast(result); | 2141 dictionary = StringDictionary::cast(result); |
| 2137 break; | 2142 break; |
| 2138 } | 2143 } |
| 2139 case CALLBACKS: { | 2144 case CALLBACKS: { |
| 2140 PropertyDetails d = | 2145 PropertyDetails d = |
| 2141 PropertyDetails(details.attributes(), CALLBACKS, details.index()); | 2146 PropertyDetails(details.attributes(), CALLBACKS, details.index()); |
| 2142 Object* value = r.GetCallbacksObject(); | 2147 Object* value = r.GetCallbacksObject(); |
| 2143 if (IsGlobalObject()) { | 2148 if (IsGlobalObject()) { |
| 2144 value = Heap::AllocateJSGlobalPropertyCell(value); | 2149 value = Heap::AllocateJSGlobalPropertyCell(value); |
| 2145 if (value->IsFailure()) return value; | 2150 if (value->IsFailure()) return value; |
| 2146 } | 2151 } |
| 2147 Object* result = dictionary->AddStringEntry(r.GetKey(), value, d); | 2152 Object* result = dictionary->Add(r.GetKey(), value, d); |
| 2148 if (result->IsFailure()) return result; | 2153 if (result->IsFailure()) return result; |
| 2149 dictionary = Dictionary::cast(result); | 2154 dictionary = StringDictionary::cast(result); |
| 2150 break; | 2155 break; |
| 2151 } | 2156 } |
| 2152 case MAP_TRANSITION: | 2157 case MAP_TRANSITION: |
| 2153 case CONSTANT_TRANSITION: | 2158 case CONSTANT_TRANSITION: |
| 2154 case NULL_DESCRIPTOR: | 2159 case NULL_DESCRIPTOR: |
| 2155 case INTERCEPTOR: | 2160 case INTERCEPTOR: |
| 2156 break; | 2161 break; |
| 2157 default: | 2162 default: |
| 2158 case NORMAL: | 2163 case NORMAL: |
| 2159 UNREACHABLE(); | 2164 UNREACHABLE(); |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2212 Object* JSObject::NormalizeElements() { | 2217 Object* JSObject::NormalizeElements() { |
| 2213 if (!HasFastElements()) return this; | 2218 if (!HasFastElements()) return this; |
| 2214 | 2219 |
| 2215 // Get number of entries. | 2220 // Get number of entries. |
| 2216 FixedArray* array = FixedArray::cast(elements()); | 2221 FixedArray* array = FixedArray::cast(elements()); |
| 2217 | 2222 |
| 2218 // Compute the effective length. | 2223 // Compute the effective length. |
| 2219 int length = IsJSArray() ? | 2224 int length = IsJSArray() ? |
| 2220 Smi::cast(JSArray::cast(this)->length())->value() : | 2225 Smi::cast(JSArray::cast(this)->length())->value() : |
| 2221 array->length(); | 2226 array->length(); |
| 2222 Object* obj = Dictionary::Allocate(length); | 2227 Object* obj = NumberDictionary::Allocate(length); |
| 2223 if (obj->IsFailure()) return obj; | 2228 if (obj->IsFailure()) return obj; |
| 2224 Dictionary* dictionary = Dictionary::cast(obj); | 2229 NumberDictionary* dictionary = NumberDictionary::cast(obj); |
| 2225 // Copy entries. | 2230 // Copy entries. |
| 2226 for (int i = 0; i < length; i++) { | 2231 for (int i = 0; i < length; i++) { |
| 2227 Object* value = array->get(i); | 2232 Object* value = array->get(i); |
| 2228 if (!value->IsTheHole()) { | 2233 if (!value->IsTheHole()) { |
| 2229 PropertyDetails details = PropertyDetails(NONE, NORMAL); | 2234 PropertyDetails details = PropertyDetails(NONE, NORMAL); |
| 2230 Object* result = dictionary->AddNumberEntry(i, array->get(i), details); | 2235 Object* result = dictionary->AddNumberEntry(i, array->get(i), details); |
| 2231 if (result->IsFailure()) return result; | 2236 if (result->IsFailure()) return result; |
| 2232 dictionary = Dictionary::cast(result); | 2237 dictionary = NumberDictionary::cast(result); |
| 2233 } | 2238 } |
| 2234 } | 2239 } |
| 2235 // Switch to using the dictionary as the backing storage for elements. | 2240 // Switch to using the dictionary as the backing storage for elements. |
| 2236 set_elements(dictionary); | 2241 set_elements(dictionary); |
| 2237 | 2242 |
| 2238 Counters::elements_to_dictionary.Increment(); | 2243 Counters::elements_to_dictionary.Increment(); |
| 2239 | 2244 |
| 2240 #ifdef DEBUG | 2245 #ifdef DEBUG |
| 2241 if (FLAG_trace_normalization) { | 2246 if (FLAG_trace_normalization) { |
| 2242 PrintF("Object elements have been normalized:\n"); | 2247 PrintF("Object elements have been normalized:\n"); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2299 if (HasFastElements()) { | 2304 if (HasFastElements()) { |
| 2300 uint32_t length = IsJSArray() ? | 2305 uint32_t length = IsJSArray() ? |
| 2301 static_cast<uint32_t>(Smi::cast(JSArray::cast(this)->length())->value()) : | 2306 static_cast<uint32_t>(Smi::cast(JSArray::cast(this)->length())->value()) : |
| 2302 static_cast<uint32_t>(FixedArray::cast(elements())->length()); | 2307 static_cast<uint32_t>(FixedArray::cast(elements())->length()); |
| 2303 if (index < length) { | 2308 if (index < length) { |
| 2304 FixedArray::cast(elements())->set_the_hole(index); | 2309 FixedArray::cast(elements())->set_the_hole(index); |
| 2305 } | 2310 } |
| 2306 return Heap::true_value(); | 2311 return Heap::true_value(); |
| 2307 } | 2312 } |
| 2308 ASSERT(!HasFastElements()); | 2313 ASSERT(!HasFastElements()); |
| 2309 Dictionary* dictionary = element_dictionary(); | 2314 NumberDictionary* dictionary = element_dictionary(); |
| 2310 int entry = dictionary->FindNumberEntry(index); | 2315 int entry = dictionary->FindEntry(index); |
| 2311 if (entry != Dictionary::kNotFound) { | 2316 if (entry != NumberDictionary::kNotFound) { |
| 2312 return dictionary->DeleteProperty(entry, mode); | 2317 return dictionary->DeleteProperty(entry, mode); |
| 2313 } | 2318 } |
| 2314 return Heap::true_value(); | 2319 return Heap::true_value(); |
| 2315 } | 2320 } |
| 2316 | 2321 |
| 2317 | 2322 |
| 2318 Object* JSObject::DeleteElementWithInterceptor(uint32_t index) { | 2323 Object* JSObject::DeleteElementWithInterceptor(uint32_t index) { |
| 2319 // Make sure that the top context does not change when doing | 2324 // Make sure that the top context does not change when doing |
| 2320 // callbacks or interceptor calls. | 2325 // callbacks or interceptor calls. |
| 2321 AssertNoContextChange ncc; | 2326 AssertNoContextChange ncc; |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2373 | 2378 |
| 2374 if (HasFastElements()) { | 2379 if (HasFastElements()) { |
| 2375 uint32_t length = IsJSArray() ? | 2380 uint32_t length = IsJSArray() ? |
| 2376 static_cast<uint32_t>(Smi::cast(JSArray::cast(this)->length())->value()) : | 2381 static_cast<uint32_t>(Smi::cast(JSArray::cast(this)->length())->value()) : |
| 2377 static_cast<uint32_t>(FixedArray::cast(elements())->length()); | 2382 static_cast<uint32_t>(FixedArray::cast(elements())->length()); |
| 2378 if (index < length) { | 2383 if (index < length) { |
| 2379 FixedArray::cast(elements())->set_the_hole(index); | 2384 FixedArray::cast(elements())->set_the_hole(index); |
| 2380 } | 2385 } |
| 2381 return Heap::true_value(); | 2386 return Heap::true_value(); |
| 2382 } else { | 2387 } else { |
| 2383 Dictionary* dictionary = element_dictionary(); | 2388 NumberDictionary* dictionary = element_dictionary(); |
| 2384 int entry = dictionary->FindNumberEntry(index); | 2389 int entry = dictionary->FindEntry(index); |
| 2385 if (entry != Dictionary::kNotFound) { | 2390 if (entry != NumberDictionary::kNotFound) { |
| 2386 return dictionary->DeleteProperty(entry, mode); | 2391 return dictionary->DeleteProperty(entry, mode); |
| 2387 } | 2392 } |
| 2388 } | 2393 } |
| 2389 return Heap::true_value(); | 2394 return Heap::true_value(); |
| 2390 } | 2395 } |
| 2391 | 2396 |
| 2392 | 2397 |
| 2393 Object* JSObject::DeleteProperty(String* name, DeleteMode mode) { | 2398 Object* JSObject::DeleteProperty(String* name, DeleteMode mode) { |
| 2394 // ECMA-262, 3rd, 8.6.2.5 | 2399 // ECMA-262, 3rd, 8.6.2.5 |
| 2395 ASSERT(name->IsString()); | 2400 ASSERT(name->IsString()); |
| (...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2680 } | 2685 } |
| 2681 } | 2686 } |
| 2682 | 2687 |
| 2683 uint32_t index; | 2688 uint32_t index; |
| 2684 bool is_element = name->AsArrayIndex(&index); | 2689 bool is_element = name->AsArrayIndex(&index); |
| 2685 if (is_element && IsJSArray()) return Heap::undefined_value(); | 2690 if (is_element && IsJSArray()) return Heap::undefined_value(); |
| 2686 | 2691 |
| 2687 if (is_element) { | 2692 if (is_element) { |
| 2688 // Lookup the index. | 2693 // Lookup the index. |
| 2689 if (!HasFastElements()) { | 2694 if (!HasFastElements()) { |
| 2690 Dictionary* dictionary = element_dictionary(); | 2695 NumberDictionary* dictionary = element_dictionary(); |
| 2691 int entry = dictionary->FindNumberEntry(index); | 2696 int entry = dictionary->FindEntry(index); |
| 2692 if (entry != Dictionary::kNotFound) { | 2697 if (entry != NumberDictionary::kNotFound) { |
| 2693 Object* result = dictionary->ValueAt(entry); | 2698 Object* result = dictionary->ValueAt(entry); |
| 2694 PropertyDetails details = dictionary->DetailsAt(entry); | 2699 PropertyDetails details = dictionary->DetailsAt(entry); |
| 2695 if (details.IsReadOnly()) return Heap::undefined_value(); | 2700 if (details.IsReadOnly()) return Heap::undefined_value(); |
| 2696 if (details.type() == CALLBACKS) { | 2701 if (details.type() == CALLBACKS) { |
| 2697 // Only accessors allowed as elements. | 2702 // Only accessors allowed as elements. |
| 2698 ASSERT(result->IsFixedArray()); | 2703 ASSERT(result->IsFixedArray()); |
| 2699 return result; | 2704 return result; |
| 2700 } | 2705 } |
| 2701 } | 2706 } |
| 2702 } | 2707 } |
| (...skipping 15 matching lines...) Expand all Loading... |
| 2718 if (structure->IsFailure()) return structure; | 2723 if (structure->IsFailure()) return structure; |
| 2719 PropertyDetails details = PropertyDetails(attributes, CALLBACKS); | 2724 PropertyDetails details = PropertyDetails(attributes, CALLBACKS); |
| 2720 | 2725 |
| 2721 if (is_element) { | 2726 if (is_element) { |
| 2722 // Normalize object to make this operation simple. | 2727 // Normalize object to make this operation simple. |
| 2723 Object* ok = NormalizeElements(); | 2728 Object* ok = NormalizeElements(); |
| 2724 if (ok->IsFailure()) return ok; | 2729 if (ok->IsFailure()) return ok; |
| 2725 | 2730 |
| 2726 // Update the dictionary with the new CALLBACKS property. | 2731 // Update the dictionary with the new CALLBACKS property. |
| 2727 Object* dict = | 2732 Object* dict = |
| 2728 element_dictionary()->SetOrAddNumberEntry(index, structure, details); | 2733 element_dictionary()->Set(index, structure, details); |
| 2729 if (dict->IsFailure()) return dict; | 2734 if (dict->IsFailure()) return dict; |
| 2730 | 2735 |
| 2731 // If name is an index we need to stay in slow case. | 2736 // If name is an index we need to stay in slow case. |
| 2732 Dictionary* elements = Dictionary::cast(dict); | 2737 NumberDictionary* elements = NumberDictionary::cast(dict); |
| 2733 elements->set_requires_slow_elements(); | 2738 elements->set_requires_slow_elements(); |
| 2734 // Set the potential new dictionary on the object. | 2739 // Set the potential new dictionary on the object. |
| 2735 set_elements(Dictionary::cast(dict)); | 2740 set_elements(NumberDictionary::cast(dict)); |
| 2736 } else { | 2741 } else { |
| 2737 // Normalize object to make this operation simple. | 2742 // Normalize object to make this operation simple. |
| 2738 Object* ok = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES); | 2743 Object* ok = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES); |
| 2739 if (ok->IsFailure()) return ok; | 2744 if (ok->IsFailure()) return ok; |
| 2740 | 2745 |
| 2741 // For the global object allocate a new map to invalidate the global inline | 2746 // For the global object allocate a new map to invalidate the global inline |
| 2742 // caches which have a global property cell reference directly in the code. | 2747 // caches which have a global property cell reference directly in the code. |
| 2743 if (IsGlobalObject()) { | 2748 if (IsGlobalObject()) { |
| 2744 Object* new_map = map()->CopyDropDescriptors(); | 2749 Object* new_map = map()->CopyDropDescriptors(); |
| 2745 if (new_map->IsFailure()) return new_map; | 2750 if (new_map->IsFailure()) return new_map; |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2792 | 2797 |
| 2793 // Make the lookup and include prototypes. | 2798 // Make the lookup and include prototypes. |
| 2794 int accessor_index = is_getter ? kGetterIndex : kSetterIndex; | 2799 int accessor_index = is_getter ? kGetterIndex : kSetterIndex; |
| 2795 uint32_t index; | 2800 uint32_t index; |
| 2796 if (name->AsArrayIndex(&index)) { | 2801 if (name->AsArrayIndex(&index)) { |
| 2797 for (Object* obj = this; | 2802 for (Object* obj = this; |
| 2798 obj != Heap::null_value(); | 2803 obj != Heap::null_value(); |
| 2799 obj = JSObject::cast(obj)->GetPrototype()) { | 2804 obj = JSObject::cast(obj)->GetPrototype()) { |
| 2800 JSObject* jsObject = JSObject::cast(obj); | 2805 JSObject* jsObject = JSObject::cast(obj); |
| 2801 if (!jsObject->HasFastElements()) { | 2806 if (!jsObject->HasFastElements()) { |
| 2802 Dictionary* dictionary = jsObject->element_dictionary(); | 2807 NumberDictionary* dictionary = jsObject->element_dictionary(); |
| 2803 int entry = dictionary->FindNumberEntry(index); | 2808 int entry = dictionary->FindEntry(index); |
| 2804 if (entry != Dictionary::kNotFound) { | 2809 if (entry != NumberDictionary::kNotFound) { |
| 2805 Object* element = dictionary->ValueAt(entry); | 2810 Object* element = dictionary->ValueAt(entry); |
| 2806 PropertyDetails details = dictionary->DetailsAt(entry); | 2811 PropertyDetails details = dictionary->DetailsAt(entry); |
| 2807 if (details.type() == CALLBACKS) { | 2812 if (details.type() == CALLBACKS) { |
| 2808 // Only accessors allowed as elements. | 2813 // Only accessors allowed as elements. |
| 2809 return FixedArray::cast(element)->get(accessor_index); | 2814 return FixedArray::cast(element)->get(accessor_index); |
| 2810 } | 2815 } |
| 2811 } | 2816 } |
| 2812 } | 2817 } |
| 2813 } | 2818 } |
| 2814 } else { | 2819 } else { |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2997 } | 3002 } |
| 2998 return false; | 3003 return false; |
| 2999 } | 3004 } |
| 3000 | 3005 |
| 3001 | 3006 |
| 3002 Object* FixedArray::AddKeysFromJSArray(JSArray* array) { | 3007 Object* FixedArray::AddKeysFromJSArray(JSArray* array) { |
| 3003 if (array->HasFastElements()) { | 3008 if (array->HasFastElements()) { |
| 3004 return UnionOfKeys(array->elements()); | 3009 return UnionOfKeys(array->elements()); |
| 3005 } | 3010 } |
| 3006 ASSERT(!array->HasFastElements()); | 3011 ASSERT(!array->HasFastElements()); |
| 3007 Dictionary* dict = array->element_dictionary(); | 3012 NumberDictionary* dict = array->element_dictionary(); |
| 3008 int size = dict->NumberOfElements(); | 3013 int size = dict->NumberOfElements(); |
| 3009 | 3014 |
| 3010 // Allocate a temporary fixed array. | 3015 // Allocate a temporary fixed array. |
| 3011 Object* object = Heap::AllocateFixedArray(size); | 3016 Object* object = Heap::AllocateFixedArray(size); |
| 3012 if (object->IsFailure()) return object; | 3017 if (object->IsFailure()) return object; |
| 3013 FixedArray* key_array = FixedArray::cast(object); | 3018 FixedArray* key_array = FixedArray::cast(object); |
| 3014 | 3019 |
| 3015 int capacity = dict->Capacity(); | 3020 int capacity = dict->Capacity(); |
| 3016 int pos = 0; | 3021 int pos = 0; |
| 3017 // Copy the elements from the JSArray to the temporary fixed array. | 3022 // Copy the elements from the JSArray to the temporary fixed array. |
| (...skipping 2050 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5068 #endif | 5073 #endif |
| 5069 WriteBarrierMode mode = elems->GetWriteBarrierMode(); | 5074 WriteBarrierMode mode = elems->GetWriteBarrierMode(); |
| 5070 if (HasFastElements()) { | 5075 if (HasFastElements()) { |
| 5071 FixedArray* old_elements = FixedArray::cast(elements()); | 5076 FixedArray* old_elements = FixedArray::cast(elements()); |
| 5072 uint32_t old_length = static_cast<uint32_t>(old_elements->length()); | 5077 uint32_t old_length = static_cast<uint32_t>(old_elements->length()); |
| 5073 // Fill out the new array with this content and array holes. | 5078 // Fill out the new array with this content and array holes. |
| 5074 for (uint32_t i = 0; i < old_length; i++) { | 5079 for (uint32_t i = 0; i < old_length; i++) { |
| 5075 elems->set(i, old_elements->get(i), mode); | 5080 elems->set(i, old_elements->get(i), mode); |
| 5076 } | 5081 } |
| 5077 } else { | 5082 } else { |
| 5078 Dictionary* dictionary = Dictionary::cast(elements()); | 5083 NumberDictionary* dictionary = NumberDictionary::cast(elements()); |
| 5079 for (int i = 0; i < dictionary->Capacity(); i++) { | 5084 for (int i = 0; i < dictionary->Capacity(); i++) { |
| 5080 Object* key = dictionary->KeyAt(i); | 5085 Object* key = dictionary->KeyAt(i); |
| 5081 if (key->IsNumber()) { | 5086 if (key->IsNumber()) { |
| 5082 uint32_t entry = static_cast<uint32_t>(key->Number()); | 5087 uint32_t entry = static_cast<uint32_t>(key->Number()); |
| 5083 elems->set(entry, dictionary->ValueAt(i), mode); | 5088 elems->set(entry, dictionary->ValueAt(i), mode); |
| 5084 } | 5089 } |
| 5085 } | 5090 } |
| 5086 } | 5091 } |
| 5087 set_elements(elems); | 5092 set_elements(elems); |
| 5088 } | 5093 } |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5233 if (HasFastElements()) { | 5238 if (HasFastElements()) { |
| 5234 uint32_t length = IsJSArray() ? | 5239 uint32_t length = IsJSArray() ? |
| 5235 static_cast<uint32_t>( | 5240 static_cast<uint32_t>( |
| 5236 Smi::cast(JSArray::cast(this)->length())->value()) : | 5241 Smi::cast(JSArray::cast(this)->length())->value()) : |
| 5237 static_cast<uint32_t>(FixedArray::cast(elements())->length()); | 5242 static_cast<uint32_t>(FixedArray::cast(elements())->length()); |
| 5238 if ((index < length) && | 5243 if ((index < length) && |
| 5239 !FixedArray::cast(elements())->get(index)->IsTheHole()) { | 5244 !FixedArray::cast(elements())->get(index)->IsTheHole()) { |
| 5240 return true; | 5245 return true; |
| 5241 } | 5246 } |
| 5242 } else { | 5247 } else { |
| 5243 if (element_dictionary()->FindNumberEntry(index) != Dictionary::kNotFound) { | 5248 if (element_dictionary()->FindEntry(index) |
| 5249 != NumberDictionary::kNotFound) { |
| 5244 return true; | 5250 return true; |
| 5245 } | 5251 } |
| 5246 } | 5252 } |
| 5247 | 5253 |
| 5248 // Handle [] on String objects. | 5254 // Handle [] on String objects. |
| 5249 if (this->IsStringObjectWithCharacterAt(index)) return true; | 5255 if (this->IsStringObjectWithCharacterAt(index)) return true; |
| 5250 | 5256 |
| 5251 Object* pt = GetPrototype(); | 5257 Object* pt = GetPrototype(); |
| 5252 if (pt == Heap::null_value()) return false; | 5258 if (pt == Heap::null_value()) return false; |
| 5253 return JSObject::cast(pt)->HasElementWithReceiver(receiver, index); | 5259 return JSObject::cast(pt)->HasElementWithReceiver(receiver, index); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5310 if (this->IsStringObjectWithCharacterAt(index)) return true; | 5316 if (this->IsStringObjectWithCharacterAt(index)) return true; |
| 5311 | 5317 |
| 5312 if (HasFastElements()) { | 5318 if (HasFastElements()) { |
| 5313 uint32_t length = IsJSArray() ? | 5319 uint32_t length = IsJSArray() ? |
| 5314 static_cast<uint32_t>( | 5320 static_cast<uint32_t>( |
| 5315 Smi::cast(JSArray::cast(this)->length())->value()) : | 5321 Smi::cast(JSArray::cast(this)->length())->value()) : |
| 5316 static_cast<uint32_t>(FixedArray::cast(elements())->length()); | 5322 static_cast<uint32_t>(FixedArray::cast(elements())->length()); |
| 5317 return (index < length) && | 5323 return (index < length) && |
| 5318 !FixedArray::cast(elements())->get(index)->IsTheHole(); | 5324 !FixedArray::cast(elements())->get(index)->IsTheHole(); |
| 5319 } else { | 5325 } else { |
| 5320 return element_dictionary()->FindNumberEntry(index) | 5326 return element_dictionary()->FindEntry(index) |
| 5321 != Dictionary::kNotFound; | 5327 != NumberDictionary::kNotFound; |
| 5322 } | 5328 } |
| 5323 } | 5329 } |
| 5324 | 5330 |
| 5325 | 5331 |
| 5326 bool JSObject::HasElementWithReceiver(JSObject* receiver, uint32_t index) { | 5332 bool JSObject::HasElementWithReceiver(JSObject* receiver, uint32_t index) { |
| 5327 // Check access rights if needed. | 5333 // Check access rights if needed. |
| 5328 if (IsAccessCheckNeeded() && | 5334 if (IsAccessCheckNeeded() && |
| 5329 !Top::MayIndexedAccess(this, index, v8::ACCESS_HAS)) { | 5335 !Top::MayIndexedAccess(this, index, v8::ACCESS_HAS)) { |
| 5330 Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS); | 5336 Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS); |
| 5331 return false; | 5337 return false; |
| 5332 } | 5338 } |
| 5333 | 5339 |
| 5334 // Check for lookup interceptor | 5340 // Check for lookup interceptor |
| 5335 if (HasIndexedInterceptor()) { | 5341 if (HasIndexedInterceptor()) { |
| 5336 return HasElementWithInterceptor(receiver, index); | 5342 return HasElementWithInterceptor(receiver, index); |
| 5337 } | 5343 } |
| 5338 | 5344 |
| 5339 if (HasFastElements()) { | 5345 if (HasFastElements()) { |
| 5340 uint32_t length = IsJSArray() ? | 5346 uint32_t length = IsJSArray() ? |
| 5341 static_cast<uint32_t>( | 5347 static_cast<uint32_t>( |
| 5342 Smi::cast(JSArray::cast(this)->length())->value()) : | 5348 Smi::cast(JSArray::cast(this)->length())->value()) : |
| 5343 static_cast<uint32_t>(FixedArray::cast(elements())->length()); | 5349 static_cast<uint32_t>(FixedArray::cast(elements())->length()); |
| 5344 if ((index < length) && | 5350 if ((index < length) && |
| 5345 !FixedArray::cast(elements())->get(index)->IsTheHole()) return true; | 5351 !FixedArray::cast(elements())->get(index)->IsTheHole()) return true; |
| 5346 } else { | 5352 } else { |
| 5347 if (element_dictionary()->FindNumberEntry(index) != Dictionary::kNotFound) { | 5353 if (element_dictionary()->FindEntry(index) |
| 5354 != NumberDictionary::kNotFound) { |
| 5348 return true; | 5355 return true; |
| 5349 } | 5356 } |
| 5350 } | 5357 } |
| 5351 | 5358 |
| 5352 // Handle [] on String objects. | 5359 // Handle [] on String objects. |
| 5353 if (this->IsStringObjectWithCharacterAt(index)) return true; | 5360 if (this->IsStringObjectWithCharacterAt(index)) return true; |
| 5354 | 5361 |
| 5355 Object* pt = GetPrototype(); | 5362 Object* pt = GetPrototype(); |
| 5356 if (pt == Heap::null_value()) return false; | 5363 if (pt == Heap::null_value()) return false; |
| 5357 return JSObject::cast(pt)->HasElementWithReceiver(receiver, index); | 5364 return JSObject::cast(pt)->HasElementWithReceiver(receiver, index); |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5472 | 5479 |
| 5473 Object* JSObject::SetElementWithoutInterceptor(uint32_t index, Object* value) { | 5480 Object* JSObject::SetElementWithoutInterceptor(uint32_t index, Object* value) { |
| 5474 // Fast case. | 5481 // Fast case. |
| 5475 if (HasFastElements()) return SetFastElement(index, value); | 5482 if (HasFastElements()) return SetFastElement(index, value); |
| 5476 | 5483 |
| 5477 // Dictionary case. | 5484 // Dictionary case. |
| 5478 ASSERT(!HasFastElements()); | 5485 ASSERT(!HasFastElements()); |
| 5479 | 5486 |
| 5480 // Insert element in the dictionary. | 5487 // Insert element in the dictionary. |
| 5481 FixedArray* elms = FixedArray::cast(elements()); | 5488 FixedArray* elms = FixedArray::cast(elements()); |
| 5482 Dictionary* dictionary = Dictionary::cast(elms); | 5489 NumberDictionary* dictionary = NumberDictionary::cast(elms); |
| 5483 | 5490 |
| 5484 int entry = dictionary->FindNumberEntry(index); | 5491 int entry = dictionary->FindEntry(index); |
| 5485 if (entry != Dictionary::kNotFound) { | 5492 if (entry != NumberDictionary::kNotFound) { |
| 5486 Object* element = dictionary->ValueAt(entry); | 5493 Object* element = dictionary->ValueAt(entry); |
| 5487 PropertyDetails details = dictionary->DetailsAt(entry); | 5494 PropertyDetails details = dictionary->DetailsAt(entry); |
| 5488 if (details.type() == CALLBACKS) { | 5495 if (details.type() == CALLBACKS) { |
| 5489 // Only accessors allowed as elements. | 5496 // Only accessors allowed as elements. |
| 5490 FixedArray* structure = FixedArray::cast(element); | 5497 FixedArray* structure = FixedArray::cast(element); |
| 5491 if (structure->get(kSetterIndex)->IsJSFunction()) { | 5498 if (structure->get(kSetterIndex)->IsJSFunction()) { |
| 5492 JSFunction* setter = JSFunction::cast(structure->get(kSetterIndex)); | 5499 JSFunction* setter = JSFunction::cast(structure->get(kSetterIndex)); |
| 5493 return SetPropertyWithDefinedSetter(setter, value); | 5500 return SetPropertyWithDefinedSetter(setter, value); |
| 5494 } else { | 5501 } else { |
| 5495 Handle<Object> self(this); | 5502 Handle<Object> self(this); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 5524 if (return_value->IsFailure()) return return_value; | 5531 if (return_value->IsFailure()) return return_value; |
| 5525 } | 5532 } |
| 5526 | 5533 |
| 5527 // Attempt to put this object back in fast case. | 5534 // Attempt to put this object back in fast case. |
| 5528 if (ShouldConvertToFastElements()) { | 5535 if (ShouldConvertToFastElements()) { |
| 5529 uint32_t new_length = 0; | 5536 uint32_t new_length = 0; |
| 5530 if (IsJSArray()) { | 5537 if (IsJSArray()) { |
| 5531 CHECK(Array::IndexFromObject(JSArray::cast(this)->length(), &new_length)); | 5538 CHECK(Array::IndexFromObject(JSArray::cast(this)->length(), &new_length)); |
| 5532 JSArray::cast(this)->set_length(Smi::FromInt(new_length)); | 5539 JSArray::cast(this)->set_length(Smi::FromInt(new_length)); |
| 5533 } else { | 5540 } else { |
| 5534 new_length = Dictionary::cast(elements())->max_number_key() + 1; | 5541 new_length = NumberDictionary::cast(elements())->max_number_key() + 1; |
| 5535 } | 5542 } |
| 5536 Object* obj = Heap::AllocateFixedArrayWithHoles(new_length); | 5543 Object* obj = Heap::AllocateFixedArrayWithHoles(new_length); |
| 5537 if (obj->IsFailure()) return obj; | 5544 if (obj->IsFailure()) return obj; |
| 5538 SetFastElements(FixedArray::cast(obj)); | 5545 SetFastElements(FixedArray::cast(obj)); |
| 5539 #ifdef DEBUG | 5546 #ifdef DEBUG |
| 5540 if (FLAG_trace_normalization) { | 5547 if (FLAG_trace_normalization) { |
| 5541 PrintF("Object elements are fast case again:\n"); | 5548 PrintF("Object elements are fast case again:\n"); |
| 5542 Print(); | 5549 Print(); |
| 5543 } | 5550 } |
| 5544 #endif | 5551 #endif |
| (...skipping 22 matching lines...) Expand all Loading... |
| 5567 uint32_t index) { | 5574 uint32_t index) { |
| 5568 // Get element works for both JSObject and JSArray since | 5575 // Get element works for both JSObject and JSArray since |
| 5569 // JSArray::length cannot change. | 5576 // JSArray::length cannot change. |
| 5570 if (HasFastElements()) { | 5577 if (HasFastElements()) { |
| 5571 FixedArray* elms = FixedArray::cast(elements()); | 5578 FixedArray* elms = FixedArray::cast(elements()); |
| 5572 if (index < static_cast<uint32_t>(elms->length())) { | 5579 if (index < static_cast<uint32_t>(elms->length())) { |
| 5573 Object* value = elms->get(index); | 5580 Object* value = elms->get(index); |
| 5574 if (!value->IsTheHole()) return value; | 5581 if (!value->IsTheHole()) return value; |
| 5575 } | 5582 } |
| 5576 } else { | 5583 } else { |
| 5577 Dictionary* dictionary = element_dictionary(); | 5584 NumberDictionary* dictionary = element_dictionary(); |
| 5578 int entry = dictionary->FindNumberEntry(index); | 5585 int entry = dictionary->FindEntry(index); |
| 5579 if (entry != Dictionary::kNotFound) { | 5586 if (entry != NumberDictionary::kNotFound) { |
| 5580 Object* element = dictionary->ValueAt(entry); | 5587 Object* element = dictionary->ValueAt(entry); |
| 5581 PropertyDetails details = dictionary->DetailsAt(entry); | 5588 PropertyDetails details = dictionary->DetailsAt(entry); |
| 5582 if (details.type() == CALLBACKS) { | 5589 if (details.type() == CALLBACKS) { |
| 5583 // Only accessors allowed as elements. | 5590 // Only accessors allowed as elements. |
| 5584 FixedArray* structure = FixedArray::cast(element); | 5591 FixedArray* structure = FixedArray::cast(element); |
| 5585 Object* getter = structure->get(kGetterIndex); | 5592 Object* getter = structure->get(kGetterIndex); |
| 5586 if (getter->IsJSFunction()) { | 5593 if (getter->IsJSFunction()) { |
| 5587 return GetPropertyWithDefinedGetter(receiver, | 5594 return GetPropertyWithDefinedGetter(receiver, |
| 5588 JSFunction::cast(getter)); | 5595 JSFunction::cast(getter)); |
| 5589 } else { | 5596 } else { |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5651 | 5658 |
| 5652 // Get element works for both JSObject and JSArray since | 5659 // Get element works for both JSObject and JSArray since |
| 5653 // JSArray::length cannot change. | 5660 // JSArray::length cannot change. |
| 5654 if (HasFastElements()) { | 5661 if (HasFastElements()) { |
| 5655 FixedArray* elms = FixedArray::cast(elements()); | 5662 FixedArray* elms = FixedArray::cast(elements()); |
| 5656 if (index < static_cast<uint32_t>(elms->length())) { | 5663 if (index < static_cast<uint32_t>(elms->length())) { |
| 5657 Object* value = elms->get(index); | 5664 Object* value = elms->get(index); |
| 5658 if (!value->IsTheHole()) return value; | 5665 if (!value->IsTheHole()) return value; |
| 5659 } | 5666 } |
| 5660 } else { | 5667 } else { |
| 5661 Dictionary* dictionary = element_dictionary(); | 5668 NumberDictionary* dictionary = element_dictionary(); |
| 5662 int entry = dictionary->FindNumberEntry(index); | 5669 int entry = dictionary->FindEntry(index); |
| 5663 if (entry != Dictionary::kNotFound) { | 5670 if (entry != NumberDictionary::kNotFound) { |
| 5664 Object* element = dictionary->ValueAt(entry); | 5671 Object* element = dictionary->ValueAt(entry); |
| 5665 PropertyDetails details = dictionary->DetailsAt(entry); | 5672 PropertyDetails details = dictionary->DetailsAt(entry); |
| 5666 if (details.type() == CALLBACKS) { | 5673 if (details.type() == CALLBACKS) { |
| 5667 // Only accessors allowed as elements. | 5674 // Only accessors allowed as elements. |
| 5668 FixedArray* structure = FixedArray::cast(element); | 5675 FixedArray* structure = FixedArray::cast(element); |
| 5669 Object* getter = structure->get(kGetterIndex); | 5676 Object* getter = structure->get(kGetterIndex); |
| 5670 if (getter->IsJSFunction()) { | 5677 if (getter->IsJSFunction()) { |
| 5671 return GetPropertyWithDefinedGetter(receiver, | 5678 return GetPropertyWithDefinedGetter(receiver, |
| 5672 JSFunction::cast(getter)); | 5679 JSFunction::cast(getter)); |
| 5673 } else { | 5680 } else { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 5689 int capacity = 0; | 5696 int capacity = 0; |
| 5690 int number_of_elements = 0; | 5697 int number_of_elements = 0; |
| 5691 | 5698 |
| 5692 if (HasFastElements()) { | 5699 if (HasFastElements()) { |
| 5693 FixedArray* elms = FixedArray::cast(elements()); | 5700 FixedArray* elms = FixedArray::cast(elements()); |
| 5694 capacity = elms->length(); | 5701 capacity = elms->length(); |
| 5695 for (int i = 0; i < capacity; i++) { | 5702 for (int i = 0; i < capacity; i++) { |
| 5696 if (!elms->get(i)->IsTheHole()) number_of_elements++; | 5703 if (!elms->get(i)->IsTheHole()) number_of_elements++; |
| 5697 } | 5704 } |
| 5698 } else { | 5705 } else { |
| 5699 Dictionary* dictionary = Dictionary::cast(elements()); | 5706 NumberDictionary* dictionary = NumberDictionary::cast(elements()); |
| 5700 capacity = dictionary->Capacity(); | 5707 capacity = dictionary->Capacity(); |
| 5701 number_of_elements = dictionary->NumberOfElements(); | 5708 number_of_elements = dictionary->NumberOfElements(); |
| 5702 } | 5709 } |
| 5703 | 5710 |
| 5704 if (capacity == 0) return true; | 5711 if (capacity == 0) return true; |
| 5705 return (number_of_elements > (capacity / 2)); | 5712 return (number_of_elements > (capacity / 2)); |
| 5706 } | 5713 } |
| 5707 | 5714 |
| 5708 | 5715 |
| 5709 bool JSObject::ShouldConvertToSlowElements(int new_capacity) { | 5716 bool JSObject::ShouldConvertToSlowElements(int new_capacity) { |
| 5710 ASSERT(HasFastElements()); | 5717 ASSERT(HasFastElements()); |
| 5711 // Keep the array in fast case if the current backing storage is | 5718 // Keep the array in fast case if the current backing storage is |
| 5712 // almost filled and if the new capacity is no more than twice the | 5719 // almost filled and if the new capacity is no more than twice the |
| 5713 // old capacity. | 5720 // old capacity. |
| 5714 int elements_length = FixedArray::cast(elements())->length(); | 5721 int elements_length = FixedArray::cast(elements())->length(); |
| 5715 return !HasDenseElements() || ((new_capacity / 2) > elements_length); | 5722 return !HasDenseElements() || ((new_capacity / 2) > elements_length); |
| 5716 } | 5723 } |
| 5717 | 5724 |
| 5718 | 5725 |
| 5719 bool JSObject::ShouldConvertToFastElements() { | 5726 bool JSObject::ShouldConvertToFastElements() { |
| 5720 ASSERT(!HasFastElements()); | 5727 ASSERT(!HasFastElements()); |
| 5721 Dictionary* dictionary = Dictionary::cast(elements()); | 5728 NumberDictionary* dictionary = NumberDictionary::cast(elements()); |
| 5722 // If the elements are sparse, we should not go back to fast case. | 5729 // If the elements are sparse, we should not go back to fast case. |
| 5723 if (!HasDenseElements()) return false; | 5730 if (!HasDenseElements()) return false; |
| 5724 // If an element has been added at a very high index in the elements | 5731 // If an element has been added at a very high index in the elements |
| 5725 // dictionary, we cannot go back to fast case. | 5732 // dictionary, we cannot go back to fast case. |
| 5726 if (dictionary->requires_slow_elements()) return false; | 5733 if (dictionary->requires_slow_elements()) return false; |
| 5727 // An object requiring access checks is never allowed to have fast | 5734 // An object requiring access checks is never allowed to have fast |
| 5728 // elements. If it had fast elements we would skip security checks. | 5735 // elements. If it had fast elements we would skip security checks. |
| 5729 if (IsAccessCheckNeeded()) return false; | 5736 if (IsAccessCheckNeeded()) return false; |
| 5730 // If the dictionary backing storage takes up roughly half as much | 5737 // If the dictionary backing storage takes up roughly half as much |
| 5731 // space as a fast-case backing storage would the array should have | 5738 // space as a fast-case backing storage would the array should have |
| 5732 // fast elements. | 5739 // fast elements. |
| 5733 uint32_t length = 0; | 5740 uint32_t length = 0; |
| 5734 if (IsJSArray()) { | 5741 if (IsJSArray()) { |
| 5735 CHECK(Array::IndexFromObject(JSArray::cast(this)->length(), &length)); | 5742 CHECK(Array::IndexFromObject(JSArray::cast(this)->length(), &length)); |
| 5736 } else { | 5743 } else { |
| 5737 length = dictionary->max_number_key(); | 5744 length = dictionary->max_number_key(); |
| 5738 } | 5745 } |
| 5739 return static_cast<uint32_t>(dictionary->Capacity()) >= | 5746 return static_cast<uint32_t>(dictionary->Capacity()) >= |
| 5740 (length / (2 * Dictionary::kElementSize)); | 5747 (length / (2 * NumberDictionary::kEntrySize)); |
| 5741 } | 5748 } |
| 5742 | 5749 |
| 5743 | 5750 template<typename Shape, typename Key> |
| 5744 void Dictionary::CopyValuesTo(FixedArray* elements) { | 5751 void Dictionary<Shape, Key>::CopyValuesTo(FixedArray* elements) { |
| 5745 int pos = 0; | 5752 int pos = 0; |
| 5746 int capacity = Capacity(); | 5753 int capacity = HashTable<Shape, Key>::Capacity(); |
| 5747 WriteBarrierMode mode = elements->GetWriteBarrierMode(); | 5754 WriteBarrierMode mode = elements->GetWriteBarrierMode(); |
| 5748 for (int i = 0; i < capacity; i++) { | 5755 for (int i = 0; i < capacity; i++) { |
| 5749 Object* k = KeyAt(i); | 5756 Object* k = Dictionary<Shape, Key>::KeyAt(i); |
| 5750 if (IsKey(k)) elements->set(pos++, ValueAt(i), mode); | 5757 if (Dictionary<Shape, Key>::IsKey(k)) { |
| 5758 elements->set(pos++, ValueAt(i), mode); |
| 5759 } |
| 5751 } | 5760 } |
| 5752 ASSERT(pos == elements->length()); | 5761 ASSERT(pos == elements->length()); |
| 5753 } | 5762 } |
| 5754 | 5763 |
| 5755 | 5764 |
| 5756 InterceptorInfo* JSObject::GetNamedInterceptor() { | 5765 InterceptorInfo* JSObject::GetNamedInterceptor() { |
| 5757 ASSERT(map()->has_named_interceptor()); | 5766 ASSERT(map()->has_named_interceptor()); |
| 5758 JSFunction* constructor = JSFunction::cast(map()->constructor()); | 5767 JSFunction* constructor = JSFunction::cast(map()->constructor()); |
| 5759 Object* template_info = constructor->shared()->function_data(); | 5768 Object* template_info = constructor->shared()->function_data(); |
| 5760 Object* result = | 5769 Object* result = |
| (...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5946 if (this->IsStringObjectWithCharacterAt(index)) return true; | 5955 if (this->IsStringObjectWithCharacterAt(index)) return true; |
| 5947 | 5956 |
| 5948 if (HasFastElements()) { | 5957 if (HasFastElements()) { |
| 5949 uint32_t length = IsJSArray() ? | 5958 uint32_t length = IsJSArray() ? |
| 5950 static_cast<uint32_t>( | 5959 static_cast<uint32_t>( |
| 5951 Smi::cast(JSArray::cast(this)->length())->value()) : | 5960 Smi::cast(JSArray::cast(this)->length())->value()) : |
| 5952 static_cast<uint32_t>(FixedArray::cast(elements())->length()); | 5961 static_cast<uint32_t>(FixedArray::cast(elements())->length()); |
| 5953 return (index < length) && | 5962 return (index < length) && |
| 5954 !FixedArray::cast(elements())->get(index)->IsTheHole(); | 5963 !FixedArray::cast(elements())->get(index)->IsTheHole(); |
| 5955 } | 5964 } |
| 5956 return element_dictionary()->FindNumberEntry(index) | 5965 return element_dictionary()->FindEntry(index) |
| 5957 != Dictionary::kNotFound; | 5966 != NumberDictionary::kNotFound; |
| 5958 } | 5967 } |
| 5959 | 5968 |
| 5960 | 5969 |
| 5961 bool JSObject::HasRealNamedCallbackProperty(String* key) { | 5970 bool JSObject::HasRealNamedCallbackProperty(String* key) { |
| 5962 // Check access rights if needed. | 5971 // Check access rights if needed. |
| 5963 if (IsAccessCheckNeeded() && | 5972 if (IsAccessCheckNeeded() && |
| 5964 !Top::MayNamedAccess(this, key, v8::ACCESS_HAS)) { | 5973 !Top::MayNamedAccess(this, key, v8::ACCESS_HAS)) { |
| 5965 Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS); | 5974 Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS); |
| 5966 return false; | 5975 return false; |
| 5967 } | 5976 } |
| (...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6180 return counter; | 6189 return counter; |
| 6181 } | 6190 } |
| 6182 | 6191 |
| 6183 | 6192 |
| 6184 int JSObject::GetEnumElementKeys(FixedArray* storage) { | 6193 int JSObject::GetEnumElementKeys(FixedArray* storage) { |
| 6185 return GetLocalElementKeys(storage, | 6194 return GetLocalElementKeys(storage, |
| 6186 static_cast<PropertyAttributes>(DONT_ENUM)); | 6195 static_cast<PropertyAttributes>(DONT_ENUM)); |
| 6187 } | 6196 } |
| 6188 | 6197 |
| 6189 | 6198 |
| 6190 // The NumberKey uses carries the uint32_t as key. | 6199 bool NumberDictionaryShape::IsMatch(uint32_t key, Object* other) { |
| 6191 // This avoids allocation in HasProperty. | 6200 ASSERT(other->IsNumber()); |
| 6192 class NumberKey : public HashTableKey { | 6201 return key == static_cast<uint32_t>(other->Number()); |
| 6193 public: | 6202 } |
| 6194 explicit NumberKey(uint32_t number) : number_(number) { } | |
| 6195 | 6203 |
| 6196 bool IsMatch(Object* number) { | |
| 6197 return number_ == ToUint32(number); | |
| 6198 } | |
| 6199 | 6204 |
| 6200 uint32_t Hash() { return ComputeIntegerHash(number_); } | 6205 uint32_t NumberDictionaryShape::Hash(uint32_t key) { |
| 6206 return ComputeIntegerHash(key); |
| 6207 } |
| 6201 | 6208 |
| 6202 HashFunction GetHashFunction() { return NumberHash; } | |
| 6203 | 6209 |
| 6204 Object* GetObject() { | 6210 uint32_t NumberDictionaryShape::HashForObject(uint32_t key, Object* other) { |
| 6205 return Heap::NumberFromDouble(number_); | 6211 ASSERT(other->IsNumber()); |
| 6206 } | 6212 return ComputeIntegerHash(static_cast<uint32_t>(other->Number())); |
| 6213 } |
| 6207 | 6214 |
| 6208 bool IsStringKey() { return false; } | |
| 6209 | 6215 |
| 6210 private: | 6216 Object* NumberDictionaryShape::AsObject(uint32_t key) { |
| 6211 static uint32_t NumberHash(Object* obj) { | 6217 return Heap::NumberFromUint32(key); |
| 6212 return ComputeIntegerHash(ToUint32(obj)); | 6218 } |
| 6213 } | |
| 6214 | 6219 |
| 6215 static uint32_t ToUint32(Object* obj) { | |
| 6216 ASSERT(obj->IsNumber()); | |
| 6217 return static_cast<uint32_t>(obj->Number()); | |
| 6218 } | |
| 6219 | 6220 |
| 6220 uint32_t number_; | 6221 bool StringDictionaryShape::IsMatch(String* key, Object* other) { |
| 6221 }; | 6222 // We know that all entries in a hash table had their hash keys created. |
| 6223 // Use that knowledge to have fast failure. |
| 6224 if (key->Hash() != String::cast(other)->Hash()) return false; |
| 6225 return key->Equals(String::cast(other)); |
| 6226 } |
| 6227 |
| 6228 |
| 6229 uint32_t StringDictionaryShape::Hash(String* key) { |
| 6230 return key->Hash(); |
| 6231 } |
| 6232 |
| 6233 |
| 6234 uint32_t StringDictionaryShape::HashForObject(String* key, Object* other) { |
| 6235 return String::cast(other)->Hash(); |
| 6236 } |
| 6237 |
| 6238 |
| 6239 Object* StringDictionaryShape::AsObject(String* key) { |
| 6240 return key; |
| 6241 } |
| 6222 | 6242 |
| 6223 | 6243 |
| 6224 // StringKey simply carries a string object as key. | 6244 // StringKey simply carries a string object as key. |
| 6225 class StringKey : public HashTableKey { | 6245 class StringKey : public HashTableKey { |
| 6226 public: | 6246 public: |
| 6227 explicit StringKey(String* string) : | 6247 explicit StringKey(String* string) : |
| 6228 string_(string), | 6248 string_(string), |
| 6229 hash_(StringHash(string)) { } | 6249 hash_(HashForObject(string)) { } |
| 6230 | 6250 |
| 6231 bool IsMatch(Object* string) { | 6251 bool IsMatch(Object* string) { |
| 6232 // We know that all entries in a hash table had their hash keys created. | 6252 // We know that all entries in a hash table had their hash keys created. |
| 6233 // Use that knowledge to have fast failure. | 6253 // Use that knowledge to have fast failure. |
| 6234 if (hash_ != StringHash(string)) { | 6254 if (hash_ != HashForObject(string)) { |
| 6235 return false; | 6255 return false; |
| 6236 } | 6256 } |
| 6237 return string_->Equals(String::cast(string)); | 6257 return string_->Equals(String::cast(string)); |
| 6238 } | 6258 } |
| 6239 | 6259 |
| 6240 uint32_t Hash() { return hash_; } | 6260 uint32_t Hash() { return hash_; } |
| 6241 | 6261 |
| 6242 HashFunction GetHashFunction() { return StringHash; } | 6262 uint32_t HashForObject(Object* other) { return String::cast(other)->Hash(); } |
| 6243 | 6263 |
| 6244 Object* GetObject() { return string_; } | 6264 Object* AsObject() { return string_; } |
| 6245 | |
| 6246 static uint32_t StringHash(Object* obj) { | |
| 6247 return String::cast(obj)->Hash(); | |
| 6248 } | |
| 6249 | |
| 6250 bool IsStringKey() { return true; } | |
| 6251 | 6265 |
| 6252 String* string_; | 6266 String* string_; |
| 6253 uint32_t hash_; | 6267 uint32_t hash_; |
| 6254 }; | 6268 }; |
| 6255 | 6269 |
| 6256 | 6270 |
| 6257 // StringSharedKeys are used as keys in the eval cache. | 6271 // StringSharedKeys are used as keys in the eval cache. |
| 6258 class StringSharedKey : public HashTableKey { | 6272 class StringSharedKey : public HashTableKey { |
| 6259 public: | 6273 public: |
| 6260 StringSharedKey(String* source, SharedFunctionInfo* shared) | 6274 StringSharedKey(String* source, SharedFunctionInfo* shared) |
| 6261 : source_(source), shared_(shared) { } | 6275 : source_(source), shared_(shared) { } |
| 6262 | 6276 |
| 6263 bool IsMatch(Object* other) { | 6277 bool IsMatch(Object* other) { |
| 6264 if (!other->IsFixedArray()) return false; | 6278 if (!other->IsFixedArray()) return false; |
| 6265 FixedArray* pair = FixedArray::cast(other); | 6279 FixedArray* pair = FixedArray::cast(other); |
| 6266 SharedFunctionInfo* shared = SharedFunctionInfo::cast(pair->get(0)); | 6280 SharedFunctionInfo* shared = SharedFunctionInfo::cast(pair->get(0)); |
| 6267 if (shared != shared_) return false; | 6281 if (shared != shared_) return false; |
| 6268 String* source = String::cast(pair->get(1)); | 6282 String* source = String::cast(pair->get(1)); |
| 6269 return source->Equals(source_); | 6283 return source->Equals(source_); |
| 6270 } | 6284 } |
| 6271 | 6285 |
| 6272 typedef uint32_t (*HashFunction)(Object* obj); | |
| 6273 | |
| 6274 virtual HashFunction GetHashFunction() { return StringSharedHash; } | |
| 6275 | |
| 6276 static uint32_t StringSharedHashHelper(String* source, | 6286 static uint32_t StringSharedHashHelper(String* source, |
| 6277 SharedFunctionInfo* shared) { | 6287 SharedFunctionInfo* shared) { |
| 6278 uint32_t hash = source->Hash(); | 6288 uint32_t hash = source->Hash(); |
| 6279 if (shared->HasSourceCode()) { | 6289 if (shared->HasSourceCode()) { |
| 6280 // Instead of using the SharedFunctionInfo pointer in the hash | 6290 // Instead of using the SharedFunctionInfo pointer in the hash |
| 6281 // code computation, we use a combination of the hash of the | 6291 // code computation, we use a combination of the hash of the |
| 6282 // script source code and the start and end positions. We do | 6292 // script source code and the start and end positions. We do |
| 6283 // this to ensure that the cache entries can survive garbage | 6293 // this to ensure that the cache entries can survive garbage |
| 6284 // collection. | 6294 // collection. |
| 6285 Script* script = Script::cast(shared->script()); | 6295 Script* script = Script::cast(shared->script()); |
| 6286 hash ^= String::cast(script->source())->Hash(); | 6296 hash ^= String::cast(script->source())->Hash(); |
| 6287 hash += shared->start_position(); | 6297 hash += shared->start_position(); |
| 6288 } | 6298 } |
| 6289 return hash; | 6299 return hash; |
| 6290 } | 6300 } |
| 6291 | 6301 |
| 6292 static uint32_t StringSharedHash(Object* obj) { | 6302 uint32_t Hash() { |
| 6303 return StringSharedHashHelper(source_, shared_); |
| 6304 } |
| 6305 |
| 6306 uint32_t HashForObject(Object* obj) { |
| 6293 FixedArray* pair = FixedArray::cast(obj); | 6307 FixedArray* pair = FixedArray::cast(obj); |
| 6294 SharedFunctionInfo* shared = SharedFunctionInfo::cast(pair->get(0)); | 6308 SharedFunctionInfo* shared = SharedFunctionInfo::cast(pair->get(0)); |
| 6295 String* source = String::cast(pair->get(1)); | 6309 String* source = String::cast(pair->get(1)); |
| 6296 return StringSharedHashHelper(source, shared); | 6310 return StringSharedHashHelper(source, shared); |
| 6297 } | 6311 } |
| 6298 | 6312 |
| 6299 virtual uint32_t Hash() { | 6313 Object* AsObject() { |
| 6300 return StringSharedHashHelper(source_, shared_); | |
| 6301 } | |
| 6302 | |
| 6303 virtual Object* GetObject() { | |
| 6304 Object* obj = Heap::AllocateFixedArray(2); | 6314 Object* obj = Heap::AllocateFixedArray(2); |
| 6305 if (obj->IsFailure()) return obj; | 6315 if (obj->IsFailure()) return obj; |
| 6306 FixedArray* pair = FixedArray::cast(obj); | 6316 FixedArray* pair = FixedArray::cast(obj); |
| 6307 pair->set(0, shared_); | 6317 pair->set(0, shared_); |
| 6308 pair->set(1, source_); | 6318 pair->set(1, source_); |
| 6309 return pair; | 6319 return pair; |
| 6310 } | 6320 } |
| 6311 | 6321 |
| 6312 virtual bool IsStringKey() { return false; } | |
| 6313 | |
| 6314 private: | 6322 private: |
| 6315 String* source_; | 6323 String* source_; |
| 6316 SharedFunctionInfo* shared_; | 6324 SharedFunctionInfo* shared_; |
| 6317 }; | 6325 }; |
| 6318 | 6326 |
| 6319 | 6327 |
| 6320 // RegExpKey carries the source and flags of a regular expression as key. | 6328 // RegExpKey carries the source and flags of a regular expression as key. |
| 6321 class RegExpKey : public HashTableKey { | 6329 class RegExpKey : public HashTableKey { |
| 6322 public: | 6330 public: |
| 6323 RegExpKey(String* string, JSRegExp::Flags flags) | 6331 RegExpKey(String* string, JSRegExp::Flags flags) |
| 6324 : string_(string), | 6332 : string_(string), |
| 6325 flags_(Smi::FromInt(flags.value())) { } | 6333 flags_(Smi::FromInt(flags.value())) { } |
| 6326 | 6334 |
| 6327 bool IsMatch(Object* obj) { | 6335 bool IsMatch(Object* obj) { |
| 6328 FixedArray* val = FixedArray::cast(obj); | 6336 FixedArray* val = FixedArray::cast(obj); |
| 6329 return string_->Equals(String::cast(val->get(JSRegExp::kSourceIndex))) | 6337 return string_->Equals(String::cast(val->get(JSRegExp::kSourceIndex))) |
| 6330 && (flags_ == val->get(JSRegExp::kFlagsIndex)); | 6338 && (flags_ == val->get(JSRegExp::kFlagsIndex)); |
| 6331 } | 6339 } |
| 6332 | 6340 |
| 6333 uint32_t Hash() { return RegExpHash(string_, flags_); } | 6341 uint32_t Hash() { return RegExpHash(string_, flags_); } |
| 6334 | 6342 |
| 6335 HashFunction GetHashFunction() { return RegExpObjectHash; } | 6343 Object* AsObject() { |
| 6336 | |
| 6337 Object* GetObject() { | |
| 6338 // Plain hash maps, which is where regexp keys are used, don't | 6344 // Plain hash maps, which is where regexp keys are used, don't |
| 6339 // use this function. | 6345 // use this function. |
| 6340 UNREACHABLE(); | 6346 UNREACHABLE(); |
| 6341 return NULL; | 6347 return NULL; |
| 6342 } | 6348 } |
| 6343 | 6349 |
| 6344 static uint32_t RegExpObjectHash(Object* obj) { | 6350 uint32_t HashForObject(Object* obj) { |
| 6345 FixedArray* val = FixedArray::cast(obj); | 6351 FixedArray* val = FixedArray::cast(obj); |
| 6346 return RegExpHash(String::cast(val->get(JSRegExp::kSourceIndex)), | 6352 return RegExpHash(String::cast(val->get(JSRegExp::kSourceIndex)), |
| 6347 Smi::cast(val->get(JSRegExp::kFlagsIndex))); | 6353 Smi::cast(val->get(JSRegExp::kFlagsIndex))); |
| 6348 } | 6354 } |
| 6349 | 6355 |
| 6350 static uint32_t RegExpHash(String* string, Smi* flags) { | 6356 static uint32_t RegExpHash(String* string, Smi* flags) { |
| 6351 return string->Hash() + flags->value(); | 6357 return string->Hash() + flags->value(); |
| 6352 } | 6358 } |
| 6353 | 6359 |
| 6354 bool IsStringKey() { return false; } | |
| 6355 | |
| 6356 String* string_; | 6360 String* string_; |
| 6357 Smi* flags_; | 6361 Smi* flags_; |
| 6358 }; | 6362 }; |
| 6359 | 6363 |
| 6360 // Utf8SymbolKey carries a vector of chars as key. | 6364 // Utf8SymbolKey carries a vector of chars as key. |
| 6361 class Utf8SymbolKey : public HashTableKey { | 6365 class Utf8SymbolKey : public HashTableKey { |
| 6362 public: | 6366 public: |
| 6363 explicit Utf8SymbolKey(Vector<const char> string) | 6367 explicit Utf8SymbolKey(Vector<const char> string) |
| 6364 : string_(string), length_field_(0) { } | 6368 : string_(string), length_field_(0) { } |
| 6365 | 6369 |
| 6366 bool IsMatch(Object* string) { | 6370 bool IsMatch(Object* string) { |
| 6367 return String::cast(string)->IsEqualTo(string_); | 6371 return String::cast(string)->IsEqualTo(string_); |
| 6368 } | 6372 } |
| 6369 | 6373 |
| 6370 HashFunction GetHashFunction() { | |
| 6371 return StringHash; | |
| 6372 } | |
| 6373 | |
| 6374 uint32_t Hash() { | 6374 uint32_t Hash() { |
| 6375 if (length_field_ != 0) return length_field_ >> String::kHashShift; | 6375 if (length_field_ != 0) return length_field_ >> String::kHashShift; |
| 6376 unibrow::Utf8InputBuffer<> buffer(string_.start(), | 6376 unibrow::Utf8InputBuffer<> buffer(string_.start(), |
| 6377 static_cast<unsigned>(string_.length())); | 6377 static_cast<unsigned>(string_.length())); |
| 6378 chars_ = buffer.Length(); | 6378 chars_ = buffer.Length(); |
| 6379 length_field_ = String::ComputeLengthAndHashField(&buffer, chars_); | 6379 length_field_ = String::ComputeLengthAndHashField(&buffer, chars_); |
| 6380 uint32_t result = length_field_ >> String::kHashShift; | 6380 uint32_t result = length_field_ >> String::kHashShift; |
| 6381 ASSERT(result != 0); // Ensure that the hash value of 0 is never computed. | 6381 ASSERT(result != 0); // Ensure that the hash value of 0 is never computed. |
| 6382 return result; | 6382 return result; |
| 6383 } | 6383 } |
| 6384 | 6384 |
| 6385 Object* GetObject() { | 6385 uint32_t HashForObject(Object* other) { |
| 6386 return String::cast(other)->Hash(); |
| 6387 } |
| 6388 |
| 6389 Object* AsObject() { |
| 6386 if (length_field_ == 0) Hash(); | 6390 if (length_field_ == 0) Hash(); |
| 6387 return Heap::AllocateSymbol(string_, chars_, length_field_); | 6391 return Heap::AllocateSymbol(string_, chars_, length_field_); |
| 6388 } | 6392 } |
| 6389 | 6393 |
| 6390 static uint32_t StringHash(Object* obj) { | |
| 6391 return String::cast(obj)->Hash(); | |
| 6392 } | |
| 6393 | |
| 6394 bool IsStringKey() { return true; } | |
| 6395 | |
| 6396 Vector<const char> string_; | 6394 Vector<const char> string_; |
| 6397 uint32_t length_field_; | 6395 uint32_t length_field_; |
| 6398 int chars_; // Caches the number of characters when computing the hash code. | 6396 int chars_; // Caches the number of characters when computing the hash code. |
| 6399 }; | 6397 }; |
| 6400 | 6398 |
| 6401 | 6399 |
| 6402 // SymbolKey carries a string/symbol object as key. | 6400 // SymbolKey carries a string/symbol object as key. |
| 6403 class SymbolKey : public HashTableKey { | 6401 class SymbolKey : public HashTableKey { |
| 6404 public: | 6402 public: |
| 6405 explicit SymbolKey(String* string) : string_(string) { } | 6403 explicit SymbolKey(String* string) : string_(string) { } |
| 6406 | 6404 |
| 6407 HashFunction GetHashFunction() { | |
| 6408 return StringHash; | |
| 6409 } | |
| 6410 | |
| 6411 bool IsMatch(Object* string) { | 6405 bool IsMatch(Object* string) { |
| 6412 return String::cast(string)->Equals(string_); | 6406 return String::cast(string)->Equals(string_); |
| 6413 } | 6407 } |
| 6414 | 6408 |
| 6415 uint32_t Hash() { return string_->Hash(); } | 6409 uint32_t Hash() { return string_->Hash(); } |
| 6416 | 6410 |
| 6417 Object* GetObject() { | 6411 uint32_t HashForObject(Object* other) { |
| 6412 return String::cast(other)->Hash(); |
| 6413 } |
| 6414 |
| 6415 Object* AsObject() { |
| 6418 // If the string is a cons string, attempt to flatten it so that | 6416 // If the string is a cons string, attempt to flatten it so that |
| 6419 // symbols will most often be flat strings. | 6417 // symbols will most often be flat strings. |
| 6420 if (StringShape(string_).IsCons()) { | 6418 if (StringShape(string_).IsCons()) { |
| 6421 ConsString* cons_string = ConsString::cast(string_); | 6419 ConsString* cons_string = ConsString::cast(string_); |
| 6422 cons_string->TryFlatten(); | 6420 cons_string->TryFlatten(); |
| 6423 if (cons_string->second()->length() == 0) { | 6421 if (cons_string->second()->length() == 0) { |
| 6424 string_ = cons_string->first(); | 6422 string_ = cons_string->first(); |
| 6425 } | 6423 } |
| 6426 } | 6424 } |
| 6427 // Transform string to symbol if possible. | 6425 // Transform string to symbol if possible. |
| 6428 Map* map = Heap::SymbolMapForString(string_); | 6426 Map* map = Heap::SymbolMapForString(string_); |
| 6429 if (map != NULL) { | 6427 if (map != NULL) { |
| 6430 string_->set_map(map); | 6428 string_->set_map(map); |
| 6431 ASSERT(string_->IsSymbol()); | 6429 ASSERT(string_->IsSymbol()); |
| 6432 return string_; | 6430 return string_; |
| 6433 } | 6431 } |
| 6434 // Otherwise allocate a new symbol. | 6432 // Otherwise allocate a new symbol. |
| 6435 StringInputBuffer buffer(string_); | 6433 StringInputBuffer buffer(string_); |
| 6436 return Heap::AllocateInternalSymbol(&buffer, | 6434 return Heap::AllocateInternalSymbol(&buffer, |
| 6437 string_->length(), | 6435 string_->length(), |
| 6438 string_->length_field()); | 6436 string_->length_field()); |
| 6439 } | 6437 } |
| 6440 | 6438 |
| 6441 static uint32_t StringHash(Object* obj) { | 6439 static uint32_t StringHash(Object* obj) { |
| 6442 return String::cast(obj)->Hash(); | 6440 return String::cast(obj)->Hash(); |
| 6443 } | 6441 } |
| 6444 | 6442 |
| 6445 bool IsStringKey() { return true; } | |
| 6446 | |
| 6447 String* string_; | 6443 String* string_; |
| 6448 }; | 6444 }; |
| 6449 | 6445 |
| 6450 | 6446 |
| 6451 template<int prefix_size, int element_size> | 6447 template<typename Shape, typename Key> |
| 6452 void HashTable<prefix_size, element_size>::IteratePrefix(ObjectVisitor* v) { | 6448 void HashTable<Shape, Key>::IteratePrefix(ObjectVisitor* v) { |
| 6453 IteratePointers(v, 0, kElementsStartOffset); | 6449 IteratePointers(v, 0, kElementsStartOffset); |
| 6454 } | 6450 } |
| 6455 | 6451 |
| 6456 | 6452 |
| 6457 template<int prefix_size, int element_size> | 6453 template<typename Shape, typename Key> |
| 6458 void HashTable<prefix_size, element_size>::IterateElements(ObjectVisitor* v) { | 6454 void HashTable<Shape, Key>::IterateElements(ObjectVisitor* v) { |
| 6459 IteratePointers(v, | 6455 IteratePointers(v, |
| 6460 kElementsStartOffset, | 6456 kElementsStartOffset, |
| 6461 kHeaderSize + length() * kPointerSize); | 6457 kHeaderSize + length() * kPointerSize); |
| 6462 } | 6458 } |
| 6463 | 6459 |
| 6464 | 6460 |
| 6465 template<int prefix_size, int element_size> | 6461 template<typename Shape, typename Key> |
| 6466 Object* HashTable<prefix_size, element_size>::Allocate(int at_least_space_for) { | 6462 Object* HashTable<Shape, Key>::Allocate( |
| 6463 int at_least_space_for) { |
| 6467 int capacity = RoundUpToPowerOf2(at_least_space_for); | 6464 int capacity = RoundUpToPowerOf2(at_least_space_for); |
| 6468 if (capacity < 4) capacity = 4; // Guarantee min capacity. | 6465 if (capacity < 4) capacity = 4; // Guarantee min capacity. |
| 6469 Object* obj = Heap::AllocateHashTable(EntryToIndex(capacity)); | 6466 Object* obj = Heap::AllocateHashTable(EntryToIndex(capacity)); |
| 6470 if (!obj->IsFailure()) { | 6467 if (!obj->IsFailure()) { |
| 6471 HashTable::cast(obj)->SetNumberOfElements(0); | 6468 HashTable::cast(obj)->SetNumberOfElements(0); |
| 6472 HashTable::cast(obj)->SetCapacity(capacity); | 6469 HashTable::cast(obj)->SetCapacity(capacity); |
| 6473 } | 6470 } |
| 6474 return obj; | 6471 return obj; |
| 6475 } | 6472 } |
| 6476 | 6473 |
| 6477 | 6474 |
| 6475 |
| 6478 // Find entry for key otherwise return -1. | 6476 // Find entry for key otherwise return -1. |
| 6479 template <int prefix_size, int element_size> | 6477 template<typename Shape, typename Key> |
| 6480 int HashTable<prefix_size, element_size>::FindEntry(HashTableKey* key) { | 6478 int HashTable<Shape, Key>::FindEntry(Key key) { |
| 6481 uint32_t nof = NumberOfElements(); | 6479 uint32_t nof = NumberOfElements(); |
| 6482 if (nof == 0) return kNotFound; // Bail out if empty. | 6480 if (nof == 0) return kNotFound; // Bail out if empty. |
| 6483 | 6481 |
| 6484 uint32_t capacity = Capacity(); | 6482 uint32_t capacity = Capacity(); |
| 6485 uint32_t hash = key->Hash(); | 6483 uint32_t hash = Shape::Hash(key); |
| 6486 uint32_t entry = GetProbe(hash, 0, capacity); | 6484 uint32_t entry = GetProbe(hash, 0, capacity); |
| 6487 | 6485 |
| 6488 Object* element = KeyAt(entry); | 6486 Object* element = KeyAt(entry); |
| 6489 uint32_t passed_elements = 0; | 6487 uint32_t passed_elements = 0; |
| 6490 if (!element->IsNull()) { | 6488 if (!element->IsNull()) { |
| 6491 if (!element->IsUndefined() && key->IsMatch(element)) return entry; | 6489 if (!element->IsUndefined() && Shape::IsMatch(key, element)) return entry; |
| 6492 if (++passed_elements == nof) return kNotFound; | 6490 if (++passed_elements == nof) return kNotFound; |
| 6493 } | 6491 } |
| 6494 for (uint32_t i = 1; !element->IsUndefined(); i++) { | 6492 for (uint32_t i = 1; !element->IsUndefined(); i++) { |
| 6495 entry = GetProbe(hash, i, capacity); | 6493 entry = GetProbe(hash, i, capacity); |
| 6496 element = KeyAt(entry); | 6494 element = KeyAt(entry); |
| 6497 if (!element->IsNull()) { | 6495 if (!element->IsNull()) { |
| 6498 if (!element->IsUndefined() && key->IsMatch(element)) return entry; | 6496 if (!element->IsUndefined() && Shape::IsMatch(key, element)) return entry; |
| 6499 if (++passed_elements == nof) return kNotFound; | 6497 if (++passed_elements == nof) return kNotFound; |
| 6500 } | 6498 } |
| 6501 } | 6499 } |
| 6502 return kNotFound; | 6500 return kNotFound; |
| 6503 } | 6501 } |
| 6504 | 6502 |
| 6505 | 6503 |
| 6506 template<int prefix_size, int element_size> | 6504 template<typename Shape, typename Key> |
| 6507 Object* HashTable<prefix_size, element_size>::EnsureCapacity( | 6505 Object* HashTable<Shape, Key>::EnsureCapacity(int n, Key key) { |
| 6508 int n, HashTableKey* key) { | |
| 6509 int capacity = Capacity(); | 6506 int capacity = Capacity(); |
| 6510 int nof = NumberOfElements() + n; | 6507 int nof = NumberOfElements() + n; |
| 6511 // Make sure 50% is free | 6508 // Make sure 50% is free |
| 6512 if (nof + (nof >> 1) <= capacity) return this; | 6509 if (nof + (nof >> 1) <= capacity) return this; |
| 6513 | 6510 |
| 6514 Object* obj = Allocate(nof * 2); | 6511 Object* obj = Allocate(nof * 2); |
| 6515 if (obj->IsFailure()) return obj; | 6512 if (obj->IsFailure()) return obj; |
| 6516 HashTable* table = HashTable::cast(obj); | 6513 HashTable* table = HashTable::cast(obj); |
| 6517 WriteBarrierMode mode = table->GetWriteBarrierMode(); | 6514 WriteBarrierMode mode = table->GetWriteBarrierMode(); |
| 6518 | 6515 |
| 6519 // Copy prefix to new array. | 6516 // Copy prefix to new array. |
| 6520 for (int i = kPrefixStartIndex; i < kPrefixStartIndex + prefix_size; i++) { | 6517 for (int i = kPrefixStartIndex; |
| 6518 i < kPrefixStartIndex + Shape::kPrefixSize; |
| 6519 i++) { |
| 6521 table->set(i, get(i), mode); | 6520 table->set(i, get(i), mode); |
| 6522 } | 6521 } |
| 6523 // Rehash the elements. | 6522 // Rehash the elements. |
| 6524 uint32_t (*Hash)(Object* key) = key->GetHashFunction(); | |
| 6525 for (int i = 0; i < capacity; i++) { | 6523 for (int i = 0; i < capacity; i++) { |
| 6526 uint32_t from_index = EntryToIndex(i); | 6524 uint32_t from_index = EntryToIndex(i); |
| 6527 Object* key = get(from_index); | 6525 Object* k = get(from_index); |
| 6528 if (IsKey(key)) { | 6526 if (IsKey(k)) { |
| 6527 uint32_t hash = Shape::HashForObject(key, k); |
| 6529 uint32_t insertion_index = | 6528 uint32_t insertion_index = |
| 6530 EntryToIndex(table->FindInsertionEntry(key, Hash(key))); | 6529 EntryToIndex(table->FindInsertionEntry(hash)); |
| 6531 for (int j = 0; j < element_size; j++) { | 6530 for (int j = 0; j < Shape::kEntrySize; j++) { |
| 6532 table->set(insertion_index + j, get(from_index + j), mode); | 6531 table->set(insertion_index + j, get(from_index + j), mode); |
| 6533 } | 6532 } |
| 6534 } | 6533 } |
| 6535 } | 6534 } |
| 6536 table->SetNumberOfElements(NumberOfElements()); | 6535 table->SetNumberOfElements(NumberOfElements()); |
| 6537 return table; | 6536 return table; |
| 6538 } | 6537 } |
| 6539 | 6538 |
| 6540 | 6539 |
| 6541 template<int prefix_size, int element_size> | 6540 template<typename Shape, typename Key> |
| 6542 uint32_t HashTable<prefix_size, element_size>::FindInsertionEntry( | 6541 uint32_t HashTable<Shape, Key>::FindInsertionEntry(uint32_t hash) { |
| 6543 Object* key, | |
| 6544 uint32_t hash) { | |
| 6545 uint32_t capacity = Capacity(); | 6542 uint32_t capacity = Capacity(); |
| 6546 uint32_t entry = GetProbe(hash, 0, capacity); | 6543 uint32_t entry = GetProbe(hash, 0, capacity); |
| 6547 Object* element = KeyAt(entry); | 6544 Object* element = KeyAt(entry); |
| 6548 | 6545 |
| 6549 for (uint32_t i = 1; !(element->IsUndefined() || element->IsNull()); i++) { | 6546 for (uint32_t i = 1; !(element->IsUndefined() || element->IsNull()); i++) { |
| 6550 entry = GetProbe(hash, i, capacity); | 6547 entry = GetProbe(hash, i, capacity); |
| 6551 element = KeyAt(entry); | 6548 element = KeyAt(entry); |
| 6552 } | 6549 } |
| 6553 | 6550 |
| 6554 return entry; | 6551 return entry; |
| 6555 } | 6552 } |
| 6556 | 6553 |
| 6554 // Force instantiation of template instances class. |
| 6555 // Please note this list is compiler dependent. |
| 6557 | 6556 |
| 6558 // Force instantiation of SymbolTable's base class | 6557 template class HashTable<SymbolTableShape, HashTableKey*>; |
| 6559 template class HashTable<0, 1>; | |
| 6560 | 6558 |
| 6559 template class HashTable<CompilationCacheShape, HashTableKey*>; |
| 6561 | 6560 |
| 6562 // Force instantiation of Dictionary's base class | 6561 template class HashTable<MapCacheShape, HashTableKey*>; |
| 6563 template class HashTable<2, 3>; | |
| 6564 | 6562 |
| 6563 template class Dictionary<StringDictionaryShape, String*>; |
| 6565 | 6564 |
| 6566 // Force instantiation of EvalCache's base class | 6565 template class Dictionary<NumberDictionaryShape, uint32_t>; |
| 6567 template class HashTable<0, 2>; | |
| 6568 | 6566 |
| 6567 template Object* Dictionary<NumberDictionaryShape, uint32_t>::Allocate( |
| 6568 int); |
| 6569 |
| 6570 template Object* Dictionary<StringDictionaryShape, String*>::Allocate( |
| 6571 int); |
| 6572 |
| 6573 template Object* Dictionary<NumberDictionaryShape, uint32_t>::AtPut( |
| 6574 uint32_t, Object*); |
| 6575 |
| 6576 template Object* Dictionary<NumberDictionaryShape, uint32_t>::SlowReverseLookup( |
| 6577 Object*); |
| 6578 |
| 6579 template Object* Dictionary<StringDictionaryShape, String*>::SlowReverseLookup( |
| 6580 Object*); |
| 6581 |
| 6582 template void Dictionary<NumberDictionaryShape, uint32_t>::CopyKeysTo( |
| 6583 FixedArray*, PropertyAttributes); |
| 6584 |
| 6585 template Object* Dictionary<StringDictionaryShape, String*>::DeleteProperty( |
| 6586 int, JSObject::DeleteMode); |
| 6587 |
| 6588 template Object* Dictionary<NumberDictionaryShape, uint32_t>::DeleteProperty( |
| 6589 int, JSObject::DeleteMode); |
| 6590 |
| 6591 template void Dictionary<StringDictionaryShape, String*>::CopyKeysTo( |
| 6592 FixedArray*); |
| 6593 |
| 6594 template int |
| 6595 Dictionary<StringDictionaryShape, String*>::NumberOfElementsFilterAttributes( |
| 6596 PropertyAttributes); |
| 6597 |
| 6598 template Object* Dictionary<StringDictionaryShape, String*>::Add( |
| 6599 String*, Object*, PropertyDetails); |
| 6600 |
| 6601 template Object* |
| 6602 Dictionary<StringDictionaryShape, String*>::GenerateNewEnumerationIndices(); |
| 6603 |
| 6604 template int |
| 6605 Dictionary<NumberDictionaryShape, uint32_t>::NumberOfElementsFilterAttributes( |
| 6606 PropertyAttributes); |
| 6607 |
| 6608 template Object* Dictionary<NumberDictionaryShape, uint32_t>::Add( |
| 6609 uint32_t, Object*, PropertyDetails); |
| 6610 |
| 6611 template Object* Dictionary<NumberDictionaryShape, uint32_t>::EnsureCapacity( |
| 6612 int, uint32_t); |
| 6613 |
| 6614 template Object* Dictionary<StringDictionaryShape, String*>::EnsureCapacity( |
| 6615 int, String*); |
| 6616 |
| 6617 template Object* Dictionary<NumberDictionaryShape, uint32_t>::AddEntry( |
| 6618 uint32_t, Object*, PropertyDetails, uint32_t); |
| 6619 |
| 6620 template Object* Dictionary<StringDictionaryShape, String*>::AddEntry( |
| 6621 String*, Object*, PropertyDetails, uint32_t); |
| 6622 |
| 6623 template |
| 6624 int Dictionary<NumberDictionaryShape, uint32_t>::NumberOfEnumElements(); |
| 6625 |
| 6626 template |
| 6627 int Dictionary<StringDictionaryShape, String*>::NumberOfEnumElements(); |
| 6569 | 6628 |
| 6570 // Collates undefined and unexisting elements below limit from position | 6629 // Collates undefined and unexisting elements below limit from position |
| 6571 // zero of the elements. The object stays in Dictionary mode. | 6630 // zero of the elements. The object stays in Dictionary mode. |
| 6572 Object* JSObject::PrepareSlowElementsForSort(uint32_t limit) { | 6631 Object* JSObject::PrepareSlowElementsForSort(uint32_t limit) { |
| 6573 ASSERT(!HasFastElements()); | 6632 ASSERT(!HasFastElements()); |
| 6574 // Must stay in dictionary mode, either because of requires_slow_elements, | 6633 // Must stay in dictionary mode, either because of requires_slow_elements, |
| 6575 // or because we are not going to sort (and therefore compact) all of the | 6634 // or because we are not going to sort (and therefore compact) all of the |
| 6576 // elements. | 6635 // elements. |
| 6577 Dictionary* dict = element_dictionary(); | 6636 NumberDictionary* dict = element_dictionary(); |
| 6578 HeapNumber* result_double = NULL; | 6637 HeapNumber* result_double = NULL; |
| 6579 if (limit > static_cast<uint32_t>(Smi::kMaxValue)) { | 6638 if (limit > static_cast<uint32_t>(Smi::kMaxValue)) { |
| 6580 // Allocate space for result before we start mutating the object. | 6639 // Allocate space for result before we start mutating the object. |
| 6581 Object* new_double = Heap::AllocateHeapNumber(0.0); | 6640 Object* new_double = Heap::AllocateHeapNumber(0.0); |
| 6582 if (new_double->IsFailure()) return new_double; | 6641 if (new_double->IsFailure()) return new_double; |
| 6583 result_double = HeapNumber::cast(new_double); | 6642 result_double = HeapNumber::cast(new_double); |
| 6584 } | 6643 } |
| 6585 | 6644 |
| 6586 int capacity = dict->Capacity(); | 6645 int capacity = dict->Capacity(); |
| 6587 Object* obj = Dictionary::Allocate(dict->Capacity()); | 6646 Object* obj = NumberDictionary::Allocate(dict->Capacity()); |
| 6588 if (obj->IsFailure()) return obj; | 6647 if (obj->IsFailure()) return obj; |
| 6589 Dictionary* new_dict = Dictionary::cast(obj); | 6648 NumberDictionary* new_dict = NumberDictionary::cast(obj); |
| 6590 | 6649 |
| 6591 AssertNoAllocation no_alloc; | 6650 AssertNoAllocation no_alloc; |
| 6592 | 6651 |
| 6593 uint32_t pos = 0; | 6652 uint32_t pos = 0; |
| 6594 uint32_t undefs = 0; | 6653 uint32_t undefs = 0; |
| 6595 for (int i = 0; i < capacity; i++) { | 6654 for (int i = 0; i < capacity; i++) { |
| 6596 Object* k = dict->KeyAt(i); | 6655 Object* k = dict->KeyAt(i); |
| 6597 if (dict->IsKey(k)) { | 6656 if (dict->IsKey(k)) { |
| 6598 ASSERT(k->IsNumber()); | 6657 ASSERT(k->IsNumber()); |
| 6599 ASSERT(!k->IsSmi() || Smi::cast(k)->value() >= 0); | 6658 ASSERT(!k->IsSmi() || Smi::cast(k)->value() >= 0); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6640 | 6699 |
| 6641 | 6700 |
| 6642 // Collects all defined (non-hole) and non-undefined (array) elements at | 6701 // Collects all defined (non-hole) and non-undefined (array) elements at |
| 6643 // the start of the elements array. | 6702 // the start of the elements array. |
| 6644 // If the object is in dictionary mode, it is converted to fast elements | 6703 // If the object is in dictionary mode, it is converted to fast elements |
| 6645 // mode. | 6704 // mode. |
| 6646 Object* JSObject::PrepareElementsForSort(uint32_t limit) { | 6705 Object* JSObject::PrepareElementsForSort(uint32_t limit) { |
| 6647 if (!HasFastElements()) { | 6706 if (!HasFastElements()) { |
| 6648 // Convert to fast elements containing only the existing properties. | 6707 // Convert to fast elements containing only the existing properties. |
| 6649 // Ordering is irrelevant, since we are going to sort anyway. | 6708 // Ordering is irrelevant, since we are going to sort anyway. |
| 6650 Dictionary* dict = element_dictionary(); | 6709 NumberDictionary* dict = element_dictionary(); |
| 6651 if (IsJSArray() || dict->requires_slow_elements() || | 6710 if (IsJSArray() || dict->requires_slow_elements() || |
| 6652 dict->max_number_key() >= limit) { | 6711 dict->max_number_key() >= limit) { |
| 6653 return PrepareSlowElementsForSort(limit); | 6712 return PrepareSlowElementsForSort(limit); |
| 6654 } | 6713 } |
| 6655 // Convert to fast elements. | 6714 // Convert to fast elements. |
| 6656 | 6715 |
| 6657 PretenureFlag tenure = Heap::InNewSpace(this) ? NOT_TENURED: TENURED; | 6716 PretenureFlag tenure = Heap::InNewSpace(this) ? NOT_TENURED: TENURED; |
| 6658 Object* new_array = | 6717 Object* new_array = |
| 6659 Heap::AllocateFixedArray(dict->NumberOfElements(), tenure); | 6718 Heap::AllocateFixedArray(dict->NumberOfElements(), tenure); |
| 6660 if (new_array->IsFailure()) { | 6719 if (new_array->IsFailure()) { |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6780 if (entry != kNotFound) { | 6839 if (entry != kNotFound) { |
| 6781 *s = KeyAt(entry); | 6840 *s = KeyAt(entry); |
| 6782 return this; | 6841 return this; |
| 6783 } | 6842 } |
| 6784 | 6843 |
| 6785 // Adding new symbol. Grow table if needed. | 6844 // Adding new symbol. Grow table if needed. |
| 6786 Object* obj = EnsureCapacity(1, key); | 6845 Object* obj = EnsureCapacity(1, key); |
| 6787 if (obj->IsFailure()) return obj; | 6846 if (obj->IsFailure()) return obj; |
| 6788 | 6847 |
| 6789 // Create symbol object. | 6848 // Create symbol object. |
| 6790 Object* symbol = key->GetObject(); | 6849 Object* symbol = key->AsObject(); |
| 6791 if (symbol->IsFailure()) return symbol; | 6850 if (symbol->IsFailure()) return symbol; |
| 6792 | 6851 |
| 6793 // If the symbol table grew as part of EnsureCapacity, obj is not | 6852 // If the symbol table grew as part of EnsureCapacity, obj is not |
| 6794 // the current symbol table and therefore we cannot use | 6853 // the current symbol table and therefore we cannot use |
| 6795 // SymbolTable::cast here. | 6854 // SymbolTable::cast here. |
| 6796 SymbolTable* table = reinterpret_cast<SymbolTable*>(obj); | 6855 SymbolTable* table = reinterpret_cast<SymbolTable*>(obj); |
| 6797 | 6856 |
| 6798 // Add the new symbol and return it along with the symbol table. | 6857 // Add the new symbol and return it along with the symbol table. |
| 6799 entry = table->FindInsertionEntry(symbol, key->Hash()); | 6858 entry = table->FindInsertionEntry(key->Hash()); |
| 6800 table->set(EntryToIndex(entry), symbol); | 6859 table->set(EntryToIndex(entry), symbol); |
| 6801 table->ElementAdded(); | 6860 table->ElementAdded(); |
| 6802 *s = symbol; | 6861 *s = symbol; |
| 6803 return table; | 6862 return table; |
| 6804 } | 6863 } |
| 6805 | 6864 |
| 6806 | 6865 |
| 6807 Object* CompilationCacheTable::Lookup(String* src) { | 6866 Object* CompilationCacheTable::Lookup(String* src) { |
| 6808 StringKey key(src); | 6867 StringKey key(src); |
| 6809 int entry = FindEntry(&key); | 6868 int entry = FindEntry(&key); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 6829 } | 6888 } |
| 6830 | 6889 |
| 6831 | 6890 |
| 6832 Object* CompilationCacheTable::Put(String* src, Object* value) { | 6891 Object* CompilationCacheTable::Put(String* src, Object* value) { |
| 6833 StringKey key(src); | 6892 StringKey key(src); |
| 6834 Object* obj = EnsureCapacity(1, &key); | 6893 Object* obj = EnsureCapacity(1, &key); |
| 6835 if (obj->IsFailure()) return obj; | 6894 if (obj->IsFailure()) return obj; |
| 6836 | 6895 |
| 6837 CompilationCacheTable* cache = | 6896 CompilationCacheTable* cache = |
| 6838 reinterpret_cast<CompilationCacheTable*>(obj); | 6897 reinterpret_cast<CompilationCacheTable*>(obj); |
| 6839 int entry = cache->FindInsertionEntry(src, key.Hash()); | 6898 int entry = cache->FindInsertionEntry(key.Hash()); |
| 6840 cache->set(EntryToIndex(entry), src); | 6899 cache->set(EntryToIndex(entry), src); |
| 6841 cache->set(EntryToIndex(entry) + 1, value); | 6900 cache->set(EntryToIndex(entry) + 1, value); |
| 6842 cache->ElementAdded(); | 6901 cache->ElementAdded(); |
| 6843 return cache; | 6902 return cache; |
| 6844 } | 6903 } |
| 6845 | 6904 |
| 6846 | 6905 |
| 6847 Object* CompilationCacheTable::PutEval(String* src, | 6906 Object* CompilationCacheTable::PutEval(String* src, |
| 6848 Context* context, | 6907 Context* context, |
| 6849 Object* value) { | 6908 Object* value) { |
| 6850 StringSharedKey key(src, context->closure()->shared()); | 6909 StringSharedKey key(src, context->closure()->shared()); |
| 6851 Object* obj = EnsureCapacity(1, &key); | 6910 Object* obj = EnsureCapacity(1, &key); |
| 6852 if (obj->IsFailure()) return obj; | 6911 if (obj->IsFailure()) return obj; |
| 6853 | 6912 |
| 6854 CompilationCacheTable* cache = | 6913 CompilationCacheTable* cache = |
| 6855 reinterpret_cast<CompilationCacheTable*>(obj); | 6914 reinterpret_cast<CompilationCacheTable*>(obj); |
| 6856 int entry = cache->FindInsertionEntry(src, key.Hash()); | 6915 int entry = cache->FindInsertionEntry(key.Hash()); |
| 6857 | 6916 |
| 6858 Object* k = key.GetObject(); | 6917 Object* k = key.AsObject(); |
| 6859 if (k->IsFailure()) return k; | 6918 if (k->IsFailure()) return k; |
| 6860 | 6919 |
| 6861 cache->set(EntryToIndex(entry), k); | 6920 cache->set(EntryToIndex(entry), k); |
| 6862 cache->set(EntryToIndex(entry) + 1, value); | 6921 cache->set(EntryToIndex(entry) + 1, value); |
| 6863 cache->ElementAdded(); | 6922 cache->ElementAdded(); |
| 6864 return cache; | 6923 return cache; |
| 6865 } | 6924 } |
| 6866 | 6925 |
| 6867 | 6926 |
| 6868 Object* CompilationCacheTable::PutRegExp(String* src, | 6927 Object* CompilationCacheTable::PutRegExp(String* src, |
| 6869 JSRegExp::Flags flags, | 6928 JSRegExp::Flags flags, |
| 6870 FixedArray* value) { | 6929 FixedArray* value) { |
| 6871 RegExpKey key(src, flags); | 6930 RegExpKey key(src, flags); |
| 6872 Object* obj = EnsureCapacity(1, &key); | 6931 Object* obj = EnsureCapacity(1, &key); |
| 6873 if (obj->IsFailure()) return obj; | 6932 if (obj->IsFailure()) return obj; |
| 6874 | 6933 |
| 6875 CompilationCacheTable* cache = | 6934 CompilationCacheTable* cache = |
| 6876 reinterpret_cast<CompilationCacheTable*>(obj); | 6935 reinterpret_cast<CompilationCacheTable*>(obj); |
| 6877 int entry = cache->FindInsertionEntry(value, key.Hash()); | 6936 int entry = cache->FindInsertionEntry(key.Hash()); |
| 6878 cache->set(EntryToIndex(entry), value); | 6937 cache->set(EntryToIndex(entry), value); |
| 6879 cache->set(EntryToIndex(entry) + 1, value); | 6938 cache->set(EntryToIndex(entry) + 1, value); |
| 6880 cache->ElementAdded(); | 6939 cache->ElementAdded(); |
| 6881 return cache; | 6940 return cache; |
| 6882 } | 6941 } |
| 6883 | 6942 |
| 6884 | 6943 |
| 6885 // SymbolsKey used for HashTable where key is array of symbols. | 6944 // SymbolsKey used for HashTable where key is array of symbols. |
| 6886 class SymbolsKey : public HashTableKey { | 6945 class SymbolsKey : public HashTableKey { |
| 6887 public: | 6946 public: |
| 6888 explicit SymbolsKey(FixedArray* symbols) : symbols_(symbols) { } | 6947 explicit SymbolsKey(FixedArray* symbols) : symbols_(symbols) { } |
| 6889 | 6948 |
| 6890 bool IsMatch(Object* symbols) { | 6949 bool IsMatch(Object* symbols) { |
| 6891 FixedArray* o = FixedArray::cast(symbols); | 6950 FixedArray* o = FixedArray::cast(symbols); |
| 6892 int len = symbols_->length(); | 6951 int len = symbols_->length(); |
| 6893 if (o->length() != len) return false; | 6952 if (o->length() != len) return false; |
| 6894 for (int i = 0; i < len; i++) { | 6953 for (int i = 0; i < len; i++) { |
| 6895 if (o->get(i) != symbols_->get(i)) return false; | 6954 if (o->get(i) != symbols_->get(i)) return false; |
| 6896 } | 6955 } |
| 6897 return true; | 6956 return true; |
| 6898 } | 6957 } |
| 6899 | 6958 |
| 6900 uint32_t Hash() { return SymbolsHash(symbols_); } | 6959 uint32_t Hash() { return HashForObject(symbols_); } |
| 6901 | 6960 |
| 6902 HashFunction GetHashFunction() { return SymbolsHash; } | 6961 uint32_t HashForObject(Object* obj) { |
| 6903 | |
| 6904 Object* GetObject() { return symbols_; } | |
| 6905 | |
| 6906 static uint32_t SymbolsHash(Object* obj) { | |
| 6907 FixedArray* symbols = FixedArray::cast(obj); | 6962 FixedArray* symbols = FixedArray::cast(obj); |
| 6908 int len = symbols->length(); | 6963 int len = symbols->length(); |
| 6909 uint32_t hash = 0; | 6964 uint32_t hash = 0; |
| 6910 for (int i = 0; i < len; i++) { | 6965 for (int i = 0; i < len; i++) { |
| 6911 hash ^= String::cast(symbols->get(i))->Hash(); | 6966 hash ^= String::cast(symbols->get(i))->Hash(); |
| 6912 } | 6967 } |
| 6913 return hash; | 6968 return hash; |
| 6914 } | 6969 } |
| 6915 | 6970 |
| 6916 bool IsStringKey() { return false; } | 6971 Object* AsObject() { return symbols_; } |
| 6917 | 6972 |
| 6918 private: | 6973 private: |
| 6919 FixedArray* symbols_; | 6974 FixedArray* symbols_; |
| 6920 }; | 6975 }; |
| 6921 | 6976 |
| 6922 | 6977 |
| 6923 Object* MapCache::Lookup(FixedArray* array) { | 6978 Object* MapCache::Lookup(FixedArray* array) { |
| 6924 SymbolsKey key(array); | 6979 SymbolsKey key(array); |
| 6925 int entry = FindEntry(&key); | 6980 int entry = FindEntry(&key); |
| 6926 if (entry == kNotFound) return Heap::undefined_value(); | 6981 if (entry == kNotFound) return Heap::undefined_value(); |
| 6927 return get(EntryToIndex(entry) + 1); | 6982 return get(EntryToIndex(entry) + 1); |
| 6928 } | 6983 } |
| 6929 | 6984 |
| 6930 | 6985 |
| 6931 Object* MapCache::Put(FixedArray* array, Map* value) { | 6986 Object* MapCache::Put(FixedArray* array, Map* value) { |
| 6932 SymbolsKey key(array); | 6987 SymbolsKey key(array); |
| 6933 Object* obj = EnsureCapacity(1, &key); | 6988 Object* obj = EnsureCapacity(1, &key); |
| 6934 if (obj->IsFailure()) return obj; | 6989 if (obj->IsFailure()) return obj; |
| 6935 | 6990 |
| 6936 MapCache* cache = reinterpret_cast<MapCache*>(obj); | 6991 MapCache* cache = reinterpret_cast<MapCache*>(obj); |
| 6937 int entry = cache->FindInsertionEntry(array, key.Hash()); | 6992 int entry = cache->FindInsertionEntry(key.Hash()); |
| 6938 cache->set(EntryToIndex(entry), array); | 6993 cache->set(EntryToIndex(entry), array); |
| 6939 cache->set(EntryToIndex(entry) + 1, value); | 6994 cache->set(EntryToIndex(entry) + 1, value); |
| 6940 cache->ElementAdded(); | 6995 cache->ElementAdded(); |
| 6941 return cache; | 6996 return cache; |
| 6942 } | 6997 } |
| 6943 | 6998 |
| 6944 | 6999 |
| 6945 Object* Dictionary::Allocate(int at_least_space_for) { | 7000 template<typename Shape, typename Key> |
| 6946 Object* obj = DictionaryBase::Allocate(at_least_space_for); | 7001 Object* Dictionary<Shape, Key>::Allocate(int at_least_space_for) { |
| 7002 Object* obj = HashTable<Shape, Key>::Allocate(at_least_space_for); |
| 6947 // Initialize the next enumeration index. | 7003 // Initialize the next enumeration index. |
| 6948 if (!obj->IsFailure()) { | 7004 if (!obj->IsFailure()) { |
| 6949 Dictionary::cast(obj)-> | 7005 Dictionary<Shape, Key>::cast(obj)-> |
| 6950 SetNextEnumerationIndex(PropertyDetails::kInitialIndex); | 7006 SetNextEnumerationIndex(PropertyDetails::kInitialIndex); |
| 6951 } | 7007 } |
| 6952 return obj; | 7008 return obj; |
| 6953 } | 7009 } |
| 6954 | 7010 |
| 6955 | 7011 |
| 6956 Object* Dictionary::GenerateNewEnumerationIndices() { | 7012 template<typename Shape, typename Key> |
| 6957 int length = NumberOfElements(); | 7013 Object* Dictionary<Shape, Key>::GenerateNewEnumerationIndices() { |
| 7014 int length = HashTable<Shape, Key>::NumberOfElements(); |
| 6958 | 7015 |
| 6959 // Allocate and initialize iteration order array. | 7016 // Allocate and initialize iteration order array. |
| 6960 Object* obj = Heap::AllocateFixedArray(length); | 7017 Object* obj = Heap::AllocateFixedArray(length); |
| 6961 if (obj->IsFailure()) return obj; | 7018 if (obj->IsFailure()) return obj; |
| 6962 FixedArray* iteration_order = FixedArray::cast(obj); | 7019 FixedArray* iteration_order = FixedArray::cast(obj); |
| 6963 for (int i = 0; i < length; i++) { | 7020 for (int i = 0; i < length; i++) { |
| 6964 iteration_order->set(i, Smi::FromInt(i), SKIP_WRITE_BARRIER); | 7021 iteration_order->set(i, Smi::FromInt(i), SKIP_WRITE_BARRIER); |
| 6965 } | 7022 } |
| 6966 | 7023 |
| 6967 // Allocate array with enumeration order. | 7024 // Allocate array with enumeration order. |
| 6968 obj = Heap::AllocateFixedArray(length); | 7025 obj = Heap::AllocateFixedArray(length); |
| 6969 if (obj->IsFailure()) return obj; | 7026 if (obj->IsFailure()) return obj; |
| 6970 FixedArray* enumeration_order = FixedArray::cast(obj); | 7027 FixedArray* enumeration_order = FixedArray::cast(obj); |
| 6971 | 7028 |
| 6972 // Fill the enumeration order array with property details. | 7029 // Fill the enumeration order array with property details. |
| 6973 int capacity = Capacity(); | 7030 int capacity = HashTable<Shape, Key>::Capacity(); |
| 6974 int pos = 0; | 7031 int pos = 0; |
| 6975 for (int i = 0; i < capacity; i++) { | 7032 for (int i = 0; i < capacity; i++) { |
| 6976 if (IsKey(KeyAt(i))) { | 7033 if (Dictionary<Shape, Key>::IsKey(Dictionary<Shape, Key>::KeyAt(i))) { |
| 6977 enumeration_order->set(pos++, | 7034 enumeration_order->set(pos++, |
| 6978 Smi::FromInt(DetailsAt(i).index()), | 7035 Smi::FromInt(DetailsAt(i).index()), |
| 6979 SKIP_WRITE_BARRIER); | 7036 SKIP_WRITE_BARRIER); |
| 6980 } | 7037 } |
| 6981 } | 7038 } |
| 6982 | 7039 |
| 6983 // Sort the arrays wrt. enumeration order. | 7040 // Sort the arrays wrt. enumeration order. |
| 6984 iteration_order->SortPairs(enumeration_order, enumeration_order->length()); | 7041 iteration_order->SortPairs(enumeration_order, enumeration_order->length()); |
| 6985 | 7042 |
| 6986 // Overwrite the enumeration_order with the enumeration indices. | 7043 // Overwrite the enumeration_order with the enumeration indices. |
| 6987 for (int i = 0; i < length; i++) { | 7044 for (int i = 0; i < length; i++) { |
| 6988 int index = Smi::cast(iteration_order->get(i))->value(); | 7045 int index = Smi::cast(iteration_order->get(i))->value(); |
| 6989 int enum_index = PropertyDetails::kInitialIndex + i; | 7046 int enum_index = PropertyDetails::kInitialIndex + i; |
| 6990 enumeration_order->set(index, | 7047 enumeration_order->set(index, |
| 6991 Smi::FromInt(enum_index), | 7048 Smi::FromInt(enum_index), |
| 6992 SKIP_WRITE_BARRIER); | 7049 SKIP_WRITE_BARRIER); |
| 6993 } | 7050 } |
| 6994 | 7051 |
| 6995 // Update the dictionary with new indices. | 7052 // Update the dictionary with new indices. |
| 6996 capacity = Capacity(); | 7053 capacity = HashTable<Shape, Key>::Capacity(); |
| 6997 pos = 0; | 7054 pos = 0; |
| 6998 for (int i = 0; i < capacity; i++) { | 7055 for (int i = 0; i < capacity; i++) { |
| 6999 if (IsKey(KeyAt(i))) { | 7056 if (Dictionary<Shape, Key>::IsKey(Dictionary<Shape, Key>::KeyAt(i))) { |
| 7000 int enum_index = Smi::cast(enumeration_order->get(pos++))->value(); | 7057 int enum_index = Smi::cast(enumeration_order->get(pos++))->value(); |
| 7001 PropertyDetails details = DetailsAt(i); | 7058 PropertyDetails details = DetailsAt(i); |
| 7002 PropertyDetails new_details = | 7059 PropertyDetails new_details = |
| 7003 PropertyDetails(details.attributes(), details.type(), enum_index); | 7060 PropertyDetails(details.attributes(), details.type(), enum_index); |
| 7004 DetailsAtPut(i, new_details); | 7061 DetailsAtPut(i, new_details); |
| 7005 } | 7062 } |
| 7006 } | 7063 } |
| 7007 | 7064 |
| 7008 // Set the next enumeration index. | 7065 // Set the next enumeration index. |
| 7009 SetNextEnumerationIndex(PropertyDetails::kInitialIndex+length); | 7066 SetNextEnumerationIndex(PropertyDetails::kInitialIndex+length); |
| 7010 return this; | 7067 return this; |
| 7011 } | 7068 } |
| 7012 | 7069 |
| 7013 | 7070 template<typename Shape, typename Key> |
| 7014 Object* Dictionary::EnsureCapacity(int n, HashTableKey* key) { | 7071 Object* Dictionary<Shape, Key>::EnsureCapacity(int n, Key key) { |
| 7015 // Check whether there are enough enumeration indices to add n elements. | 7072 // Check whether there are enough enumeration indices to add n elements. |
| 7016 if (key->IsStringKey() && | 7073 if (Shape::kIsEnumerable && |
| 7017 !PropertyDetails::IsValidIndex(NextEnumerationIndex() + n)) { | 7074 !PropertyDetails::IsValidIndex(NextEnumerationIndex() + n)) { |
| 7018 // If not, we generate new indices for the properties. | 7075 // If not, we generate new indices for the properties. |
| 7019 Object* result = GenerateNewEnumerationIndices(); | 7076 Object* result = GenerateNewEnumerationIndices(); |
| 7020 if (result->IsFailure()) return result; | 7077 if (result->IsFailure()) return result; |
| 7021 } | 7078 } |
| 7022 return DictionaryBase::EnsureCapacity(n, key); | 7079 return HashTable<Shape, Key>::EnsureCapacity(n, key); |
| 7023 } | 7080 } |
| 7024 | 7081 |
| 7025 | 7082 |
| 7026 void Dictionary::RemoveNumberEntries(uint32_t from, uint32_t to) { | 7083 void NumberDictionary::RemoveNumberEntries(uint32_t from, uint32_t to) { |
| 7027 // Do nothing if the interval [from, to) is empty. | 7084 // Do nothing if the interval [from, to) is empty. |
| 7028 if (from >= to) return; | 7085 if (from >= to) return; |
| 7029 | 7086 |
| 7030 int removed_entries = 0; | 7087 int removed_entries = 0; |
| 7031 Object* sentinel = Heap::null_value(); | 7088 Object* sentinel = Heap::null_value(); |
| 7032 int capacity = Capacity(); | 7089 int capacity = Capacity(); |
| 7033 for (int i = 0; i < capacity; i++) { | 7090 for (int i = 0; i < capacity; i++) { |
| 7034 Object* key = KeyAt(i); | 7091 Object* key = KeyAt(i); |
| 7035 if (key->IsNumber()) { | 7092 if (key->IsNumber()) { |
| 7036 uint32_t number = static_cast<uint32_t>(key->Number()); | 7093 uint32_t number = static_cast<uint32_t>(key->Number()); |
| 7037 if (from <= number && number < to) { | 7094 if (from <= number && number < to) { |
| 7038 SetEntry(i, sentinel, sentinel, Smi::FromInt(0)); | 7095 SetEntry(i, sentinel, sentinel, Smi::FromInt(0)); |
| 7039 removed_entries++; | 7096 removed_entries++; |
| 7040 } | 7097 } |
| 7041 } | 7098 } |
| 7042 } | 7099 } |
| 7043 | 7100 |
| 7044 // Update the number of elements. | 7101 // Update the number of elements. |
| 7045 SetNumberOfElements(NumberOfElements() - removed_entries); | 7102 SetNumberOfElements(NumberOfElements() - removed_entries); |
| 7046 } | 7103 } |
| 7047 | 7104 |
| 7048 | 7105 |
| 7049 Object* Dictionary::DeleteProperty(int entry, JSObject::DeleteMode mode) { | 7106 template<typename Shape, typename Key> |
| 7107 Object* Dictionary<Shape, Key>::DeleteProperty(int entry, |
| 7108 JSObject::DeleteMode mode) { |
| 7050 PropertyDetails details = DetailsAt(entry); | 7109 PropertyDetails details = DetailsAt(entry); |
| 7051 // Ignore attributes if forcing a deletion. | 7110 // Ignore attributes if forcing a deletion. |
| 7052 if (details.IsDontDelete() && mode == JSObject::NORMAL_DELETION) { | 7111 if (details.IsDontDelete() && mode == JSObject::NORMAL_DELETION) { |
| 7053 return Heap::false_value(); | 7112 return Heap::false_value(); |
| 7054 } | 7113 } |
| 7055 SetEntry(entry, Heap::null_value(), Heap::null_value(), Smi::FromInt(0)); | 7114 SetEntry(entry, Heap::null_value(), Heap::null_value(), Smi::FromInt(0)); |
| 7056 ElementRemoved(); | 7115 HashTable<Shape, Key>::ElementRemoved(); |
| 7057 return Heap::true_value(); | 7116 return Heap::true_value(); |
| 7058 } | 7117 } |
| 7059 | 7118 |
| 7060 | 7119 |
| 7061 int Dictionary::FindStringEntry(String* key) { | 7120 template<typename Shape, typename Key> |
| 7062 StringKey k(key); | 7121 Object* Dictionary<Shape, Key>::AtPut(Key key, Object* value) { |
| 7063 return FindEntry(&k); | |
| 7064 } | |
| 7065 | |
| 7066 | |
| 7067 int Dictionary::FindNumberEntry(uint32_t index) { | |
| 7068 NumberKey k(index); | |
| 7069 return FindEntry(&k); | |
| 7070 } | |
| 7071 | |
| 7072 | |
| 7073 Object* Dictionary::AtPut(HashTableKey* key, Object* value) { | |
| 7074 int entry = FindEntry(key); | 7122 int entry = FindEntry(key); |
| 7075 | 7123 |
| 7076 // If the entry is present set the value; | 7124 // If the entry is present set the value; |
| 7077 if (entry != kNotFound) { | 7125 if (entry != Dictionary<Shape, Key>::kNotFound) { |
| 7078 ValueAtPut(entry, value); | 7126 ValueAtPut(entry, value); |
| 7079 return this; | 7127 return this; |
| 7080 } | 7128 } |
| 7081 | 7129 |
| 7082 // Check whether the dictionary should be extended. | 7130 // Check whether the dictionary should be extended. |
| 7083 Object* obj = EnsureCapacity(1, key); | 7131 Object* obj = EnsureCapacity(1, key); |
| 7084 if (obj->IsFailure()) return obj; | 7132 if (obj->IsFailure()) return obj; |
| 7085 Object* k = key->GetObject(); | 7133 |
| 7134 Object* k = Shape::AsObject(key); |
| 7086 if (k->IsFailure()) return k; | 7135 if (k->IsFailure()) return k; |
| 7087 PropertyDetails details = PropertyDetails(NONE, NORMAL); | 7136 PropertyDetails details = PropertyDetails(NONE, NORMAL); |
| 7088 Dictionary::cast(obj)->AddEntry(k, value, details, key->Hash()); | 7137 return Dictionary<Shape, Key>::cast(obj)-> |
| 7089 return obj; | 7138 AddEntry(key, value, details, Shape::Hash(key)); |
| 7090 } | 7139 } |
| 7091 | 7140 |
| 7092 | 7141 |
| 7093 Object* Dictionary::Add(HashTableKey* key, Object* value, | 7142 template<typename Shape, typename Key> |
| 7094 PropertyDetails details) { | 7143 Object* Dictionary<Shape, Key>::Add(Key key, |
| 7144 Object* value, |
| 7145 PropertyDetails details) { |
| 7146 // Valdate key is absent. |
| 7147 SLOW_ASSERT((FindEntry(key) == Dictionary<Shape, Key>::kNotFound)); |
| 7095 // Check whether the dictionary should be extended. | 7148 // Check whether the dictionary should be extended. |
| 7096 Object* obj = EnsureCapacity(1, key); | 7149 Object* obj = EnsureCapacity(1, key); |
| 7097 if (obj->IsFailure()) return obj; | 7150 if (obj->IsFailure()) return obj; |
| 7098 // Compute the key object. | 7151 return Dictionary<Shape, Key>::cast(obj)-> |
| 7099 Object* k = key->GetObject(); | 7152 AddEntry(key, value, details, Shape::Hash(key)); |
| 7100 if (k->IsFailure()) return k; | |
| 7101 Dictionary::cast(obj)->AddEntry(k, value, details, key->Hash()); | |
| 7102 return obj; | |
| 7103 } | 7153 } |
| 7104 | 7154 |
| 7105 | 7155 |
| 7106 // Add a key, value pair to the dictionary. | 7156 // Add a key, value pair to the dictionary. |
| 7107 void Dictionary::AddEntry(Object* key, | 7157 template<typename Shape, typename Key> |
| 7108 Object* value, | 7158 Object* Dictionary<Shape, Key>::AddEntry(Key key, |
| 7109 PropertyDetails details, | 7159 Object* value, |
| 7110 uint32_t hash) { | 7160 PropertyDetails details, |
| 7111 uint32_t entry = FindInsertionEntry(key, hash); | 7161 uint32_t hash) { |
| 7162 // Compute the key object. |
| 7163 Object* k = Shape::AsObject(key); |
| 7164 if (k->IsFailure()) return k; |
| 7165 |
| 7166 uint32_t entry = Dictionary<Shape, Key>::FindInsertionEntry(hash); |
| 7112 // Insert element at empty or deleted entry | 7167 // Insert element at empty or deleted entry |
| 7113 if (details.index() == 0 && key->IsString()) { | 7168 if (details.index() == 0 && Shape::kIsEnumerable) { |
| 7114 // Assign an enumeration index to the property and update | 7169 // Assign an enumeration index to the property and update |
| 7115 // SetNextEnumerationIndex. | 7170 // SetNextEnumerationIndex. |
| 7116 int index = NextEnumerationIndex(); | 7171 int index = NextEnumerationIndex(); |
| 7117 details = PropertyDetails(details.attributes(), details.type(), index); | 7172 details = PropertyDetails(details.attributes(), details.type(), index); |
| 7118 SetNextEnumerationIndex(index + 1); | 7173 SetNextEnumerationIndex(index + 1); |
| 7119 } | 7174 } |
| 7120 SetEntry(entry, key, value, details); | 7175 SetEntry(entry, k, value, details); |
| 7121 ASSERT(KeyAt(entry)->IsNumber() || KeyAt(entry)->IsString()); | 7176 ASSERT((Dictionary<Shape, Key>::KeyAt(entry)->IsNumber() |
| 7122 ElementAdded(); | 7177 || Dictionary<Shape, Key>::KeyAt(entry)->IsString())); |
| 7178 HashTable<Shape, Key>::ElementAdded(); |
| 7179 return this; |
| 7123 } | 7180 } |
| 7124 | 7181 |
| 7125 | 7182 |
| 7126 void Dictionary::UpdateMaxNumberKey(uint32_t key) { | 7183 void NumberDictionary::UpdateMaxNumberKey(uint32_t key) { |
| 7127 // If the dictionary requires slow elements an element has already | 7184 // If the dictionary requires slow elements an element has already |
| 7128 // been added at a high index. | 7185 // been added at a high index. |
| 7129 if (requires_slow_elements()) return; | 7186 if (requires_slow_elements()) return; |
| 7130 // Check if this index is high enough that we should require slow | 7187 // Check if this index is high enough that we should require slow |
| 7131 // elements. | 7188 // elements. |
| 7132 if (key > kRequiresSlowElementsLimit) { | 7189 if (key > kRequiresSlowElementsLimit) { |
| 7133 set_requires_slow_elements(); | 7190 set_requires_slow_elements(); |
| 7134 return; | 7191 return; |
| 7135 } | 7192 } |
| 7136 // Update max key value. | 7193 // Update max key value. |
| 7137 Object* max_index_object = get(kMaxNumberKeyIndex); | 7194 Object* max_index_object = get(kMaxNumberKeyIndex); |
| 7138 if (!max_index_object->IsSmi() || max_number_key() < key) { | 7195 if (!max_index_object->IsSmi() || max_number_key() < key) { |
| 7139 set(kMaxNumberKeyIndex, | 7196 FixedArray::set(kMaxNumberKeyIndex, |
| 7140 Smi::FromInt(key << kRequiresSlowElementsTagSize), | 7197 Smi::FromInt(key << kRequiresSlowElementsTagSize), |
| 7141 SKIP_WRITE_BARRIER); | 7198 SKIP_WRITE_BARRIER); |
| 7142 } | 7199 } |
| 7143 } | 7200 } |
| 7144 | 7201 |
| 7145 | 7202 |
| 7146 Object* Dictionary::AddStringEntry(String* key, | 7203 Object* NumberDictionary::AddNumberEntry(uint32_t key, |
| 7147 Object* value, | 7204 Object* value, |
| 7148 PropertyDetails details) { | 7205 PropertyDetails details) { |
| 7149 StringKey k(key); | 7206 UpdateMaxNumberKey(key); |
| 7150 SLOW_ASSERT(FindEntry(&k) == kNotFound); | 7207 SLOW_ASSERT(FindEntry(key) == kNotFound); |
| 7151 return Add(&k, value, details); | 7208 return Add(key, value, details); |
| 7152 } | 7209 } |
| 7153 | 7210 |
| 7154 | 7211 |
| 7155 Object* Dictionary::AddNumberEntry(uint32_t key, | 7212 Object* NumberDictionary::AtNumberPut(uint32_t key, Object* value) { |
| 7156 Object* value, | |
| 7157 PropertyDetails details) { | |
| 7158 NumberKey k(key); | |
| 7159 UpdateMaxNumberKey(key); | 7213 UpdateMaxNumberKey(key); |
| 7160 SLOW_ASSERT(FindEntry(&k) == kNotFound); | 7214 return AtPut(key, value); |
| 7161 return Add(&k, value, details); | |
| 7162 } | 7215 } |
| 7163 | 7216 |
| 7164 | 7217 |
| 7165 Object* Dictionary::AtNumberPut(uint32_t key, Object* value) { | 7218 Object* NumberDictionary::Set(uint32_t key, |
| 7166 NumberKey k(key); | 7219 Object* value, |
| 7167 UpdateMaxNumberKey(key); | 7220 PropertyDetails details) { |
| 7168 return AtPut(&k, value); | 7221 int entry = FindEntry(key); |
| 7169 } | 7222 if (entry == kNotFound) return AddNumberEntry(key, value, details); |
| 7170 | |
| 7171 | |
| 7172 Object* Dictionary::SetStringEntry(int entry, | |
| 7173 String* key, | |
| 7174 Object* value, | |
| 7175 PropertyDetails details) { | |
| 7176 // Preserve enumeration index. | 7223 // Preserve enumeration index. |
| 7177 details = PropertyDetails(details.attributes(), | 7224 details = PropertyDetails(details.attributes(), |
| 7178 details.type(), | 7225 details.type(), |
| 7179 DetailsAt(entry).index()); | 7226 DetailsAt(entry).index()); |
| 7180 SetEntry(entry, key, value, details); | 7227 SetEntry(entry, NumberDictionaryShape::AsObject(key), value, details); |
| 7181 return this; | 7228 return this; |
| 7182 } | 7229 } |
| 7183 | 7230 |
| 7184 | 7231 |
| 7185 Object* Dictionary::SetOrAddNumberEntry(uint32_t key, | |
| 7186 Object* value, | |
| 7187 PropertyDetails details) { | |
| 7188 NumberKey k(key); | |
| 7189 int entry = FindEntry(&k); | |
| 7190 if (entry == -1) return AddNumberEntry(key, value, details); | |
| 7191 // Preserve enumeration index. | |
| 7192 details = PropertyDetails(details.attributes(), | |
| 7193 details.type(), | |
| 7194 DetailsAt(entry).index()); | |
| 7195 SetEntry(entry, k.GetObject(), value, details); | |
| 7196 return this; | |
| 7197 } | |
| 7198 | 7232 |
| 7199 | 7233 template<typename Shape, typename Key> |
| 7200 int Dictionary::NumberOfElementsFilterAttributes(PropertyAttributes filter) { | 7234 int Dictionary<Shape, Key>::NumberOfElementsFilterAttributes( |
| 7201 int capacity = Capacity(); | 7235 PropertyAttributes filter) { |
| 7236 int capacity = HashTable<Shape, Key>::Capacity(); |
| 7202 int result = 0; | 7237 int result = 0; |
| 7203 for (int i = 0; i < capacity; i++) { | 7238 for (int i = 0; i < capacity; i++) { |
| 7204 Object* k = KeyAt(i); | 7239 Object* k = HashTable<Shape, Key>::KeyAt(i); |
| 7205 if (IsKey(k)) { | 7240 if (HashTable<Shape, Key>::IsKey(k)) { |
| 7206 PropertyAttributes attr = DetailsAt(i).attributes(); | 7241 PropertyAttributes attr = DetailsAt(i).attributes(); |
| 7207 if ((attr & filter) == 0) result++; | 7242 if ((attr & filter) == 0) result++; |
| 7208 } | 7243 } |
| 7209 } | 7244 } |
| 7210 return result; | 7245 return result; |
| 7211 } | 7246 } |
| 7212 | 7247 |
| 7213 | 7248 |
| 7214 int Dictionary::NumberOfEnumElements() { | 7249 template<typename Shape, typename Key> |
| 7250 int Dictionary<Shape, Key>::NumberOfEnumElements() { |
| 7215 return NumberOfElementsFilterAttributes( | 7251 return NumberOfElementsFilterAttributes( |
| 7216 static_cast<PropertyAttributes>(DONT_ENUM)); | 7252 static_cast<PropertyAttributes>(DONT_ENUM)); |
| 7217 } | 7253 } |
| 7218 | 7254 |
| 7219 | 7255 |
| 7220 void Dictionary::CopyKeysTo(FixedArray* storage, PropertyAttributes filter) { | 7256 template<typename Shape, typename Key> |
| 7257 void Dictionary<Shape, Key>::CopyKeysTo(FixedArray* storage, |
| 7258 PropertyAttributes filter) { |
| 7221 ASSERT(storage->length() >= NumberOfEnumElements()); | 7259 ASSERT(storage->length() >= NumberOfEnumElements()); |
| 7222 int capacity = Capacity(); | 7260 int capacity = HashTable<Shape, Key>::Capacity(); |
| 7223 int index = 0; | 7261 int index = 0; |
| 7224 for (int i = 0; i < capacity; i++) { | 7262 for (int i = 0; i < capacity; i++) { |
| 7225 Object* k = KeyAt(i); | 7263 Object* k = HashTable<Shape, Key>::KeyAt(i); |
| 7226 if (IsKey(k)) { | 7264 if (HashTable<Shape, Key>::IsKey(k)) { |
| 7227 PropertyAttributes attr = DetailsAt(i).attributes(); | 7265 PropertyAttributes attr = DetailsAt(i).attributes(); |
| 7228 if ((attr & filter) == 0) storage->set(index++, k); | 7266 if ((attr & filter) == 0) storage->set(index++, k); |
| 7229 } | 7267 } |
| 7230 } | 7268 } |
| 7231 storage->SortPairs(storage, index); | 7269 storage->SortPairs(storage, index); |
| 7232 ASSERT(storage->length() >= index); | 7270 ASSERT(storage->length() >= index); |
| 7233 } | 7271 } |
| 7234 | 7272 |
| 7235 | 7273 |
| 7236 void Dictionary::CopyEnumKeysTo(FixedArray* storage, FixedArray* sort_array) { | 7274 void StringDictionary::CopyEnumKeysTo(FixedArray* storage, |
| 7275 FixedArray* sort_array) { |
| 7237 ASSERT(storage->length() >= NumberOfEnumElements()); | 7276 ASSERT(storage->length() >= NumberOfEnumElements()); |
| 7238 int capacity = Capacity(); | 7277 int capacity = Capacity(); |
| 7239 int index = 0; | 7278 int index = 0; |
| 7240 for (int i = 0; i < capacity; i++) { | 7279 for (int i = 0; i < capacity; i++) { |
| 7241 Object* k = KeyAt(i); | 7280 Object* k = KeyAt(i); |
| 7242 if (IsKey(k)) { | 7281 if (IsKey(k)) { |
| 7243 PropertyDetails details = DetailsAt(i); | 7282 PropertyDetails details = DetailsAt(i); |
| 7244 if (!details.IsDontEnum()) { | 7283 if (!details.IsDontEnum()) { |
| 7245 storage->set(index, k); | 7284 storage->set(index, k); |
| 7246 sort_array->set(index, | 7285 sort_array->set(index, |
| 7247 Smi::FromInt(details.index()), | 7286 Smi::FromInt(details.index()), |
| 7248 SKIP_WRITE_BARRIER); | 7287 SKIP_WRITE_BARRIER); |
| 7249 index++; | 7288 index++; |
| 7250 } | 7289 } |
| 7251 } | 7290 } |
| 7252 } | 7291 } |
| 7253 storage->SortPairs(sort_array, sort_array->length()); | 7292 storage->SortPairs(sort_array, sort_array->length()); |
| 7254 ASSERT(storage->length() >= index); | 7293 ASSERT(storage->length() >= index); |
| 7255 } | 7294 } |
| 7256 | 7295 |
| 7257 | 7296 |
| 7258 void Dictionary::CopyKeysTo(FixedArray* storage) { | 7297 template<typename Shape, typename Key> |
| 7298 void Dictionary<Shape, Key>::CopyKeysTo(FixedArray* storage) { |
| 7259 ASSERT(storage->length() >= NumberOfElementsFilterAttributes( | 7299 ASSERT(storage->length() >= NumberOfElementsFilterAttributes( |
| 7260 static_cast<PropertyAttributes>(NONE))); | 7300 static_cast<PropertyAttributes>(NONE))); |
| 7261 int capacity = Capacity(); | 7301 int capacity = HashTable<Shape, Key>::Capacity(); |
| 7262 int index = 0; | 7302 int index = 0; |
| 7263 for (int i = 0; i < capacity; i++) { | 7303 for (int i = 0; i < capacity; i++) { |
| 7264 Object* k = KeyAt(i); | 7304 Object* k = HashTable<Shape, Key>::KeyAt(i); |
| 7265 if (IsKey(k)) { | 7305 if (HashTable<Shape, Key>::IsKey(k)) { |
| 7266 storage->set(index++, k); | 7306 storage->set(index++, k); |
| 7267 } | 7307 } |
| 7268 } | 7308 } |
| 7269 ASSERT(storage->length() >= index); | 7309 ASSERT(storage->length() >= index); |
| 7270 } | 7310 } |
| 7271 | 7311 |
| 7272 | 7312 |
| 7273 // Backwards lookup (slow). | 7313 // Backwards lookup (slow). |
| 7274 Object* Dictionary::SlowReverseLookup(Object* value) { | 7314 template<typename Shape, typename Key> |
| 7275 int capacity = Capacity(); | 7315 Object* Dictionary<Shape, Key>::SlowReverseLookup(Object* value) { |
| 7316 int capacity = HashTable<Shape, Key>::Capacity(); |
| 7276 for (int i = 0; i < capacity; i++) { | 7317 for (int i = 0; i < capacity; i++) { |
| 7277 Object* k = KeyAt(i); | 7318 Object* k = HashTable<Shape, Key>::KeyAt(i); |
| 7278 if (IsKey(k)) { | 7319 if (Dictionary<Shape, Key>::IsKey(k)) { |
| 7279 Object* e = ValueAt(i); | 7320 Object* e = ValueAt(i); |
| 7280 if (e->IsJSGlobalPropertyCell()) { | 7321 if (e->IsJSGlobalPropertyCell()) { |
| 7281 e = JSGlobalPropertyCell::cast(e)->value(); | 7322 e = JSGlobalPropertyCell::cast(e)->value(); |
| 7282 } | 7323 } |
| 7283 if (e == value) return k; | 7324 if (e == value) return k; |
| 7284 } | 7325 } |
| 7285 } | 7326 } |
| 7286 return Heap::undefined_value(); | 7327 return Heap::undefined_value(); |
| 7287 } | 7328 } |
| 7288 | 7329 |
| 7289 | 7330 |
| 7290 Object* Dictionary::TransformPropertiesToFastFor(JSObject* obj, | 7331 Object* StringDictionary::TransformPropertiesToFastFor( |
| 7291 int unused_property_fields) { | 7332 JSObject* obj, int unused_property_fields) { |
| 7292 // Make sure we preserve dictionary representation if there are too many | 7333 // Make sure we preserve dictionary representation if there are too many |
| 7293 // descriptors. | 7334 // descriptors. |
| 7294 if (NumberOfElements() > DescriptorArray::kMaxNumberOfDescriptors) return obj; | 7335 if (NumberOfElements() > DescriptorArray::kMaxNumberOfDescriptors) return obj; |
| 7295 | 7336 |
| 7296 // Figure out if it is necessary to generate new enumeration indices. | 7337 // Figure out if it is necessary to generate new enumeration indices. |
| 7297 int max_enumeration_index = | 7338 int max_enumeration_index = |
| 7298 NextEnumerationIndex() + | 7339 NextEnumerationIndex() + |
| 7299 (DescriptorArray::kMaxNumberOfDescriptors - NumberOfElements()); | 7340 (DescriptorArray::kMaxNumberOfDescriptors - |
| 7341 NumberOfElements()); |
| 7300 if (!PropertyDetails::IsValidIndex(max_enumeration_index)) { | 7342 if (!PropertyDetails::IsValidIndex(max_enumeration_index)) { |
| 7301 Object* result = GenerateNewEnumerationIndices(); | 7343 Object* result = GenerateNewEnumerationIndices(); |
| 7302 if (result->IsFailure()) return result; | 7344 if (result->IsFailure()) return result; |
| 7303 } | 7345 } |
| 7304 | 7346 |
| 7305 int instance_descriptor_length = 0; | 7347 int instance_descriptor_length = 0; |
| 7306 int number_of_fields = 0; | 7348 int number_of_fields = 0; |
| 7307 | 7349 |
| 7308 // Compute the length of the instance descriptor. | 7350 // Compute the length of the instance descriptor. |
| 7309 int capacity = Capacity(); | 7351 int capacity = Capacity(); |
| (...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7638 int BreakPointInfo::GetBreakPointCount() { | 7680 int BreakPointInfo::GetBreakPointCount() { |
| 7639 // No break point. | 7681 // No break point. |
| 7640 if (break_point_objects()->IsUndefined()) return 0; | 7682 if (break_point_objects()->IsUndefined()) return 0; |
| 7641 // Single beak point. | 7683 // Single beak point. |
| 7642 if (!break_point_objects()->IsFixedArray()) return 1; | 7684 if (!break_point_objects()->IsFixedArray()) return 1; |
| 7643 // Multiple break points. | 7685 // Multiple break points. |
| 7644 return FixedArray::cast(break_point_objects())->length(); | 7686 return FixedArray::cast(break_point_objects())->length(); |
| 7645 } | 7687 } |
| 7646 #endif | 7688 #endif |
| 7647 | 7689 |
| 7690 |
| 7648 } } // namespace v8::internal | 7691 } } // namespace v8::internal |
| OLD | NEW |