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