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

Side by Side Diff: src/objects.cc

Issue 7348008: Merge up to 8597 to experimental/gc from the bleeding edge. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/gc/
Patch Set: '' Created 9 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 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 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 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
53 #endif 53 #endif
54 54
55 namespace v8 { 55 namespace v8 {
56 namespace internal { 56 namespace internal {
57 57
58 // Getters and setters are stored in a fixed array property. These are 58 // Getters and setters are stored in a fixed array property. These are
59 // constants for their indices. 59 // constants for their indices.
60 const int kGetterIndex = 0; 60 const int kGetterIndex = 0;
61 const int kSetterIndex = 1; 61 const int kSetterIndex = 1;
62 62
63 uint64_t FixedDoubleArray::kHoleNanInt64 = -1;
64 uint64_t FixedDoubleArray::kCanonicalNonHoleNanLower32 = 0x7FF00000;
65 uint64_t FixedDoubleArray::kCanonicalNonHoleNanInt64 =
66 kCanonicalNonHoleNanLower32 << 32;
63 67
64 MUST_USE_RESULT static MaybeObject* CreateJSValue(JSFunction* constructor, 68 MUST_USE_RESULT static MaybeObject* CreateJSValue(JSFunction* constructor,
65 Object* value) { 69 Object* value) {
66 Object* result; 70 Object* result;
67 { MaybeObject* maybe_result = 71 { MaybeObject* maybe_result =
68 constructor->GetHeap()->AllocateJSObject(constructor); 72 constructor->GetHeap()->AllocateJSObject(constructor);
69 if (!maybe_result->ToObject(&result)) return maybe_result; 73 if (!maybe_result->ToObject(&result)) return maybe_result;
70 } 74 }
71 JSValue::cast(result)->set_value(value); 75 JSValue::cast(result)->set_value(value);
72 return result; 76 return result;
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
135 139
136 void Object::Lookup(String* name, LookupResult* result) { 140 void Object::Lookup(String* name, LookupResult* result) {
137 Object* holder = NULL; 141 Object* holder = NULL;
138 if (IsSmi()) { 142 if (IsSmi()) {
139 Context* global_context = Isolate::Current()->context()->global_context(); 143 Context* global_context = Isolate::Current()->context()->global_context();
140 holder = global_context->number_function()->instance_prototype(); 144 holder = global_context->number_function()->instance_prototype();
141 } else { 145 } else {
142 HeapObject* heap_object = HeapObject::cast(this); 146 HeapObject* heap_object = HeapObject::cast(this);
143 if (heap_object->IsJSObject()) { 147 if (heap_object->IsJSObject()) {
144 return JSObject::cast(this)->Lookup(name, result); 148 return JSObject::cast(this)->Lookup(name, result);
149 } else if (heap_object->IsJSProxy()) {
150 return result->HandlerResult();
145 } 151 }
146 Context* global_context = Isolate::Current()->context()->global_context(); 152 Context* global_context = Isolate::Current()->context()->global_context();
147 if (heap_object->IsString()) { 153 if (heap_object->IsString()) {
148 holder = global_context->string_function()->instance_prototype(); 154 holder = global_context->string_function()->instance_prototype();
149 } else if (heap_object->IsHeapNumber()) { 155 } else if (heap_object->IsHeapNumber()) {
150 holder = global_context->number_function()->instance_prototype(); 156 holder = global_context->number_function()->instance_prototype();
151 } else if (heap_object->IsBoolean()) { 157 } else if (heap_object->IsBoolean()) {
152 holder = global_context->boolean_function()->instance_prototype(); 158 holder = global_context->boolean_function()->instance_prototype();
153 } else if (heap_object->IsJSProxy()) {
154 return result->HandlerResult();
155 } 159 }
156 } 160 }
157 ASSERT(holder != NULL); // Cannot handle null or undefined. 161 ASSERT(holder != NULL); // Cannot handle null or undefined.
158 JSObject::cast(holder)->Lookup(name, result); 162 JSObject::cast(holder)->Lookup(name, result);
159 } 163 }
160 164
161 165
162 MaybeObject* Object::GetPropertyWithReceiver(Object* receiver, 166 MaybeObject* Object::GetPropertyWithReceiver(Object* receiver,
163 String* name, 167 String* name,
164 PropertyAttributes* attributes) { 168 PropertyAttributes* attributes) {
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
231 MaybeObject* Object::GetPropertyWithHandler(Object* receiver_raw, 235 MaybeObject* Object::GetPropertyWithHandler(Object* receiver_raw,
232 String* name_raw, 236 String* name_raw,
233 Object* handler_raw) { 237 Object* handler_raw) {
234 Isolate* isolate = name_raw->GetIsolate(); 238 Isolate* isolate = name_raw->GetIsolate();
235 HandleScope scope; 239 HandleScope scope;
236 Handle<Object> receiver(receiver_raw); 240 Handle<Object> receiver(receiver_raw);
237 Handle<Object> name(name_raw); 241 Handle<Object> name(name_raw);
238 Handle<Object> handler(handler_raw); 242 Handle<Object> handler(handler_raw);
239 243
240 // Extract trap function. 244 // Extract trap function.
241 LookupResult lookup; 245 Handle<String> trap_name = isolate->factory()->LookupAsciiSymbol("get");
242 Handle<Object> trap(v8::internal::GetProperty(handler, "get", &lookup)); 246 Handle<Object> trap(v8::internal::GetProperty(handler, trap_name));
243 if (!lookup.IsFound()) { 247 if (trap->IsUndefined()) {
244 // Get the derived `get' property. 248 // Get the derived `get' property.
245 trap = isolate->derived_get_trap(); 249 trap = isolate->derived_get_trap();
246 } 250 }
247 251
248 // Call trap function. 252 // Call trap function.
249 Object** args[] = { receiver.location(), name.location() }; 253 Object** args[] = { receiver.location(), name.location() };
250 bool has_exception; 254 bool has_exception;
251 Handle<Object> result = 255 Handle<Object> result =
252 Execution::Call(trap, handler, ARRAY_SIZE(args), args, &has_exception); 256 Execution::Call(trap, handler, ARRAY_SIZE(args), args, &has_exception);
253 if (has_exception) return Failure::Exception(); 257 if (has_exception) return Failure::Exception();
(...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after
484 { MaybeObject* maybe_new_map = map()->CopyDropDescriptors(); 488 { MaybeObject* maybe_new_map = map()->CopyDropDescriptors();
485 if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map; 489 if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map;
486 } 490 }
487 set_map(Map::cast(new_map)); 491 set_map(Map::cast(new_map));
488 } 492 }
489 JSGlobalPropertyCell* cell = 493 JSGlobalPropertyCell* cell =
490 JSGlobalPropertyCell::cast(dictionary->ValueAt(entry)); 494 JSGlobalPropertyCell::cast(dictionary->ValueAt(entry));
491 cell->set_value(cell->GetHeap()->the_hole_value()); 495 cell->set_value(cell->GetHeap()->the_hole_value());
492 dictionary->DetailsAtPut(entry, details.AsDeleted()); 496 dictionary->DetailsAtPut(entry, details.AsDeleted());
493 } else { 497 } else {
494 return dictionary->DeleteProperty(entry, mode); 498 Object* deleted = dictionary->DeleteProperty(entry, mode);
499 if (deleted == GetHeap()->true_value()) {
500 FixedArray* new_properties = NULL;
501 MaybeObject* maybe_properties = dictionary->Shrink(name);
502 if (!maybe_properties->To(&new_properties)) {
503 return maybe_properties;
504 }
505 set_properties(new_properties);
506 }
507 return deleted;
495 } 508 }
496 } 509 }
497 return GetHeap()->true_value(); 510 return GetHeap()->true_value();
498 } 511 }
499 512
500 513
501 bool JSObject::IsDirty() { 514 bool JSObject::IsDirty() {
502 Object* cons_obj = map()->constructor(); 515 Object* cons_obj = map()->constructor();
503 if (!cons_obj->IsJSFunction()) 516 if (!cons_obj->IsJSFunction())
504 return true; 517 return true;
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
633 if (IsSmi()) { 646 if (IsSmi()) {
634 Heap* heap = Isolate::Current()->heap(); 647 Heap* heap = Isolate::Current()->heap();
635 Context* context = heap->isolate()->context()->global_context(); 648 Context* context = heap->isolate()->context()->global_context();
636 return context->number_function()->instance_prototype(); 649 return context->number_function()->instance_prototype();
637 } 650 }
638 651
639 HeapObject* heap_object = HeapObject::cast(this); 652 HeapObject* heap_object = HeapObject::cast(this);
640 653
641 // The object is either a number, a string, a boolean, 654 // The object is either a number, a string, a boolean,
642 // a real JS object, or a Harmony proxy. 655 // a real JS object, or a Harmony proxy.
643 if (heap_object->IsJSObject() || heap_object->IsJSProxy()) { 656 if (heap_object->IsJSReceiver()) {
644 return heap_object->map()->prototype(); 657 return heap_object->map()->prototype();
645 } 658 }
646 Heap* heap = heap_object->GetHeap(); 659 Heap* heap = heap_object->GetHeap();
647 Context* context = heap->isolate()->context()->global_context(); 660 Context* context = heap->isolate()->context()->global_context();
648 661
649 if (heap_object->IsHeapNumber()) { 662 if (heap_object->IsHeapNumber()) {
650 return context->number_function()->instance_prototype(); 663 return context->number_function()->instance_prototype();
651 } 664 }
652 if (heap_object->IsString()) { 665 if (heap_object->IsString()) {
653 return context->string_function()->instance_prototype(); 666 return context->string_function()->instance_prototype();
(...skipping 529 matching lines...) Expand 10 before | Expand all | Expand 10 after
1183 } 1196 }
1184 break; 1197 break;
1185 } 1198 }
1186 return; 1199 return;
1187 } 1200 }
1188 1201
1189 switch (type) { 1202 switch (type) {
1190 case FIXED_ARRAY_TYPE: 1203 case FIXED_ARRAY_TYPE:
1191 FixedArray::BodyDescriptor::IterateBody(this, object_size, v); 1204 FixedArray::BodyDescriptor::IterateBody(this, object_size, v);
1192 break; 1205 break;
1206 case FIXED_DOUBLE_ARRAY_TYPE:
1207 break;
1193 case JS_OBJECT_TYPE: 1208 case JS_OBJECT_TYPE:
1194 case JS_CONTEXT_EXTENSION_OBJECT_TYPE: 1209 case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
1195 case JS_VALUE_TYPE: 1210 case JS_VALUE_TYPE:
1196 case JS_ARRAY_TYPE: 1211 case JS_ARRAY_TYPE:
1197 case JS_REGEXP_TYPE: 1212 case JS_REGEXP_TYPE:
1198 case JS_GLOBAL_PROXY_TYPE: 1213 case JS_GLOBAL_PROXY_TYPE:
1199 case JS_GLOBAL_OBJECT_TYPE: 1214 case JS_GLOBAL_OBJECT_TYPE:
1200 case JS_BUILTINS_OBJECT_TYPE: 1215 case JS_BUILTINS_OBJECT_TYPE:
1201 case JS_MESSAGE_OBJECT_TYPE: 1216 case JS_MESSAGE_OBJECT_TYPE:
1202 JSObject::BodyDescriptor::IterateBody(this, object_size, v); 1217 JSObject::BodyDescriptor::IterateBody(this, object_size, v);
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
1287 // allocation when producing post-crash stack traces, so we print into a 1302 // allocation when producing post-crash stack traces, so we print into a
1288 // buffer that is plenty big enough for any floating point number, then 1303 // buffer that is plenty big enough for any floating point number, then
1289 // print that using vsnprintf (which may truncate but never allocate if 1304 // print that using vsnprintf (which may truncate but never allocate if
1290 // there is no more space in the buffer). 1305 // there is no more space in the buffer).
1291 EmbeddedVector<char, 100> buffer; 1306 EmbeddedVector<char, 100> buffer;
1292 OS::SNPrintF(buffer, "%.16g", Number()); 1307 OS::SNPrintF(buffer, "%.16g", Number());
1293 accumulator->Add("%s", buffer.start()); 1308 accumulator->Add("%s", buffer.start());
1294 } 1309 }
1295 1310
1296 1311
1297 String* JSObject::class_name() { 1312 String* JSReceiver::class_name() {
1298 if (IsJSFunction()) { 1313 if (IsJSFunction() && IsJSFunctionProxy()) {
1299 return GetHeap()->function_class_symbol(); 1314 return GetHeap()->function_class_symbol();
1300 } 1315 }
1301 if (map()->constructor()->IsJSFunction()) { 1316 if (map()->constructor()->IsJSFunction()) {
1302 JSFunction* constructor = JSFunction::cast(map()->constructor()); 1317 JSFunction* constructor = JSFunction::cast(map()->constructor());
1303 return String::cast(constructor->shared()->instance_class_name()); 1318 return String::cast(constructor->shared()->instance_class_name());
1304 } 1319 }
1305 // If the constructor is not present, return "Object". 1320 // If the constructor is not present, return "Object".
1306 return GetHeap()->Object_symbol(); 1321 return GetHeap()->Object_symbol();
1307 } 1322 }
1308 1323
1309 1324
1310 String* JSObject::constructor_name() { 1325 String* JSReceiver::constructor_name() {
1311 if (map()->constructor()->IsJSFunction()) { 1326 if (map()->constructor()->IsJSFunction()) {
1312 JSFunction* constructor = JSFunction::cast(map()->constructor()); 1327 JSFunction* constructor = JSFunction::cast(map()->constructor());
1313 String* name = String::cast(constructor->shared()->name()); 1328 String* name = String::cast(constructor->shared()->name());
1314 if (name->length() > 0) return name; 1329 if (name->length() > 0) return name;
1315 String* inferred_name = constructor->shared()->inferred_name(); 1330 String* inferred_name = constructor->shared()->inferred_name();
1316 if (inferred_name->length() > 0) return inferred_name; 1331 if (inferred_name->length() > 0) return inferred_name;
1317 Object* proto = GetPrototype(); 1332 Object* proto = GetPrototype();
1318 if (proto->IsJSObject()) return JSObject::cast(proto)->constructor_name(); 1333 if (proto->IsJSObject()) return JSObject::cast(proto)->constructor_name();
1319 } 1334 }
1335 // TODO(rossberg): what about proxies?
1320 // If the constructor is not present, return "Object". 1336 // If the constructor is not present, return "Object".
1321 return GetHeap()->Object_symbol(); 1337 return GetHeap()->Object_symbol();
1322 } 1338 }
1323 1339
1324 1340
1325 MaybeObject* JSObject::AddFastPropertyUsingMap(Map* new_map, 1341 MaybeObject* JSObject::AddFastPropertyUsingMap(Map* new_map,
1326 String* name, 1342 String* name,
1327 Object* value) { 1343 Object* value) {
1328 int index = new_map->PropertyIndexFor(name); 1344 int index = new_map->PropertyIndexFor(name);
1329 if (map()->unused_property_fields() == 0) { 1345 if (map()->unused_property_fields() == 0) {
(...skipping 434 matching lines...) Expand 10 before | Expand all | Expand 10 after
1764 MaybeObject* raw_result = 1780 MaybeObject* raw_result =
1765 this_handle->SetPropertyPostInterceptor(*name_handle, 1781 this_handle->SetPropertyPostInterceptor(*name_handle,
1766 *value_handle, 1782 *value_handle,
1767 attributes, 1783 attributes,
1768 strict_mode); 1784 strict_mode);
1769 RETURN_IF_SCHEDULED_EXCEPTION(isolate); 1785 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
1770 return raw_result; 1786 return raw_result;
1771 } 1787 }
1772 1788
1773 1789
1774 MaybeObject* JSObject::SetProperty(String* name, 1790 MaybeObject* JSReceiver::SetProperty(String* name,
1775 Object* value, 1791 Object* value,
1776 PropertyAttributes attributes, 1792 PropertyAttributes attributes,
1777 StrictModeFlag strict_mode) { 1793 StrictModeFlag strict_mode) {
1778 LookupResult result; 1794 LookupResult result;
1779 LocalLookup(name, &result); 1795 LocalLookup(name, &result);
1780 return SetProperty(&result, name, value, attributes, strict_mode); 1796 return SetProperty(&result, name, value, attributes, strict_mode);
1781 } 1797 }
1782 1798
1783 1799
1784 MaybeObject* JSObject::SetPropertyWithCallback(Object* structure, 1800 MaybeObject* JSObject::SetPropertyWithCallback(Object* structure,
1785 String* name, 1801 String* name,
1786 Object* value, 1802 Object* value,
1787 JSObject* holder, 1803 JSObject* holder,
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
1896 MaybeObject* JSObject::SetElementWithCallbackSetterInPrototypes( 1912 MaybeObject* JSObject::SetElementWithCallbackSetterInPrototypes(
1897 uint32_t index, 1913 uint32_t index,
1898 Object* value, 1914 Object* value,
1899 bool* found, 1915 bool* found,
1900 StrictModeFlag strict_mode) { 1916 StrictModeFlag strict_mode) {
1901 Heap* heap = GetHeap(); 1917 Heap* heap = GetHeap();
1902 for (Object* pt = GetPrototype(); 1918 for (Object* pt = GetPrototype();
1903 pt != heap->null_value(); 1919 pt != heap->null_value();
1904 pt = pt->GetPrototype()) { 1920 pt = pt->GetPrototype()) {
1905 if (!JSObject::cast(pt)->HasDictionaryElements()) { 1921 if (!JSObject::cast(pt)->HasDictionaryElements()) {
1906 continue; 1922 continue;
1907 } 1923 }
1908 NumberDictionary* dictionary = JSObject::cast(pt)->element_dictionary(); 1924 NumberDictionary* dictionary = JSObject::cast(pt)->element_dictionary();
1909 int entry = dictionary->FindEntry(index); 1925 int entry = dictionary->FindEntry(index);
1910 if (entry != NumberDictionary::kNotFound) { 1926 if (entry != NumberDictionary::kNotFound) {
1911 PropertyDetails details = dictionary->DetailsAt(entry); 1927 PropertyDetails details = dictionary->DetailsAt(entry);
1912 if (details.type() == CALLBACKS) { 1928 if (details.type() == CALLBACKS) {
1913 *found = true; 1929 *found = true;
1914 return SetElementWithCallback(dictionary->ValueAt(entry), 1930 return SetElementWithCallback(dictionary->ValueAt(entry),
1915 index, 1931 index,
1916 value, 1932 value,
(...skipping 30 matching lines...) Expand all
1947 cache->Update(descriptors, name, number); 1963 cache->Update(descriptors, name, number);
1948 } 1964 }
1949 if (number != DescriptorArray::kNotFound) { 1965 if (number != DescriptorArray::kNotFound) {
1950 result->DescriptorResult(holder, descriptors->GetDetails(number), number); 1966 result->DescriptorResult(holder, descriptors->GetDetails(number), number);
1951 } else { 1967 } else {
1952 result->NotFound(); 1968 result->NotFound();
1953 } 1969 }
1954 } 1970 }
1955 1971
1956 1972
1973 static JSObject::ElementsKind GetElementsKindFromExternalArrayType(
1974 ExternalArrayType array_type) {
1975 switch (array_type) {
1976 case kExternalByteArray:
1977 return JSObject::EXTERNAL_BYTE_ELEMENTS;
1978 break;
1979 case kExternalUnsignedByteArray:
1980 return JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS;
1981 break;
1982 case kExternalShortArray:
1983 return JSObject::EXTERNAL_SHORT_ELEMENTS;
1984 break;
1985 case kExternalUnsignedShortArray:
1986 return JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS;
1987 break;
1988 case kExternalIntArray:
1989 return JSObject::EXTERNAL_INT_ELEMENTS;
1990 break;
1991 case kExternalUnsignedIntArray:
1992 return JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS;
1993 break;
1994 case kExternalFloatArray:
1995 return JSObject::EXTERNAL_FLOAT_ELEMENTS;
1996 break;
1997 case kExternalDoubleArray:
1998 return JSObject::EXTERNAL_DOUBLE_ELEMENTS;
1999 break;
2000 case kExternalPixelArray:
2001 return JSObject::EXTERNAL_PIXEL_ELEMENTS;
2002 break;
2003 }
2004 UNREACHABLE();
2005 return JSObject::DICTIONARY_ELEMENTS;
2006 }
2007
2008
1957 MaybeObject* Map::GetExternalArrayElementsMap(ExternalArrayType array_type, 2009 MaybeObject* Map::GetExternalArrayElementsMap(ExternalArrayType array_type,
1958 bool safe_to_add_transition) { 2010 bool safe_to_add_transition) {
1959 Heap* current_heap = GetHeap(); 2011 Heap* current_heap = GetHeap();
1960 DescriptorArray* descriptors = instance_descriptors(); 2012 DescriptorArray* descriptors = instance_descriptors();
1961 String* external_array_sentinel_name = current_heap->empty_symbol(); 2013 String* external_array_sentinel_name = current_heap->empty_symbol();
1962 2014
1963 if (safe_to_add_transition) { 2015 if (safe_to_add_transition) {
1964 // It's only safe to manipulate the descriptor array if it would be 2016 // It's only safe to manipulate the descriptor array if it would be
1965 // safe to add a transition. 2017 // safe to add a transition.
1966 2018
(...skipping 22 matching lines...) Expand all
1989 } 2041 }
1990 } 2042 }
1991 2043
1992 // No transition to an existing external array map. Make a new one. 2044 // No transition to an existing external array map. Make a new one.
1993 Object* obj; 2045 Object* obj;
1994 { MaybeObject* maybe_map = CopyDropTransitions(); 2046 { MaybeObject* maybe_map = CopyDropTransitions();
1995 if (!maybe_map->ToObject(&obj)) return maybe_map; 2047 if (!maybe_map->ToObject(&obj)) return maybe_map;
1996 } 2048 }
1997 Map* new_map = Map::cast(obj); 2049 Map* new_map = Map::cast(obj);
1998 2050
1999 new_map->set_has_fast_elements(false); 2051 new_map->set_elements_kind(GetElementsKindFromExternalArrayType(array_type));
2000 new_map->set_has_external_array_elements(true);
2001 GetIsolate()->counters()->map_to_external_array_elements()->Increment(); 2052 GetIsolate()->counters()->map_to_external_array_elements()->Increment();
2002 2053
2003 // Only remember the map transition if the object's map is NOT equal to the 2054 // Only remember the map transition if the object's map is NOT equal to the
2004 // global object_function's map and there is not an already existing 2055 // global object_function's map and there is not an already existing
2005 // non-matching external array transition. 2056 // non-matching external array transition.
2006 bool allow_map_transition = 2057 bool allow_map_transition =
2007 safe_to_add_transition && 2058 safe_to_add_transition &&
2008 (GetIsolate()->context()->global_context()->object_function()->map() != 2059 (GetIsolate()->context()->global_context()->object_function()->map() !=
2009 map()); 2060 map());
2010 if (allow_map_transition) { 2061 if (allow_map_transition) {
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
2146 } 2197 }
2147 2198
2148 HandleScope scope; 2199 HandleScope scope;
2149 Handle<Object> value_handle(value); 2200 Handle<Object> value_handle(value);
2150 Heap* heap = GetHeap(); 2201 Heap* heap = GetHeap();
2151 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_SET); 2202 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_SET);
2152 return *value_handle; 2203 return *value_handle;
2153 } 2204 }
2154 2205
2155 2206
2156 MaybeObject* JSObject::SetProperty(LookupResult* result, 2207 MaybeObject* JSReceiver::SetProperty(LookupResult* result,
2208 String* key,
2209 Object* value,
2210 PropertyAttributes attributes,
2211 StrictModeFlag strict_mode) {
2212 if (result->IsFound() && result->type() == HANDLER) {
2213 return JSProxy::cast(this)->SetPropertyWithHandler(
2214 key, value, attributes, strict_mode);
2215 } else {
2216 return JSObject::cast(this)->SetPropertyForResult(
2217 result, key, value, attributes, strict_mode);
2218 }
2219 }
2220
2221
2222 MUST_USE_RESULT MaybeObject* JSProxy::SetPropertyWithHandler(
2223 String* name_raw,
2224 Object* value_raw,
2225 PropertyAttributes attributes,
2226 StrictModeFlag strict_mode) {
2227 Isolate* isolate = GetIsolate();
2228 HandleScope scope;
2229 Handle<Object> receiver(this);
2230 Handle<Object> name(name_raw);
2231 Handle<Object> value(value_raw);
2232 Handle<Object> handler(this->handler());
2233
2234 // Extract trap function.
2235 Handle<String> trap_name = isolate->factory()->LookupAsciiSymbol("set");
2236 Handle<Object> trap(v8::internal::GetProperty(handler, trap_name));
2237 if (trap->IsUndefined()) {
2238 trap = isolate->derived_set_trap();
2239 }
2240
2241 // Call trap function.
2242 Object** args[] = {
2243 receiver.location(), name.location(), value.location()
2244 };
2245 bool has_exception;
2246 Handle<Object> result =
2247 Execution::Call(trap, handler, ARRAY_SIZE(args), args, &has_exception);
2248 if (has_exception) return Failure::Exception();
2249
2250 return *value;
2251 }
2252
2253
2254 MUST_USE_RESULT PropertyAttributes JSProxy::GetPropertyAttributeWithHandler(
2255 JSReceiver* receiver_raw,
2256 String* name_raw,
2257 bool* has_exception) {
2258 Isolate* isolate = GetIsolate();
2259 HandleScope scope;
2260 Handle<JSReceiver> receiver(receiver_raw);
2261 Handle<Object> name(name_raw);
2262 Handle<Object> handler(this->handler());
2263
2264 // Extract trap function.
2265 Handle<String> trap_name =
2266 isolate->factory()->LookupAsciiSymbol("getPropertyDescriptor");
2267 Handle<Object> trap(v8::internal::GetProperty(handler, trap_name));
2268 if (trap->IsUndefined()) {
2269 Handle<Object> args[] = { handler, trap_name };
2270 Handle<Object> error = isolate->factory()->NewTypeError(
2271 "handler_trap_missing", HandleVector(args, ARRAY_SIZE(args)));
2272 isolate->Throw(*error);
2273 *has_exception = true;
2274 return NONE;
2275 }
2276
2277 // Call trap function.
2278 Object** args[] = { name.location() };
2279 Handle<Object> result =
2280 Execution::Call(trap, handler, ARRAY_SIZE(args), args, has_exception);
2281 if (has_exception) return NONE;
2282
2283 // TODO(rossberg): convert result to PropertyAttributes
2284 USE(result);
2285 return NONE;
2286 }
2287
2288
2289 MaybeObject* JSObject::SetPropertyForResult(LookupResult* result,
2157 String* name, 2290 String* name,
2158 Object* value, 2291 Object* value,
2159 PropertyAttributes attributes, 2292 PropertyAttributes attributes,
2160 StrictModeFlag strict_mode) { 2293 StrictModeFlag strict_mode) {
2161 Heap* heap = GetHeap(); 2294 Heap* heap = GetHeap();
2162 // Make sure that the top context does not change when doing callbacks or 2295 // Make sure that the top context does not change when doing callbacks or
2163 // interceptor calls. 2296 // interceptor calls.
2164 AssertNoContextChange ncc; 2297 AssertNoContextChange ncc;
2165 2298
2166 // Optimization for 2-byte strings often used as keys in a decompression 2299 // Optimization for 2-byte strings often used as keys in a decompression
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after
2431 result = getter(v8::Utils::ToLocal(name_handle), info); 2564 result = getter(v8::Utils::ToLocal(name_handle), info);
2432 } 2565 }
2433 if (!result.IsEmpty()) return DONT_ENUM; 2566 if (!result.IsEmpty()) return DONT_ENUM;
2434 } 2567 }
2435 return holder_handle->GetPropertyAttributePostInterceptor(*receiver_handle, 2568 return holder_handle->GetPropertyAttributePostInterceptor(*receiver_handle,
2436 *name_handle, 2569 *name_handle,
2437 continue_search); 2570 continue_search);
2438 } 2571 }
2439 2572
2440 2573
2441 PropertyAttributes JSObject::GetPropertyAttributeWithReceiver( 2574 PropertyAttributes JSReceiver::GetPropertyAttributeWithReceiver(
2442 JSObject* receiver, 2575 JSReceiver* receiver,
2443 String* key) { 2576 String* key) {
2444 uint32_t index = 0; 2577 uint32_t index = 0;
2445 if (key->AsArrayIndex(&index)) { 2578 if (IsJSObject() && key->AsArrayIndex(&index)) {
2446 if (HasElementWithReceiver(receiver, index)) return NONE; 2579 if (JSObject::cast(this)->HasElementWithReceiver(receiver, index))
2580 return NONE;
2447 return ABSENT; 2581 return ABSENT;
2448 } 2582 }
2449 // Named property. 2583 // Named property.
2450 LookupResult result; 2584 LookupResult result;
2451 Lookup(key, &result); 2585 Lookup(key, &result);
2452 return GetPropertyAttribute(receiver, &result, key, true); 2586 return GetPropertyAttribute(receiver, &result, key, true);
2453 } 2587 }
2454 2588
2455 2589
2456 PropertyAttributes JSObject::GetPropertyAttribute(JSObject* receiver, 2590 PropertyAttributes JSReceiver::GetPropertyAttribute(JSReceiver* receiver,
2457 LookupResult* result, 2591 LookupResult* result,
2458 String* name, 2592 String* name,
2459 bool continue_search) { 2593 bool continue_search) {
2460 // Check access rights if needed. 2594 // Check access rights if needed.
2461 if (IsAccessCheckNeeded()) { 2595 if (IsAccessCheckNeeded()) {
2596 JSObject* this_obj = JSObject::cast(this);
2462 Heap* heap = GetHeap(); 2597 Heap* heap = GetHeap();
2463 if (!heap->isolate()->MayNamedAccess(this, name, v8::ACCESS_HAS)) { 2598 if (!heap->isolate()->MayNamedAccess(this_obj, name, v8::ACCESS_HAS)) {
2464 return GetPropertyAttributeWithFailedAccessCheck(receiver, 2599 return this_obj->GetPropertyAttributeWithFailedAccessCheck(
2465 result, 2600 receiver, result, name, continue_search);
2466 name,
2467 continue_search);
2468 } 2601 }
2469 } 2602 }
2470 if (result->IsProperty()) { 2603 if (result->IsProperty()) {
2471 switch (result->type()) { 2604 switch (result->type()) {
2472 case NORMAL: // fall through 2605 case NORMAL: // fall through
2473 case FIELD: 2606 case FIELD:
2474 case CONSTANT_FUNCTION: 2607 case CONSTANT_FUNCTION:
2475 case CALLBACKS: 2608 case CALLBACKS:
2476 return result->GetAttributes(); 2609 return result->GetAttributes();
2610 case HANDLER: {
2611 // TODO(rossberg): propagate exceptions properly.
2612 bool has_exception = false;
2613 return JSProxy::cast(this)->GetPropertyAttributeWithHandler(
2614 receiver, name, &has_exception);
2615 }
2477 case INTERCEPTOR: 2616 case INTERCEPTOR:
2478 return result->holder()-> 2617 return result->holder()->GetPropertyAttributeWithInterceptor(
2479 GetPropertyAttributeWithInterceptor(receiver, name, continue_search); 2618 JSObject::cast(receiver), name, continue_search);
2480 default: 2619 default:
2481 UNREACHABLE(); 2620 UNREACHABLE();
2482 } 2621 }
2483 } 2622 }
2484 return ABSENT; 2623 return ABSENT;
2485 } 2624 }
2486 2625
2487 2626
2488 PropertyAttributes JSObject::GetLocalPropertyAttribute(String* name) { 2627 PropertyAttributes JSReceiver::GetLocalPropertyAttribute(String* name) {
2489 // Check whether the name is an array index. 2628 // Check whether the name is an array index.
2490 uint32_t index = 0; 2629 uint32_t index = 0;
2491 if (name->AsArrayIndex(&index)) { 2630 if (IsJSObject() && name->AsArrayIndex(&index)) {
2492 if (HasLocalElement(index)) return NONE; 2631 if (JSObject::cast(this)->HasLocalElement(index)) return NONE;
2493 return ABSENT; 2632 return ABSENT;
2494 } 2633 }
2495 // Named property. 2634 // Named property.
2496 LookupResult result; 2635 LookupResult result;
2497 LocalLookup(name, &result); 2636 LocalLookup(name, &result);
2498 return GetPropertyAttribute(this, &result, name, false); 2637 return GetPropertyAttribute(this, &result, name, false);
2499 } 2638 }
2500 2639
2501 2640
2502 MaybeObject* NormalizedMapCache::Get(JSObject* obj, 2641 MaybeObject* NormalizedMapCache::Get(JSObject* obj,
2503 PropertyNormalizationMode mode) { 2642 PropertyNormalizationMode mode) {
2504 Isolate* isolate = obj->GetIsolate(); 2643 Isolate* isolate = obj->GetIsolate();
2505 Map* fast = obj->map(); 2644 Map* fast = obj->map();
2506 int index = Hash(fast) % kEntries; 2645 int index = fast->Hash() % kEntries;
2507 Object* result = get(index); 2646 Object* result = get(index);
2508 if (result->IsMap() && CheckHit(Map::cast(result), fast, mode)) { 2647 if (result->IsMap() &&
2648 Map::cast(result)->EquivalentToForNormalization(fast, mode)) {
2509 #ifdef DEBUG 2649 #ifdef DEBUG
2650 Map::cast(result)->SharedMapVerify();
2510 if (FLAG_enable_slow_asserts) { 2651 if (FLAG_enable_slow_asserts) {
2511 // The cached map should match newly created normalized map bit-by-bit. 2652 // The cached map should match newly created normalized map bit-by-bit.
2512 Object* fresh; 2653 Object* fresh;
2513 { MaybeObject* maybe_fresh = 2654 { MaybeObject* maybe_fresh =
2514 fast->CopyNormalized(mode, SHARED_NORMALIZED_MAP); 2655 fast->CopyNormalized(mode, SHARED_NORMALIZED_MAP);
2515 if (maybe_fresh->ToObject(&fresh)) { 2656 if (maybe_fresh->ToObject(&fresh)) {
2516 ASSERT(memcmp(Map::cast(fresh)->address(), 2657 ASSERT(memcmp(Map::cast(fresh)->address(),
2517 Map::cast(result)->address(), 2658 Map::cast(result)->address(),
2518 Map::kSize) == 0); 2659 Map::kSize) == 0);
2519 } 2660 }
(...skipping 15 matching lines...) Expand all
2535 2676
2536 2677
2537 void NormalizedMapCache::Clear() { 2678 void NormalizedMapCache::Clear() {
2538 int entries = length(); 2679 int entries = length();
2539 for (int i = 0; i != entries; i++) { 2680 for (int i = 0; i != entries; i++) {
2540 set_undefined(i); 2681 set_undefined(i);
2541 } 2682 }
2542 } 2683 }
2543 2684
2544 2685
2545 int NormalizedMapCache::Hash(Map* fast) {
2546 // For performance reasons we only hash the 3 most variable fields of a map:
2547 // constructor, prototype and bit_field2.
2548
2549 // Shift away the tag.
2550 int hash = (static_cast<uint32_t>(
2551 reinterpret_cast<uintptr_t>(fast->constructor())) >> 2);
2552
2553 // XOR-ing the prototype and constructor directly yields too many zero bits
2554 // when the two pointers are close (which is fairly common).
2555 // To avoid this we shift the prototype 4 bits relatively to the constructor.
2556 hash ^= (static_cast<uint32_t>(
2557 reinterpret_cast<uintptr_t>(fast->prototype())) << 2);
2558
2559 return hash ^ (hash >> 16) ^ fast->bit_field2();
2560 }
2561
2562
2563 bool NormalizedMapCache::CheckHit(Map* slow,
2564 Map* fast,
2565 PropertyNormalizationMode mode) {
2566 #ifdef DEBUG
2567 slow->SharedMapVerify();
2568 #endif
2569 return
2570 slow->constructor() == fast->constructor() &&
2571 slow->prototype() == fast->prototype() &&
2572 slow->inobject_properties() == ((mode == CLEAR_INOBJECT_PROPERTIES) ?
2573 0 :
2574 fast->inobject_properties()) &&
2575 slow->instance_type() == fast->instance_type() &&
2576 slow->bit_field() == fast->bit_field() &&
2577 slow->bit_field2() == fast->bit_field2() &&
2578 (slow->bit_field3() & ~(1<<Map::kIsShared)) == fast->bit_field3();
2579 }
2580
2581
2582 MaybeObject* JSObject::UpdateMapCodeCache(String* name, Code* code) { 2686 MaybeObject* JSObject::UpdateMapCodeCache(String* name, Code* code) {
2583 if (map()->is_shared()) { 2687 if (map()->is_shared()) {
2584 // Fast case maps are never marked as shared. 2688 // Fast case maps are never marked as shared.
2585 ASSERT(!HasFastProperties()); 2689 ASSERT(!HasFastProperties());
2586 // Replace the map with an identical copy that can be safely modified. 2690 // Replace the map with an identical copy that can be safely modified.
2587 Object* obj; 2691 Object* obj;
2588 { MaybeObject* maybe_obj = map()->CopyNormalized(KEEP_INOBJECT_PROPERTIES, 2692 { MaybeObject* maybe_obj = map()->CopyNormalized(KEEP_INOBJECT_PROPERTIES,
2589 UNIQUE_NORMALIZED_MAP); 2693 UNIQUE_NORMALIZED_MAP);
2590 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 2694 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
2591 } 2695 }
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
2720 MaybeObject* JSObject::TransformToFastProperties(int unused_property_fields) { 2824 MaybeObject* JSObject::TransformToFastProperties(int unused_property_fields) {
2721 if (HasFastProperties()) return this; 2825 if (HasFastProperties()) return this;
2722 ASSERT(!IsGlobalObject()); 2826 ASSERT(!IsGlobalObject());
2723 return property_dictionary()-> 2827 return property_dictionary()->
2724 TransformPropertiesToFastFor(this, unused_property_fields); 2828 TransformPropertiesToFastFor(this, unused_property_fields);
2725 } 2829 }
2726 2830
2727 2831
2728 MaybeObject* JSObject::NormalizeElements() { 2832 MaybeObject* JSObject::NormalizeElements() {
2729 ASSERT(!HasExternalArrayElements()); 2833 ASSERT(!HasExternalArrayElements());
2730 if (HasDictionaryElements()) return this;
2731 Map* old_map = map();
2732 ASSERT(old_map->has_fast_elements());
2733 2834
2734 Object* obj; 2835 // Find the backing store.
2735 { MaybeObject* maybe_obj = old_map->GetSlowElementsMap(); 2836 FixedArray* array = FixedArray::cast(elements());
2736 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 2837 Map* old_map = array->map();
2838 bool is_arguments =
2839 (old_map == old_map->GetHeap()->non_strict_arguments_elements_map());
2840 if (is_arguments) {
2841 array = FixedArray::cast(array->get(1));
2737 } 2842 }
2738 Map* new_map = Map::cast(obj); 2843 if (array->IsDictionary()) return array;
2739 2844
2740 // Get number of entries. 2845 ASSERT(HasFastElements() || HasFastArgumentsElements());
2741 FixedArray* array = FixedArray::cast(elements()); 2846 // Compute the effective length and allocate a new backing store.
2847 int length = IsJSArray()
2848 ? Smi::cast(JSArray::cast(this)->length())->value()
2849 : array->length();
2850 NumberDictionary* dictionary = NULL;
2851 { Object* object;
2852 MaybeObject* maybe = NumberDictionary::Allocate(length);
2853 if (!maybe->ToObject(&object)) return maybe;
2854 dictionary = NumberDictionary::cast(object);
2855 }
2742 2856
2743 // Compute the effective length. 2857 // Copy the elements to the new backing store.
2744 int length = IsJSArray() ? 2858 bool has_double_elements = old_map->has_fast_double_elements();
2745 Smi::cast(JSArray::cast(this)->length())->value() :
2746 array->length();
2747 { MaybeObject* maybe_obj = NumberDictionary::Allocate(length);
2748 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
2749 }
2750 NumberDictionary* dictionary = NumberDictionary::cast(obj);
2751 // Copy entries.
2752 for (int i = 0; i < length; i++) { 2859 for (int i = 0; i < length; i++) {
2753 Object* value = array->get(i); 2860 Object* value = NULL;
2861 if (has_double_elements) {
2862 FixedDoubleArray* double_array = FixedDoubleArray::cast(array);
2863 if (double_array->is_the_hole(i)) {
2864 value = GetIsolate()->heap()->the_hole_value();
2865 } else {
2866 // Objects must be allocated in the old object space, since the
2867 // overall number of HeapNumbers needed for the conversion might
2868 // exceed the capacity of new space, and we would fail repeatedly
2869 // trying to convert the FixedDoubleArray.
2870 MaybeObject* maybe_value_object =
2871 GetHeap()->AllocateHeapNumber(double_array->get(i), TENURED);
2872 if (!maybe_value_object->ToObject(&value)) return maybe_value_object;
2873 }
2874 } else {
2875 ASSERT(old_map->has_fast_elements());
2876 value = array->get(i);
2877 }
2878 PropertyDetails details = PropertyDetails(NONE, NORMAL);
2754 if (!value->IsTheHole()) { 2879 if (!value->IsTheHole()) {
2755 PropertyDetails details = PropertyDetails(NONE, NORMAL);
2756 Object* result; 2880 Object* result;
2757 { MaybeObject* maybe_result = 2881 MaybeObject* maybe_result =
2758 dictionary->AddNumberEntry(i, array->get(i), details); 2882 dictionary->AddNumberEntry(i, value, details);
2759 if (!maybe_result->ToObject(&result)) return maybe_result; 2883 if (!maybe_result->ToObject(&result)) return maybe_result;
2760 }
2761 dictionary = NumberDictionary::cast(result); 2884 dictionary = NumberDictionary::cast(result);
2762 } 2885 }
2763 } 2886 }
2764 // Switch to using the dictionary as the backing storage for
2765 // elements. Set the new map first to satify the elements type
2766 // assert in set_elements().
2767 set_map(new_map);
2768 set_elements(dictionary);
2769 2887
2770 GetIsolate()->counters()->elements_to_dictionary()->Increment(); 2888 // Switch to using the dictionary as the backing storage for elements.
2889 if (is_arguments) {
2890 FixedArray::cast(elements())->set(1, dictionary);
2891 } else {
2892 // Set the new map first to satify the elements type assert in
2893 // set_elements().
2894 Object* new_map;
2895 MaybeObject* maybe = map()->GetSlowElementsMap();
2896 if (!maybe->ToObject(&new_map)) return maybe;
2897 set_map(Map::cast(new_map));
2898 set_elements(dictionary);
2899 }
2900
2901 old_map->GetHeap()->isolate()->counters()->elements_to_dictionary()->Increment ();
2771 2902
2772 #ifdef DEBUG 2903 #ifdef DEBUG
2773 if (FLAG_trace_normalization) { 2904 if (FLAG_trace_normalization) {
2774 PrintF("Object elements have been normalized:\n"); 2905 PrintF("Object elements have been normalized:\n");
2775 Print(); 2906 Print();
2776 } 2907 }
2777 #endif 2908 #endif
2778 2909
2779 return this; 2910 ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements());
2911 return dictionary;
2780 } 2912 }
2781 2913
2782 2914
2783 MaybeObject* JSObject::DeletePropertyPostInterceptor(String* name, 2915 MaybeObject* JSObject::DeletePropertyPostInterceptor(String* name,
2784 DeleteMode mode) { 2916 DeleteMode mode) {
2785 // Check local property, ignore interceptor. 2917 // Check local property, ignore interceptor.
2786 LookupResult result; 2918 LookupResult result;
2787 LocalLookupRealNamedProperty(name, &result); 2919 LocalLookupRealNamedProperty(name, &result);
2788 if (!result.IsProperty()) return GetHeap()->true_value(); 2920 if (!result.IsProperty()) return GetHeap()->true_value();
2789 2921
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
2843 static_cast<uint32_t>(FixedArray::cast(elements())->length()); 2975 static_cast<uint32_t>(FixedArray::cast(elements())->length());
2844 if (index < length) { 2976 if (index < length) {
2845 FixedArray::cast(elements())->set_the_hole(index); 2977 FixedArray::cast(elements())->set_the_hole(index);
2846 } 2978 }
2847 break; 2979 break;
2848 } 2980 }
2849 case DICTIONARY_ELEMENTS: { 2981 case DICTIONARY_ELEMENTS: {
2850 NumberDictionary* dictionary = element_dictionary(); 2982 NumberDictionary* dictionary = element_dictionary();
2851 int entry = dictionary->FindEntry(index); 2983 int entry = dictionary->FindEntry(index);
2852 if (entry != NumberDictionary::kNotFound) { 2984 if (entry != NumberDictionary::kNotFound) {
2853 return dictionary->DeleteProperty(entry, mode); 2985 Object* deleted = dictionary->DeleteProperty(entry, mode);
2986 if (deleted == GetHeap()->true_value()) {
2987 MaybeObject* maybe_elements = dictionary->Shrink(index);
2988 FixedArray* new_elements = NULL;
2989 if (!maybe_elements->To(&new_elements)) {
2990 return maybe_elements;
2991 }
2992 set_elements(new_elements);
2993 }
2994 return deleted;
2854 } 2995 }
2855 break; 2996 break;
2856 } 2997 }
2857 default: 2998 default:
2858 UNREACHABLE(); 2999 UNREACHABLE();
2859 break; 3000 break;
2860 } 3001 }
2861 return GetHeap()->true_value(); 3002 return GetHeap()->true_value();
2862 } 3003 }
2863 3004
(...skipping 25 matching lines...) Expand all
2889 ASSERT(result->IsBoolean()); 3030 ASSERT(result->IsBoolean());
2890 return *v8::Utils::OpenHandle(*result); 3031 return *v8::Utils::OpenHandle(*result);
2891 } 3032 }
2892 MaybeObject* raw_result = 3033 MaybeObject* raw_result =
2893 this_handle->DeleteElementPostInterceptor(index, NORMAL_DELETION); 3034 this_handle->DeleteElementPostInterceptor(index, NORMAL_DELETION);
2894 RETURN_IF_SCHEDULED_EXCEPTION(isolate); 3035 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
2895 return raw_result; 3036 return raw_result;
2896 } 3037 }
2897 3038
2898 3039
3040 MaybeObject* JSObject::DeleteFastElement(uint32_t index) {
3041 ASSERT(HasFastElements() || HasFastArgumentsElements());
3042 Heap* heap = GetHeap();
3043 FixedArray* backing_store = FixedArray::cast(elements());
3044 if (backing_store->map() == heap->non_strict_arguments_elements_map()) {
3045 backing_store = FixedArray::cast(backing_store->get(1));
3046 } else {
3047 Object* writable;
3048 MaybeObject* maybe = EnsureWritableFastElements();
3049 if (!maybe->ToObject(&writable)) return maybe;
3050 backing_store = FixedArray::cast(writable);
3051 }
3052 uint32_t length = static_cast<uint32_t>(
3053 IsJSArray()
3054 ? Smi::cast(JSArray::cast(this)->length())->value()
3055 : backing_store->length());
3056 if (index < length) {
3057 backing_store->set_the_hole(index);
3058 // If an old space backing store is larger than a certain size and
3059 // has too few used values, normalize it.
3060 // To avoid doing the check on every delete we require at least
3061 // one adjacent hole to the value being deleted.
3062 Object* hole = heap->the_hole_value();
3063 const int kMinLengthForSparsenessCheck = 64;
3064 if (backing_store->length() >= kMinLengthForSparsenessCheck &&
3065 !heap->InNewSpace(backing_store) &&
3066 ((index > 0 && backing_store->get(index - 1) == hole) ||
3067 (index + 1 < length && backing_store->get(index + 1) == hole))) {
3068 int num_used = 0;
3069 for (int i = 0; i < backing_store->length(); ++i) {
3070 if (backing_store->get(i) != hole) ++num_used;
3071 // Bail out early if more than 1/4 is used.
3072 if (4 * num_used > backing_store->length()) break;
3073 }
3074 if (4 * num_used <= backing_store->length()) {
3075 MaybeObject* result = NormalizeElements();
3076 if (result->IsFailure()) return result;
3077 }
3078 }
3079 }
3080 return heap->true_value();
3081 }
3082
3083
3084 MaybeObject* JSObject::DeleteDictionaryElement(uint32_t index,
3085 DeleteMode mode) {
3086 Isolate* isolate = GetIsolate();
3087 Heap* heap = isolate->heap();
3088 FixedArray* backing_store = FixedArray::cast(elements());
3089 bool is_arguments =
3090 (GetElementsKind() == JSObject::NON_STRICT_ARGUMENTS_ELEMENTS);
3091 if (is_arguments) {
3092 backing_store = FixedArray::cast(backing_store->get(1));
3093 }
3094 NumberDictionary* dictionary = NumberDictionary::cast(backing_store);
3095 int entry = dictionary->FindEntry(index);
3096 if (entry != NumberDictionary::kNotFound) {
3097 Object* result = dictionary->DeleteProperty(entry, mode);
3098 if (result == heap->true_value()) {
3099 MaybeObject* maybe_elements = dictionary->Shrink(index);
3100 FixedArray* new_elements = NULL;
3101 if (!maybe_elements->To(&new_elements)) {
3102 return maybe_elements;
3103 }
3104 if (is_arguments) {
3105 FixedArray::cast(elements())->set(1, new_elements);
3106 } else {
3107 set_elements(new_elements);
3108 }
3109 }
3110 if (mode == STRICT_DELETION && result == heap->false_value()) {
3111 // In strict mode, attempting to delete a non-configurable property
3112 // throws an exception.
3113 HandleScope scope(isolate);
3114 Handle<Object> holder(this);
3115 Handle<Object> name = isolate->factory()->NewNumberFromUint(index);
3116 Handle<Object> args[2] = { name, holder };
3117 Handle<Object> error =
3118 isolate->factory()->NewTypeError("strict_delete_property",
3119 HandleVector(args, 2));
3120 return isolate->Throw(*error);
3121 }
3122 }
3123 return heap->true_value();
3124 }
3125
3126
2899 MaybeObject* JSObject::DeleteElement(uint32_t index, DeleteMode mode) { 3127 MaybeObject* JSObject::DeleteElement(uint32_t index, DeleteMode mode) {
2900 Isolate* isolate = GetIsolate(); 3128 Isolate* isolate = GetIsolate();
2901 // Check access rights if needed. 3129 // Check access rights if needed.
2902 if (IsAccessCheckNeeded() && 3130 if (IsAccessCheckNeeded() &&
2903 !isolate->MayIndexedAccess(this, index, v8::ACCESS_DELETE)) { 3131 !isolate->MayIndexedAccess(this, index, v8::ACCESS_DELETE)) {
2904 isolate->ReportFailedAccessCheck(this, v8::ACCESS_DELETE); 3132 isolate->ReportFailedAccessCheck(this, v8::ACCESS_DELETE);
2905 return isolate->heap()->false_value(); 3133 return isolate->heap()->false_value();
2906 } 3134 }
2907 3135
2908 if (IsJSGlobalProxy()) { 3136 if (IsJSGlobalProxy()) {
2909 Object* proto = GetPrototype(); 3137 Object* proto = GetPrototype();
2910 if (proto->IsNull()) return isolate->heap()->false_value(); 3138 if (proto->IsNull()) return isolate->heap()->false_value();
2911 ASSERT(proto->IsJSGlobalObject()); 3139 ASSERT(proto->IsJSGlobalObject());
2912 return JSGlobalObject::cast(proto)->DeleteElement(index, mode); 3140 return JSGlobalObject::cast(proto)->DeleteElement(index, mode);
2913 } 3141 }
2914 3142
2915 if (HasIndexedInterceptor()) { 3143 if (HasIndexedInterceptor()) {
2916 // Skip interceptor if forcing deletion. 3144 // Skip interceptor if forcing deletion.
2917 if (mode == FORCE_DELETION) { 3145 return (mode == FORCE_DELETION)
2918 return DeleteElementPostInterceptor(index, mode); 3146 ? DeleteElementPostInterceptor(index, FORCE_DELETION)
2919 } 3147 : DeleteElementWithInterceptor(index);
2920 return DeleteElementWithInterceptor(index);
2921 } 3148 }
2922 3149
2923 switch (GetElementsKind()) { 3150 switch (GetElementsKind()) {
2924 case FAST_ELEMENTS: { 3151 case FAST_ELEMENTS:
2925 Object* obj; 3152 return DeleteFastElement(index);
2926 { MaybeObject* maybe_obj = EnsureWritableFastElements(); 3153
2927 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 3154 case DICTIONARY_ELEMENTS:
2928 } 3155 return DeleteDictionaryElement(index, mode);
2929 uint32_t length = IsJSArray() ? 3156
2930 static_cast<uint32_t>(Smi::cast(JSArray::cast(this)->length())->value()) : 3157 case FAST_DOUBLE_ELEMENTS: {
2931 static_cast<uint32_t>(FixedArray::cast(elements())->length()); 3158 int length = IsJSArray()
2932 if (index < length) { 3159 ? Smi::cast(JSArray::cast(this)->length())->value()
2933 FixedArray::cast(elements())->set_the_hole(index); 3160 : FixedArray::cast(elements())->length();
3161 if (index < static_cast<uint32_t>(length)) {
3162 FixedDoubleArray::cast(elements())->set_the_hole(index);
2934 } 3163 }
2935 break; 3164 break;
2936 } 3165 }
2937 case EXTERNAL_PIXEL_ELEMENTS: 3166 case EXTERNAL_PIXEL_ELEMENTS:
2938 case EXTERNAL_BYTE_ELEMENTS: 3167 case EXTERNAL_BYTE_ELEMENTS:
2939 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 3168 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
2940 case EXTERNAL_SHORT_ELEMENTS: 3169 case EXTERNAL_SHORT_ELEMENTS:
2941 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 3170 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
2942 case EXTERNAL_INT_ELEMENTS: 3171 case EXTERNAL_INT_ELEMENTS:
2943 case EXTERNAL_UNSIGNED_INT_ELEMENTS: 3172 case EXTERNAL_UNSIGNED_INT_ELEMENTS:
2944 case EXTERNAL_FLOAT_ELEMENTS: 3173 case EXTERNAL_FLOAT_ELEMENTS:
2945 case EXTERNAL_DOUBLE_ELEMENTS: 3174 case EXTERNAL_DOUBLE_ELEMENTS:
2946 // Pixel and external array elements cannot be deleted. Just 3175 // Pixel and external array elements cannot be deleted. Just
2947 // silently ignore here. 3176 // silently ignore here.
2948 break; 3177 break;
2949 case DICTIONARY_ELEMENTS: { 3178
2950 NumberDictionary* dictionary = element_dictionary(); 3179 case NON_STRICT_ARGUMENTS_ELEMENTS: {
2951 int entry = dictionary->FindEntry(index); 3180 FixedArray* parameter_map = FixedArray::cast(elements());
2952 if (entry != NumberDictionary::kNotFound) { 3181 uint32_t length = parameter_map->length();
2953 Object* result = dictionary->DeleteProperty(entry, mode); 3182 Object* probe =
2954 if (mode == STRICT_DELETION && result == 3183 index < (length - 2) ? parameter_map->get(index + 2) : NULL;
2955 isolate->heap()->false_value()) { 3184 if (probe != NULL && !probe->IsTheHole()) {
2956 // In strict mode, deleting a non-configurable property throws 3185 // TODO(kmillikin): We could check if this was the last aliased
2957 // exception. dictionary->DeleteProperty will return false_value() 3186 // parameter, and revert to normal elements in that case. That
2958 // if a non-configurable property is being deleted. 3187 // would enable GC of the context.
2959 HandleScope scope; 3188 parameter_map->set_the_hole(index + 2);
2960 Handle<Object> self(this); 3189 } else {
2961 Handle<Object> i = isolate->factory()->NewNumberFromUint(index); 3190 FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
2962 Handle<Object> args[2] = { i, self }; 3191 if (arguments->IsDictionary()) {
2963 return isolate->Throw(*isolate->factory()->NewTypeError( 3192 return DeleteDictionaryElement(index, mode);
2964 "strict_delete_property", HandleVector(args, 2))); 3193 } else {
3194 return DeleteFastElement(index);
2965 } 3195 }
2966 } 3196 }
2967 break; 3197 break;
2968 } 3198 }
2969 default:
2970 UNREACHABLE();
2971 break;
2972 } 3199 }
2973 return isolate->heap()->true_value(); 3200 return isolate->heap()->true_value();
2974 } 3201 }
2975 3202
2976 3203
2977 MaybeObject* JSObject::DeleteProperty(String* name, DeleteMode mode) { 3204 MaybeObject* JSObject::DeleteProperty(String* name, DeleteMode mode) {
2978 Isolate* isolate = GetIsolate(); 3205 Isolate* isolate = GetIsolate();
2979 // ECMA-262, 3rd, 8.6.2.5 3206 // ECMA-262, 3rd, 8.6.2.5
2980 ASSERT(name->IsString()); 3207 ASSERT(name->IsString());
2981 3208
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
3024 { MaybeObject* maybe_obj = 3251 { MaybeObject* maybe_obj =
3025 NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); 3252 NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
3026 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 3253 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
3027 } 3254 }
3028 // Make sure the properties are normalized before removing the entry. 3255 // Make sure the properties are normalized before removing the entry.
3029 return DeleteNormalizedProperty(name, mode); 3256 return DeleteNormalizedProperty(name, mode);
3030 } 3257 }
3031 } 3258 }
3032 3259
3033 3260
3261 bool JSObject::ReferencesObjectFromElements(FixedArray* elements,
3262 ElementsKind kind,
3263 Object* object) {
3264 ASSERT(kind == FAST_ELEMENTS || kind == DICTIONARY_ELEMENTS);
3265 if (kind == FAST_ELEMENTS) {
3266 int length = IsJSArray()
3267 ? Smi::cast(JSArray::cast(this)->length())->value()
3268 : elements->length();
3269 for (int i = 0; i < length; ++i) {
3270 Object* element = elements->get(i);
3271 if (!element->IsTheHole() && element == object) return true;
3272 }
3273 } else {
3274 Object* key = NumberDictionary::cast(elements)->SlowReverseLookup(object);
3275 if (!key->IsUndefined()) return true;
3276 }
3277 return false;
3278 }
3279
3280
3034 // Check whether this object references another object. 3281 // Check whether this object references another object.
3035 bool JSObject::ReferencesObject(Object* obj) { 3282 bool JSObject::ReferencesObject(Object* obj) {
3036 Map* map_of_this = map(); 3283 Map* map_of_this = map();
3037 Heap* heap = GetHeap(); 3284 Heap* heap = GetHeap();
3038 AssertNoAllocation no_alloc; 3285 AssertNoAllocation no_alloc;
3039 3286
3040 // Is the object the constructor for this object? 3287 // Is the object the constructor for this object?
3041 if (map_of_this->constructor() == obj) { 3288 if (map_of_this->constructor() == obj) {
3042 return true; 3289 return true;
3043 } 3290 }
3044 3291
3045 // Is the object the prototype for this object? 3292 // Is the object the prototype for this object?
3046 if (map_of_this->prototype() == obj) { 3293 if (map_of_this->prototype() == obj) {
3047 return true; 3294 return true;
3048 } 3295 }
3049 3296
3050 // Check if the object is among the named properties. 3297 // Check if the object is among the named properties.
3051 Object* key = SlowReverseLookup(obj); 3298 Object* key = SlowReverseLookup(obj);
3052 if (!key->IsUndefined()) { 3299 if (!key->IsUndefined()) {
3053 return true; 3300 return true;
3054 } 3301 }
3055 3302
3056 // Check if the object is among the indexed properties. 3303 // Check if the object is among the indexed properties.
3057 switch (GetElementsKind()) { 3304 ElementsKind kind = GetElementsKind();
3305 switch (kind) {
3058 case EXTERNAL_PIXEL_ELEMENTS: 3306 case EXTERNAL_PIXEL_ELEMENTS:
3059 case EXTERNAL_BYTE_ELEMENTS: 3307 case EXTERNAL_BYTE_ELEMENTS:
3060 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 3308 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
3061 case EXTERNAL_SHORT_ELEMENTS: 3309 case EXTERNAL_SHORT_ELEMENTS:
3062 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 3310 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
3063 case EXTERNAL_INT_ELEMENTS: 3311 case EXTERNAL_INT_ELEMENTS:
3064 case EXTERNAL_UNSIGNED_INT_ELEMENTS: 3312 case EXTERNAL_UNSIGNED_INT_ELEMENTS:
3065 case EXTERNAL_FLOAT_ELEMENTS: 3313 case EXTERNAL_FLOAT_ELEMENTS:
3066 case EXTERNAL_DOUBLE_ELEMENTS: 3314 case EXTERNAL_DOUBLE_ELEMENTS:
3315 case FAST_DOUBLE_ELEMENTS:
3067 // Raw pixels and external arrays do not reference other 3316 // Raw pixels and external arrays do not reference other
3068 // objects. 3317 // objects.
3069 break; 3318 break;
3070 case FAST_ELEMENTS: { 3319 case FAST_ELEMENTS:
3071 int length = IsJSArray() ? 3320 case DICTIONARY_ELEMENTS: {
3072 Smi::cast(JSArray::cast(this)->length())->value() : 3321 FixedArray* elements = FixedArray::cast(this->elements());
3073 FixedArray::cast(elements())->length(); 3322 if (ReferencesObjectFromElements(elements, kind, obj)) return true;
3074 for (int i = 0; i < length; i++) {
3075 Object* element = FixedArray::cast(elements())->get(i);
3076 if (!element->IsTheHole() && element == obj) {
3077 return true;
3078 }
3079 }
3080 break; 3323 break;
3081 } 3324 }
3082 case DICTIONARY_ELEMENTS: { 3325 case NON_STRICT_ARGUMENTS_ELEMENTS: {
3083 key = element_dictionary()->SlowReverseLookup(obj); 3326 FixedArray* parameter_map = FixedArray::cast(elements());
3084 if (!key->IsUndefined()) { 3327 // Check the mapped parameters.
3085 return true; 3328 int length = parameter_map->length();
3329 for (int i = 2; i < length; ++i) {
3330 Object* value = parameter_map->get(i);
3331 if (!value->IsTheHole() && value == obj) return true;
3086 } 3332 }
3333 // Check the arguments.
3334 FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
3335 kind = arguments->IsDictionary() ? DICTIONARY_ELEMENTS : FAST_ELEMENTS;
3336 if (ReferencesObjectFromElements(arguments, kind, obj)) return true;
3087 break; 3337 break;
3088 } 3338 }
3089 default:
3090 UNREACHABLE();
3091 break;
3092 } 3339 }
3093 3340
3094 // For functions check the context. 3341 // For functions check the context.
3095 if (IsJSFunction()) { 3342 if (IsJSFunction()) {
3096 // Get the constructor function for arguments array. 3343 // Get the constructor function for arguments array.
3097 JSObject* arguments_boilerplate = 3344 JSObject* arguments_boilerplate =
3098 heap->isolate()->context()->global_context()-> 3345 heap->isolate()->context()->global_context()->
3099 arguments_boilerplate(); 3346 arguments_boilerplate();
3100 JSFunction* arguments_function = 3347 JSFunction* arguments_function =
3101 JSFunction::cast(arguments_boilerplate->map()->constructor()); 3348 JSFunction::cast(arguments_boilerplate->map()->constructor());
(...skipping 14 matching lines...) Expand all
3116 if (ctxobj->map()->constructor() == arguments_function) { 3363 if (ctxobj->map()->constructor() == arguments_function) {
3117 if (ctxobj->ReferencesObject(obj)) { 3364 if (ctxobj->ReferencesObject(obj)) {
3118 return true; 3365 return true;
3119 } 3366 }
3120 } else if (ctxobj == obj) { 3367 } else if (ctxobj == obj) {
3121 return true; 3368 return true;
3122 } 3369 }
3123 } 3370 }
3124 } 3371 }
3125 3372
3126 // Check the context extension if any. 3373 // Check the context extension (if any) if it can have references.
3127 if (context->has_extension()) { 3374 if (context->has_extension() && !context->IsCatchContext()) {
3128 return context->extension()->ReferencesObject(obj); 3375 return JSObject::cast(context->extension())->ReferencesObject(obj);
3129 } 3376 }
3130 } 3377 }
3131 3378
3132 // No references to object. 3379 // No references to object.
3133 return false; 3380 return false;
3134 } 3381 }
3135 3382
3136 3383
3137 MaybeObject* JSObject::PreventExtensions() { 3384 MaybeObject* JSObject::PreventExtensions() {
3138 Isolate* isolate = GetIsolate(); 3385 Isolate* isolate = GetIsolate();
3139 if (IsAccessCheckNeeded() && 3386 if (IsAccessCheckNeeded() &&
3140 !isolate->MayNamedAccess(this, 3387 !isolate->MayNamedAccess(this,
3141 isolate->heap()->undefined_value(), 3388 isolate->heap()->undefined_value(),
3142 v8::ACCESS_KEYS)) { 3389 v8::ACCESS_KEYS)) {
3143 isolate->ReportFailedAccessCheck(this, v8::ACCESS_KEYS); 3390 isolate->ReportFailedAccessCheck(this, v8::ACCESS_KEYS);
3144 return isolate->heap()->false_value(); 3391 return isolate->heap()->false_value();
3145 } 3392 }
3146 3393
3147 if (IsJSGlobalProxy()) { 3394 if (IsJSGlobalProxy()) {
3148 Object* proto = GetPrototype(); 3395 Object* proto = GetPrototype();
3149 if (proto->IsNull()) return this; 3396 if (proto->IsNull()) return this;
3150 ASSERT(proto->IsJSGlobalObject()); 3397 ASSERT(proto->IsJSGlobalObject());
3151 return JSObject::cast(proto)->PreventExtensions(); 3398 return JSObject::cast(proto)->PreventExtensions();
3152 } 3399 }
3153 3400
3154 // If there are fast elements we normalize. 3401 // If there are fast elements we normalize.
3155 if (HasFastElements()) { 3402 NumberDictionary* dictionary = NULL;
3156 Object* ok; 3403 { MaybeObject* maybe = NormalizeElements();
3157 { MaybeObject* maybe_ok = NormalizeElements(); 3404 if (!maybe->To<NumberDictionary>(&dictionary)) return maybe;
3158 if (!maybe_ok->ToObject(&ok)) return maybe_ok;
3159 }
3160 } 3405 }
3406 ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements());
3161 // Make sure that we never go back to fast case. 3407 // Make sure that we never go back to fast case.
3162 element_dictionary()->set_requires_slow_elements(); 3408 dictionary->set_requires_slow_elements();
3163 3409
3164 // Do a map transition, other objects with this map may still 3410 // Do a map transition, other objects with this map may still
3165 // be extensible. 3411 // be extensible.
3166 Object* new_map; 3412 Map* new_map;
3167 { MaybeObject* maybe_new_map = map()->CopyDropTransitions(); 3413 { MaybeObject* maybe = map()->CopyDropTransitions();
3168 if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map; 3414 if (!maybe->To<Map>(&new_map)) return maybe;
3169 } 3415 }
3170 Map::cast(new_map)->set_is_extensible(false); 3416 new_map->set_is_extensible(false);
3171 set_map(Map::cast(new_map)); 3417 set_map(new_map);
3172 ASSERT(!map()->is_extensible()); 3418 ASSERT(!map()->is_extensible());
3173 return new_map; 3419 return new_map;
3174 } 3420 }
3175 3421
3176 3422
3177 // Tests for the fast common case for property enumeration: 3423 // Tests for the fast common case for property enumeration:
3178 // - This object and all prototypes has an enum cache (which means that it has 3424 // - This object and all prototypes has an enum cache (which means that it has
3179 // no interceptors and needs no access checks). 3425 // no interceptors and needs no access checks).
3180 // - This object has no elements. 3426 // - This object has no elements.
3181 // - No prototype has enumerable properties/elements. 3427 // - No prototype has enumerable properties/elements.
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
3238 DescriptorArray* descs = instance_descriptors(); 3484 DescriptorArray* descs = instance_descriptors();
3239 for (int i = 0; i < descs->number_of_descriptors(); i++) { 3485 for (int i = 0; i < descs->number_of_descriptors(); i++) {
3240 if (name->Equals(descs->GetKey(i)) && descs->GetType(i) == CALLBACKS) { 3486 if (name->Equals(descs->GetKey(i)) && descs->GetType(i) == CALLBACKS) {
3241 return descs->GetCallbacks(i); 3487 return descs->GetCallbacks(i);
3242 } 3488 }
3243 } 3489 }
3244 return NULL; 3490 return NULL;
3245 } 3491 }
3246 3492
3247 3493
3494 void JSReceiver::LocalLookup(String* name, LookupResult* result) {
3495 if (IsJSProxy()) {
3496 result->HandlerResult();
3497 } else {
3498 JSObject::cast(this)->LocalLookup(name, result);
3499 }
3500 }
3501
3502
3248 void JSObject::LocalLookup(String* name, LookupResult* result) { 3503 void JSObject::LocalLookup(String* name, LookupResult* result) {
3249 ASSERT(name->IsString()); 3504 ASSERT(name->IsString());
3250 3505
3251 Heap* heap = GetHeap(); 3506 Heap* heap = GetHeap();
3252 3507
3253 if (IsJSGlobalProxy()) { 3508 if (IsJSGlobalProxy()) {
3254 Object* proto = GetPrototype(); 3509 Object* proto = GetPrototype();
3255 if (proto->IsNull()) return result->NotFound(); 3510 if (proto->IsNull()) return result->NotFound();
3256 ASSERT(proto->IsJSGlobalObject()); 3511 ASSERT(proto->IsJSGlobalObject());
3257 return JSObject::cast(proto)->LocalLookup(name, result); 3512 return JSObject::cast(proto)->LocalLookup(name, result);
3258 } 3513 }
3259 3514
3260 // Do not use inline caching if the object is a non-global object 3515 // Do not use inline caching if the object is a non-global object
3261 // that requires access checks. 3516 // that requires access checks.
3262 if (!IsJSGlobalProxy() && IsAccessCheckNeeded()) { 3517 if (!IsJSGlobalProxy() && IsAccessCheckNeeded()) {
3263 result->DisallowCaching(); 3518 result->DisallowCaching();
3264 } 3519 }
3265 3520
3266 // Check __proto__ before interceptor. 3521 // Check __proto__ before interceptor.
3267 if (name->Equals(heap->Proto_symbol()) && 3522 if (name->Equals(heap->Proto_symbol()) && !IsJSContextExtensionObject()) {
3268 !IsJSContextExtensionObject()) {
3269 result->ConstantResult(this); 3523 result->ConstantResult(this);
3270 return; 3524 return;
3271 } 3525 }
3272 3526
3273 // Check for lookup interceptor except when bootstrapping. 3527 // Check for lookup interceptor except when bootstrapping.
3274 if (HasNamedInterceptor() && !heap->isolate()->bootstrapper()->IsActive()) { 3528 if (HasNamedInterceptor() && !heap->isolate()->bootstrapper()->IsActive()) {
3275 result->InterceptorResult(this); 3529 result->InterceptorResult(this);
3276 return; 3530 return;
3277 } 3531 }
3278 3532
3279 LocalLookupRealNamedProperty(name, result); 3533 LocalLookupRealNamedProperty(name, result);
3280 } 3534 }
3281 3535
3282 3536
3283 void JSObject::Lookup(String* name, LookupResult* result) { 3537 void JSReceiver::Lookup(String* name, LookupResult* result) {
3284 // Ecma-262 3rd 8.6.2.4 3538 // Ecma-262 3rd 8.6.2.4
3285 Heap* heap = GetHeap(); 3539 Heap* heap = GetHeap();
3286 for (Object* current = this; 3540 for (Object* current = this;
3287 current != heap->null_value(); 3541 current != heap->null_value();
3288 current = JSObject::cast(current)->GetPrototype()) { 3542 current = JSObject::cast(current)->GetPrototype()) {
3289 JSObject::cast(current)->LocalLookup(name, result); 3543 JSObject::cast(current)->LocalLookup(name, result);
3290 if (result->IsProperty()) return; 3544 if (result->IsProperty()) return;
3291 } 3545 }
3292 result->NotFound(); 3546 result->NotFound();
3293 } 3547 }
3294 3548
3295 3549
3296 // Search object and it's prototype chain for callback properties. 3550 // Search object and it's prototype chain for callback properties.
3297 void JSObject::LookupCallback(String* name, LookupResult* result) { 3551 void JSObject::LookupCallback(String* name, LookupResult* result) {
3298 Heap* heap = GetHeap(); 3552 Heap* heap = GetHeap();
3299 for (Object* current = this; 3553 for (Object* current = this;
3300 current != heap->null_value(); 3554 current != heap->null_value();
3301 current = JSObject::cast(current)->GetPrototype()) { 3555 current = JSObject::cast(current)->GetPrototype()) {
3302 JSObject::cast(current)->LocalLookupRealNamedProperty(name, result); 3556 JSObject::cast(current)->LocalLookupRealNamedProperty(name, result);
3303 if (result->IsProperty() && result->type() == CALLBACKS) return; 3557 if (result->IsProperty() && result->type() == CALLBACKS) return;
3304 } 3558 }
3305 result->NotFound(); 3559 result->NotFound();
3306 } 3560 }
3307 3561
3308 3562
3563 // Search for a getter or setter in an elements dictionary. Returns either
3564 // undefined if the element is read-only, or the getter/setter pair (fixed
3565 // array) if there is an existing one, or the hole value if the element does
3566 // not exist or is a normal non-getter/setter data element.
3567 static Object* FindGetterSetterInDictionary(NumberDictionary* dictionary,
3568 uint32_t index,
3569 Heap* heap) {
3570 int entry = dictionary->FindEntry(index);
3571 if (entry != NumberDictionary::kNotFound) {
3572 Object* result = dictionary->ValueAt(entry);
3573 PropertyDetails details = dictionary->DetailsAt(entry);
3574 if (details.IsReadOnly()) return heap->undefined_value();
3575 if (details.type() == CALLBACKS && result->IsFixedArray()) return result;
3576 }
3577 return heap->the_hole_value();
3578 }
3579
3580
3309 MaybeObject* JSObject::DefineGetterSetter(String* name, 3581 MaybeObject* JSObject::DefineGetterSetter(String* name,
3310 PropertyAttributes attributes) { 3582 PropertyAttributes attributes) {
3311 Heap* heap = GetHeap(); 3583 Heap* heap = GetHeap();
3312 // Make sure that the top context does not change when doing callbacks or 3584 // Make sure that the top context does not change when doing callbacks or
3313 // interceptor calls. 3585 // interceptor calls.
3314 AssertNoContextChange ncc; 3586 AssertNoContextChange ncc;
3315 3587
3316 // Try to flatten before operating on the string. 3588 // Try to flatten before operating on the string.
3317 name->TryFlatten(); 3589 name->TryFlatten();
3318 3590
(...skipping 10 matching lines...) Expand all
3329 break; 3601 break;
3330 case EXTERNAL_PIXEL_ELEMENTS: 3602 case EXTERNAL_PIXEL_ELEMENTS:
3331 case EXTERNAL_BYTE_ELEMENTS: 3603 case EXTERNAL_BYTE_ELEMENTS:
3332 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 3604 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
3333 case EXTERNAL_SHORT_ELEMENTS: 3605 case EXTERNAL_SHORT_ELEMENTS:
3334 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 3606 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
3335 case EXTERNAL_INT_ELEMENTS: 3607 case EXTERNAL_INT_ELEMENTS:
3336 case EXTERNAL_UNSIGNED_INT_ELEMENTS: 3608 case EXTERNAL_UNSIGNED_INT_ELEMENTS:
3337 case EXTERNAL_FLOAT_ELEMENTS: 3609 case EXTERNAL_FLOAT_ELEMENTS:
3338 case EXTERNAL_DOUBLE_ELEMENTS: 3610 case EXTERNAL_DOUBLE_ELEMENTS:
3611 case FAST_DOUBLE_ELEMENTS:
3339 // Ignore getters and setters on pixel and external array 3612 // Ignore getters and setters on pixel and external array
3340 // elements. 3613 // elements.
3341 return heap->undefined_value(); 3614 return heap->undefined_value();
3342 case DICTIONARY_ELEMENTS: { 3615 case DICTIONARY_ELEMENTS: {
3343 // Lookup the index. 3616 Object* probe =
3344 NumberDictionary* dictionary = element_dictionary(); 3617 FindGetterSetterInDictionary(element_dictionary(), index, heap);
3345 int entry = dictionary->FindEntry(index); 3618 if (!probe->IsTheHole()) return probe;
3346 if (entry != NumberDictionary::kNotFound) { 3619 // Otherwise allow to override it.
3347 Object* result = dictionary->ValueAt(entry); 3620 break;
3348 PropertyDetails details = dictionary->DetailsAt(entry); 3621 }
3349 if (details.IsReadOnly()) return heap->undefined_value(); 3622 case NON_STRICT_ARGUMENTS_ELEMENTS: {
3350 if (details.type() == CALLBACKS) { 3623 // Ascertain whether we have read-only properties or an existing
3351 if (result->IsFixedArray()) { 3624 // getter/setter pair in an arguments elements dictionary backing
3352 return result; 3625 // store.
3353 } 3626 FixedArray* parameter_map = FixedArray::cast(elements());
3354 // Otherwise allow to override it. 3627 uint32_t length = parameter_map->length();
3628 Object* probe =
3629 index < (length - 2) ? parameter_map->get(index + 2) : NULL;
3630 if (probe == NULL || probe->IsTheHole()) {
3631 FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
3632 if (arguments->IsDictionary()) {
3633 NumberDictionary* dictionary = NumberDictionary::cast(arguments);
3634 probe = FindGetterSetterInDictionary(dictionary, index, heap);
3635 if (!probe->IsTheHole()) return probe;
3355 } 3636 }
3356 } 3637 }
3357 break; 3638 break;
3358 } 3639 }
3359 default:
3360 UNREACHABLE();
3361 break;
3362 } 3640 }
3363 } else { 3641 } else {
3364 // Lookup the name. 3642 // Lookup the name.
3365 LookupResult result; 3643 LookupResult result;
3366 LocalLookup(name, &result); 3644 LocalLookup(name, &result);
3367 if (result.IsProperty()) { 3645 if (result.IsProperty()) {
3368 if (result.IsReadOnly()) return heap->undefined_value(); 3646 if (result.IsReadOnly()) return heap->undefined_value();
3369 if (result.type() == CALLBACKS) { 3647 if (result.type() == CALLBACKS) {
3370 Object* obj = result.GetCallbackObject(); 3648 Object* obj = result.GetCallbackObject();
3371 // Need to preserve old getters/setters. 3649 // Need to preserve old getters/setters.
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
3414 return true; 3692 return true;
3415 } 3693 }
3416 3694
3417 3695
3418 MaybeObject* JSObject::SetElementCallback(uint32_t index, 3696 MaybeObject* JSObject::SetElementCallback(uint32_t index,
3419 Object* structure, 3697 Object* structure,
3420 PropertyAttributes attributes) { 3698 PropertyAttributes attributes) {
3421 PropertyDetails details = PropertyDetails(attributes, CALLBACKS); 3699 PropertyDetails details = PropertyDetails(attributes, CALLBACKS);
3422 3700
3423 // Normalize elements to make this operation simple. 3701 // Normalize elements to make this operation simple.
3424 Object* ok; 3702 NumberDictionary* dictionary = NULL;
3425 { MaybeObject* maybe_ok = NormalizeElements(); 3703 { Object* result;
3426 if (!maybe_ok->ToObject(&ok)) return maybe_ok; 3704 MaybeObject* maybe = NormalizeElements();
3705 if (!maybe->ToObject(&result)) return maybe;
3706 dictionary = NumberDictionary::cast(result);
3707 }
3708 ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements());
3709
3710 // Update the dictionary with the new CALLBACKS property.
3711 { Object* result;
3712 MaybeObject* maybe = dictionary->Set(index, structure, details);
3713 if (!maybe->ToObject(&result)) return maybe;
3714 dictionary = NumberDictionary::cast(result);
3427 } 3715 }
3428 3716
3429 // Update the dictionary with the new CALLBACKS property. 3717 dictionary->set_requires_slow_elements();
3430 Object* dict; 3718 // Update the dictionary backing store on the object.
3431 { MaybeObject* maybe_dict = 3719 if (elements()->map() == GetHeap()->non_strict_arguments_elements_map()) {
3432 element_dictionary()->Set(index, structure, details); 3720 // Also delete any parameter alias.
3433 if (!maybe_dict->ToObject(&dict)) return maybe_dict; 3721 //
3722 // TODO(kmillikin): when deleting the last parameter alias we could
3723 // switch to a direct backing store without the parameter map. This
3724 // would allow GC of the context.
3725 FixedArray* parameter_map = FixedArray::cast(elements());
3726 uint32_t length = parameter_map->length();
3727 if (index < length - 2) {
3728 parameter_map->set(index + 2, GetHeap()->the_hole_value());
3729 }
3730 parameter_map->set(1, dictionary);
3731 } else {
3732 set_elements(dictionary);
3434 } 3733 }
3435 3734
3436 NumberDictionary* elements = NumberDictionary::cast(dict);
3437 elements->set_requires_slow_elements();
3438 // Set the potential new dictionary on the object.
3439 set_elements(elements);
3440
3441 return structure; 3735 return structure;
3442 } 3736 }
3443 3737
3444 3738
3445 MaybeObject* JSObject::SetPropertyCallback(String* name, 3739 MaybeObject* JSObject::SetPropertyCallback(String* name,
3446 Object* structure, 3740 Object* structure,
3447 PropertyAttributes attributes) { 3741 PropertyAttributes attributes) {
3448 PropertyDetails details = PropertyDetails(attributes, CALLBACKS); 3742 PropertyDetails details = PropertyDetails(attributes, CALLBACKS);
3449 3743
3450 bool convert_back_to_fast = HasFastProperties() && 3744 bool convert_back_to_fast = HasFastProperties() &&
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
3556 break; 3850 break;
3557 case EXTERNAL_PIXEL_ELEMENTS: 3851 case EXTERNAL_PIXEL_ELEMENTS:
3558 case EXTERNAL_BYTE_ELEMENTS: 3852 case EXTERNAL_BYTE_ELEMENTS:
3559 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 3853 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
3560 case EXTERNAL_SHORT_ELEMENTS: 3854 case EXTERNAL_SHORT_ELEMENTS:
3561 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 3855 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
3562 case EXTERNAL_INT_ELEMENTS: 3856 case EXTERNAL_INT_ELEMENTS:
3563 case EXTERNAL_UNSIGNED_INT_ELEMENTS: 3857 case EXTERNAL_UNSIGNED_INT_ELEMENTS:
3564 case EXTERNAL_FLOAT_ELEMENTS: 3858 case EXTERNAL_FLOAT_ELEMENTS:
3565 case EXTERNAL_DOUBLE_ELEMENTS: 3859 case EXTERNAL_DOUBLE_ELEMENTS:
3860 case FAST_DOUBLE_ELEMENTS:
3566 // Ignore getters and setters on pixel and external array 3861 // Ignore getters and setters on pixel and external array
3567 // elements. 3862 // elements.
3568 return isolate->heap()->undefined_value(); 3863 return isolate->heap()->undefined_value();
3569 case DICTIONARY_ELEMENTS: 3864 case DICTIONARY_ELEMENTS:
3570 break; 3865 break;
3571 default: 3866 case NON_STRICT_ARGUMENTS_ELEMENTS:
3572 UNREACHABLE(); 3867 UNIMPLEMENTED();
3573 break; 3868 break;
3574 } 3869 }
3575 3870
3576 Object* ok; 3871 Object* ok;
3577 { MaybeObject* maybe_ok = 3872 { MaybeObject* maybe_ok =
3578 SetElementCallback(index, info, info->property_attributes()); 3873 SetElementCallback(index, info, info->property_attributes());
3579 if (!maybe_ok->ToObject(&ok)) return maybe_ok; 3874 if (!maybe_ok->ToObject(&ok)) return maybe_ok;
3580 } 3875 }
3581 } else { 3876 } else {
3582 // Lookup the name. 3877 // Lookup the name.
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after
3806 4101
3807 void Map::RemoveFromCodeCache(String* name, Code* code, int index) { 4102 void Map::RemoveFromCodeCache(String* name, Code* code, int index) {
3808 // No GC is supposed to happen between a call to IndexInCodeCache and 4103 // No GC is supposed to happen between a call to IndexInCodeCache and
3809 // RemoveFromCodeCache so the code cache must be there. 4104 // RemoveFromCodeCache so the code cache must be there.
3810 ASSERT(!code_cache()->IsFixedArray()); 4105 ASSERT(!code_cache()->IsFixedArray());
3811 CodeCache::cast(code_cache())->RemoveByIndex(name, code, index); 4106 CodeCache::cast(code_cache())->RemoveByIndex(name, code, index);
3812 } 4107 }
3813 4108
3814 4109
3815 void Map::TraverseTransitionTree(TraverseCallback callback, void* data) { 4110 void Map::TraverseTransitionTree(TraverseCallback callback, void* data) {
4111 // Traverse the transition tree without using a stack. We do this by
4112 // reversing the pointers in the maps and descriptor arrays.
3816 Map* current = this; 4113 Map* current = this;
3817 Map* meta_map = GetHeap()->meta_map(); 4114 Map* meta_map = GetHeap()->meta_map();
4115 Object** map_or_index_field = NULL;
3818 while (current != meta_map) { 4116 while (current != meta_map) {
3819 DescriptorArray* d = reinterpret_cast<DescriptorArray*>( 4117 DescriptorArray* d = reinterpret_cast<DescriptorArray*>(
3820 *RawField(current, Map::kInstanceDescriptorsOrBitField3Offset)); 4118 *RawField(current, Map::kInstanceDescriptorsOrBitField3Offset));
3821 if (d->IsEmpty()) { 4119 if (!d->IsEmpty()) {
3822 Map* prev = current->map(); 4120 FixedArray* contents = reinterpret_cast<FixedArray*>(
3823 current->set_map(meta_map); 4121 d->get(DescriptorArray::kContentArrayIndex));
3824 callback(current, data); 4122 map_or_index_field = RawField(contents, HeapObject::kMapOffset);
3825 current = prev; 4123 Object* map_or_index = *map_or_index_field;
3826 continue; 4124 bool map_done = true; // Controls a nested continue statement.
4125 for (int i = map_or_index->IsSmi() ? Smi::cast(map_or_index)->value() : 0;
4126 i < contents->length();
4127 i += 2) {
4128 PropertyDetails details(Smi::cast(contents->get(i + 1)));
4129 if (details.IsTransition()) {
4130 // Found a map in the transition array. We record our progress in
4131 // the transition array by recording the current map in the map field
4132 // of the next map and recording the index in the transition array in
4133 // the map field of the array.
4134 Map* next = Map::cast(contents->get(i));
4135 next->set_map(current);
4136 *map_or_index_field = Smi::FromInt(i + 2);
4137 current = next;
4138 map_done = false;
4139 break;
4140 }
4141 }
4142 if (!map_done) continue;
4143 } else {
4144 map_or_index_field = NULL;
4145 }
4146 // That was the regular transitions, now for the prototype transitions.
4147 FixedArray* prototype_transitions =
4148 current->unchecked_prototype_transitions();
4149 Object** proto_map_or_index_field =
4150 RawField(prototype_transitions, HeapObject::kMapOffset);
4151 Object* map_or_index = *proto_map_or_index_field;
4152 const int start = kProtoTransitionHeaderSize + kProtoTransitionMapOffset;
4153 int i = map_or_index->IsSmi() ? Smi::cast(map_or_index)->value() : start;
4154 if (i < prototype_transitions->length()) {
4155 // Found a map in the prototype transition array. Record progress in
4156 // an analogous way to the regular transitions array above.
4157 Object* perhaps_map = prototype_transitions->get(i);
4158 if (perhaps_map->IsMap()) {
4159 Map* next = Map::cast(perhaps_map);
4160 next->set_map(current);
4161 *proto_map_or_index_field =
4162 Smi::FromInt(i + kProtoTransitionElementsPerEntry);
4163 current = next;
4164 continue;
4165 }
4166 }
4167 *proto_map_or_index_field = GetHeap()->fixed_array_map();
4168 if (map_or_index_field != NULL) {
4169 *map_or_index_field = GetHeap()->fixed_array_map();
3827 } 4170 }
3828 4171
3829 FixedArray* contents = reinterpret_cast<FixedArray*>( 4172 // The callback expects a map to have a real map as its map, so we save
3830 d->get(DescriptorArray::kContentArrayIndex)); 4173 // the map field, which is being used to track the traversal and put the
3831 Object** map_or_index_field = RawField(contents, HeapObject::kMapOffset); 4174 // correct map (the meta_map) in place while we do the callback.
3832 Object* map_or_index = *map_or_index_field;
3833 bool map_done = true;
3834 for (int i = map_or_index->IsSmi() ? Smi::cast(map_or_index)->value() : 0;
3835 i < contents->length();
3836 i += 2) {
3837 PropertyDetails details(Smi::cast(contents->get(i + 1)));
3838 if (details.IsTransition()) {
3839 Map* next = reinterpret_cast<Map*>(contents->get(i));
3840 next->set_map(current);
3841 *map_or_index_field = Smi::FromInt(i + 2);
3842 current = next;
3843 map_done = false;
3844 break;
3845 }
3846 }
3847 if (!map_done) continue;
3848 *map_or_index_field = GetHeap()->fixed_array_map();
3849 Map* prev = current->map(); 4175 Map* prev = current->map();
3850 current->set_map(meta_map); 4176 current->set_map(meta_map);
3851 callback(current, data); 4177 callback(current, data);
3852 current = prev; 4178 current = prev;
3853 } 4179 }
3854 } 4180 }
3855 4181
3856 4182
3857 MaybeObject* CodeCache::Update(String* name, Code* code) { 4183 MaybeObject* CodeCache::Update(String* name, Code* code) {
3858 // The number of monomorphic stubs for normal load/store/call IC's can grow to 4184 // The number of monomorphic stubs for normal load/store/call IC's can grow to
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after
4068 } 4394 }
4069 FixedArray* pair = FixedArray::cast(obj); 4395 FixedArray* pair = FixedArray::cast(obj);
4070 pair->set(0, name_); 4396 pair->set(0, name_);
4071 pair->set(1, code_); 4397 pair->set(1, code_);
4072 return pair; 4398 return pair;
4073 } 4399 }
4074 4400
4075 private: 4401 private:
4076 String* name_; 4402 String* name_;
4077 Code::Flags flags_; 4403 Code::Flags flags_;
4404 // TODO(jkummerow): We should be able to get by without this.
4078 Code* code_; 4405 Code* code_;
4079 }; 4406 };
4080 4407
4081 4408
4082 Object* CodeCacheHashTable::Lookup(String* name, Code::Flags flags) { 4409 Object* CodeCacheHashTable::Lookup(String* name, Code::Flags flags) {
4083 CodeCacheHashTableKey key(name, flags); 4410 CodeCacheHashTableKey key(name, flags);
4084 int entry = FindEntry(&key); 4411 int entry = FindEntry(&key);
4085 if (entry == kNotFound) return GetHeap()->undefined_value(); 4412 if (entry == kNotFound) return GetHeap()->undefined_value();
4086 return get(EntryToIndex(entry) + 1); 4413 return get(EntryToIndex(entry) + 1);
4087 } 4414 }
4088 4415
4089 4416
4090 MaybeObject* CodeCacheHashTable::Put(String* name, Code* code) { 4417 MaybeObject* CodeCacheHashTable::Put(String* name, Code* code) {
4091 CodeCacheHashTableKey key(name, code); 4418 CodeCacheHashTableKey key(name, code);
4092 Object* obj; 4419 Object* obj;
4093 { MaybeObject* maybe_obj = EnsureCapacity(1, &key); 4420 { MaybeObject* maybe_obj = EnsureCapacity(1, &key);
4094 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 4421 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
4095 } 4422 }
4096 4423
4097 // Don't use this, as the table might have grown. 4424 // Don't use |this|, as the table might have grown.
4098 CodeCacheHashTable* cache = reinterpret_cast<CodeCacheHashTable*>(obj); 4425 CodeCacheHashTable* cache = reinterpret_cast<CodeCacheHashTable*>(obj);
4099 4426
4100 int entry = cache->FindInsertionEntry(key.Hash()); 4427 int entry = cache->FindInsertionEntry(key.Hash());
4101 Object* k; 4428 Object* k;
4102 { MaybeObject* maybe_k = key.AsObject(); 4429 { MaybeObject* maybe_k = key.AsObject();
4103 if (!maybe_k->ToObject(&k)) return maybe_k; 4430 if (!maybe_k->ToObject(&k)) return maybe_k;
4104 } 4431 }
4105 4432
4106 cache->set(EntryToIndex(entry), k); 4433 cache->set(EntryToIndex(entry), k);
4107 cache->set(EntryToIndex(entry) + 1, code); 4434 cache->set(EntryToIndex(entry) + 1, code);
(...skipping 25 matching lines...) Expand all
4133 if (element->IsSmi() && key->IsSmi() && (element == key)) return true; 4460 if (element->IsSmi() && key->IsSmi() && (element == key)) return true;
4134 if (element->IsString() && 4461 if (element->IsString() &&
4135 key->IsString() && String::cast(element)->Equals(String::cast(key))) { 4462 key->IsString() && String::cast(element)->Equals(String::cast(key))) {
4136 return true; 4463 return true;
4137 } 4464 }
4138 } 4465 }
4139 return false; 4466 return false;
4140 } 4467 }
4141 4468
4142 4469
4470 MaybeObject* PolymorphicCodeCache::Update(MapList* maps,
4471 Code::Flags flags,
4472 Code* code) {
4473 // Initialize cache if necessary.
4474 if (cache()->IsUndefined()) {
4475 Object* result;
4476 { MaybeObject* maybe_result =
4477 PolymorphicCodeCacheHashTable::Allocate(
4478 PolymorphicCodeCacheHashTable::kInitialSize);
4479 if (!maybe_result->ToObject(&result)) return maybe_result;
4480 }
4481 set_cache(result);
4482 } else {
4483 // This entry shouldn't be contained in the cache yet.
4484 ASSERT(PolymorphicCodeCacheHashTable::cast(cache())
4485 ->Lookup(maps, flags)->IsUndefined());
4486 }
4487 PolymorphicCodeCacheHashTable* hash_table =
4488 PolymorphicCodeCacheHashTable::cast(cache());
4489 Object* new_cache;
4490 { MaybeObject* maybe_new_cache = hash_table->Put(maps, flags, code);
4491 if (!maybe_new_cache->ToObject(&new_cache)) return maybe_new_cache;
4492 }
4493 set_cache(new_cache);
4494 return this;
4495 }
4496
4497
4498 Object* PolymorphicCodeCache::Lookup(MapList* maps, Code::Flags flags) {
4499 if (!cache()->IsUndefined()) {
4500 PolymorphicCodeCacheHashTable* hash_table =
4501 PolymorphicCodeCacheHashTable::cast(cache());
4502 return hash_table->Lookup(maps, flags);
4503 } else {
4504 return GetHeap()->undefined_value();
4505 }
4506 }
4507
4508
4509 // Despite their name, object of this class are not stored in the actual
4510 // hash table; instead they're temporarily used for lookups. It is therefore
4511 // safe to have a weak (non-owning) pointer to a MapList as a member field.
4512 class PolymorphicCodeCacheHashTableKey : public HashTableKey {
4513 public:
4514 // Callers must ensure that |maps| outlives the newly constructed object.
4515 PolymorphicCodeCacheHashTableKey(MapList* maps, int code_flags)
4516 : maps_(maps),
4517 code_flags_(code_flags) {}
4518
4519 bool IsMatch(Object* other) {
4520 MapList other_maps(kDefaultListAllocationSize);
4521 int other_flags;
4522 FromObject(other, &other_flags, &other_maps);
4523 if (code_flags_ != other_flags) return false;
4524 if (maps_->length() != other_maps.length()) return false;
4525 // Compare just the hashes first because it's faster.
4526 int this_hash = MapsHashHelper(maps_, code_flags_);
4527 int other_hash = MapsHashHelper(&other_maps, other_flags);
4528 if (this_hash != other_hash) return false;
4529
4530 // Full comparison: for each map in maps_, look for an equivalent map in
4531 // other_maps. This implementation is slow, but probably good enough for
4532 // now because the lists are short (<= 4 elements currently).
4533 for (int i = 0; i < maps_->length(); ++i) {
4534 bool match_found = false;
4535 for (int j = 0; j < other_maps.length(); ++j) {
4536 if (maps_->at(i)->EquivalentTo(other_maps.at(j))) {
4537 match_found = true;
4538 break;
4539 }
4540 }
4541 if (!match_found) return false;
4542 }
4543 return true;
4544 }
4545
4546 static uint32_t MapsHashHelper(MapList* maps, int code_flags) {
4547 uint32_t hash = code_flags;
4548 for (int i = 0; i < maps->length(); ++i) {
4549 hash ^= maps->at(i)->Hash();
4550 }
4551 return hash;
4552 }
4553
4554 uint32_t Hash() {
4555 return MapsHashHelper(maps_, code_flags_);
4556 }
4557
4558 uint32_t HashForObject(Object* obj) {
4559 MapList other_maps(kDefaultListAllocationSize);
4560 int other_flags;
4561 FromObject(obj, &other_flags, &other_maps);
4562 return MapsHashHelper(&other_maps, other_flags);
4563 }
4564
4565 MUST_USE_RESULT MaybeObject* AsObject() {
4566 Object* obj;
4567 // The maps in |maps_| must be copied to a newly allocated FixedArray,
4568 // both because the referenced MapList is short-lived, and because C++
4569 // objects can't be stored in the heap anyway.
4570 { MaybeObject* maybe_obj =
4571 HEAP->AllocateUninitializedFixedArray(maps_->length() + 1);
4572 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
4573 }
4574 FixedArray* list = FixedArray::cast(obj);
4575 list->set(0, Smi::FromInt(code_flags_));
4576 for (int i = 0; i < maps_->length(); ++i) {
4577 list->set(i + 1, maps_->at(i));
4578 }
4579 return list;
4580 }
4581
4582 private:
4583 static MapList* FromObject(Object* obj, int* code_flags, MapList* maps) {
4584 FixedArray* list = FixedArray::cast(obj);
4585 maps->Rewind(0);
4586 *code_flags = Smi::cast(list->get(0))->value();
4587 for (int i = 1; i < list->length(); ++i) {
4588 maps->Add(Map::cast(list->get(i)));
4589 }
4590 return maps;
4591 }
4592
4593 MapList* maps_; // weak.
4594 int code_flags_;
4595 static const int kDefaultListAllocationSize = kMaxKeyedPolymorphism + 1;
4596 };
4597
4598
4599 Object* PolymorphicCodeCacheHashTable::Lookup(MapList* maps, int code_flags) {
4600 PolymorphicCodeCacheHashTableKey key(maps, code_flags);
4601 int entry = FindEntry(&key);
4602 if (entry == kNotFound) return GetHeap()->undefined_value();
4603 return get(EntryToIndex(entry) + 1);
4604 }
4605
4606
4607 MaybeObject* PolymorphicCodeCacheHashTable::Put(MapList* maps,
4608 int code_flags,
4609 Code* code) {
4610 PolymorphicCodeCacheHashTableKey key(maps, code_flags);
4611 Object* obj;
4612 { MaybeObject* maybe_obj = EnsureCapacity(1, &key);
4613 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
4614 }
4615 PolymorphicCodeCacheHashTable* cache =
4616 reinterpret_cast<PolymorphicCodeCacheHashTable*>(obj);
4617 int entry = cache->FindInsertionEntry(key.Hash());
4618 { MaybeObject* maybe_obj = key.AsObject();
4619 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
4620 }
4621 cache->set(EntryToIndex(entry), obj);
4622 cache->set(EntryToIndex(entry) + 1, code);
4623 cache->ElementAdded();
4624 return cache;
4625 }
4626
4627
4143 MaybeObject* FixedArray::AddKeysFromJSArray(JSArray* array) { 4628 MaybeObject* FixedArray::AddKeysFromJSArray(JSArray* array) {
4144 ASSERT(!array->HasExternalArrayElements()); 4629 ASSERT(!array->HasExternalArrayElements());
4145 switch (array->GetElementsKind()) { 4630 switch (array->GetElementsKind()) {
4146 case JSObject::FAST_ELEMENTS: 4631 case JSObject::FAST_ELEMENTS:
4147 return UnionOfKeys(FixedArray::cast(array->elements())); 4632 return UnionOfKeys(FixedArray::cast(array->elements()));
4148 case JSObject::DICTIONARY_ELEMENTS: { 4633 case JSObject::DICTIONARY_ELEMENTS: {
4149 NumberDictionary* dict = array->element_dictionary(); 4634 NumberDictionary* dict = array->element_dictionary();
4150 int size = dict->NumberOfElements(); 4635 int size = dict->NumberOfElements();
4151 4636
4152 // Allocate a temporary fixed array. 4637 // Allocate a temporary fixed array.
4153 Object* object; 4638 Object* object;
4154 { MaybeObject* maybe_object = GetHeap()->AllocateFixedArray(size); 4639 { MaybeObject* maybe_object = GetHeap()->AllocateFixedArray(size);
4155 if (!maybe_object->ToObject(&object)) return maybe_object; 4640 if (!maybe_object->ToObject(&object)) return maybe_object;
4156 } 4641 }
4157 FixedArray* key_array = FixedArray::cast(object); 4642 FixedArray* key_array = FixedArray::cast(object);
4158 4643
4159 int capacity = dict->Capacity(); 4644 int capacity = dict->Capacity();
4160 int pos = 0; 4645 int pos = 0;
4161 // Copy the elements from the JSArray to the temporary fixed array. 4646 // Copy the elements from the JSArray to the temporary fixed array.
4162 for (int i = 0; i < capacity; i++) { 4647 for (int i = 0; i < capacity; i++) {
4163 if (dict->IsKey(dict->KeyAt(i))) { 4648 if (dict->IsKey(dict->KeyAt(i))) {
4164 key_array->set(pos++, dict->ValueAt(i)); 4649 key_array->set(pos++, dict->ValueAt(i));
4165 } 4650 }
4166 } 4651 }
4167 // Compute the union of this and the temporary fixed array. 4652 // Compute the union of this and the temporary fixed array.
4168 return UnionOfKeys(key_array); 4653 return UnionOfKeys(key_array);
4169 } 4654 }
4170 default: 4655 case JSObject::NON_STRICT_ARGUMENTS_ELEMENTS:
4171 UNREACHABLE(); 4656 UNIMPLEMENTED();
4657 break;
4658 case JSObject::EXTERNAL_BYTE_ELEMENTS:
4659 case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
4660 case JSObject::EXTERNAL_SHORT_ELEMENTS:
4661 case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
4662 case JSObject::EXTERNAL_INT_ELEMENTS:
4663 case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS:
4664 case JSObject::EXTERNAL_FLOAT_ELEMENTS:
4665 case JSObject::EXTERNAL_DOUBLE_ELEMENTS:
4666 case JSObject::EXTERNAL_PIXEL_ELEMENTS:
4667 case JSObject::FAST_DOUBLE_ELEMENTS:
4668 break;
4172 } 4669 }
4173 UNREACHABLE(); 4670 UNREACHABLE();
4174 return GetHeap()->null_value(); // Failure case needs to "return" a value. 4671 return GetHeap()->null_value(); // Failure case needs to "return" a value.
4175 } 4672 }
4176 4673
4177 4674
4178 MaybeObject* FixedArray::UnionOfKeys(FixedArray* other) { 4675 MaybeObject* FixedArray::UnionOfKeys(FixedArray* other) {
4179 int len0 = length(); 4676 int len0 = length();
4180 #ifdef DEBUG 4677 #ifdef DEBUG
4181 if (FLAG_enable_slow_asserts) { 4678 if (FLAG_enable_slow_asserts) {
(...skipping 1362 matching lines...) Expand 10 before | Expand all | Expand 10 after
5544 uc32 r = decoder->GetNext(); 6041 uc32 r = decoder->GetNext();
5545 if (Get(i) != r) return false; 6042 if (Get(i) != r) return false;
5546 } 6043 }
5547 return i == slen && !decoder->has_more(); 6044 return i == slen && !decoder->has_more();
5548 } 6045 }
5549 6046
5550 6047
5551 bool String::IsAsciiEqualTo(Vector<const char> str) { 6048 bool String::IsAsciiEqualTo(Vector<const char> str) {
5552 int slen = length(); 6049 int slen = length();
5553 if (str.length() != slen) return false; 6050 if (str.length() != slen) return false;
5554 if (this->IsSeqAsciiString()) { 6051 if (IsFlat() && IsAsciiRepresentation()) {
5555 SeqAsciiString* seq = SeqAsciiString::cast(this); 6052 return CompareChars(ToAsciiVector().start(), str.start(), slen) == 0;
5556 char* ch = seq->GetChars(); 6053 }
5557 for (int i = 0; i < slen; i++, ch++) { 6054 for (int i = 0; i < slen; i++) {
5558 if (*ch != str[i]) return false; 6055 if (Get(i) != static_cast<uint16_t>(str[i])) return false;
5559 }
5560 } else {
5561 for (int i = 0; i < slen; i++) {
5562 if (Get(i) != static_cast<uint16_t>(str[i])) return false;
5563 }
5564 } 6056 }
5565 return true; 6057 return true;
5566 } 6058 }
5567 6059
5568 6060
5569 bool String::IsTwoByteEqualTo(Vector<const uc16> str) { 6061 bool String::IsTwoByteEqualTo(Vector<const uc16> str) {
5570 int slen = length(); 6062 int slen = length();
5571 if (str.length() != slen) return false; 6063 if (str.length() != slen) return false;
6064 if (IsFlat() && IsTwoByteRepresentation()) {
6065 return CompareChars(ToUC16Vector().start(), str.start(), slen) == 0;
6066 }
5572 for (int i = 0; i < slen; i++) { 6067 for (int i = 0; i < slen; i++) {
5573 if (Get(i) != str[i]) return false; 6068 if (Get(i) != str[i]) return false;
5574 } 6069 }
5575 return true; 6070 return true;
5576 } 6071 }
5577 6072
5578 6073
5579 uint32_t String::ComputeAndSetHash() { 6074 uint32_t String::ComputeAndSetHash() {
5580 // Should only be called if hash code has not yet been computed. 6075 // Should only be called if hash code has not yet been computed.
5581 ASSERT(!HasHashCode()); 6076 ASSERT(!HasHashCode());
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after
5781 ASSERT(target->prototype() == this || 6276 ASSERT(target->prototype() == this ||
5782 target->prototype() == real_prototype); 6277 target->prototype() == real_prototype);
5783 // Getter prototype() is read-only, set_prototype() has side effects. 6278 // Getter prototype() is read-only, set_prototype() has side effects.
5784 *RawField(target, Map::kPrototypeOffset) = real_prototype; 6279 *RawField(target, Map::kPrototypeOffset) = real_prototype;
5785 } 6280 }
5786 } 6281 }
5787 } 6282 }
5788 } 6283 }
5789 6284
5790 6285
6286 int Map::Hash() {
6287 // For performance reasons we only hash the 3 most variable fields of a map:
6288 // constructor, prototype and bit_field2.
6289
6290 // Shift away the tag.
6291 int hash = (static_cast<uint32_t>(
6292 reinterpret_cast<uintptr_t>(constructor())) >> 2);
6293
6294 // XOR-ing the prototype and constructor directly yields too many zero bits
6295 // when the two pointers are close (which is fairly common).
6296 // To avoid this we shift the prototype 4 bits relatively to the constructor.
6297 hash ^= (static_cast<uint32_t>(
6298 reinterpret_cast<uintptr_t>(prototype())) << 2);
6299
6300 return hash ^ (hash >> 16) ^ bit_field2();
6301 }
6302
6303
6304 bool Map::EquivalentToForNormalization(Map* other,
6305 PropertyNormalizationMode mode) {
6306 return
6307 constructor() == other->constructor() &&
6308 prototype() == other->prototype() &&
6309 inobject_properties() == ((mode == CLEAR_INOBJECT_PROPERTIES) ?
6310 0 :
6311 other->inobject_properties()) &&
6312 instance_type() == other->instance_type() &&
6313 bit_field() == other->bit_field() &&
6314 bit_field2() == other->bit_field2() &&
6315 (bit_field3() & ~(1<<Map::kIsShared)) ==
6316 (other->bit_field3() & ~(1<<Map::kIsShared));
6317 }
6318
6319
5791 void JSFunction::JSFunctionIterateBody(int object_size, ObjectVisitor* v) { 6320 void JSFunction::JSFunctionIterateBody(int object_size, ObjectVisitor* v) {
5792 // Iterate over all fields in the body but take care in dealing with 6321 // Iterate over all fields in the body but take care in dealing with
5793 // the code entry. 6322 // the code entry.
5794 IteratePointers(v, kPropertiesOffset, kCodeEntryOffset); 6323 IteratePointers(v, kPropertiesOffset, kCodeEntryOffset);
5795 v->VisitCodeEntry(this->address() + kCodeEntryOffset); 6324 v->VisitCodeEntry(this->address() + kCodeEntryOffset);
5796 IteratePointers(v, kCodeEntryOffset + kPointerSize, object_size); 6325 IteratePointers(v, kCodeEntryOffset + kPointerSize, object_size);
5797 } 6326 }
5798 6327
5799 6328
5800 void JSFunction::MarkForLazyRecompilation() { 6329 void JSFunction::MarkForLazyRecompilation() {
5801 ASSERT(is_compiled() && !IsOptimized()); 6330 ASSERT(is_compiled() && !IsOptimized());
5802 ASSERT(shared()->allows_lazy_compilation() || 6331 ASSERT(shared()->allows_lazy_compilation() ||
5803 code()->optimizable()); 6332 code()->optimizable());
5804 Builtins* builtins = GetIsolate()->builtins(); 6333 Builtins* builtins = GetIsolate()->builtins();
5805 ReplaceCode(builtins->builtin(Builtins::kLazyRecompile)); 6334 ReplaceCode(builtins->builtin(Builtins::kLazyRecompile));
5806 } 6335 }
5807 6336
5808 6337
5809 uint32_t JSFunction::SourceHash() {
5810 uint32_t hash = 0;
5811 Object* script = shared()->script();
5812 if (!script->IsUndefined()) {
5813 Object* source = Script::cast(script)->source();
5814 if (source->IsUndefined()) hash = String::cast(source)->Hash();
5815 }
5816 hash ^= ComputeIntegerHash(shared()->start_position_and_type());
5817 hash += ComputeIntegerHash(shared()->end_position());
5818 return hash;
5819 }
5820
5821
5822 bool JSFunction::IsInlineable() { 6338 bool JSFunction::IsInlineable() {
5823 if (IsBuiltin()) return false; 6339 if (IsBuiltin()) return false;
5824 SharedFunctionInfo* shared_info = shared(); 6340 SharedFunctionInfo* shared_info = shared();
5825 // Check that the function has a script associated with it. 6341 // Check that the function has a script associated with it.
5826 if (!shared_info->script()->IsScript()) return false; 6342 if (!shared_info->script()->IsScript()) return false;
5827 if (shared_info->optimization_disabled()) return false; 6343 if (shared_info->optimization_disabled()) return false;
5828 Code* code = shared_info->code(); 6344 Code* code = shared_info->code();
5829 if (code->kind() == Code::OPTIMIZED_FUNCTION) return true; 6345 if (code->kind() == Code::OPTIMIZED_FUNCTION) return true;
5830 // If we never ran this (unlikely) then lets try to optimize it. 6346 // If we never ran this (unlikely) then lets try to optimize it.
5831 if (code->kind() != Code::FUNCTION) return true; 6347 if (code->kind() != Code::FUNCTION) return true;
(...skipping 448 matching lines...) Expand 10 before | Expand all | Expand 10 after
6280 Builtins* builtins = heap->isolate()->builtins(); 6796 Builtins* builtins = heap->isolate()->builtins();
6281 ASSERT_EQ(builtins->builtin(Builtins::kJSConstructStubCountdown), 6797 ASSERT_EQ(builtins->builtin(Builtins::kJSConstructStubCountdown),
6282 construct_stub()); 6798 construct_stub());
6283 set_construct_stub(builtins->builtin(Builtins::kJSConstructStubGeneric)); 6799 set_construct_stub(builtins->builtin(Builtins::kJSConstructStubGeneric));
6284 6800
6285 int slack = map->unused_property_fields(); 6801 int slack = map->unused_property_fields();
6286 map->TraverseTransitionTree(&GetMinInobjectSlack, &slack); 6802 map->TraverseTransitionTree(&GetMinInobjectSlack, &slack);
6287 if (slack != 0) { 6803 if (slack != 0) {
6288 // Resize the initial map and all maps in its transition tree. 6804 // Resize the initial map and all maps in its transition tree.
6289 map->TraverseTransitionTree(&ShrinkInstanceSize, &slack); 6805 map->TraverseTransitionTree(&ShrinkInstanceSize, &slack);
6806
6290 // Give the correct expected_nof_properties to initial maps created later. 6807 // Give the correct expected_nof_properties to initial maps created later.
6291 ASSERT(expected_nof_properties() >= slack); 6808 ASSERT(expected_nof_properties() >= slack);
6292 set_expected_nof_properties(expected_nof_properties() - slack); 6809 set_expected_nof_properties(expected_nof_properties() - slack);
6293 } 6810 }
6294 } 6811 }
6295 6812
6296 6813
6297 void ObjectVisitor::VisitCodeTarget(RelocInfo* rinfo) { 6814 void ObjectVisitor::VisitCodeTarget(RelocInfo* rinfo) {
6298 ASSERT(RelocInfo::IsCodeTarget(rinfo->rmode())); 6815 ASSERT(RelocInfo::IsCodeTarget(rinfo->rmode()));
6299 Object* target = Code::GetCodeFromTargetAddress(rinfo->target_address()); 6816 Object* target = Code::GetCodeFromTargetAddress(rinfo->target_address());
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after
6464 RelocInfo* info = it.rinfo(); 6981 RelocInfo* info = it.rinfo();
6465 Object* object = info->target_object(); 6982 Object* object = info->target_object();
6466 if (object->IsMap()) return Map::cast(object); 6983 if (object->IsMap()) return Map::cast(object);
6467 } 6984 }
6468 return NULL; 6985 return NULL;
6469 } 6986 }
6470 6987
6471 6988
6472 #ifdef ENABLE_DISASSEMBLER 6989 #ifdef ENABLE_DISASSEMBLER
6473 6990
6474 #ifdef OBJECT_PRINT
6475
6476 void DeoptimizationInputData::DeoptimizationInputDataPrint(FILE* out) { 6991 void DeoptimizationInputData::DeoptimizationInputDataPrint(FILE* out) {
6477 disasm::NameConverter converter; 6992 disasm::NameConverter converter;
6478 int deopt_count = DeoptCount(); 6993 int deopt_count = DeoptCount();
6479 PrintF(out, "Deoptimization Input Data (deopt points = %d)\n", deopt_count); 6994 PrintF(out, "Deoptimization Input Data (deopt points = %d)\n", deopt_count);
6480 if (0 == deopt_count) return; 6995 if (0 == deopt_count) return;
6481 6996
6482 PrintF(out, "%6s %6s %6s %12s\n", "index", "ast id", "argc", "commands"); 6997 PrintF(out, "%6s %6s %6s %12s\n", "index", "ast id", "argc", "commands");
6483 for (int i = 0; i < deopt_count; i++) { 6998 for (int i = 0; i < deopt_count; i++) {
6484 int command_count = 0; 6999 int command_count = 0;
6485 PrintF(out, "%6d %6d %6d", 7000 PrintF(out, "%6d %6d %6d",
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
6612 for (int i = 0; i < this->DeoptPoints(); i++) { 7127 for (int i = 0; i < this->DeoptPoints(); i++) {
6613 int pc_and_state = this->PcAndState(i)->value(); 7128 int pc_and_state = this->PcAndState(i)->value();
6614 PrintF("%6d %8d %s\n", 7129 PrintF("%6d %8d %s\n",
6615 this->AstId(i)->value(), 7130 this->AstId(i)->value(),
6616 FullCodeGenerator::PcField::decode(pc_and_state), 7131 FullCodeGenerator::PcField::decode(pc_and_state),
6617 FullCodeGenerator::State2String( 7132 FullCodeGenerator::State2String(
6618 FullCodeGenerator::StateField::decode(pc_and_state))); 7133 FullCodeGenerator::StateField::decode(pc_and_state)));
6619 } 7134 }
6620 } 7135 }
6621 7136
6622 #endif
6623
6624 7137
6625 // Identify kind of code. 7138 // Identify kind of code.
6626 const char* Code::Kind2String(Kind kind) { 7139 const char* Code::Kind2String(Kind kind) {
6627 switch (kind) { 7140 switch (kind) {
6628 case FUNCTION: return "FUNCTION"; 7141 case FUNCTION: return "FUNCTION";
6629 case OPTIMIZED_FUNCTION: return "OPTIMIZED_FUNCTION"; 7142 case OPTIMIZED_FUNCTION: return "OPTIMIZED_FUNCTION";
6630 case STUB: return "STUB"; 7143 case STUB: return "STUB";
6631 case BUILTIN: return "BUILTIN"; 7144 case BUILTIN: return "BUILTIN";
6632 case LOAD_IC: return "LOAD_IC"; 7145 case LOAD_IC: return "LOAD_IC";
6633 case KEYED_LOAD_IC: return "KEYED_LOAD_IC"; 7146 case KEYED_LOAD_IC: return "KEYED_LOAD_IC";
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
6690 if (extra == kStrictMode) { 7203 if (extra == kStrictMode) {
6691 name = "STRICT"; 7204 name = "STRICT";
6692 } 7205 }
6693 break; 7206 break;
6694 default: 7207 default:
6695 break; 7208 break;
6696 } 7209 }
6697 if (name != NULL) { 7210 if (name != NULL) {
6698 PrintF(out, "extra_ic_state = %s\n", name); 7211 PrintF(out, "extra_ic_state = %s\n", name);
6699 } else { 7212 } else {
6700 PrintF(out, "etra_ic_state = %d\n", extra); 7213 PrintF(out, "extra_ic_state = %d\n", extra);
6701 } 7214 }
6702 } 7215 }
6703 7216
6704 7217
6705 void Code::Disassemble(const char* name, FILE* out) { 7218 void Code::Disassemble(const char* name, FILE* out) {
6706 PrintF(out, "kind = %s\n", Kind2String(kind())); 7219 PrintF(out, "kind = %s\n", Kind2String(kind()));
6707 if (is_inline_cache_stub()) { 7220 if (is_inline_cache_stub()) {
6708 PrintF(out, "ic_state = %s\n", ICState2String(ic_state())); 7221 PrintF(out, "ic_state = %s\n", ICState2String(ic_state()));
6709 PrintExtraICState(out, kind(), extra_ic_state()); 7222 PrintExtraICState(out, kind(), extra_ic_state());
6710 PrintF(out, "ic_in_loop = %d\n", ic_in_loop() == IN_LOOP); 7223 PrintF(out, "ic_in_loop = %d\n", ic_in_loop() == IN_LOOP);
6711 if (ic_state() == MONOMORPHIC) { 7224 if (ic_state() == MONOMORPHIC) {
6712 PrintF(out, "type = %s\n", PropertyType2String(type())); 7225 PrintF(out, "type = %s\n", PropertyType2String(type()));
6713 } 7226 }
7227 if (is_call_stub() || is_keyed_call_stub()) {
7228 PrintF(out, "argc = %d\n", arguments_count());
7229 }
6714 } 7230 }
6715 if ((name != NULL) && (name[0] != '\0')) { 7231 if ((name != NULL) && (name[0] != '\0')) {
6716 PrintF(out, "name = %s\n", name); 7232 PrintF(out, "name = %s\n", name);
6717 } 7233 }
6718 if (kind() == OPTIMIZED_FUNCTION) { 7234 if (kind() == OPTIMIZED_FUNCTION) {
6719 PrintF(out, "stack_slots = %d\n", stack_slots()); 7235 PrintF(out, "stack_slots = %d\n", stack_slots());
6720 } 7236 }
6721 7237
6722 PrintF(out, "Instructions (size = %d)\n", instruction_size()); 7238 PrintF(out, "Instructions (size = %d)\n", instruction_size());
6723 Disassembler::Decode(out, this); 7239 Disassembler::Decode(out, this);
6724 PrintF(out, "\n"); 7240 PrintF(out, "\n");
6725 7241
6726 #ifdef DEBUG
6727 if (kind() == FUNCTION) { 7242 if (kind() == FUNCTION) {
6728 DeoptimizationOutputData* data = 7243 DeoptimizationOutputData* data =
6729 DeoptimizationOutputData::cast(this->deoptimization_data()); 7244 DeoptimizationOutputData::cast(this->deoptimization_data());
6730 data->DeoptimizationOutputDataPrint(out); 7245 data->DeoptimizationOutputDataPrint(out);
6731 } else if (kind() == OPTIMIZED_FUNCTION) { 7246 } else if (kind() == OPTIMIZED_FUNCTION) {
6732 DeoptimizationInputData* data = 7247 DeoptimizationInputData* data =
6733 DeoptimizationInputData::cast(this->deoptimization_data()); 7248 DeoptimizationInputData::cast(this->deoptimization_data());
6734 data->DeoptimizationInputDataPrint(out); 7249 data->DeoptimizationInputDataPrint(out);
6735 } 7250 }
6736 PrintF("\n"); 7251 PrintF("\n");
6737 #endif
6738 7252
6739 if (kind() == OPTIMIZED_FUNCTION) { 7253 if (kind() == OPTIMIZED_FUNCTION) {
6740 SafepointTable table(this); 7254 SafepointTable table(this);
6741 PrintF(out, "Safepoints (size = %u)\n", table.size()); 7255 PrintF(out, "Safepoints (size = %u)\n", table.size());
6742 for (unsigned i = 0; i < table.length(); i++) { 7256 for (unsigned i = 0; i < table.length(); i++) {
6743 unsigned pc_offset = table.GetPcOffset(i); 7257 unsigned pc_offset = table.GetPcOffset(i);
6744 PrintF(out, "%p %4d ", (instruction_start() + pc_offset), pc_offset); 7258 PrintF(out, "%p %4d ", (instruction_start() + pc_offset), pc_offset);
6745 table.PrintEntry(i); 7259 table.PrintEntry(i);
6746 PrintF(out, " (sp -> fp)"); 7260 PrintF(out, " (sp -> fp)");
6747 SafepointEntry entry = table.GetEntry(i); 7261 SafepointEntry entry = table.GetEntry(i);
(...skipping 26 matching lines...) Expand all
6774 } 7288 }
6775 } 7289 }
6776 7290
6777 PrintF("RelocInfo (size = %d)\n", relocation_size()); 7291 PrintF("RelocInfo (size = %d)\n", relocation_size());
6778 for (RelocIterator it(this); !it.done(); it.next()) it.rinfo()->Print(out); 7292 for (RelocIterator it(this); !it.done(); it.next()) it.rinfo()->Print(out);
6779 PrintF(out, "\n"); 7293 PrintF(out, "\n");
6780 } 7294 }
6781 #endif // ENABLE_DISASSEMBLER 7295 #endif // ENABLE_DISASSEMBLER
6782 7296
6783 7297
7298 static void CopyFastElementsToFast(FixedArray* source,
7299 FixedArray* destination,
7300 WriteBarrierMode mode) {
7301 uint32_t count = static_cast<uint32_t>(source->length());
7302 for (uint32_t i = 0; i < count; ++i) {
7303 destination->set(i, source->get(i), mode);
7304 }
7305 }
7306
7307
7308 static void CopySlowElementsToFast(NumberDictionary* source,
7309 FixedArray* destination,
7310 WriteBarrierMode mode) {
7311 for (int i = 0; i < source->Capacity(); ++i) {
7312 Object* key = source->KeyAt(i);
7313 if (key->IsNumber()) {
7314 uint32_t entry = static_cast<uint32_t>(key->Number());
7315 destination->set(entry, source->ValueAt(i), mode);
7316 }
7317 }
7318 }
7319
7320
6784 MaybeObject* JSObject::SetFastElementsCapacityAndLength(int capacity, 7321 MaybeObject* JSObject::SetFastElementsCapacityAndLength(int capacity,
6785 int length) { 7322 int length) {
6786 Heap* heap = GetHeap(); 7323 Heap* heap = GetHeap();
6787 // We should never end in here with a pixel or external array. 7324 // We should never end in here with a pixel or external array.
6788 ASSERT(!HasExternalArrayElements()); 7325 ASSERT(!HasExternalArrayElements());
6789 7326
7327 // Allocate a new fast elements backing store.
7328 FixedArray* new_elements = NULL;
7329 { Object* object;
7330 MaybeObject* maybe = heap->AllocateFixedArrayWithHoles(capacity);
7331 if (!maybe->ToObject(&object)) return maybe;
7332 new_elements = FixedArray::cast(object);
7333 }
7334
7335 // Find the new map to use for this object if there is a map change.
7336 Map* new_map = NULL;
7337 if (elements()->map() != heap->non_strict_arguments_elements_map()) {
7338 Object* object;
7339 MaybeObject* maybe = map()->GetFastElementsMap();
7340 if (!maybe->ToObject(&object)) return maybe;
7341 new_map = Map::cast(object);
7342 }
7343
7344 AssertNoAllocation no_gc;
7345 WriteBarrierMode mode = new_elements->GetWriteBarrierMode(no_gc);
7346 switch (GetElementsKind()) {
7347 case FAST_ELEMENTS:
7348 CopyFastElementsToFast(FixedArray::cast(elements()), new_elements, mode);
7349 set_map(new_map);
7350 set_elements(new_elements);
7351 break;
7352 case DICTIONARY_ELEMENTS:
7353 CopySlowElementsToFast(NumberDictionary::cast(elements()),
7354 new_elements,
7355 mode);
7356 set_map(new_map);
7357 set_elements(new_elements);
7358 break;
7359 case NON_STRICT_ARGUMENTS_ELEMENTS: {
7360 // The object's map and the parameter map are unchanged, the unaliased
7361 // arguments are copied to the new backing store.
7362 FixedArray* parameter_map = FixedArray::cast(elements());
7363 FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
7364 if (arguments->IsDictionary()) {
7365 CopySlowElementsToFast(NumberDictionary::cast(arguments),
7366 new_elements,
7367 mode);
7368 } else {
7369 CopyFastElementsToFast(arguments, new_elements, mode);
7370 }
7371 parameter_map->set(1, new_elements);
7372 break;
7373 }
7374 case FAST_DOUBLE_ELEMENTS: {
7375 FixedDoubleArray* old_elements = FixedDoubleArray::cast(elements());
7376 uint32_t old_length = static_cast<uint32_t>(old_elements->length());
7377 // Fill out the new array with this content and array holes.
7378 for (uint32_t i = 0; i < old_length; i++) {
7379 if (!old_elements->is_the_hole(i)) {
7380 Object* obj;
7381 // Objects must be allocated in the old object space, since the
7382 // overall number of HeapNumbers needed for the conversion might
7383 // exceed the capacity of new space, and we would fail repeatedly
7384 // trying to convert the FixedDoubleArray.
7385 MaybeObject* maybe_value_object =
7386 GetHeap()->AllocateHeapNumber(old_elements->get(i), TENURED);
7387 if (!maybe_value_object->ToObject(&obj)) return maybe_value_object;
7388 // Force write barrier. It's not worth trying to exploit
7389 // elems->GetWriteBarrierMode(), since it requires an
7390 // AssertNoAllocation stack object that would have to be positioned
7391 // after the HeapNumber allocation anyway.
7392 new_elements->set(i, obj, UPDATE_WRITE_BARRIER);
7393 }
7394 }
7395 break;
7396 }
7397 case EXTERNAL_BYTE_ELEMENTS:
7398 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
7399 case EXTERNAL_SHORT_ELEMENTS:
7400 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
7401 case EXTERNAL_INT_ELEMENTS:
7402 case EXTERNAL_UNSIGNED_INT_ELEMENTS:
7403 case EXTERNAL_FLOAT_ELEMENTS:
7404 case EXTERNAL_DOUBLE_ELEMENTS:
7405 case EXTERNAL_PIXEL_ELEMENTS:
7406 UNREACHABLE();
7407 break;
7408 }
7409
7410 // Update the length if necessary.
7411 if (IsJSArray()) {
7412 JSArray::cast(this)->set_length(Smi::FromInt(length));
7413 }
7414
7415 return new_elements;
7416 }
7417
7418
7419 MaybeObject* JSObject::SetFastDoubleElementsCapacityAndLength(
7420 int capacity,
7421 int length) {
7422 Heap* heap = GetHeap();
7423 // We should never end in here with a pixel or external array.
7424 ASSERT(!HasExternalArrayElements());
7425
6790 Object* obj; 7426 Object* obj;
6791 { MaybeObject* maybe_obj = heap->AllocateFixedArrayWithHoles(capacity); 7427 { MaybeObject* maybe_obj =
7428 heap->AllocateUninitializedFixedDoubleArray(capacity);
6792 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 7429 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
6793 } 7430 }
6794 FixedArray* elems = FixedArray::cast(obj); 7431 FixedDoubleArray* elems = FixedDoubleArray::cast(obj);
6795 7432
6796 { MaybeObject* maybe_obj = map()->GetFastElementsMap(); 7433 { MaybeObject* maybe_obj = map()->GetFastDoubleElementsMap();
6797 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 7434 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
6798 } 7435 }
6799 Map* new_map = Map::cast(obj); 7436 Map* new_map = Map::cast(obj);
6800 7437
6801 AssertNoAllocation no_gc; 7438 AssertNoAllocation no_gc;
6802 WriteBarrierMode mode = elems->GetWriteBarrierMode(no_gc);
6803 switch (GetElementsKind()) { 7439 switch (GetElementsKind()) {
6804 case FAST_ELEMENTS: { 7440 case FAST_ELEMENTS: {
6805 FixedArray* old_elements = FixedArray::cast(elements()); 7441 elems->Initialize(FixedArray::cast(elements()));
6806 uint32_t old_length = static_cast<uint32_t>(old_elements->length()); 7442 break;
6807 // Fill out the new array with this content and array holes. 7443 }
6808 for (uint32_t i = 0; i < old_length; i++) { 7444 case FAST_DOUBLE_ELEMENTS: {
6809 elems->set(i, old_elements->get(i), mode); 7445 elems->Initialize(FixedDoubleArray::cast(elements()));
6810 }
6811 break; 7446 break;
6812 } 7447 }
6813 case DICTIONARY_ELEMENTS: { 7448 case DICTIONARY_ELEMENTS: {
6814 NumberDictionary* dictionary = NumberDictionary::cast(elements()); 7449 elems->Initialize(NumberDictionary::cast(elements()));
6815 for (int i = 0; i < dictionary->Capacity(); i++) {
6816 Object* key = dictionary->KeyAt(i);
6817 if (key->IsNumber()) {
6818 uint32_t entry = static_cast<uint32_t>(key->Number());
6819 elems->set(entry, dictionary->ValueAt(i), mode);
6820 }
6821 }
6822 break; 7450 break;
6823 } 7451 }
6824 default: 7452 default:
6825 UNREACHABLE(); 7453 UNREACHABLE();
6826 break; 7454 break;
6827 } 7455 }
6828 7456
6829 set_map(new_map); 7457 set_map(new_map);
6830 set_elements(elems); 7458 set_elements(elems);
6831 7459
6832 if (IsJSArray()) { 7460 if (IsJSArray()) {
6833 JSArray::cast(this)->set_length(Smi::FromInt(length)); 7461 JSArray::cast(this)->set_length(Smi::FromInt(length));
6834 } 7462 }
6835 7463
6836 return this; 7464 return this;
6837 } 7465 }
6838 7466
6839 7467
6840 MaybeObject* JSObject::SetSlowElements(Object* len) { 7468 MaybeObject* JSObject::SetSlowElements(Object* len) {
6841 // We should never end in here with a pixel or external array. 7469 // We should never end in here with a pixel or external array.
6842 ASSERT(!HasExternalArrayElements()); 7470 ASSERT(!HasExternalArrayElements());
6843 7471
6844 uint32_t new_length = static_cast<uint32_t>(len->Number()); 7472 uint32_t new_length = static_cast<uint32_t>(len->Number());
6845 7473
6846 switch (GetElementsKind()) { 7474 switch (GetElementsKind()) {
6847 case FAST_ELEMENTS: { 7475 case FAST_ELEMENTS: {
6848 // Make sure we never try to shrink dense arrays into sparse arrays. 7476 // Make sure we never try to shrink dense arrays into sparse arrays.
6849 ASSERT(static_cast<uint32_t>(FixedArray::cast(elements())->length()) <= 7477 ASSERT(static_cast<uint32_t>(FixedArray::cast(elements())->length()) <=
6850 new_length); 7478 new_length);
6851 Object* obj; 7479 MaybeObject* result = NormalizeElements();
6852 { MaybeObject* maybe_obj = NormalizeElements(); 7480 if (result->IsFailure()) return result;
6853 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
6854 }
6855 7481
6856 // Update length for JSArrays. 7482 // Update length for JSArrays.
6857 if (IsJSArray()) JSArray::cast(this)->set_length(len); 7483 if (IsJSArray()) JSArray::cast(this)->set_length(len);
6858 break; 7484 break;
6859 } 7485 }
6860 case DICTIONARY_ELEMENTS: { 7486 case DICTIONARY_ELEMENTS: {
6861 if (IsJSArray()) { 7487 if (IsJSArray()) {
6862 uint32_t old_length = 7488 uint32_t old_length =
6863 static_cast<uint32_t>(JSArray::cast(this)->length()->Number()); 7489 static_cast<uint32_t>(JSArray::cast(this)->length()->Number());
6864 element_dictionary()->RemoveNumberEntries(new_length, old_length), 7490 element_dictionary()->RemoveNumberEntries(new_length, old_length),
6865 JSArray::cast(this)->set_length(len); 7491 JSArray::cast(this)->set_length(len);
6866 } 7492 }
6867 break; 7493 break;
6868 } 7494 }
6869 default: 7495 case NON_STRICT_ARGUMENTS_ELEMENTS:
7496 UNIMPLEMENTED();
7497 break;
7498 case EXTERNAL_BYTE_ELEMENTS:
7499 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
7500 case EXTERNAL_SHORT_ELEMENTS:
7501 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
7502 case EXTERNAL_INT_ELEMENTS:
7503 case EXTERNAL_UNSIGNED_INT_ELEMENTS:
7504 case EXTERNAL_FLOAT_ELEMENTS:
7505 case EXTERNAL_DOUBLE_ELEMENTS:
7506 case EXTERNAL_PIXEL_ELEMENTS:
7507 case FAST_DOUBLE_ELEMENTS:
6870 UNREACHABLE(); 7508 UNREACHABLE();
6871 break; 7509 break;
6872 } 7510 }
6873 return this; 7511 return this;
6874 } 7512 }
6875 7513
6876 7514
6877 MaybeObject* JSArray::Initialize(int capacity) { 7515 MaybeObject* JSArray::Initialize(int capacity) {
6878 Heap* heap = GetHeap(); 7516 Heap* heap = GetHeap();
6879 ASSERT(capacity >= 0); 7517 ASSERT(capacity >= 0);
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
6924 if (value < 0) return ArrayLengthRangeError(GetHeap()); 7562 if (value < 0) return ArrayLengthRangeError(GetHeap());
6925 switch (GetElementsKind()) { 7563 switch (GetElementsKind()) {
6926 case FAST_ELEMENTS: { 7564 case FAST_ELEMENTS: {
6927 int old_capacity = FixedArray::cast(elements())->length(); 7565 int old_capacity = FixedArray::cast(elements())->length();
6928 if (value <= old_capacity) { 7566 if (value <= old_capacity) {
6929 if (IsJSArray()) { 7567 if (IsJSArray()) {
6930 Object* obj; 7568 Object* obj;
6931 { MaybeObject* maybe_obj = EnsureWritableFastElements(); 7569 { MaybeObject* maybe_obj = EnsureWritableFastElements();
6932 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 7570 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
6933 } 7571 }
6934 int old_length = FastD2I(JSArray::cast(this)->length()->Number()); 7572 FixedArray* fast_elements = FixedArray::cast(elements());
6935 // NOTE: We may be able to optimize this by removing the 7573 if (2 * value <= old_capacity) {
6936 // last part of the elements backing storage array and 7574 // If more than half the elements won't be used, trim the array.
6937 // setting the capacity to the new size. 7575 if (value == 0) {
6938 for (int i = value; i < old_length; i++) { 7576 initialize_elements();
6939 FixedArray::cast(elements())->set_the_hole(i); 7577 } else {
7578 fast_elements->set_length(value);
7579 Address filler_start = fast_elements->address() +
7580 FixedArray::OffsetOfElementAt(value);
7581 int filler_size = (old_capacity - value) * kPointerSize;
7582 GetHeap()->CreateFillerObjectAt(filler_start, filler_size);
7583 }
7584 } else {
7585 // Otherwise, fill the unused tail with holes.
7586 int old_length = FastD2I(JSArray::cast(this)->length()->Number());
7587 for (int i = value; i < old_length; i++) {
7588 fast_elements->set_the_hole(i);
7589 }
6940 } 7590 }
6941 JSArray::cast(this)->set_length(Smi::cast(smi_length)); 7591 JSArray::cast(this)->set_length(Smi::cast(smi_length));
6942 } 7592 }
6943 return this; 7593 return this;
6944 } 7594 }
6945 int min = NewElementsCapacity(old_capacity); 7595 int min = NewElementsCapacity(old_capacity);
6946 int new_capacity = value > min ? value : min; 7596 int new_capacity = value > min ? value : min;
6947 if (new_capacity <= kMaxFastElementsLength || 7597 if (new_capacity <= kMaxFastElementsLength ||
6948 !ShouldConvertToSlowElements(new_capacity)) { 7598 !ShouldConvertToSlowElements(new_capacity)) {
6949 Object* obj; 7599 MaybeObject* result =
6950 { MaybeObject* maybe_obj = 7600 SetFastElementsCapacityAndLength(new_capacity, value);
6951 SetFastElementsCapacityAndLength(new_capacity, value); 7601 if (result->IsFailure()) return result;
6952 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
6953 }
6954 return this; 7602 return this;
6955 } 7603 }
6956 break; 7604 break;
6957 } 7605 }
6958 case DICTIONARY_ELEMENTS: { 7606 case DICTIONARY_ELEMENTS: {
6959 if (IsJSArray()) { 7607 if (IsJSArray()) {
6960 if (value == 0) { 7608 if (value == 0) {
6961 // If the length of a slow array is reset to zero, we clear 7609 // If the length of a slow array is reset to zero, we clear
6962 // the array and flush backing storage. This has the added 7610 // the array and flush backing storage. This has the added
6963 // benefit that the array returns to fast mode. 7611 // benefit that the array returns to fast mode.
6964 Object* obj; 7612 Object* obj;
6965 { MaybeObject* maybe_obj = ResetElements(); 7613 { MaybeObject* maybe_obj = ResetElements();
6966 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 7614 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
6967 } 7615 }
6968 } else { 7616 } else {
6969 // Remove deleted elements. 7617 // Remove deleted elements.
6970 uint32_t old_length = 7618 uint32_t old_length =
6971 static_cast<uint32_t>(JSArray::cast(this)->length()->Number()); 7619 static_cast<uint32_t>(JSArray::cast(this)->length()->Number());
6972 element_dictionary()->RemoveNumberEntries(value, old_length); 7620 element_dictionary()->RemoveNumberEntries(value, old_length);
6973 } 7621 }
6974 JSArray::cast(this)->set_length(Smi::cast(smi_length)); 7622 JSArray::cast(this)->set_length(Smi::cast(smi_length));
6975 } 7623 }
6976 return this; 7624 return this;
6977 } 7625 }
6978 default: 7626 case NON_STRICT_ARGUMENTS_ELEMENTS:
7627 case EXTERNAL_BYTE_ELEMENTS:
7628 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
7629 case EXTERNAL_SHORT_ELEMENTS:
7630 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
7631 case EXTERNAL_INT_ELEMENTS:
7632 case EXTERNAL_UNSIGNED_INT_ELEMENTS:
7633 case EXTERNAL_FLOAT_ELEMENTS:
7634 case EXTERNAL_DOUBLE_ELEMENTS:
7635 case EXTERNAL_PIXEL_ELEMENTS:
7636 case FAST_DOUBLE_ELEMENTS:
6979 UNREACHABLE(); 7637 UNREACHABLE();
6980 break; 7638 break;
6981 } 7639 }
6982 } 7640 }
6983 7641
6984 // General slow case. 7642 // General slow case.
6985 if (len->IsNumber()) { 7643 if (len->IsNumber()) {
6986 uint32_t length; 7644 uint32_t length;
6987 if (len->ToArrayIndex(&length)) { 7645 if (len->ToArrayIndex(&length)) {
6988 return SetSlowElements(len); 7646 return SetSlowElements(len);
(...skipping 10 matching lines...) Expand all
6999 } 7657 }
7000 FixedArray::cast(obj)->set(0, len); 7658 FixedArray::cast(obj)->set(0, len);
7001 if (IsJSArray()) JSArray::cast(this)->set_length(Smi::FromInt(1)); 7659 if (IsJSArray()) JSArray::cast(this)->set_length(Smi::FromInt(1));
7002 set_elements(FixedArray::cast(obj)); 7660 set_elements(FixedArray::cast(obj));
7003 return this; 7661 return this;
7004 } 7662 }
7005 7663
7006 7664
7007 Object* Map::GetPrototypeTransition(Object* prototype) { 7665 Object* Map::GetPrototypeTransition(Object* prototype) {
7008 FixedArray* cache = prototype_transitions(); 7666 FixedArray* cache = prototype_transitions();
7009 int capacity = cache->length(); 7667 int number_of_transitions = NumberOfProtoTransitions();
7010 if (capacity == 0) return NULL; 7668 const int proto_offset =
7011 int finger = Smi::cast(cache->get(0))->value(); 7669 kProtoTransitionHeaderSize + kProtoTransitionPrototypeOffset;
7012 for (int i = 1; i < finger; i += 2) { 7670 const int map_offset = kProtoTransitionHeaderSize + kProtoTransitionMapOffset;
7013 if (cache->get(i) == prototype) return cache->get(i + 1); 7671 const int step = kProtoTransitionElementsPerEntry;
7672 for (int i = 0; i < number_of_transitions; i++) {
7673 if (cache->get(proto_offset + i * step) == prototype) {
7674 Object* map = cache->get(map_offset + i * step);
7675 ASSERT(map->IsMap());
7676 return map;
7677 }
7014 } 7678 }
7015 return NULL; 7679 return NULL;
7016 } 7680 }
7017 7681
7018 7682
7019 MaybeObject* Map::PutPrototypeTransition(Object* prototype, Map* map) { 7683 MaybeObject* Map::PutPrototypeTransition(Object* prototype, Map* map) {
7684 ASSERT(map->IsMap());
7685 ASSERT(HeapObject::cast(prototype)->map()->IsMap());
7020 // Don't cache prototype transition if this map is shared. 7686 // Don't cache prototype transition if this map is shared.
7021 if (is_shared() || !FLAG_cache_prototype_transitions) return this; 7687 if (is_shared() || !FLAG_cache_prototype_transitions) return this;
7022 7688
7023 FixedArray* cache = prototype_transitions(); 7689 FixedArray* cache = prototype_transitions();
7024 7690
7025 int capacity = cache->length(); 7691 const int step = kProtoTransitionElementsPerEntry;
7692 const int header = kProtoTransitionHeaderSize;
7026 7693
7027 int finger = (capacity == 0) ? 1 : Smi::cast(cache->get(0))->value(); 7694 int capacity = (cache->length() - header) / step;
7028 7695
7029 if (finger >= capacity) { 7696 int transitions = NumberOfProtoTransitions() + 1;
7697
7698 if (transitions > capacity) {
7030 if (capacity > kMaxCachedPrototypeTransitions) return this; 7699 if (capacity > kMaxCachedPrototypeTransitions) return this;
7031 7700
7032 FixedArray* new_cache; 7701 FixedArray* new_cache;
7033 { MaybeObject* maybe_cache = GetHeap()->AllocateFixedArray(finger * 2 + 1); 7702 // Grow array by factor 2 over and above what we need.
7703 { MaybeObject* maybe_cache =
7704 GetHeap()->AllocateFixedArray(transitions * 2 * step + header);
7034 if (!maybe_cache->To<FixedArray>(&new_cache)) return maybe_cache; 7705 if (!maybe_cache->To<FixedArray>(&new_cache)) return maybe_cache;
7035 } 7706 }
7036 7707
7037 for (int i = 1; i < capacity; i++) new_cache->set(i, cache->get(i)); 7708 for (int i = 0; i < capacity * step; i++) {
7709 new_cache->set(i + header, cache->get(i + header));
7710 }
7038 cache = new_cache; 7711 cache = new_cache;
7039 set_prototype_transitions(cache); 7712 set_prototype_transitions(cache);
7040 } 7713 }
7041 7714
7042 cache->set(finger, prototype); 7715 int last = transitions - 1;
7043 cache->set(finger + 1, map); 7716
7044 cache->set(0, Smi::FromInt(finger + 2)); 7717 cache->set(header + last * step + kProtoTransitionPrototypeOffset, prototype);
7718 cache->set(header + last * step + kProtoTransitionMapOffset, map);
7719 SetNumberOfProtoTransitions(transitions);
7045 7720
7046 return cache; 7721 return cache;
7047 } 7722 }
7048 7723
7049 7724
7050 MaybeObject* JSObject::SetPrototype(Object* value, 7725 MaybeObject* JSReceiver::SetPrototype(Object* value,
7051 bool skip_hidden_prototypes) { 7726 bool skip_hidden_prototypes) {
7727 #ifdef DEBUG
7728 int size = Size();
7729 #endif
7730
7052 Heap* heap = GetHeap(); 7731 Heap* heap = GetHeap();
7053 // Silently ignore the change if value is not a JSObject or null. 7732 // Silently ignore the change if value is not a JSObject or null.
7054 // SpiderMonkey behaves this way. 7733 // SpiderMonkey behaves this way.
7055 if (!value->IsJSObject() && !value->IsNull()) return value; 7734 if (!value->IsJSReceiver() && !value->IsNull()) return value;
7056 7735
7057 // From 8.6.2 Object Internal Methods 7736 // From 8.6.2 Object Internal Methods
7058 // ... 7737 // ...
7059 // In addition, if [[Extensible]] is false the value of the [[Class]] and 7738 // In addition, if [[Extensible]] is false the value of the [[Class]] and
7060 // [[Prototype]] internal properties of the object may not be modified. 7739 // [[Prototype]] internal properties of the object may not be modified.
7061 // ... 7740 // ...
7062 // Implementation specific extensions that modify [[Class]], [[Prototype]] 7741 // Implementation specific extensions that modify [[Class]], [[Prototype]]
7063 // or [[Extensible]] must not violate the invariants defined in the preceding 7742 // or [[Extensible]] must not violate the invariants defined in the preceding
7064 // paragraph. 7743 // paragraph.
7065 if (!this->map()->is_extensible()) { 7744 if (!this->map()->is_extensible()) {
(...skipping 10 matching lines...) Expand all
7076 // chain. 7755 // chain.
7077 for (Object* pt = value; pt != heap->null_value(); pt = pt->GetPrototype()) { 7756 for (Object* pt = value; pt != heap->null_value(); pt = pt->GetPrototype()) {
7078 if (JSObject::cast(pt) == this) { 7757 if (JSObject::cast(pt) == this) {
7079 // Cycle detected. 7758 // Cycle detected.
7080 HandleScope scope; 7759 HandleScope scope;
7081 return heap->isolate()->Throw( 7760 return heap->isolate()->Throw(
7082 *FACTORY->NewError("cyclic_proto", HandleVector<Object>(NULL, 0))); 7761 *FACTORY->NewError("cyclic_proto", HandleVector<Object>(NULL, 0)));
7083 } 7762 }
7084 } 7763 }
7085 7764
7086 JSObject* real_receiver = this; 7765 JSReceiver* real_receiver = this;
7087 7766
7088 if (skip_hidden_prototypes) { 7767 if (skip_hidden_prototypes) {
7089 // Find the first object in the chain whose prototype object is not 7768 // Find the first object in the chain whose prototype object is not
7090 // hidden and set the new prototype on that object. 7769 // hidden and set the new prototype on that object.
7091 Object* current_proto = real_receiver->GetPrototype(); 7770 Object* current_proto = real_receiver->GetPrototype();
7092 while (current_proto->IsJSObject() && 7771 while (current_proto->IsJSObject() &&
7093 JSObject::cast(current_proto)->map()->is_hidden_prototype()) { 7772 JSObject::cast(current_proto)->map()->is_hidden_prototype()) {
7094 real_receiver = JSObject::cast(current_proto); 7773 real_receiver = JSObject::cast(current_proto);
7095 current_proto = current_proto->GetPrototype(); 7774 current_proto = current_proto->GetPrototype();
7096 } 7775 }
(...skipping 15 matching lines...) Expand all
7112 map->PutPrototypeTransition(value, Map::cast(new_map)); 7791 map->PutPrototypeTransition(value, Map::cast(new_map));
7113 if (maybe_new_cache->IsFailure()) return maybe_new_cache; 7792 if (maybe_new_cache->IsFailure()) return maybe_new_cache;
7114 } 7793 }
7115 7794
7116 Map::cast(new_map)->set_prototype(value); 7795 Map::cast(new_map)->set_prototype(value);
7117 } 7796 }
7118 ASSERT(Map::cast(new_map)->prototype() == value); 7797 ASSERT(Map::cast(new_map)->prototype() == value);
7119 real_receiver->set_map(Map::cast(new_map)); 7798 real_receiver->set_map(Map::cast(new_map));
7120 7799
7121 heap->ClearInstanceofCache(); 7800 heap->ClearInstanceofCache();
7122 7801 ASSERT(size == Size());
7123 return value; 7802 return value;
7124 } 7803 }
7125 7804
7126 7805
7127 bool JSObject::HasElementPostInterceptor(JSObject* receiver, uint32_t index) { 7806 bool JSObject::HasElementPostInterceptor(JSReceiver* receiver, uint32_t index) {
7128 switch (GetElementsKind()) { 7807 switch (GetElementsKind()) {
7129 case FAST_ELEMENTS: { 7808 case FAST_ELEMENTS: {
7130 uint32_t length = IsJSArray() ? 7809 uint32_t length = IsJSArray() ?
7131 static_cast<uint32_t> 7810 static_cast<uint32_t>
7132 (Smi::cast(JSArray::cast(this)->length())->value()) : 7811 (Smi::cast(JSArray::cast(this)->length())->value()) :
7133 static_cast<uint32_t>(FixedArray::cast(elements())->length()); 7812 static_cast<uint32_t>(FixedArray::cast(elements())->length());
7134 if ((index < length) && 7813 if ((index < length) &&
7135 !FixedArray::cast(elements())->get(index)->IsTheHole()) { 7814 !FixedArray::cast(elements())->get(index)->IsTheHole()) {
7136 return true; 7815 return true;
7137 } 7816 }
7138 break; 7817 break;
7139 } 7818 }
7140 case EXTERNAL_PIXEL_ELEMENTS: { 7819 case EXTERNAL_PIXEL_ELEMENTS: {
7141 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements()); 7820 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements());
7142 if (index < static_cast<uint32_t>(pixels->length())) { 7821 if (index < static_cast<uint32_t>(pixels->length())) {
7143 return true; 7822 return true;
7144 } 7823 }
7145 break; 7824 break;
7146 } 7825 }
7147 case EXTERNAL_BYTE_ELEMENTS: 7826 case EXTERNAL_BYTE_ELEMENTS:
7148 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 7827 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
7149 case EXTERNAL_SHORT_ELEMENTS: 7828 case EXTERNAL_SHORT_ELEMENTS:
7150 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 7829 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
7151 case EXTERNAL_INT_ELEMENTS: 7830 case EXTERNAL_INT_ELEMENTS:
7152 case EXTERNAL_UNSIGNED_INT_ELEMENTS: 7831 case EXTERNAL_UNSIGNED_INT_ELEMENTS:
7153 case EXTERNAL_FLOAT_ELEMENTS: 7832 case EXTERNAL_FLOAT_ELEMENTS:
7154 case EXTERNAL_DOUBLE_ELEMENTS: { 7833 case EXTERNAL_DOUBLE_ELEMENTS:
7834 case FAST_DOUBLE_ELEMENTS: {
7155 ExternalArray* array = ExternalArray::cast(elements()); 7835 ExternalArray* array = ExternalArray::cast(elements());
7156 if (index < static_cast<uint32_t>(array->length())) { 7836 if (index < static_cast<uint32_t>(array->length())) {
7157 return true; 7837 return true;
7158 } 7838 }
7159 break; 7839 break;
7160 } 7840 }
7161 case DICTIONARY_ELEMENTS: { 7841 case DICTIONARY_ELEMENTS: {
7162 if (element_dictionary()->FindEntry(index) 7842 if (element_dictionary()->FindEntry(index)
7163 != NumberDictionary::kNotFound) { 7843 != NumberDictionary::kNotFound) {
7164 return true; 7844 return true;
7165 } 7845 }
7166 break; 7846 break;
7167 } 7847 }
7168 default: 7848 case NON_STRICT_ARGUMENTS_ELEMENTS:
7169 UNREACHABLE(); 7849 UNREACHABLE();
7170 break; 7850 break;
7171 } 7851 }
7172 7852
7173 // Handle [] on String objects. 7853 // Handle [] on String objects.
7174 if (this->IsStringObjectWithCharacterAt(index)) return true; 7854 if (this->IsStringObjectWithCharacterAt(index)) return true;
7175 7855
7176 Object* pt = GetPrototype(); 7856 Object* pt = GetPrototype();
7177 if (pt->IsNull()) return false; 7857 if (pt->IsNull()) return false;
7178 return JSObject::cast(pt)->HasElementWithReceiver(receiver, index); 7858 return JSObject::cast(pt)->HasElementWithReceiver(receiver, index);
7179 } 7859 }
7180 7860
7181 7861
7182 bool JSObject::HasElementWithInterceptor(JSObject* receiver, uint32_t index) { 7862 bool JSObject::HasElementWithInterceptor(JSReceiver* receiver, uint32_t index) {
7183 Isolate* isolate = GetIsolate(); 7863 Isolate* isolate = GetIsolate();
7184 // Make sure that the top context does not change when doing 7864 // Make sure that the top context does not change when doing
7185 // callbacks or interceptor calls. 7865 // callbacks or interceptor calls.
7186 AssertNoContextChange ncc; 7866 AssertNoContextChange ncc;
7187 HandleScope scope(isolate); 7867 HandleScope scope(isolate);
7188 Handle<InterceptorInfo> interceptor(GetIndexedInterceptor()); 7868 Handle<InterceptorInfo> interceptor(GetIndexedInterceptor());
7189 Handle<JSObject> receiver_handle(receiver); 7869 Handle<JSReceiver> receiver_handle(receiver);
7190 Handle<JSObject> holder_handle(this); 7870 Handle<JSObject> holder_handle(this);
7191 CustomArguments args(isolate, interceptor->data(), receiver, this); 7871 CustomArguments args(isolate, interceptor->data(), receiver, this);
7192 v8::AccessorInfo info(args.end()); 7872 v8::AccessorInfo info(args.end());
7193 if (!interceptor->query()->IsUndefined()) { 7873 if (!interceptor->query()->IsUndefined()) {
7194 v8::IndexedPropertyQuery query = 7874 v8::IndexedPropertyQuery query =
7195 v8::ToCData<v8::IndexedPropertyQuery>(interceptor->query()); 7875 v8::ToCData<v8::IndexedPropertyQuery>(interceptor->query());
7196 LOG(isolate, 7876 LOG(isolate,
7197 ApiIndexedPropertyAccess("interceptor-indexed-has", this, index)); 7877 ApiIndexedPropertyAccess("interceptor-indexed-has", this, index));
7198 v8::Handle<v8::Integer> result; 7878 v8::Handle<v8::Integer> result;
7199 { 7879 {
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
7272 case EXTERNAL_SHORT_ELEMENTS: 7952 case EXTERNAL_SHORT_ELEMENTS:
7273 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 7953 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
7274 case EXTERNAL_INT_ELEMENTS: 7954 case EXTERNAL_INT_ELEMENTS:
7275 case EXTERNAL_UNSIGNED_INT_ELEMENTS: 7955 case EXTERNAL_UNSIGNED_INT_ELEMENTS:
7276 case EXTERNAL_FLOAT_ELEMENTS: 7956 case EXTERNAL_FLOAT_ELEMENTS:
7277 case EXTERNAL_DOUBLE_ELEMENTS: { 7957 case EXTERNAL_DOUBLE_ELEMENTS: {
7278 ExternalArray* array = ExternalArray::cast(elements()); 7958 ExternalArray* array = ExternalArray::cast(elements());
7279 if (index < static_cast<uint32_t>(array->length())) return FAST_ELEMENT; 7959 if (index < static_cast<uint32_t>(array->length())) return FAST_ELEMENT;
7280 break; 7960 break;
7281 } 7961 }
7962 case FAST_DOUBLE_ELEMENTS:
7963 UNREACHABLE();
7964 break;
7282 case DICTIONARY_ELEMENTS: { 7965 case DICTIONARY_ELEMENTS: {
7283 if (element_dictionary()->FindEntry(index) != 7966 if (element_dictionary()->FindEntry(index) !=
7284 NumberDictionary::kNotFound) { 7967 NumberDictionary::kNotFound) {
7285 return DICTIONARY_ELEMENT; 7968 return DICTIONARY_ELEMENT;
7286 } 7969 }
7287 break; 7970 break;
7288 } 7971 }
7289 default: 7972 case NON_STRICT_ARGUMENTS_ELEMENTS: {
7290 UNREACHABLE(); 7973 // Aliased parameters and non-aliased elements in a fast backing store
7974 // behave as FAST_ELEMENT. Non-aliased elements in a dictionary
7975 // backing store behave as DICTIONARY_ELEMENT.
7976 FixedArray* parameter_map = FixedArray::cast(elements());
7977 uint32_t length = parameter_map->length();
7978 Object* probe =
7979 index < (length - 2) ? parameter_map->get(index + 2) : NULL;
7980 if (probe != NULL && !probe->IsTheHole()) return FAST_ELEMENT;
7981 // If not aliased, check the arguments.
7982 FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
7983 if (arguments->IsDictionary()) {
7984 NumberDictionary* dictionary = NumberDictionary::cast(arguments);
7985 if (dictionary->FindEntry(index) != NumberDictionary::kNotFound) {
7986 return DICTIONARY_ELEMENT;
7987 }
7988 } else {
7989 length = arguments->length();
7990 probe = (index < length) ? arguments->get(index) : NULL;
7991 if (probe != NULL && !probe->IsTheHole()) return FAST_ELEMENT;
7992 }
7291 break; 7993 break;
7994 }
7292 } 7995 }
7293 7996
7294 return UNDEFINED_ELEMENT; 7997 return UNDEFINED_ELEMENT;
7295 } 7998 }
7296 7999
7297 8000
7298 bool JSObject::HasElementWithReceiver(JSObject* receiver, uint32_t index) { 8001 bool JSObject::HasElementInElements(FixedArray* elements,
8002 ElementsKind kind,
8003 uint32_t index) {
8004 ASSERT(kind == FAST_ELEMENTS || kind == DICTIONARY_ELEMENTS);
8005 if (kind == FAST_ELEMENTS) {
8006 int length = IsJSArray()
8007 ? Smi::cast(JSArray::cast(this)->length())->value()
8008 : elements->length();
8009 if (index < static_cast<uint32_t>(length) &&
8010 !elements->get(index)->IsTheHole()) {
8011 return true;
8012 }
8013 } else {
8014 if (NumberDictionary::cast(elements)->FindEntry(index) !=
8015 NumberDictionary::kNotFound) {
8016 return true;
8017 }
8018 }
8019 return false;
8020 }
8021
8022
8023 bool JSObject::HasElementWithReceiver(JSReceiver* receiver, uint32_t index) {
7299 // Check access rights if needed. 8024 // Check access rights if needed.
7300 if (IsAccessCheckNeeded()) { 8025 if (IsAccessCheckNeeded()) {
7301 Heap* heap = GetHeap(); 8026 Heap* heap = GetHeap();
7302 if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) { 8027 if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) {
7303 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS); 8028 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS);
7304 return false; 8029 return false;
7305 } 8030 }
7306 } 8031 }
7307 8032
7308 // Check for lookup interceptor 8033 // Check for lookup interceptor
7309 if (HasIndexedInterceptor()) { 8034 if (HasIndexedInterceptor()) {
7310 return HasElementWithInterceptor(receiver, index); 8035 return HasElementWithInterceptor(receiver, index);
7311 } 8036 }
7312 8037
7313 switch (GetElementsKind()) { 8038 ElementsKind kind = GetElementsKind();
8039 switch (kind) {
7314 case FAST_ELEMENTS: { 8040 case FAST_ELEMENTS: {
7315 uint32_t length = IsJSArray() ? 8041 uint32_t length = IsJSArray() ?
7316 static_cast<uint32_t> 8042 static_cast<uint32_t>
7317 (Smi::cast(JSArray::cast(this)->length())->value()) : 8043 (Smi::cast(JSArray::cast(this)->length())->value()) :
7318 static_cast<uint32_t>(FixedArray::cast(elements())->length()); 8044 static_cast<uint32_t>(FixedArray::cast(elements())->length());
7319 if ((index < length) && 8045 if ((index < length) &&
7320 !FixedArray::cast(elements())->get(index)->IsTheHole()) return true; 8046 !FixedArray::cast(elements())->get(index)->IsTheHole()) return true;
7321 break; 8047 break;
7322 } 8048 }
7323 case EXTERNAL_PIXEL_ELEMENTS: { 8049 case EXTERNAL_PIXEL_ELEMENTS: {
(...skipping 10 matching lines...) Expand all
7334 case EXTERNAL_INT_ELEMENTS: 8060 case EXTERNAL_INT_ELEMENTS:
7335 case EXTERNAL_UNSIGNED_INT_ELEMENTS: 8061 case EXTERNAL_UNSIGNED_INT_ELEMENTS:
7336 case EXTERNAL_FLOAT_ELEMENTS: 8062 case EXTERNAL_FLOAT_ELEMENTS:
7337 case EXTERNAL_DOUBLE_ELEMENTS: { 8063 case EXTERNAL_DOUBLE_ELEMENTS: {
7338 ExternalArray* array = ExternalArray::cast(elements()); 8064 ExternalArray* array = ExternalArray::cast(elements());
7339 if (index < static_cast<uint32_t>(array->length())) { 8065 if (index < static_cast<uint32_t>(array->length())) {
7340 return true; 8066 return true;
7341 } 8067 }
7342 break; 8068 break;
7343 } 8069 }
8070 case FAST_DOUBLE_ELEMENTS:
8071 UNREACHABLE();
8072 break;
7344 case DICTIONARY_ELEMENTS: { 8073 case DICTIONARY_ELEMENTS: {
7345 if (element_dictionary()->FindEntry(index) 8074 if (element_dictionary()->FindEntry(index)
7346 != NumberDictionary::kNotFound) { 8075 != NumberDictionary::kNotFound) {
7347 return true; 8076 return true;
7348 } 8077 }
7349 break; 8078 break;
7350 } 8079 }
7351 default: 8080 case NON_STRICT_ARGUMENTS_ELEMENTS: {
7352 UNREACHABLE(); 8081 FixedArray* parameter_map = FixedArray::cast(elements());
8082 uint32_t length = parameter_map->length();
8083 Object* probe =
8084 (index < length - 2) ? parameter_map->get(index + 2) : NULL;
8085 if (probe != NULL && !probe->IsTheHole()) return true;
8086
8087 // Not a mapped parameter, check the arguments.
8088 FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
8089 kind = arguments->IsDictionary() ? DICTIONARY_ELEMENTS : FAST_ELEMENTS;
8090 if (HasElementInElements(arguments, kind, index)) return true;
7353 break; 8091 break;
8092 }
7354 } 8093 }
7355 8094
7356 // Handle [] on String objects. 8095 // Handle [] on String objects.
7357 if (this->IsStringObjectWithCharacterAt(index)) return true; 8096 if (this->IsStringObjectWithCharacterAt(index)) return true;
7358 8097
7359 Object* pt = GetPrototype(); 8098 Object* pt = GetPrototype();
7360 if (pt->IsNull()) return false; 8099 if (pt->IsNull()) return false;
7361 return JSObject::cast(pt)->HasElementWithReceiver(receiver, index); 8100 return JSObject::cast(pt)->HasElementWithReceiver(receiver, index);
7362 } 8101 }
7363 8102
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
7409 8148
7410 // api style callbacks. 8149 // api style callbacks.
7411 if (structure->IsAccessorInfo()) { 8150 if (structure->IsAccessorInfo()) {
7412 Handle<AccessorInfo> data(AccessorInfo::cast(structure)); 8151 Handle<AccessorInfo> data(AccessorInfo::cast(structure));
7413 Object* fun_obj = data->getter(); 8152 Object* fun_obj = data->getter();
7414 v8::AccessorGetter call_fun = v8::ToCData<v8::AccessorGetter>(fun_obj); 8153 v8::AccessorGetter call_fun = v8::ToCData<v8::AccessorGetter>(fun_obj);
7415 HandleScope scope(isolate); 8154 HandleScope scope(isolate);
7416 Handle<JSObject> self(JSObject::cast(receiver)); 8155 Handle<JSObject> self(JSObject::cast(receiver));
7417 Handle<JSObject> holder_handle(JSObject::cast(holder)); 8156 Handle<JSObject> holder_handle(JSObject::cast(holder));
7418 Handle<Object> number = isolate->factory()->NewNumberFromUint(index); 8157 Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
7419 Handle<String> key(isolate->factory()->NumberToString(number)); 8158 Handle<String> key = isolate->factory()->NumberToString(number);
7420 LOG(isolate, ApiNamedPropertyAccess("load", *self, *key)); 8159 LOG(isolate, ApiNamedPropertyAccess("load", *self, *key));
7421 CustomArguments args(isolate, data->data(), *self, *holder_handle); 8160 CustomArguments args(isolate, data->data(), *self, *holder_handle);
7422 v8::AccessorInfo info(args.end()); 8161 v8::AccessorInfo info(args.end());
7423 v8::Handle<v8::Value> result; 8162 v8::Handle<v8::Value> result;
7424 { 8163 {
7425 // Leaving JavaScript. 8164 // Leaving JavaScript.
7426 VMState state(isolate, EXTERNAL); 8165 VMState state(isolate, EXTERNAL);
7427 result = call_fun(v8::Utils::ToLocal(key), info); 8166 result = call_fun(v8::Utils::ToLocal(key), info);
7428 } 8167 }
7429 RETURN_IF_SCHEDULED_EXCEPTION(isolate); 8168 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
7504 *isolate->factory()->NewTypeError("no_setter_in_callback", 8243 *isolate->factory()->NewTypeError("no_setter_in_callback",
7505 HandleVector(args, 2))); 8244 HandleVector(args, 2)));
7506 } 8245 }
7507 } 8246 }
7508 8247
7509 UNREACHABLE(); 8248 UNREACHABLE();
7510 return NULL; 8249 return NULL;
7511 } 8250 }
7512 8251
7513 8252
8253 bool JSObject::HasFastArgumentsElements() {
8254 Heap* heap = GetHeap();
8255 if (!elements()->IsFixedArray()) return false;
8256 FixedArray* elements = FixedArray::cast(this->elements());
8257 if (elements->map() != heap->non_strict_arguments_elements_map()) {
8258 return false;
8259 }
8260 FixedArray* arguments = FixedArray::cast(elements->get(1));
8261 return !arguments->IsDictionary();
8262 }
8263
8264
8265 bool JSObject::HasDictionaryArgumentsElements() {
8266 Heap* heap = GetHeap();
8267 if (!elements()->IsFixedArray()) return false;
8268 FixedArray* elements = FixedArray::cast(this->elements());
8269 if (elements->map() != heap->non_strict_arguments_elements_map()) {
8270 return false;
8271 }
8272 FixedArray* arguments = FixedArray::cast(elements->get(1));
8273 return arguments->IsDictionary();
8274 }
8275
8276
7514 // Adding n elements in fast case is O(n*n). 8277 // Adding n elements in fast case is O(n*n).
7515 // Note: revisit design to have dual undefined values to capture absent 8278 // Note: revisit design to have dual undefined values to capture absent
7516 // elements. 8279 // elements.
7517 MaybeObject* JSObject::SetFastElement(uint32_t index, 8280 MaybeObject* JSObject::SetFastElement(uint32_t index,
7518 Object* value, 8281 Object* value,
7519 StrictModeFlag strict_mode, 8282 StrictModeFlag strict_mode,
7520 bool check_prototype) { 8283 bool check_prototype) {
7521 ASSERT(HasFastElements()); 8284 ASSERT(HasFastElements() || HasFastArgumentsElements());
7522 8285
7523 Object* elms_obj; 8286 FixedArray* backing_store = FixedArray::cast(elements());
7524 { MaybeObject* maybe_elms_obj = EnsureWritableFastElements(); 8287 if (backing_store->map() == GetHeap()->non_strict_arguments_elements_map()) {
7525 if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj; 8288 backing_store = FixedArray::cast(backing_store->get(1));
8289 } else {
8290 Object* writable;
8291 MaybeObject* maybe = EnsureWritableFastElements();
8292 if (!maybe->ToObject(&writable)) return maybe;
8293 backing_store = FixedArray::cast(writable);
7526 } 8294 }
7527 FixedArray* elms = FixedArray::cast(elms_obj); 8295 uint32_t length = static_cast<uint32_t>(backing_store->length());
7528 uint32_t elms_length = static_cast<uint32_t>(elms->length());
7529 8296
7530 if (check_prototype && 8297 if (check_prototype &&
7531 (index >= elms_length || elms->get(index)->IsTheHole())) { 8298 (index >= length || backing_store->get(index)->IsTheHole())) {
7532 bool found; 8299 bool found;
7533 MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index, 8300 MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index,
7534 value, 8301 value,
8302 &found,
8303 strict_mode);
8304 if (found) return result;
8305 }
8306
8307 // Check whether there is extra space in fixed array.
8308 if (index < length) {
8309 backing_store->set(index, value);
8310 if (IsJSArray()) {
8311 // Update the length of the array if needed.
8312 uint32_t array_length = 0;
8313 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length));
8314 if (index >= array_length) {
8315 JSArray::cast(this)->set_length(Smi::FromInt(index + 1));
8316 }
8317 }
8318 return value;
8319 }
8320
8321 // Allow gap in fast case.
8322 if ((index - length) < kMaxGap) {
8323 // Try allocating extra space.
8324 int new_capacity = NewElementsCapacity(index + 1);
8325 if (new_capacity <= kMaxFastElementsLength ||
8326 !ShouldConvertToSlowElements(new_capacity)) {
8327 ASSERT(static_cast<uint32_t>(new_capacity) > index);
8328 Object* new_elements;
8329 MaybeObject* maybe =
8330 SetFastElementsCapacityAndLength(new_capacity, index + 1);
8331 if (!maybe->ToObject(&new_elements)) return maybe;
8332 FixedArray::cast(new_elements)->set(index, value);
8333 return value;
8334 }
8335 }
8336
8337 // Otherwise default to slow case.
8338 MaybeObject* result = NormalizeElements();
8339 if (result->IsFailure()) return result;
8340 return SetDictionaryElement(index, value, strict_mode, check_prototype);
8341 }
8342
8343
8344 MaybeObject* JSObject::SetDictionaryElement(uint32_t index,
8345 Object* value,
8346 StrictModeFlag strict_mode,
8347 bool check_prototype) {
8348 ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements());
8349 Isolate* isolate = GetIsolate();
8350 Heap* heap = isolate->heap();
8351
8352 // Insert element in the dictionary.
8353 FixedArray* elements = FixedArray::cast(this->elements());
8354 bool is_arguments =
8355 (elements->map() == heap->non_strict_arguments_elements_map());
8356 NumberDictionary* dictionary = NULL;
8357 if (is_arguments) {
8358 dictionary = NumberDictionary::cast(elements->get(1));
8359 } else {
8360 dictionary = NumberDictionary::cast(elements);
8361 }
8362
8363 int entry = dictionary->FindEntry(index);
8364 if (entry != NumberDictionary::kNotFound) {
8365 Object* element = dictionary->ValueAt(entry);
8366 PropertyDetails details = dictionary->DetailsAt(entry);
8367 if (details.type() == CALLBACKS) {
8368 return SetElementWithCallback(element, index, value, this, strict_mode);
8369 } else {
8370 dictionary->UpdateMaxNumberKey(index);
8371 // If put fails in strict mode, throw an exception.
8372 if (!dictionary->ValueAtPut(entry, value) && strict_mode == kStrictMode) {
8373 Handle<Object> holder(this);
8374 Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
8375 Handle<Object> args[2] = { number, holder };
8376 Handle<Object> error =
8377 isolate->factory()->NewTypeError("strict_read_only_property",
8378 HandleVector(args, 2));
8379 return isolate->Throw(*error);
8380 }
8381 }
8382 } else {
8383 // Index not already used. Look for an accessor in the prototype chain.
8384 if (check_prototype) {
8385 bool found;
8386 MaybeObject* result =
8387 SetElementWithCallbackSetterInPrototypes(
8388 index, value, &found, strict_mode);
8389 if (found) return result;
8390 }
8391 // When we set the is_extensible flag to false we always force the
8392 // element into dictionary mode (and force them to stay there).
8393 if (!map()->is_extensible()) {
8394 if (strict_mode == kNonStrictMode) {
8395 return isolate->heap()->undefined_value();
8396 } else {
8397 Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
8398 Handle<String> name = isolate->factory()->NumberToString(number);
8399 Handle<Object> args[1] = { name };
8400 Handle<Object> error =
8401 isolate->factory()->NewTypeError("object_not_extensible",
8402 HandleVector(args, 1));
8403 return isolate->Throw(*error);
8404 }
8405 }
8406 Object* new_dictionary;
8407 MaybeObject* maybe = dictionary->AtNumberPut(index, value);
8408 if (!maybe->ToObject(&new_dictionary)) return maybe;
8409 if (dictionary != NumberDictionary::cast(new_dictionary)) {
8410 if (is_arguments) {
8411 elements->set(1, new_dictionary);
8412 } else {
8413 set_elements(HeapObject::cast(new_dictionary));
8414 }
8415 dictionary = NumberDictionary::cast(new_dictionary);
8416 }
8417 }
8418
8419 // Update the array length if this JSObject is an array.
8420 if (IsJSArray()) {
8421 MaybeObject* result =
8422 JSArray::cast(this)->JSArrayUpdateLengthFromIndex(index, value);
8423 if (result->IsFailure()) return result;
8424 }
8425
8426 // Attempt to put this object back in fast case.
8427 if (ShouldConvertToFastElements()) {
8428 uint32_t new_length = 0;
8429 if (IsJSArray()) {
8430 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&new_length));
8431 } else {
8432 new_length = dictionary->max_number_key() + 1;
8433 }
8434 MaybeObject* result =
8435 SetFastElementsCapacityAndLength(new_length, new_length);
8436 if (result->IsFailure()) return result;
8437 #ifdef DEBUG
8438 if (FLAG_trace_normalization) {
8439 PrintF("Object elements are fast case again:\n");
8440 Print();
8441 }
8442 #endif
8443 }
8444 return value;
8445 }
8446
8447
8448 MUST_USE_RESULT MaybeObject* JSObject::SetFastDoubleElement(
8449 uint32_t index,
8450 Object* value,
8451 StrictModeFlag strict_mode,
8452 bool check_prototype) {
8453 ASSERT(HasFastDoubleElements());
8454
8455 FixedDoubleArray* elms = FixedDoubleArray::cast(elements());
8456 uint32_t elms_length = static_cast<uint32_t>(elms->length());
8457
8458 // If storing to an element that isn't in the array, pass the store request
8459 // up the prototype chain before storing in the receiver's elements.
8460 if (check_prototype &&
8461 (index >= elms_length || elms->is_the_hole(index))) {
8462 bool found;
8463 MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index,
8464 value,
7535 &found, 8465 &found,
7536 strict_mode); 8466 strict_mode);
7537 if (found) return result; 8467 if (found) return result;
7538 } 8468 }
7539 8469
8470 // If the value object is not a heap number, switch to fast elements and try
8471 // again.
8472 bool value_is_smi = value->IsSmi();
8473 if (!value->IsNumber()) {
8474 Object* obj;
8475 uint32_t length = elms_length;
8476 if (IsJSArray()) {
8477 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length));
8478 }
8479 MaybeObject* maybe_obj =
8480 SetFastElementsCapacityAndLength(elms_length, length);
8481 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
8482 return SetFastElement(index, value, strict_mode, check_prototype);
8483 }
7540 8484
7541 // Check whether there is extra space in fixed array.. 8485 double double_value = value_is_smi
8486 ? static_cast<double>(Smi::cast(value)->value())
8487 : HeapNumber::cast(value)->value();
8488
8489 // Check whether there is extra space in the fixed array.
7542 if (index < elms_length) { 8490 if (index < elms_length) {
7543 elms->set(index, value); 8491 elms->set(index, double_value);
7544 if (IsJSArray()) { 8492 if (IsJSArray()) {
7545 // Update the length of the array if needed. 8493 // Update the length of the array if needed.
7546 uint32_t array_length = 0; 8494 uint32_t array_length = 0;
7547 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length)); 8495 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length));
7548 if (index >= array_length) { 8496 if (index >= array_length) {
7549 JSArray::cast(this)->set_length(Smi::FromInt(index + 1)); 8497 JSArray::cast(this)->set_length(Smi::FromInt(index + 1));
7550 } 8498 }
7551 } 8499 }
7552 return value; 8500 return value;
7553 } 8501 }
7554 8502
7555 // Allow gap in fast case. 8503 // Allow gap in fast case.
7556 if ((index - elms_length) < kMaxGap) { 8504 if ((index - elms_length) < kMaxGap) {
7557 // Try allocating extra space. 8505 // Try allocating extra space.
7558 int new_capacity = NewElementsCapacity(index+1); 8506 int new_capacity = NewElementsCapacity(index+1);
7559 if (new_capacity <= kMaxFastElementsLength || 8507 if (new_capacity <= kMaxFastElementsLength ||
7560 !ShouldConvertToSlowElements(new_capacity)) { 8508 !ShouldConvertToSlowElements(new_capacity)) {
7561 ASSERT(static_cast<uint32_t>(new_capacity) > index); 8509 ASSERT(static_cast<uint32_t>(new_capacity) > index);
7562 Object* obj; 8510 Object* obj;
7563 { MaybeObject* maybe_obj = 8511 { MaybeObject* maybe_obj =
7564 SetFastElementsCapacityAndLength(new_capacity, index + 1); 8512 SetFastDoubleElementsCapacityAndLength(new_capacity,
8513 index + 1);
7565 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 8514 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
7566 } 8515 }
7567 FixedArray::cast(elements())->set(index, value); 8516 FixedDoubleArray::cast(elements())->set(index, double_value);
7568 return value; 8517 return value;
7569 } 8518 }
7570 } 8519 }
7571 8520
7572 // Otherwise default to slow case. 8521 // Otherwise default to slow case.
7573 Object* obj; 8522 Object* obj;
7574 { MaybeObject* maybe_obj = NormalizeElements(); 8523 { MaybeObject* maybe_obj = NormalizeElements();
7575 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 8524 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
7576 } 8525 }
7577 ASSERT(HasDictionaryElements()); 8526 ASSERT(HasDictionaryElements());
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
7619 } 8568 }
7620 8569
7621 8570
7622 MaybeObject* JSObject::SetElementWithoutInterceptor(uint32_t index, 8571 MaybeObject* JSObject::SetElementWithoutInterceptor(uint32_t index,
7623 Object* value, 8572 Object* value,
7624 StrictModeFlag strict_mode, 8573 StrictModeFlag strict_mode,
7625 bool check_prototype) { 8574 bool check_prototype) {
7626 Isolate* isolate = GetIsolate(); 8575 Isolate* isolate = GetIsolate();
7627 switch (GetElementsKind()) { 8576 switch (GetElementsKind()) {
7628 case FAST_ELEMENTS: 8577 case FAST_ELEMENTS:
7629 // Fast case.
7630 return SetFastElement(index, value, strict_mode, check_prototype); 8578 return SetFastElement(index, value, strict_mode, check_prototype);
8579 case FAST_DOUBLE_ELEMENTS:
8580 return SetFastDoubleElement(index, value, strict_mode, check_prototype);
7631 case EXTERNAL_PIXEL_ELEMENTS: { 8581 case EXTERNAL_PIXEL_ELEMENTS: {
7632 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements()); 8582 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements());
7633 return pixels->SetValue(index, value); 8583 return pixels->SetValue(index, value);
7634 } 8584 }
7635 case EXTERNAL_BYTE_ELEMENTS: { 8585 case EXTERNAL_BYTE_ELEMENTS: {
7636 ExternalByteArray* array = ExternalByteArray::cast(elements()); 8586 ExternalByteArray* array = ExternalByteArray::cast(elements());
7637 return array->SetValue(index, value); 8587 return array->SetValue(index, value);
7638 } 8588 }
7639 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: { 8589 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: {
7640 ExternalUnsignedByteArray* array = 8590 ExternalUnsignedByteArray* array =
(...skipping 19 matching lines...) Expand all
7660 return array->SetValue(index, value); 8610 return array->SetValue(index, value);
7661 } 8611 }
7662 case EXTERNAL_FLOAT_ELEMENTS: { 8612 case EXTERNAL_FLOAT_ELEMENTS: {
7663 ExternalFloatArray* array = ExternalFloatArray::cast(elements()); 8613 ExternalFloatArray* array = ExternalFloatArray::cast(elements());
7664 return array->SetValue(index, value); 8614 return array->SetValue(index, value);
7665 } 8615 }
7666 case EXTERNAL_DOUBLE_ELEMENTS: { 8616 case EXTERNAL_DOUBLE_ELEMENTS: {
7667 ExternalDoubleArray* array = ExternalDoubleArray::cast(elements()); 8617 ExternalDoubleArray* array = ExternalDoubleArray::cast(elements());
7668 return array->SetValue(index, value); 8618 return array->SetValue(index, value);
7669 } 8619 }
7670 case DICTIONARY_ELEMENTS: { 8620 case DICTIONARY_ELEMENTS:
7671 // Insert element in the dictionary. 8621 return SetDictionaryElement(index, value, strict_mode, check_prototype);
7672 FixedArray* elms = FixedArray::cast(elements()); 8622 case NON_STRICT_ARGUMENTS_ELEMENTS: {
7673 NumberDictionary* dictionary = NumberDictionary::cast(elms); 8623 FixedArray* parameter_map = FixedArray::cast(elements());
7674 8624 uint32_t length = parameter_map->length();
7675 int entry = dictionary->FindEntry(index); 8625 Object* probe =
7676 if (entry != NumberDictionary::kNotFound) { 8626 (index < length - 2) ? parameter_map->get(index + 2) : NULL;
7677 Object* element = dictionary->ValueAt(entry); 8627 if (probe != NULL && !probe->IsTheHole()) {
7678 PropertyDetails details = dictionary->DetailsAt(entry); 8628 Context* context = Context::cast(parameter_map->get(0));
7679 if (details.type() == CALLBACKS) { 8629 int context_index = Smi::cast(probe)->value();
7680 return SetElementWithCallback(element, 8630 ASSERT(!context->get(context_index)->IsTheHole());
7681 index, 8631 context->set(context_index, value);
7682 value, 8632 return value;
7683 this, 8633 } else {
7684 strict_mode); 8634 // Object is not mapped, defer to the arguments.
8635 FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
8636 if (arguments->IsDictionary()) {
8637 return SetDictionaryElement(index, value, strict_mode,
8638 check_prototype);
7685 } else { 8639 } else {
7686 dictionary->UpdateMaxNumberKey(index); 8640 return SetFastElement(index, value, strict_mode, check_prototype);
7687 // If put fails instrict mode, throw exception.
7688 if (!dictionary->ValueAtPut(entry, value) &&
7689 strict_mode == kStrictMode) {
7690 Handle<Object> holder(this);
7691 Handle<Object> number(isolate->factory()->NewNumberFromUint(index));
7692 Handle<Object> args[2] = { number, holder };
7693 return isolate->Throw(
7694 *isolate->factory()->NewTypeError("strict_read_only_property",
7695 HandleVector(args, 2)));
7696 }
7697 }
7698 } else {
7699 // Index not already used. Look for an accessor in the prototype chain.
7700 if (check_prototype) {
7701 bool found;
7702 MaybeObject* result =
7703 // Strict mode not needed. No-setter case already handled.
7704 SetElementWithCallbackSetterInPrototypes(index,
7705 value,
7706 &found,
7707 strict_mode);
7708 if (found) return result;
7709 }
7710 // When we set the is_extensible flag to false we always force
7711 // the element into dictionary mode (and force them to stay there).
7712 if (!map()->is_extensible()) {
7713 if (strict_mode == kNonStrictMode) {
7714 return isolate->heap()->undefined_value();
7715 } else {
7716 Handle<Object> number(isolate->factory()->NewNumberFromUint(index));
7717 Handle<String> index_string(
7718 isolate->factory()->NumberToString(number));
7719 Handle<Object> args[1] = { index_string };
7720 return isolate->Throw(
7721 *isolate->factory()->NewTypeError("object_not_extensible",
7722 HandleVector(args, 1)));
7723 }
7724 }
7725 Object* result;
7726 { MaybeObject* maybe_result = dictionary->AtNumberPut(index, value);
7727 if (!maybe_result->ToObject(&result)) return maybe_result;
7728 }
7729 if (elms != FixedArray::cast(result)) {
7730 set_elements(FixedArray::cast(result));
7731 } 8641 }
7732 } 8642 }
7733
7734 // Update the array length if this JSObject is an array.
7735 if (IsJSArray()) {
7736 JSArray* array = JSArray::cast(this);
7737 Object* return_value;
7738 { MaybeObject* maybe_return_value =
7739 array->JSArrayUpdateLengthFromIndex(index, value);
7740 if (!maybe_return_value->ToObject(&return_value)) {
7741 return maybe_return_value;
7742 }
7743 }
7744 }
7745
7746 // Attempt to put this object back in fast case.
7747 if (ShouldConvertToFastElements()) {
7748 uint32_t new_length = 0;
7749 if (IsJSArray()) {
7750 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&new_length));
7751 } else {
7752 new_length = NumberDictionary::cast(elements())->max_number_key() + 1;
7753 }
7754 Object* obj;
7755 { MaybeObject* maybe_obj =
7756 SetFastElementsCapacityAndLength(new_length, new_length);
7757 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
7758 }
7759 #ifdef DEBUG
7760 if (FLAG_trace_normalization) {
7761 PrintF("Object elements are fast case again:\n");
7762 Print();
7763 }
7764 #endif
7765 }
7766
7767 return value;
7768 } 8643 }
7769 default:
7770 UNREACHABLE();
7771 break;
7772 } 8644 }
7773 // All possible cases have been handled above. Add a return to avoid the 8645 // All possible cases have been handled above. Add a return to avoid the
7774 // complaints from the compiler. 8646 // complaints from the compiler.
7775 UNREACHABLE(); 8647 UNREACHABLE();
7776 return isolate->heap()->null_value(); 8648 return isolate->heap()->null_value();
7777 } 8649 }
7778 8650
7779 8651
7780 MaybeObject* JSArray::JSArrayUpdateLengthFromIndex(uint32_t index, 8652 MaybeObject* JSArray::JSArrayUpdateLengthFromIndex(uint32_t index,
7781 Object* value) { 8653 Object* value) {
(...skipping 19 matching lines...) Expand all
7801 // JSArray::length cannot change. 8673 // JSArray::length cannot change.
7802 switch (GetElementsKind()) { 8674 switch (GetElementsKind()) {
7803 case FAST_ELEMENTS: { 8675 case FAST_ELEMENTS: {
7804 FixedArray* elms = FixedArray::cast(elements()); 8676 FixedArray* elms = FixedArray::cast(elements());
7805 if (index < static_cast<uint32_t>(elms->length())) { 8677 if (index < static_cast<uint32_t>(elms->length())) {
7806 Object* value = elms->get(index); 8678 Object* value = elms->get(index);
7807 if (!value->IsTheHole()) return value; 8679 if (!value->IsTheHole()) return value;
7808 } 8680 }
7809 break; 8681 break;
7810 } 8682 }
8683 case FAST_DOUBLE_ELEMENTS: {
8684 FixedDoubleArray* elms = FixedDoubleArray::cast(elements());
8685 if (index < static_cast<uint32_t>(elms->length())) {
8686 if (!elms->is_the_hole(index)) {
8687 return GetHeap()->NumberFromDouble(elms->get(index));
8688 }
8689 }
8690 break;
8691 }
7811 case EXTERNAL_PIXEL_ELEMENTS: 8692 case EXTERNAL_PIXEL_ELEMENTS:
7812 case EXTERNAL_BYTE_ELEMENTS: 8693 case EXTERNAL_BYTE_ELEMENTS:
7813 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 8694 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
7814 case EXTERNAL_SHORT_ELEMENTS: 8695 case EXTERNAL_SHORT_ELEMENTS:
7815 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 8696 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
7816 case EXTERNAL_INT_ELEMENTS: 8697 case EXTERNAL_INT_ELEMENTS:
7817 case EXTERNAL_UNSIGNED_INT_ELEMENTS: 8698 case EXTERNAL_UNSIGNED_INT_ELEMENTS:
7818 case EXTERNAL_FLOAT_ELEMENTS: 8699 case EXTERNAL_FLOAT_ELEMENTS:
7819 case EXTERNAL_DOUBLE_ELEMENTS: { 8700 case EXTERNAL_DOUBLE_ELEMENTS: {
7820 MaybeObject* maybe_value = GetExternalElement(index); 8701 MaybeObject* maybe_value = GetExternalElement(index);
(...skipping 11 matching lines...) Expand all
7832 if (details.type() == CALLBACKS) { 8713 if (details.type() == CALLBACKS) {
7833 return GetElementWithCallback(receiver, 8714 return GetElementWithCallback(receiver,
7834 element, 8715 element,
7835 index, 8716 index,
7836 this); 8717 this);
7837 } 8718 }
7838 return element; 8719 return element;
7839 } 8720 }
7840 break; 8721 break;
7841 } 8722 }
7842 default: 8723 case NON_STRICT_ARGUMENTS_ELEMENTS:
7843 UNREACHABLE(); 8724 UNIMPLEMENTED();
7844 break; 8725 break;
7845 } 8726 }
7846 8727
7847 // Continue searching via the prototype chain. 8728 // Continue searching via the prototype chain.
7848 Object* pt = GetPrototype(); 8729 Object* pt = GetPrototype();
7849 if (pt->IsNull()) return GetHeap()->undefined_value(); 8730 if (pt->IsNull()) return GetHeap()->undefined_value();
7850 return pt->GetElementWithReceiver(receiver, index); 8731 return pt->GetElementWithReceiver(receiver, index);
7851 } 8732 }
7852 8733
7853 8734
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
7904 // JSArray::length cannot change. 8785 // JSArray::length cannot change.
7905 switch (GetElementsKind()) { 8786 switch (GetElementsKind()) {
7906 case FAST_ELEMENTS: { 8787 case FAST_ELEMENTS: {
7907 FixedArray* elms = FixedArray::cast(elements()); 8788 FixedArray* elms = FixedArray::cast(elements());
7908 if (index < static_cast<uint32_t>(elms->length())) { 8789 if (index < static_cast<uint32_t>(elms->length())) {
7909 Object* value = elms->get(index); 8790 Object* value = elms->get(index);
7910 if (!value->IsTheHole()) return value; 8791 if (!value->IsTheHole()) return value;
7911 } 8792 }
7912 break; 8793 break;
7913 } 8794 }
8795 case FAST_DOUBLE_ELEMENTS: {
8796 FixedDoubleArray* elms = FixedDoubleArray::cast(elements());
8797 if (index < static_cast<uint32_t>(elms->length())) {
8798 if (!elms->is_the_hole(index)) {
8799 double double_value = elms->get(index);
8800 return GetHeap()->NumberFromDouble(double_value);
8801 }
8802 }
8803 break;
8804 }
7914 case EXTERNAL_PIXEL_ELEMENTS: 8805 case EXTERNAL_PIXEL_ELEMENTS:
7915 case EXTERNAL_BYTE_ELEMENTS: 8806 case EXTERNAL_BYTE_ELEMENTS:
7916 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 8807 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
7917 case EXTERNAL_SHORT_ELEMENTS: 8808 case EXTERNAL_SHORT_ELEMENTS:
7918 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 8809 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
7919 case EXTERNAL_INT_ELEMENTS: 8810 case EXTERNAL_INT_ELEMENTS:
7920 case EXTERNAL_UNSIGNED_INT_ELEMENTS: 8811 case EXTERNAL_UNSIGNED_INT_ELEMENTS:
7921 case EXTERNAL_FLOAT_ELEMENTS: 8812 case EXTERNAL_FLOAT_ELEMENTS:
7922 case EXTERNAL_DOUBLE_ELEMENTS: { 8813 case EXTERNAL_DOUBLE_ELEMENTS: {
7923 MaybeObject* maybe_value = GetExternalElement(index); 8814 MaybeObject* maybe_value = GetExternalElement(index);
(...skipping 11 matching lines...) Expand all
7935 if (details.type() == CALLBACKS) { 8826 if (details.type() == CALLBACKS) {
7936 return GetElementWithCallback(receiver, 8827 return GetElementWithCallback(receiver,
7937 element, 8828 element,
7938 index, 8829 index,
7939 this); 8830 this);
7940 } 8831 }
7941 return element; 8832 return element;
7942 } 8833 }
7943 break; 8834 break;
7944 } 8835 }
8836 case NON_STRICT_ARGUMENTS_ELEMENTS: {
8837 FixedArray* parameter_map = FixedArray::cast(elements());
8838 uint32_t length = parameter_map->length();
8839 Object* probe =
8840 (index < length - 2) ? parameter_map->get(index + 2) : NULL;
8841 if (probe != NULL && !probe->IsTheHole()) {
8842 Context* context = Context::cast(parameter_map->get(0));
8843 int context_index = Smi::cast(probe)->value();
8844 ASSERT(!context->get(context_index)->IsTheHole());
8845 return context->get(context_index);
8846 } else {
8847 // Object is not mapped, defer to the arguments.
8848 FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
8849 if (arguments->IsDictionary()) {
8850 NumberDictionary* dictionary = NumberDictionary::cast(arguments);
8851 int entry = dictionary->FindEntry(index);
8852 if (entry != NumberDictionary::kNotFound) {
8853 Object* element = dictionary->ValueAt(entry);
8854 PropertyDetails details = dictionary->DetailsAt(entry);
8855 if (details.type() == CALLBACKS) {
8856 return GetElementWithCallback(receiver,
8857 element,
8858 index,
8859 this);
8860 }
8861 return element;
8862 }
8863 } else if (index < static_cast<uint32_t>(arguments->length())) {
8864 Object* value = arguments->get(index);
8865 if (!value->IsTheHole()) return value;
8866 }
8867 }
8868 break;
8869 }
7945 } 8870 }
7946 8871
7947 Object* pt = GetPrototype(); 8872 Object* pt = GetPrototype();
7948 Heap* heap = GetHeap(); 8873 Heap* heap = GetHeap();
7949 if (pt == heap->null_value()) return heap->undefined_value(); 8874 if (pt == heap->null_value()) return heap->undefined_value();
7950 return pt->GetElementWithReceiver(receiver, index); 8875 return pt->GetElementWithReceiver(receiver, index);
7951 } 8876 }
7952 8877
7953 8878
7954 MaybeObject* JSObject::GetExternalElement(uint32_t index) { 8879 MaybeObject* JSObject::GetExternalElement(uint32_t index) {
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
8023 break; 8948 break;
8024 } 8949 }
8025 case EXTERNAL_DOUBLE_ELEMENTS: { 8950 case EXTERNAL_DOUBLE_ELEMENTS: {
8026 ExternalDoubleArray* array = ExternalDoubleArray::cast(elements()); 8951 ExternalDoubleArray* array = ExternalDoubleArray::cast(elements());
8027 if (index < static_cast<uint32_t>(array->length())) { 8952 if (index < static_cast<uint32_t>(array->length())) {
8028 double value = array->get(index); 8953 double value = array->get(index);
8029 return GetHeap()->AllocateHeapNumber(value); 8954 return GetHeap()->AllocateHeapNumber(value);
8030 } 8955 }
8031 break; 8956 break;
8032 } 8957 }
8958 case FAST_DOUBLE_ELEMENTS:
8033 case FAST_ELEMENTS: 8959 case FAST_ELEMENTS:
8034 case DICTIONARY_ELEMENTS: 8960 case DICTIONARY_ELEMENTS:
8035 UNREACHABLE(); 8961 UNREACHABLE();
8036 break; 8962 break;
8963 case NON_STRICT_ARGUMENTS_ELEMENTS:
8964 UNIMPLEMENTED();
8965 break;
8037 } 8966 }
8038 return GetHeap()->undefined_value(); 8967 return GetHeap()->undefined_value();
8039 } 8968 }
8040 8969
8041 8970
8042 bool JSObject::HasDenseElements() { 8971 bool JSObject::HasDenseElements() {
8043 int capacity = 0; 8972 int capacity = 0;
8044 int number_of_elements = 0; 8973 int number_of_elements = 0;
8045 8974
8975 FixedArray* backing_store = FixedArray::cast(elements());
8046 switch (GetElementsKind()) { 8976 switch (GetElementsKind()) {
8047 case FAST_ELEMENTS: { 8977 case NON_STRICT_ARGUMENTS_ELEMENTS:
8048 FixedArray* elms = FixedArray::cast(elements()); 8978 backing_store = FixedArray::cast(backing_store->get(1));
8979 if (backing_store->IsDictionary()) {
8980 NumberDictionary* dictionary = NumberDictionary::cast(backing_store);
8981 capacity = dictionary->Capacity();
8982 number_of_elements = dictionary->NumberOfElements();
8983 break;
8984 }
8985 // Fall through.
8986 case FAST_ELEMENTS:
8987 capacity = backing_store->length();
8988 for (int i = 0; i < capacity; ++i) {
8989 if (!backing_store->get(i)->IsTheHole()) ++number_of_elements;
8990 }
8991 break;
8992 case DICTIONARY_ELEMENTS: {
8993 NumberDictionary* dictionary = NumberDictionary::cast(backing_store);
8994 capacity = dictionary->Capacity();
8995 number_of_elements = dictionary->NumberOfElements();
8996 break;
8997 }
8998 case FAST_DOUBLE_ELEMENTS: {
8999 FixedDoubleArray* elms = FixedDoubleArray::cast(elements());
8049 capacity = elms->length(); 9000 capacity = elms->length();
8050 for (int i = 0; i < capacity; i++) { 9001 for (int i = 0; i < capacity; i++) {
8051 if (!elms->get(i)->IsTheHole()) number_of_elements++; 9002 if (!elms->is_the_hole(i)) number_of_elements++;
8052 } 9003 }
8053 break; 9004 break;
8054 } 9005 }
8055 case EXTERNAL_PIXEL_ELEMENTS: 9006 case EXTERNAL_PIXEL_ELEMENTS:
8056 case EXTERNAL_BYTE_ELEMENTS: 9007 case EXTERNAL_BYTE_ELEMENTS:
8057 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 9008 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
8058 case EXTERNAL_SHORT_ELEMENTS: 9009 case EXTERNAL_SHORT_ELEMENTS:
8059 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 9010 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
8060 case EXTERNAL_INT_ELEMENTS: 9011 case EXTERNAL_INT_ELEMENTS:
8061 case EXTERNAL_UNSIGNED_INT_ELEMENTS: 9012 case EXTERNAL_UNSIGNED_INT_ELEMENTS:
8062 case EXTERNAL_FLOAT_ELEMENTS: 9013 case EXTERNAL_FLOAT_ELEMENTS:
8063 case EXTERNAL_DOUBLE_ELEMENTS: { 9014 case EXTERNAL_DOUBLE_ELEMENTS: {
8064 return true; 9015 return true;
8065 } 9016 }
8066 case DICTIONARY_ELEMENTS: {
8067 NumberDictionary* dictionary = NumberDictionary::cast(elements());
8068 capacity = dictionary->Capacity();
8069 number_of_elements = dictionary->NumberOfElements();
8070 break;
8071 }
8072 default:
8073 UNREACHABLE();
8074 break;
8075 } 9017 }
8076 9018 return (capacity == 0) || (number_of_elements > (capacity / 2));
8077 if (capacity == 0) return true;
8078 return (number_of_elements > (capacity / 2));
8079 } 9019 }
8080 9020
8081 9021
8082 bool JSObject::ShouldConvertToSlowElements(int new_capacity) { 9022 bool JSObject::ShouldConvertToSlowElements(int new_capacity) {
8083 ASSERT(HasFastElements());
8084 // Keep the array in fast case if the current backing storage is 9023 // Keep the array in fast case if the current backing storage is
8085 // almost filled and if the new capacity is no more than twice the 9024 // almost filled and if the new capacity is no more than twice the
8086 // old capacity. 9025 // old capacity.
8087 int elements_length = FixedArray::cast(elements())->length(); 9026 int elements_length = 0;
9027 if (elements()->map() == GetHeap()->non_strict_arguments_elements_map()) {
9028 FixedArray* backing_store = FixedArray::cast(elements());
9029 elements_length = FixedArray::cast(backing_store->get(1))->length();
9030 } else if (HasFastElements()) {
9031 elements_length = FixedArray::cast(elements())->length();
9032 } else if (HasFastDoubleElements()) {
9033 elements_length = FixedDoubleArray::cast(elements())->length();
9034 } else {
9035 UNREACHABLE();
9036 }
8088 return !HasDenseElements() || ((new_capacity / 2) > elements_length); 9037 return !HasDenseElements() || ((new_capacity / 2) > elements_length);
8089 } 9038 }
8090 9039
8091 9040
8092 bool JSObject::ShouldConvertToFastElements() { 9041 bool JSObject::ShouldConvertToFastElements() {
8093 ASSERT(HasDictionaryElements()); 9042 ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements());
8094 NumberDictionary* dictionary = NumberDictionary::cast(elements());
8095 // If the elements are sparse, we should not go back to fast case. 9043 // If the elements are sparse, we should not go back to fast case.
8096 if (!HasDenseElements()) return false; 9044 if (!HasDenseElements()) return false;
9045 // An object requiring access checks is never allowed to have fast
9046 // elements. If it had fast elements we would skip security checks.
9047 if (IsAccessCheckNeeded()) return false;
9048
9049 FixedArray* elements = FixedArray::cast(this->elements());
9050 NumberDictionary* dictionary = NULL;
9051 if (elements->map() == GetHeap()->non_strict_arguments_elements_map()) {
9052 dictionary = NumberDictionary::cast(elements->get(1));
9053 } else {
9054 dictionary = NumberDictionary::cast(elements);
9055 }
8097 // If an element has been added at a very high index in the elements 9056 // If an element has been added at a very high index in the elements
8098 // dictionary, we cannot go back to fast case. 9057 // dictionary, we cannot go back to fast case.
8099 if (dictionary->requires_slow_elements()) return false; 9058 if (dictionary->requires_slow_elements()) return false;
8100 // An object requiring access checks is never allowed to have fast
8101 // elements. If it had fast elements we would skip security checks.
8102 if (IsAccessCheckNeeded()) return false;
8103 // If the dictionary backing storage takes up roughly half as much 9059 // If the dictionary backing storage takes up roughly half as much
8104 // space as a fast-case backing storage would the array should have 9060 // space as a fast-case backing storage would the array should have
8105 // fast elements. 9061 // fast elements.
8106 uint32_t length = 0; 9062 uint32_t length = 0;
8107 if (IsJSArray()) { 9063 if (IsJSArray()) {
8108 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length)); 9064 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length));
8109 } else { 9065 } else {
8110 length = dictionary->max_number_key(); 9066 length = dictionary->max_number_key();
8111 } 9067 }
8112 return static_cast<uint32_t>(dictionary->Capacity()) >= 9068 return static_cast<uint32_t>(dictionary->Capacity()) >=
8113 (length / (2 * NumberDictionary::kEntrySize)); 9069 (length / (2 * NumberDictionary::kEntrySize));
8114 } 9070 }
8115 9071
8116 9072
9073 bool JSObject::ShouldConvertToFastDoubleElements() {
9074 if (FLAG_unbox_double_arrays) {
9075 ASSERT(HasDictionaryElements());
9076 NumberDictionary* dictionary = NumberDictionary::cast(elements());
9077 for (int i = 0; i < dictionary->Capacity(); i++) {
9078 Object* key = dictionary->KeyAt(i);
9079 if (key->IsNumber()) {
9080 if (!dictionary->ValueAt(i)->IsNumber()) return false;
9081 }
9082 }
9083 return true;
9084 } else {
9085 return false;
9086 }
9087 }
9088
9089
8117 // Certain compilers request function template instantiation when they 9090 // Certain compilers request function template instantiation when they
8118 // see the definition of the other template functions in the 9091 // see the definition of the other template functions in the
8119 // class. This requires us to have the template functions put 9092 // class. This requires us to have the template functions put
8120 // together, so even though this function belongs in objects-debug.cc, 9093 // together, so even though this function belongs in objects-debug.cc,
8121 // we keep it here instead to satisfy certain compilers. 9094 // we keep it here instead to satisfy certain compilers.
8122 #ifdef OBJECT_PRINT 9095 #ifdef OBJECT_PRINT
8123 template<typename Shape, typename Key> 9096 template<typename Shape, typename Key>
8124 void Dictionary<Shape, Key>::Print(FILE* out) { 9097 void Dictionary<Shape, Key>::Print(FILE* out) {
8125 int capacity = HashTable<Shape, Key>::Capacity(); 9098 int capacity = HashTable<Shape, Key>::Capacity();
8126 for (int i = 0; i < capacity; i++) { 9099 for (int i = 0; i < capacity; i++) {
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
8171 ASSERT(map()->has_indexed_interceptor()); 9144 ASSERT(map()->has_indexed_interceptor());
8172 JSFunction* constructor = JSFunction::cast(map()->constructor()); 9145 JSFunction* constructor = JSFunction::cast(map()->constructor());
8173 ASSERT(constructor->shared()->IsApiFunction()); 9146 ASSERT(constructor->shared()->IsApiFunction());
8174 Object* result = 9147 Object* result =
8175 constructor->shared()->get_api_func_data()->indexed_property_handler(); 9148 constructor->shared()->get_api_func_data()->indexed_property_handler();
8176 return InterceptorInfo::cast(result); 9149 return InterceptorInfo::cast(result);
8177 } 9150 }
8178 9151
8179 9152
8180 MaybeObject* JSObject::GetPropertyPostInterceptor( 9153 MaybeObject* JSObject::GetPropertyPostInterceptor(
8181 JSObject* receiver, 9154 JSReceiver* receiver,
8182 String* name, 9155 String* name,
8183 PropertyAttributes* attributes) { 9156 PropertyAttributes* attributes) {
8184 // Check local property in holder, ignore interceptor. 9157 // Check local property in holder, ignore interceptor.
8185 LookupResult result; 9158 LookupResult result;
8186 LocalLookupRealNamedProperty(name, &result); 9159 LocalLookupRealNamedProperty(name, &result);
8187 if (result.IsProperty()) { 9160 if (result.IsProperty()) {
8188 return GetProperty(receiver, &result, name, attributes); 9161 return GetProperty(receiver, &result, name, attributes);
8189 } 9162 }
8190 // Continue searching via the prototype chain. 9163 // Continue searching via the prototype chain.
8191 Object* pt = GetPrototype(); 9164 Object* pt = GetPrototype();
8192 *attributes = ABSENT; 9165 *attributes = ABSENT;
8193 if (pt->IsNull()) return GetHeap()->undefined_value(); 9166 if (pt->IsNull()) return GetHeap()->undefined_value();
8194 return pt->GetPropertyWithReceiver(receiver, name, attributes); 9167 return pt->GetPropertyWithReceiver(receiver, name, attributes);
8195 } 9168 }
8196 9169
8197 9170
8198 MaybeObject* JSObject::GetLocalPropertyPostInterceptor( 9171 MaybeObject* JSObject::GetLocalPropertyPostInterceptor(
8199 JSObject* receiver, 9172 JSReceiver* receiver,
8200 String* name, 9173 String* name,
8201 PropertyAttributes* attributes) { 9174 PropertyAttributes* attributes) {
8202 // Check local property in holder, ignore interceptor. 9175 // Check local property in holder, ignore interceptor.
8203 LookupResult result; 9176 LookupResult result;
8204 LocalLookupRealNamedProperty(name, &result); 9177 LocalLookupRealNamedProperty(name, &result);
8205 if (result.IsProperty()) { 9178 if (result.IsProperty()) {
8206 return GetProperty(receiver, &result, name, attributes); 9179 return GetProperty(receiver, &result, name, attributes);
8207 } 9180 }
8208 return GetHeap()->undefined_value(); 9181 return GetHeap()->undefined_value();
8209 } 9182 }
8210 9183
8211 9184
8212 MaybeObject* JSObject::GetPropertyWithInterceptor( 9185 MaybeObject* JSObject::GetPropertyWithInterceptor(
8213 JSObject* receiver, 9186 JSReceiver* receiver,
8214 String* name, 9187 String* name,
8215 PropertyAttributes* attributes) { 9188 PropertyAttributes* attributes) {
8216 Isolate* isolate = GetIsolate(); 9189 Isolate* isolate = GetIsolate();
8217 InterceptorInfo* interceptor = GetNamedInterceptor(); 9190 InterceptorInfo* interceptor = GetNamedInterceptor();
8218 HandleScope scope(isolate); 9191 HandleScope scope(isolate);
8219 Handle<JSObject> receiver_handle(receiver); 9192 Handle<JSReceiver> receiver_handle(receiver);
8220 Handle<JSObject> holder_handle(this); 9193 Handle<JSObject> holder_handle(this);
8221 Handle<String> name_handle(name); 9194 Handle<String> name_handle(name);
8222 9195
8223 if (!interceptor->getter()->IsUndefined()) { 9196 if (!interceptor->getter()->IsUndefined()) {
8224 v8::NamedPropertyGetter getter = 9197 v8::NamedPropertyGetter getter =
8225 v8::ToCData<v8::NamedPropertyGetter>(interceptor->getter()); 9198 v8::ToCData<v8::NamedPropertyGetter>(interceptor->getter());
8226 LOG(isolate, 9199 LOG(isolate,
8227 ApiNamedPropertyAccess("interceptor-named-get", *holder_handle, name)); 9200 ApiNamedPropertyAccess("interceptor-named-get", *holder_handle, name));
8228 CustomArguments args(isolate, interceptor->data(), receiver, this); 9201 CustomArguments args(isolate, interceptor->data(), receiver, this);
8229 v8::AccessorInfo info(args.end()); 9202 v8::AccessorInfo info(args.end());
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
8295 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 9268 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
8296 case EXTERNAL_SHORT_ELEMENTS: 9269 case EXTERNAL_SHORT_ELEMENTS:
8297 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 9270 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
8298 case EXTERNAL_INT_ELEMENTS: 9271 case EXTERNAL_INT_ELEMENTS:
8299 case EXTERNAL_UNSIGNED_INT_ELEMENTS: 9272 case EXTERNAL_UNSIGNED_INT_ELEMENTS:
8300 case EXTERNAL_FLOAT_ELEMENTS: 9273 case EXTERNAL_FLOAT_ELEMENTS:
8301 case EXTERNAL_DOUBLE_ELEMENTS: { 9274 case EXTERNAL_DOUBLE_ELEMENTS: {
8302 ExternalArray* array = ExternalArray::cast(elements()); 9275 ExternalArray* array = ExternalArray::cast(elements());
8303 return index < static_cast<uint32_t>(array->length()); 9276 return index < static_cast<uint32_t>(array->length());
8304 } 9277 }
9278 case FAST_DOUBLE_ELEMENTS:
9279 UNREACHABLE();
9280 break;
8305 case DICTIONARY_ELEMENTS: { 9281 case DICTIONARY_ELEMENTS: {
8306 return element_dictionary()->FindEntry(index) 9282 return element_dictionary()->FindEntry(index)
8307 != NumberDictionary::kNotFound; 9283 != NumberDictionary::kNotFound;
8308 } 9284 }
8309 default: 9285 case NON_STRICT_ARGUMENTS_ELEMENTS:
8310 UNREACHABLE(); 9286 UNIMPLEMENTED();
8311 break; 9287 break;
8312 } 9288 }
8313 // All possibilities have been handled above already. 9289 // All possibilities have been handled above already.
8314 UNREACHABLE(); 9290 UNREACHABLE();
8315 return GetHeap()->null_value(); 9291 return GetHeap()->null_value();
8316 } 9292 }
8317 9293
8318 9294
8319 bool JSObject::HasRealNamedCallbackProperty(String* key) { 9295 bool JSObject::HasRealNamedCallbackProperty(String* key) {
8320 // Check access rights if needed. 9296 // Check access rights if needed.
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after
8472 // mirrors. 9448 // mirrors.
8473 void JSObject::GetLocalPropertyNames(FixedArray* storage, int index) { 9449 void JSObject::GetLocalPropertyNames(FixedArray* storage, int index) {
8474 ASSERT(storage->length() >= (NumberOfLocalProperties(NONE) - index)); 9450 ASSERT(storage->length() >= (NumberOfLocalProperties(NONE) - index));
8475 if (HasFastProperties()) { 9451 if (HasFastProperties()) {
8476 DescriptorArray* descs = map()->instance_descriptors(); 9452 DescriptorArray* descs = map()->instance_descriptors();
8477 for (int i = 0; i < descs->number_of_descriptors(); i++) { 9453 for (int i = 0; i < descs->number_of_descriptors(); i++) {
8478 if (descs->IsProperty(i)) storage->set(index++, descs->GetKey(i)); 9454 if (descs->IsProperty(i)) storage->set(index++, descs->GetKey(i));
8479 } 9455 }
8480 ASSERT(storage->length() >= index); 9456 ASSERT(storage->length() >= index);
8481 } else { 9457 } else {
8482 property_dictionary()->CopyKeysTo(storage); 9458 property_dictionary()->CopyKeysTo(storage, StringDictionary::UNSORTED);
8483 } 9459 }
8484 } 9460 }
8485 9461
8486 9462
8487 int JSObject::NumberOfLocalElements(PropertyAttributes filter) { 9463 int JSObject::NumberOfLocalElements(PropertyAttributes filter) {
8488 return GetLocalElementKeys(NULL, filter); 9464 return GetLocalElementKeys(NULL, filter);
8489 } 9465 }
8490 9466
8491 9467
8492 int JSObject::NumberOfEnumElements() { 9468 int JSObject::NumberOfEnumElements() {
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
8544 int length = ExternalArray::cast(elements())->length(); 9520 int length = ExternalArray::cast(elements())->length();
8545 while (counter < length) { 9521 while (counter < length) {
8546 if (storage != NULL) { 9522 if (storage != NULL) {
8547 storage->set(counter, Smi::FromInt(counter)); 9523 storage->set(counter, Smi::FromInt(counter));
8548 } 9524 }
8549 counter++; 9525 counter++;
8550 } 9526 }
8551 ASSERT(!storage || storage->length() >= counter); 9527 ASSERT(!storage || storage->length() >= counter);
8552 break; 9528 break;
8553 } 9529 }
9530 case FAST_DOUBLE_ELEMENTS:
9531 UNREACHABLE();
9532 break;
8554 case DICTIONARY_ELEMENTS: { 9533 case DICTIONARY_ELEMENTS: {
8555 if (storage != NULL) { 9534 if (storage != NULL) {
8556 element_dictionary()->CopyKeysTo(storage, filter); 9535 element_dictionary()->CopyKeysTo(storage,
9536 filter,
9537 NumberDictionary::SORTED);
8557 } 9538 }
8558 counter = element_dictionary()->NumberOfElementsFilterAttributes(filter); 9539 counter += element_dictionary()->NumberOfElementsFilterAttributes(filter);
8559 break; 9540 break;
8560 } 9541 }
8561 default: 9542 case NON_STRICT_ARGUMENTS_ELEMENTS: {
8562 UNREACHABLE(); 9543 FixedArray* parameter_map = FixedArray::cast(elements());
9544 int mapped_length = parameter_map->length() - 2;
9545 FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
9546 if (arguments->IsDictionary()) {
9547 // Copy the keys from arguments first, because Dictionary::CopyKeysTo
9548 // will insert in storage starting at index 0.
9549 NumberDictionary* dictionary = NumberDictionary::cast(arguments);
9550 if (storage != NULL) {
9551 dictionary->CopyKeysTo(storage, filter, NumberDictionary::UNSORTED);
9552 }
9553 counter += dictionary->NumberOfElementsFilterAttributes(filter);
9554 for (int i = 0; i < mapped_length; ++i) {
9555 if (!parameter_map->get(i + 2)->IsTheHole()) {
9556 if (storage != NULL) storage->set(counter, Smi::FromInt(i));
9557 ++counter;
9558 }
9559 }
9560 if (storage != NULL) storage->SortPairs(storage, counter);
9561
9562 } else {
9563 int backing_length = arguments->length();
9564 int i = 0;
9565 for (; i < mapped_length; ++i) {
9566 if (!parameter_map->get(i + 2)->IsTheHole()) {
9567 if (storage != NULL) storage->set(counter, Smi::FromInt(i));
9568 ++counter;
9569 } else if (i < backing_length && !arguments->get(i)->IsTheHole()) {
9570 if (storage != NULL) storage->set(counter, Smi::FromInt(i));
9571 ++counter;
9572 }
9573 }
9574 for (; i < backing_length; ++i) {
9575 if (storage != NULL) storage->set(counter, Smi::FromInt(i));
9576 ++counter;
9577 }
9578 }
8563 break; 9579 break;
9580 }
8564 } 9581 }
8565 9582
8566 if (this->IsJSValue()) { 9583 if (this->IsJSValue()) {
8567 Object* val = JSValue::cast(this)->value(); 9584 Object* val = JSValue::cast(this)->value();
8568 if (val->IsString()) { 9585 if (val->IsString()) {
8569 String* str = String::cast(val); 9586 String* str = String::cast(val);
8570 if (storage) { 9587 if (storage) {
8571 for (int i = 0; i < str->length(); i++) { 9588 for (int i = 0; i < str->length(); i++) {
8572 storage->set(counter + i, Smi::FromInt(i)); 9589 storage->set(counter + i, Smi::FromInt(i));
8573 } 9590 }
(...skipping 446 matching lines...) Expand 10 before | Expand all | Expand 10 after
9020 return entry; 10037 return entry;
9021 } 10038 }
9022 ASSERT(element->IsNull() || !String::cast(element)->Equals(key)); 10039 ASSERT(element->IsNull() || !String::cast(element)->Equals(key));
9023 entry = NextProbe(entry, count++, capacity); 10040 entry = NextProbe(entry, count++, capacity);
9024 } 10041 }
9025 return kNotFound; 10042 return kNotFound;
9026 } 10043 }
9027 10044
9028 10045
9029 template<typename Shape, typename Key> 10046 template<typename Shape, typename Key>
10047 MaybeObject* HashTable<Shape, Key>::Rehash(HashTable* new_table, Key key) {
10048 ASSERT(NumberOfElements() < new_table->Capacity());
10049
10050 AssertNoAllocation no_gc;
10051 WriteBarrierMode mode = new_table->GetWriteBarrierMode(no_gc);
10052
10053 // Copy prefix to new array.
10054 for (int i = kPrefixStartIndex;
10055 i < kPrefixStartIndex + Shape::kPrefixSize;
10056 i++) {
10057 new_table->set(i, get(i), mode);
10058 }
10059
10060 // Rehash the elements.
10061 int capacity = Capacity();
10062 for (int i = 0; i < capacity; i++) {
10063 uint32_t from_index = EntryToIndex(i);
10064 Object* k = get(from_index);
10065 if (IsKey(k)) {
10066 uint32_t hash = Shape::HashForObject(key, k);
10067 uint32_t insertion_index =
10068 EntryToIndex(new_table->FindInsertionEntry(hash));
10069 for (int j = 0; j < Shape::kEntrySize; j++) {
10070 new_table->set(insertion_index + j, get(from_index + j), mode);
10071 }
10072 }
10073 }
10074 new_table->SetNumberOfElements(NumberOfElements());
10075 new_table->SetNumberOfDeletedElements(0);
10076 return new_table;
10077 }
10078
10079
10080 template<typename Shape, typename Key>
9030 MaybeObject* HashTable<Shape, Key>::EnsureCapacity(int n, Key key) { 10081 MaybeObject* HashTable<Shape, Key>::EnsureCapacity(int n, Key key) {
9031 int capacity = Capacity(); 10082 int capacity = Capacity();
9032 int nof = NumberOfElements() + n; 10083 int nof = NumberOfElements() + n;
9033 int nod = NumberOfDeletedElements(); 10084 int nod = NumberOfDeletedElements();
9034 // Return if: 10085 // Return if:
9035 // 50% is still free after adding n elements and 10086 // 50% is still free after adding n elements and
9036 // at most 50% of the free elements are deleted elements. 10087 // at most 50% of the free elements are deleted elements.
9037 if (nod <= (capacity - nof) >> 1) { 10088 if (nod <= (capacity - nof) >> 1) {
9038 int needed_free = nof >> 1; 10089 int needed_free = nof >> 1;
9039 if (nof + needed_free <= capacity) return this; 10090 if (nof + needed_free <= capacity) return this;
9040 } 10091 }
9041 10092
9042 const int kMinCapacityForPretenure = 256; 10093 const int kMinCapacityForPretenure = 256;
9043 bool pretenure = 10094 bool pretenure =
9044 (capacity > kMinCapacityForPretenure) && !GetHeap()->InNewSpace(this); 10095 (capacity > kMinCapacityForPretenure) && !GetHeap()->InNewSpace(this);
9045 Object* obj; 10096 Object* obj;
9046 { MaybeObject* maybe_obj = 10097 { MaybeObject* maybe_obj =
9047 Allocate(nof * 2, pretenure ? TENURED : NOT_TENURED); 10098 Allocate(nof * 2, pretenure ? TENURED : NOT_TENURED);
9048 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 10099 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
9049 } 10100 }
9050 10101
9051 AssertNoAllocation no_gc; 10102 return Rehash(HashTable::cast(obj), key);
9052 HashTable* table = HashTable::cast(obj);
9053 WriteBarrierMode mode = table->GetWriteBarrierMode(no_gc);
9054
9055 // Copy prefix to new array.
9056 for (int i = kPrefixStartIndex;
9057 i < kPrefixStartIndex + Shape::kPrefixSize;
9058 i++) {
9059 table->set(i, get(i), mode);
9060 }
9061 // Rehash the elements.
9062 for (int i = 0; i < capacity; i++) {
9063 uint32_t from_index = EntryToIndex(i);
9064 Object* k = get(from_index);
9065 if (IsKey(k)) {
9066 uint32_t hash = Shape::HashForObject(key, k);
9067 uint32_t insertion_index =
9068 EntryToIndex(table->FindInsertionEntry(hash));
9069 for (int j = 0; j < Shape::kEntrySize; j++) {
9070 table->set(insertion_index + j, get(from_index + j), mode);
9071 }
9072 }
9073 }
9074 table->SetNumberOfElements(NumberOfElements());
9075 table->SetNumberOfDeletedElements(0);
9076 return table;
9077 } 10103 }
9078 10104
9079 10105
10106 template<typename Shape, typename Key>
10107 MaybeObject* HashTable<Shape, Key>::Shrink(Key key) {
10108 int capacity = Capacity();
10109 int nof = NumberOfElements();
10110
10111 // Shrink to fit the number of elements if only a quarter of the
10112 // capacity is filled with elements.
10113 if (nof > (capacity >> 2)) return this;
10114 // Allocate a new dictionary with room for at least the current
10115 // number of elements. The allocation method will make sure that
10116 // there is extra room in the dictionary for additions. Don't go
10117 // lower than room for 16 elements.
10118 int at_least_room_for = nof;
10119 if (at_least_room_for < 16) return this;
10120
10121 const int kMinCapacityForPretenure = 256;
10122 bool pretenure =
10123 (at_least_room_for > kMinCapacityForPretenure) &&
10124 !GetHeap()->InNewSpace(this);
10125 Object* obj;
10126 { MaybeObject* maybe_obj =
10127 Allocate(at_least_room_for, pretenure ? TENURED : NOT_TENURED);
10128 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
10129 }
10130
10131 return Rehash(HashTable::cast(obj), key);
10132 }
10133
10134
9080 template<typename Shape, typename Key> 10135 template<typename Shape, typename Key>
9081 uint32_t HashTable<Shape, Key>::FindInsertionEntry(uint32_t hash) { 10136 uint32_t HashTable<Shape, Key>::FindInsertionEntry(uint32_t hash) {
9082 uint32_t capacity = Capacity(); 10137 uint32_t capacity = Capacity();
9083 uint32_t entry = FirstProbe(hash, capacity); 10138 uint32_t entry = FirstProbe(hash, capacity);
9084 uint32_t count = 1; 10139 uint32_t count = 1;
9085 // EnsureCapacity will guarantee the hash table is never full. 10140 // EnsureCapacity will guarantee the hash table is never full.
9086 while (true) { 10141 while (true) {
9087 Object* element = KeyAt(entry); 10142 Object* element = KeyAt(entry);
9088 if (element->IsUndefined() || element->IsNull()) break; 10143 if (element->IsUndefined() || element->IsNull()) break;
9089 entry = NextProbe(entry, count++, capacity); 10144 entry = NextProbe(entry, count++, capacity);
(...skipping 23 matching lines...) Expand all
9113 template MaybeObject* Dictionary<NumberDictionaryShape, uint32_t>::AtPut( 10168 template MaybeObject* Dictionary<NumberDictionaryShape, uint32_t>::AtPut(
9114 uint32_t, Object*); 10169 uint32_t, Object*);
9115 10170
9116 template Object* Dictionary<NumberDictionaryShape, uint32_t>::SlowReverseLookup( 10171 template Object* Dictionary<NumberDictionaryShape, uint32_t>::SlowReverseLookup(
9117 Object*); 10172 Object*);
9118 10173
9119 template Object* Dictionary<StringDictionaryShape, String*>::SlowReverseLookup( 10174 template Object* Dictionary<StringDictionaryShape, String*>::SlowReverseLookup(
9120 Object*); 10175 Object*);
9121 10176
9122 template void Dictionary<NumberDictionaryShape, uint32_t>::CopyKeysTo( 10177 template void Dictionary<NumberDictionaryShape, uint32_t>::CopyKeysTo(
9123 FixedArray*, PropertyAttributes); 10178 FixedArray*,
10179 PropertyAttributes,
10180 Dictionary<NumberDictionaryShape, uint32_t>::SortMode);
9124 10181
9125 template Object* Dictionary<StringDictionaryShape, String*>::DeleteProperty( 10182 template Object* Dictionary<StringDictionaryShape, String*>::DeleteProperty(
9126 int, JSObject::DeleteMode); 10183 int, JSObject::DeleteMode);
9127 10184
9128 template Object* Dictionary<NumberDictionaryShape, uint32_t>::DeleteProperty( 10185 template Object* Dictionary<NumberDictionaryShape, uint32_t>::DeleteProperty(
9129 int, JSObject::DeleteMode); 10186 int, JSObject::DeleteMode);
9130 10187
10188 template MaybeObject* Dictionary<StringDictionaryShape, String*>::Shrink(
10189 String*);
10190
10191 template MaybeObject* Dictionary<NumberDictionaryShape, uint32_t>::Shrink(
10192 uint32_t);
10193
9131 template void Dictionary<StringDictionaryShape, String*>::CopyKeysTo( 10194 template void Dictionary<StringDictionaryShape, String*>::CopyKeysTo(
9132 FixedArray*); 10195 FixedArray*,
10196 Dictionary<StringDictionaryShape, String*>::SortMode);
9133 10197
9134 template int 10198 template int
9135 Dictionary<StringDictionaryShape, String*>::NumberOfElementsFilterAttributes( 10199 Dictionary<StringDictionaryShape, String*>::NumberOfElementsFilterAttributes(
9136 PropertyAttributes); 10200 PropertyAttributes);
9137 10201
9138 template MaybeObject* Dictionary<StringDictionaryShape, String*>::Add( 10202 template MaybeObject* Dictionary<StringDictionaryShape, String*>::Add(
9139 String*, Object*, PropertyDetails); 10203 String*, Object*, PropertyDetails);
9140 10204
9141 template MaybeObject* 10205 template MaybeObject*
9142 Dictionary<StringDictionaryShape, String*>::GenerateNewEnumerationIndices(); 10206 Dictionary<StringDictionaryShape, String*>::GenerateNewEnumerationIndices();
(...skipping 484 matching lines...) Expand 10 before | Expand all | Expand 10 after
9627 if (!key->IsString()) return 0; 10691 if (!key->IsString()) return 0;
9628 return String::cast(key)->Hash(); 10692 return String::cast(key)->Hash();
9629 } 10693 }
9630 10694
9631 Object* AsObject() { 10695 Object* AsObject() {
9632 // The TwoCharHashTableKey is only used for looking in the symbol 10696 // The TwoCharHashTableKey is only used for looking in the symbol
9633 // table, not for adding to it. 10697 // table, not for adding to it.
9634 UNREACHABLE(); 10698 UNREACHABLE();
9635 return NULL; 10699 return NULL;
9636 } 10700 }
10701
9637 private: 10702 private:
9638 uint32_t c1_; 10703 uint32_t c1_;
9639 uint32_t c2_; 10704 uint32_t c2_;
9640 uint32_t hash_; 10705 uint32_t hash_;
9641 }; 10706 };
9642 10707
9643 10708
9644 bool SymbolTable::LookupSymbolIfExists(String* string, String** symbol) { 10709 bool SymbolTable::LookupSymbolIfExists(String* string, String** symbol) {
9645 SymbolKey key(string); 10710 SymbolKey key(string);
9646 int entry = FindEntry(&key); 10711 int entry = FindEntry(&key);
(...skipping 372 matching lines...) Expand 10 before | Expand all | Expand 10 after
10019 if (details.IsDontDelete() && mode != JSObject::FORCE_DELETION) { 11084 if (details.IsDontDelete() && mode != JSObject::FORCE_DELETION) {
10020 return heap->false_value(); 11085 return heap->false_value();
10021 } 11086 }
10022 SetEntry(entry, heap->null_value(), heap->null_value()); 11087 SetEntry(entry, heap->null_value(), heap->null_value());
10023 HashTable<Shape, Key>::ElementRemoved(); 11088 HashTable<Shape, Key>::ElementRemoved();
10024 return heap->true_value(); 11089 return heap->true_value();
10025 } 11090 }
10026 11091
10027 11092
10028 template<typename Shape, typename Key> 11093 template<typename Shape, typename Key>
11094 MaybeObject* Dictionary<Shape, Key>::Shrink(Key key) {
11095 return HashTable<Shape, Key>::Shrink(key);
11096 }
11097
11098
11099 template<typename Shape, typename Key>
10029 MaybeObject* Dictionary<Shape, Key>::AtPut(Key key, Object* value) { 11100 MaybeObject* Dictionary<Shape, Key>::AtPut(Key key, Object* value) {
10030 int entry = this->FindEntry(key); 11101 int entry = this->FindEntry(key);
10031 11102
10032 // If the entry is present set the value; 11103 // If the entry is present set the value;
10033 if (entry != Dictionary<Shape, Key>::kNotFound) { 11104 if (entry != Dictionary<Shape, Key>::kNotFound) {
10034 ValueAtPut(entry, value); 11105 ValueAtPut(entry, value);
10035 return this; 11106 return this;
10036 } 11107 }
10037 11108
10038 // Check whether the dictionary should be extended. 11109 // Check whether the dictionary should be extended.
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
10167 11238
10168 11239
10169 template<typename Shape, typename Key> 11240 template<typename Shape, typename Key>
10170 int Dictionary<Shape, Key>::NumberOfEnumElements() { 11241 int Dictionary<Shape, Key>::NumberOfEnumElements() {
10171 return NumberOfElementsFilterAttributes( 11242 return NumberOfElementsFilterAttributes(
10172 static_cast<PropertyAttributes>(DONT_ENUM)); 11243 static_cast<PropertyAttributes>(DONT_ENUM));
10173 } 11244 }
10174 11245
10175 11246
10176 template<typename Shape, typename Key> 11247 template<typename Shape, typename Key>
10177 void Dictionary<Shape, Key>::CopyKeysTo(FixedArray* storage, 11248 void Dictionary<Shape, Key>::CopyKeysTo(
10178 PropertyAttributes filter) { 11249 FixedArray* storage,
11250 PropertyAttributes filter,
11251 typename Dictionary<Shape, Key>::SortMode sort_mode) {
10179 ASSERT(storage->length() >= NumberOfEnumElements()); 11252 ASSERT(storage->length() >= NumberOfEnumElements());
10180 int capacity = HashTable<Shape, Key>::Capacity(); 11253 int capacity = HashTable<Shape, Key>::Capacity();
10181 int index = 0; 11254 int index = 0;
10182 for (int i = 0; i < capacity; i++) { 11255 for (int i = 0; i < capacity; i++) {
10183 Object* k = HashTable<Shape, Key>::KeyAt(i); 11256 Object* k = HashTable<Shape, Key>::KeyAt(i);
10184 if (HashTable<Shape, Key>::IsKey(k)) { 11257 if (HashTable<Shape, Key>::IsKey(k)) {
10185 PropertyDetails details = DetailsAt(i); 11258 PropertyDetails details = DetailsAt(i);
10186 if (details.IsDeleted()) continue; 11259 if (details.IsDeleted()) continue;
10187 PropertyAttributes attr = details.attributes(); 11260 PropertyAttributes attr = details.attributes();
10188 if ((attr & filter) == 0) storage->set(index++, k); 11261 if ((attr & filter) == 0) storage->set(index++, k);
10189 } 11262 }
10190 } 11263 }
10191 storage->SortPairs(storage, index); 11264 if (sort_mode == Dictionary<Shape, Key>::SORTED) {
11265 storage->SortPairs(storage, index);
11266 }
10192 ASSERT(storage->length() >= index); 11267 ASSERT(storage->length() >= index);
10193 } 11268 }
10194 11269
10195 11270
10196 void StringDictionary::CopyEnumKeysTo(FixedArray* storage, 11271 void StringDictionary::CopyEnumKeysTo(FixedArray* storage,
10197 FixedArray* sort_array) { 11272 FixedArray* sort_array) {
10198 ASSERT(storage->length() >= NumberOfEnumElements()); 11273 ASSERT(storage->length() >= NumberOfEnumElements());
10199 int capacity = Capacity(); 11274 int capacity = Capacity();
10200 int index = 0; 11275 int index = 0;
10201 for (int i = 0; i < capacity; i++) { 11276 for (int i = 0; i < capacity; i++) {
10202 Object* k = KeyAt(i); 11277 Object* k = KeyAt(i);
10203 if (IsKey(k)) { 11278 if (IsKey(k)) {
10204 PropertyDetails details = DetailsAt(i); 11279 PropertyDetails details = DetailsAt(i);
10205 if (details.IsDeleted() || details.IsDontEnum()) continue; 11280 if (details.IsDeleted() || details.IsDontEnum()) continue;
10206 storage->set(index, k); 11281 storage->set(index, k);
10207 sort_array->set(index, Smi::FromInt(details.index())); 11282 sort_array->set(index, Smi::FromInt(details.index()));
10208 index++; 11283 index++;
10209 } 11284 }
10210 } 11285 }
10211 storage->SortPairs(sort_array, sort_array->length()); 11286 storage->SortPairs(sort_array, sort_array->length());
10212 ASSERT(storage->length() >= index); 11287 ASSERT(storage->length() >= index);
10213 } 11288 }
10214 11289
10215 11290
10216 template<typename Shape, typename Key> 11291 template<typename Shape, typename Key>
10217 void Dictionary<Shape, Key>::CopyKeysTo(FixedArray* storage) { 11292 void Dictionary<Shape, Key>::CopyKeysTo(
11293 FixedArray* storage,
11294 typename Dictionary<Shape, Key>::SortMode sort_mode) {
10218 ASSERT(storage->length() >= NumberOfElementsFilterAttributes( 11295 ASSERT(storage->length() >= NumberOfElementsFilterAttributes(
10219 static_cast<PropertyAttributes>(NONE))); 11296 static_cast<PropertyAttributes>(NONE)));
10220 int capacity = HashTable<Shape, Key>::Capacity(); 11297 int capacity = HashTable<Shape, Key>::Capacity();
10221 int index = 0; 11298 int index = 0;
10222 for (int i = 0; i < capacity; i++) { 11299 for (int i = 0; i < capacity; i++) {
10223 Object* k = HashTable<Shape, Key>::KeyAt(i); 11300 Object* k = HashTable<Shape, Key>::KeyAt(i);
10224 if (HashTable<Shape, Key>::IsKey(k)) { 11301 if (HashTable<Shape, Key>::IsKey(k)) {
10225 PropertyDetails details = DetailsAt(i); 11302 PropertyDetails details = DetailsAt(i);
10226 if (details.IsDeleted()) continue; 11303 if (details.IsDeleted()) continue;
10227 storage->set(index++, k); 11304 storage->set(index++, k);
10228 } 11305 }
10229 } 11306 }
11307 if (sort_mode == Dictionary<Shape, Key>::SORTED) {
11308 storage->SortPairs(storage, index);
11309 }
10230 ASSERT(storage->length() >= index); 11310 ASSERT(storage->length() >= index);
10231 } 11311 }
10232 11312
10233 11313
10234 // Backwards lookup (slow). 11314 // Backwards lookup (slow).
10235 template<typename Shape, typename Key> 11315 template<typename Shape, typename Key>
10236 Object* Dictionary<Shape, Key>::SlowReverseLookup(Object* value) { 11316 Object* Dictionary<Shape, Key>::SlowReverseLookup(Object* value) {
10237 int capacity = HashTable<Shape, Key>::Capacity(); 11317 int capacity = HashTable<Shape, Key>::Capacity();
10238 for (int i = 0; i < capacity; i++) { 11318 for (int i = 0; i < capacity; i++) {
10239 Object* k = HashTable<Shape, Key>::KeyAt(i); 11319 Object* k = HashTable<Shape, Key>::KeyAt(i);
(...skipping 393 matching lines...) Expand 10 before | Expand all | Expand 10 after
10633 if (break_point_objects()->IsUndefined()) return 0; 11713 if (break_point_objects()->IsUndefined()) return 0;
10634 // Single beak point. 11714 // Single beak point.
10635 if (!break_point_objects()->IsFixedArray()) return 1; 11715 if (!break_point_objects()->IsFixedArray()) return 1;
10636 // Multiple break points. 11716 // Multiple break points.
10637 return FixedArray::cast(break_point_objects())->length(); 11717 return FixedArray::cast(break_point_objects())->length();
10638 } 11718 }
10639 #endif 11719 #endif
10640 11720
10641 11721
10642 } } // namespace v8::internal 11722 } } // 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