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

Side by Side Diff: src/objects.cc

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