Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(753)

Side by Side Diff: src/objects.cc

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

Powered by Google App Engine
This is Rietveld 408576698