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

Side by Side Diff: src/objects.cc

Issue 10209027: Implement tracking and optimizations of packed arrays. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: New upload Created 8 years, 8 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 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
49 #include "vm-state-inl.h" 49 #include "vm-state-inl.h"
50 50
51 #ifdef ENABLE_DISASSEMBLER 51 #ifdef ENABLE_DISASSEMBLER
52 #include "disasm.h" 52 #include "disasm.h"
53 #include "disassembler.h" 53 #include "disassembler.h"
54 #endif 54 #endif
55 55
56 namespace v8 { 56 namespace v8 {
57 namespace internal { 57 namespace internal {
58 58
59 void PrintElementsKind(FILE* out, ElementsKind kind) {
60 ElementsAccessor* accessor = ElementsAccessor::ForKind(kind);
61 PrintF(out, "%s", accessor->name());
62 }
63
64 59
65 MUST_USE_RESULT static MaybeObject* CreateJSValue(JSFunction* constructor, 60 MUST_USE_RESULT static MaybeObject* CreateJSValue(JSFunction* constructor,
66 Object* value) { 61 Object* value) {
67 Object* result; 62 Object* result;
68 { MaybeObject* maybe_result = 63 { MaybeObject* maybe_result =
69 constructor->GetHeap()->AllocateJSObject(constructor); 64 constructor->GetHeap()->AllocateJSObject(constructor);
70 if (!maybe_result->ToObject(&result)) return maybe_result; 65 if (!maybe_result->ToObject(&result)) return maybe_result;
71 } 66 }
72 JSValue::cast(result)->set_value(value); 67 JSValue::cast(result)->set_value(value);
73 return result; 68 return result;
(...skipping 462 matching lines...) Expand 10 before | Expand all | Expand 10 after
536 bool JSObject::IsDirty() { 531 bool JSObject::IsDirty() {
537 Object* cons_obj = map()->constructor(); 532 Object* cons_obj = map()->constructor();
538 if (!cons_obj->IsJSFunction()) 533 if (!cons_obj->IsJSFunction())
539 return true; 534 return true;
540 JSFunction* fun = JSFunction::cast(cons_obj); 535 JSFunction* fun = JSFunction::cast(cons_obj);
541 if (!fun->shared()->IsApiFunction()) 536 if (!fun->shared()->IsApiFunction())
542 return true; 537 return true;
543 // If the object is fully fast case and has the same map it was 538 // If the object is fully fast case and has the same map it was
544 // created with then no changes can have been made to it. 539 // created with then no changes can have been made to it.
545 return map() != fun->initial_map() 540 return map() != fun->initial_map()
546 || !HasFastElements() 541 || !HasFastObjectElements()
547 || !HasFastProperties(); 542 || !HasFastProperties();
548 } 543 }
549 544
550 545
551 Handle<Object> Object::GetProperty(Handle<Object> object, 546 Handle<Object> Object::GetProperty(Handle<Object> object,
552 Handle<Object> receiver, 547 Handle<Object> receiver,
553 LookupResult* result, 548 LookupResult* result,
554 Handle<String> key, 549 Handle<String> key,
555 PropertyAttributes* attributes) { 550 PropertyAttributes* attributes) {
556 Isolate* isolate = object->IsHeapObject() 551 Isolate* isolate = object->IsHeapObject()
(...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after
895 cs->set_second(heap->empty_string(), SKIP_WRITE_BARRIER); 890 cs->set_second(heap->empty_string(), SKIP_WRITE_BARRIER);
896 return result; 891 return result;
897 } 892 }
898 default: 893 default:
899 return this; 894 return this;
900 } 895 }
901 } 896 }
902 897
903 898
904 bool String::MakeExternal(v8::String::ExternalStringResource* resource) { 899 bool String::MakeExternal(v8::String::ExternalStringResource* resource) {
905 // Externalizing twice leaks the external resource, so it's 900 // Externalizing twice leaks the external resource, so its prohibited by the
906 // prohibited by the API. 901 // API.
907 ASSERT(!this->IsExternalString()); 902 ASSERT(!this->IsExternalString());
908 #ifdef DEBUG 903 #ifdef DEBUG
909 if (FLAG_enable_slow_asserts) { 904 if (FLAG_enable_slow_asserts) {
910 // Assert that the resource and the string are equivalent. 905 // Assert that the resource and the string are equivalent.
911 ASSERT(static_cast<size_t>(this->length()) == resource->length()); 906 ASSERT(static_cast<size_t>(this->length()) == resource->length());
912 ScopedVector<uc16> smart_chars(this->length()); 907 ScopedVector<uc16> smart_chars(this->length());
913 String::WriteToFlat(this, smart_chars.start(), 0, this->length()); 908 String::WriteToFlat(this, smart_chars.start(), 0, this->length());
914 ASSERT(memcmp(smart_chars.start(), 909 ASSERT(memcmp(smart_chars.start(),
915 resource->data(), 910 resource->data(),
916 resource->length() * sizeof(smart_chars[0])) == 0); 911 resource->length() * sizeof(smart_chars[0])) == 0);
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
1060 } 1055 }
1061 accumulator->Put('>'); 1056 accumulator->Put('>');
1062 } 1057 }
1063 return; 1058 return;
1064 } 1059 }
1065 1060
1066 1061
1067 void JSObject::JSObjectShortPrint(StringStream* accumulator) { 1062 void JSObject::JSObjectShortPrint(StringStream* accumulator) {
1068 switch (map()->instance_type()) { 1063 switch (map()->instance_type()) {
1069 case JS_ARRAY_TYPE: { 1064 case JS_ARRAY_TYPE: {
1070 double length = JSArray::cast(this)->length()->Number(); 1065 double length = JSArray::cast(this)->length()->IsUndefined()
1066 ? 0 :
1067 JSArray::cast(this)->length()->Number();
1071 accumulator->Add("<JS Array[%u]>", static_cast<uint32_t>(length)); 1068 accumulator->Add("<JS Array[%u]>", static_cast<uint32_t>(length));
1072 break; 1069 break;
1073 } 1070 }
1074 case JS_WEAK_MAP_TYPE: { 1071 case JS_WEAK_MAP_TYPE: {
1075 accumulator->Add("<JS WeakMap>"); 1072 accumulator->Add("<JS WeakMap>");
1076 break; 1073 break;
1077 } 1074 }
1078 case JS_REGEXP_TYPE: { 1075 case JS_REGEXP_TYPE: {
1079 accumulator->Add("<JS RegExp>"); 1076 accumulator->Add("<JS RegExp>");
1080 break; 1077 break;
(...skipping 980 matching lines...) Expand 10 before | Expand all | Expand 10 after
2061 if (result->IsProperty()) { 2058 if (result->IsProperty()) {
2062 if (result->type() == CALLBACKS && !result->IsReadOnly()) return; 2059 if (result->type() == CALLBACKS && !result->IsReadOnly()) return;
2063 // Found non-callback or read-only callback, stop looking. 2060 // Found non-callback or read-only callback, stop looking.
2064 break; 2061 break;
2065 } 2062 }
2066 } 2063 }
2067 result->NotFound(); 2064 result->NotFound();
2068 } 2065 }
2069 2066
2070 2067
2068 void JSObject::ValidateElements() {
2069 ElementsAccessor* accessor = GetElementsAccessor();
2070 accessor->Validate(this);
2071 }
2072
2073
2071 MaybeObject* JSObject::SetElementWithCallbackSetterInPrototypes( 2074 MaybeObject* JSObject::SetElementWithCallbackSetterInPrototypes(
2072 uint32_t index, 2075 uint32_t index,
2073 Object* value, 2076 Object* value,
2074 bool* found, 2077 bool* found,
2075 StrictModeFlag strict_mode) { 2078 StrictModeFlag strict_mode) {
2076 Heap* heap = GetHeap(); 2079 Heap* heap = GetHeap();
2077 for (Object* pt = GetPrototype(); 2080 for (Object* pt = GetPrototype();
2078 pt != heap->null_value(); 2081 pt != heap->null_value();
2079 pt = pt->GetPrototype()) { 2082 pt = pt->GetPrototype()) {
2080 if (pt->IsJSProxy()) { 2083 if (pt->IsJSProxy()) {
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
2192 2195
2193 2196
2194 template <class T> 2197 template <class T>
2195 static Handle<T> MaybeNull(T* p) { 2198 static Handle<T> MaybeNull(T* p) {
2196 if (p == NULL) return Handle<T>::null(); 2199 if (p == NULL) return Handle<T>::null();
2197 return Handle<T>(p); 2200 return Handle<T>(p);
2198 } 2201 }
2199 2202
2200 2203
2201 Handle<Map> Map::FindTransitionedMap(MapHandleList* candidates) { 2204 Handle<Map> Map::FindTransitionedMap(MapHandleList* candidates) {
2202 ElementsKind elms_kind = elements_kind(); 2205 ElementsKind kind = elements_kind();
2203 if (elms_kind == FAST_DOUBLE_ELEMENTS) { 2206 Handle<Map> transitioned_map = Handle<Map>::null();
2204 bool dummy = true; 2207 Handle<Map> current_map(this);
2205 Handle<Map> fast_map = 2208 bool packed = IsFastPackedElementsKind(kind);
2206 MaybeNull(LookupElementsTransitionMap(FAST_ELEMENTS, &dummy)); 2209 if (IsTransitionableFastElementsKind(kind)) {
2207 if (!fast_map.is_null() && ContainsMap(candidates, fast_map)) { 2210 while (CanTransitionToMoreGeneralFastElementsKind(kind, false)) {
2208 return fast_map; 2211 kind = GetNextMoreGeneralFastElementsKind(kind, false);
2212 bool dummy = true;
2213 Handle<Map> maybe_transitioned_map =
2214 MaybeNull(current_map->LookupElementsTransitionMap(kind, &dummy));
2215 if (maybe_transitioned_map.is_null()) break;
2216 if (ContainsMap(candidates, maybe_transitioned_map) &&
2217 (packed || !IsFastPackedElementsKind(kind))) {
2218 transitioned_map = maybe_transitioned_map;
2219 if (!IsFastPackedElementsKind(kind)) packed = false;
2220 }
2221 current_map = maybe_transitioned_map;
2209 } 2222 }
2210 return Handle<Map>::null();
2211 } 2223 }
2212 if (elms_kind == FAST_SMI_ONLY_ELEMENTS) { 2224 return transitioned_map;
2213 bool dummy = true;
2214 Handle<Map> double_map =
2215 MaybeNull(LookupElementsTransitionMap(FAST_DOUBLE_ELEMENTS, &dummy));
2216 // In the current implementation, if the DOUBLE map doesn't exist, the
2217 // FAST map can't exist either.
2218 if (double_map.is_null()) return Handle<Map>::null();
2219 Handle<Map> fast_map =
2220 MaybeNull(double_map->LookupElementsTransitionMap(FAST_ELEMENTS,
2221 &dummy));
2222 if (!fast_map.is_null() && ContainsMap(candidates, fast_map)) {
2223 return fast_map;
2224 }
2225 if (ContainsMap(candidates, double_map)) return double_map;
2226 }
2227 return Handle<Map>::null();
2228 } 2225 }
2229 2226
2227
2230 static Map* GetElementsTransitionMapFromDescriptor(Object* descriptor_contents, 2228 static Map* GetElementsTransitionMapFromDescriptor(Object* descriptor_contents,
2231 ElementsKind elements_kind) { 2229 ElementsKind elements_kind) {
2232 if (descriptor_contents->IsMap()) { 2230 if (descriptor_contents->IsMap()) {
2233 Map* map = Map::cast(descriptor_contents); 2231 Map* map = Map::cast(descriptor_contents);
2234 if (map->elements_kind() == elements_kind) { 2232 if (map->elements_kind() == elements_kind) {
2235 return map; 2233 return map;
2236 } 2234 }
2237 return NULL; 2235 return NULL;
2238 } 2236 }
2239 2237
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
2328 } else { 2326 } else {
2329 if (safe_to_add_transition != NULL) { 2327 if (safe_to_add_transition != NULL) {
2330 *safe_to_add_transition = false; 2328 *safe_to_add_transition = false;
2331 } 2329 }
2332 } 2330 }
2333 } 2331 }
2334 return NULL; 2332 return NULL;
2335 } 2333 }
2336 2334
2337 2335
2338 Map* Map::LookupElementsTransitionMap(ElementsKind elements_kind, 2336 Map* Map::LookupElementsTransitionMap(ElementsKind to_kind,
2339 bool* safe_to_add_transition) { 2337 bool* safe_to_add_transition) {
2340 // Special case: indirect SMI->FAST transition (cf. comment in 2338 ElementsKind from_kind = elements_kind();
2341 // AddElementsTransition()). 2339 if (IsFastElementsKind(from_kind) && IsFastElementsKind(to_kind)) {
2342 if (this->elements_kind() == FAST_SMI_ONLY_ELEMENTS && 2340 if (!IsMoreGeneralElementsKindTransition(from_kind, to_kind)) {
2343 elements_kind == FAST_ELEMENTS) { 2341 if (safe_to_add_transition) *safe_to_add_transition = false;
2344 Map* double_map = this->LookupElementsTransitionMap(FAST_DOUBLE_ELEMENTS, 2342 return NULL;
2345 safe_to_add_transition); 2343 }
2346 if (double_map == NULL) return double_map; 2344 ElementsKind transitioned_from_kind =
2347 return double_map->LookupElementsTransitionMap(FAST_ELEMENTS, 2345 GetNextMoreGeneralFastElementsKind(from_kind, false);
2346
2347
2348 // If the transition is a single step in the transition sequence, fall
2349 // through to looking it up and returning it. If it requires several steps,
2350 // divide and conquer.
2351 if (transitioned_from_kind != to_kind) {
2352 // If the transition is several steps in the lattice, divide and conquer.
2353 Map* from_map = LookupElementsTransitionMap(transitioned_from_kind,
2354 safe_to_add_transition);
2355 if (from_map == NULL) return NULL;
2356 return from_map->LookupElementsTransitionMap(to_kind,
2348 safe_to_add_transition); 2357 safe_to_add_transition);
2358 }
2349 } 2359 }
2360
2350 Object* descriptor_contents = GetDescriptorContents( 2361 Object* descriptor_contents = GetDescriptorContents(
2351 elements_transition_sentinel_name(), safe_to_add_transition); 2362 elements_transition_sentinel_name(), safe_to_add_transition);
2352 if (descriptor_contents != NULL) { 2363 if (descriptor_contents != NULL) {
2353 Map* maybe_transition_map = 2364 Map* maybe_transition_map =
2354 GetElementsTransitionMapFromDescriptor(descriptor_contents, 2365 GetElementsTransitionMapFromDescriptor(descriptor_contents,
2355 elements_kind); 2366 to_kind);
2356 ASSERT(maybe_transition_map == NULL || maybe_transition_map->IsMap()); 2367 ASSERT(maybe_transition_map == NULL || maybe_transition_map->IsMap());
2357 return maybe_transition_map; 2368 return maybe_transition_map;
2358 } 2369 }
2359 return NULL; 2370 return NULL;
2360 } 2371 }
2361 2372
2362 2373
2363 MaybeObject* Map::AddElementsTransition(ElementsKind elements_kind, 2374 MaybeObject* Map::AddElementsTransition(ElementsKind to_kind,
2364 Map* transitioned_map) { 2375 Map* transitioned_map) {
2365 // The map transition graph should be a tree, therefore the transition 2376 ElementsKind from_kind = elements_kind();
2366 // from SMI to FAST elements is not done directly, but by going through 2377 if (IsFastElementsKind(from_kind) && IsFastElementsKind(to_kind)) {
2367 // DOUBLE elements first. 2378 ASSERT(IsMoreGeneralElementsKindTransition(from_kind, to_kind));
2368 if (this->elements_kind() == FAST_SMI_ONLY_ELEMENTS && 2379 ElementsKind transitioned_from_kind =
2369 elements_kind == FAST_ELEMENTS) { 2380 GetNextMoreGeneralFastElementsKind(from_kind, false);
2370 bool safe_to_add = true; 2381 // The map transitions graph should be a tree, therefore transitions to
2371 Map* double_map = this->LookupElementsTransitionMap( 2382 // ElementsKind that are not adjacent in the ElementsKind sequence are not
2372 FAST_DOUBLE_ELEMENTS, &safe_to_add); 2383 // done directly, but instead by going through intermediate ElementsKinds
2373 // This method is only called when safe_to_add_transition has been found 2384 // first.
2374 // to be true earlier. 2385 if (to_kind != transitioned_from_kind) {
2375 ASSERT(safe_to_add); 2386 bool safe_to_add = true;
2387 Map* intermediate_map = LookupElementsTransitionMap(
2388 transitioned_from_kind, &safe_to_add);
2389 // This method is only called when safe_to_add_transition has been found
2390 // to be true earlier.
2391 ASSERT(safe_to_add);
2376 2392
2377 if (double_map == NULL) { 2393 if (intermediate_map == NULL) {
2378 MaybeObject* maybe_map = this->CopyDropTransitions(); 2394 MaybeObject* maybe_map = CopyDropTransitions();
2379 if (!maybe_map->To(&double_map)) return maybe_map; 2395 if (!maybe_map->To(&intermediate_map)) return maybe_map;
2380 double_map->set_elements_kind(FAST_DOUBLE_ELEMENTS); 2396 intermediate_map->set_elements_kind(transitioned_from_kind);
2381 MaybeObject* maybe_double_transition = this->AddElementsTransition( 2397 MaybeObject* maybe_transition = AddElementsTransition(
2382 FAST_DOUBLE_ELEMENTS, double_map); 2398 transitioned_from_kind, intermediate_map);
2383 if (maybe_double_transition->IsFailure()) return maybe_double_transition; 2399 if (maybe_transition->IsFailure()) return maybe_transition;
2400 }
2401 return intermediate_map->AddElementsTransition(to_kind, transitioned_map);
2384 } 2402 }
2385 return double_map->AddElementsTransition(FAST_ELEMENTS, transitioned_map);
2386 } 2403 }
2387 2404
2388 bool safe_to_add_transition = true; 2405 bool safe_to_add_transition = true;
2389 Object* descriptor_contents = GetDescriptorContents( 2406 Object* descriptor_contents = GetDescriptorContents(
2390 elements_transition_sentinel_name(), &safe_to_add_transition); 2407 elements_transition_sentinel_name(), &safe_to_add_transition);
2391 // This method is only called when safe_to_add_transition has been found 2408 // This method is only called when safe_to_add_transition has been found
2392 // to be true earlier. 2409 // to be true earlier.
2393 ASSERT(safe_to_add_transition); 2410 ASSERT(safe_to_add_transition);
2394 MaybeObject* maybe_new_contents = 2411 MaybeObject* maybe_new_contents =
2395 AddElementsTransitionMapToDescriptor(descriptor_contents, 2412 AddElementsTransitionMapToDescriptor(descriptor_contents,
(...skipping 30 matching lines...) Expand all
2426 ElementsKind from_kind = current_map->elements_kind(); 2443 ElementsKind from_kind = current_map->elements_kind();
2427 2444
2428 if (from_kind == to_kind) return current_map; 2445 if (from_kind == to_kind) return current_map;
2429 2446
2430 // Only objects with FastProperties can have DescriptorArrays and can track 2447 // Only objects with FastProperties can have DescriptorArrays and can track
2431 // element-related maps. Also don't add descriptors to maps that are shared. 2448 // element-related maps. Also don't add descriptors to maps that are shared.
2432 bool safe_to_add_transition = HasFastProperties() && 2449 bool safe_to_add_transition = HasFastProperties() &&
2433 !current_map->IsUndefined() && 2450 !current_map->IsUndefined() &&
2434 !current_map->is_shared(); 2451 !current_map->is_shared();
2435 2452
2436 // Prevent long chains of DICTIONARY -> FAST_ELEMENTS maps caused by objects 2453 // Prevent long chains of DICTIONARY -> fast object elements maps caused by
2437 // with elements that switch back and forth between dictionary and fast 2454 // objects with elements that switch back and forth between dictionary and
2438 // element mode. 2455 // fast element mode.
2439 if (from_kind == DICTIONARY_ELEMENTS && to_kind == FAST_ELEMENTS) { 2456 if (from_kind == DICTIONARY_ELEMENTS &&
2457 IsFastObjectElementsKind(to_kind)) {
2440 safe_to_add_transition = false; 2458 safe_to_add_transition = false;
2441 } 2459 }
2442 2460
2443 if (safe_to_add_transition) { 2461 if (safe_to_add_transition) {
2444 // It's only safe to manipulate the descriptor array if it would be 2462 // It's only safe to manipulate the descriptor array if it would be
2445 // safe to add a transition. 2463 // safe to add a transition.
2446 Map* maybe_transition_map = current_map->LookupElementsTransitionMap( 2464 Map* maybe_transition_map = current_map->LookupElementsTransitionMap(
2447 to_kind, &safe_to_add_transition); 2465 to_kind, &safe_to_add_transition);
2448 if (maybe_transition_map != NULL) { 2466 if (maybe_transition_map != NULL) {
2449 return maybe_transition_map; 2467 return maybe_transition_map;
(...skipping 1015 matching lines...) Expand 10 before | Expand all | Expand 10 after
3465 // Find the backing store. 3483 // Find the backing store.
3466 FixedArrayBase* array = FixedArrayBase::cast(elements()); 3484 FixedArrayBase* array = FixedArrayBase::cast(elements());
3467 Map* old_map = array->map(); 3485 Map* old_map = array->map();
3468 bool is_arguments = 3486 bool is_arguments =
3469 (old_map == old_map->GetHeap()->non_strict_arguments_elements_map()); 3487 (old_map == old_map->GetHeap()->non_strict_arguments_elements_map());
3470 if (is_arguments) { 3488 if (is_arguments) {
3471 array = FixedArrayBase::cast(FixedArray::cast(array)->get(1)); 3489 array = FixedArrayBase::cast(FixedArray::cast(array)->get(1));
3472 } 3490 }
3473 if (array->IsDictionary()) return array; 3491 if (array->IsDictionary()) return array;
3474 3492
3475 ASSERT(HasFastElements() || 3493 ASSERT(HasFastSmiOrObjectElements() ||
3476 HasFastSmiOnlyElements() ||
3477 HasFastDoubleElements() || 3494 HasFastDoubleElements() ||
3478 HasFastArgumentsElements()); 3495 HasFastArgumentsElements());
3479 // Compute the effective length and allocate a new backing store. 3496 // Compute the effective length and allocate a new backing store.
3480 int length = IsJSArray() 3497 int length = IsJSArray()
3481 ? Smi::cast(JSArray::cast(this)->length())->value() 3498 ? Smi::cast(JSArray::cast(this)->length())->value()
3482 : array->length(); 3499 : array->length();
3483 int old_capacity = 0; 3500 int old_capacity = 0;
3484 int used_elements = 0; 3501 int used_elements = 0;
3485 GetElementsCapacityAndUsage(&old_capacity, &used_elements); 3502 GetElementsCapacityAndUsage(&old_capacity, &used_elements);
3486 SeededNumberDictionary* dictionary = NULL; 3503 SeededNumberDictionary* dictionary = NULL;
(...skipping 14 matching lines...) Expand all
3501 } else { 3518 } else {
3502 // Objects must be allocated in the old object space, since the 3519 // Objects must be allocated in the old object space, since the
3503 // overall number of HeapNumbers needed for the conversion might 3520 // overall number of HeapNumbers needed for the conversion might
3504 // exceed the capacity of new space, and we would fail repeatedly 3521 // exceed the capacity of new space, and we would fail repeatedly
3505 // trying to convert the FixedDoubleArray. 3522 // trying to convert the FixedDoubleArray.
3506 MaybeObject* maybe_value_object = 3523 MaybeObject* maybe_value_object =
3507 GetHeap()->AllocateHeapNumber(double_array->get_scalar(i), TENURED); 3524 GetHeap()->AllocateHeapNumber(double_array->get_scalar(i), TENURED);
3508 if (!maybe_value_object->ToObject(&value)) return maybe_value_object; 3525 if (!maybe_value_object->ToObject(&value)) return maybe_value_object;
3509 } 3526 }
3510 } else { 3527 } else {
3511 ASSERT(old_map->has_fast_elements() || 3528 ASSERT(old_map->has_fast_smi_or_object_elements());
3512 old_map->has_fast_smi_only_elements());
3513 value = FixedArray::cast(array)->get(i); 3529 value = FixedArray::cast(array)->get(i);
3514 } 3530 }
3515 PropertyDetails details = PropertyDetails(NONE, NORMAL); 3531 PropertyDetails details = PropertyDetails(NONE, NORMAL);
3516 if (!value->IsTheHole()) { 3532 if (!value->IsTheHole()) {
3517 Object* result; 3533 Object* result;
3518 MaybeObject* maybe_result = 3534 MaybeObject* maybe_result =
3519 dictionary->AddNumberEntry(i, value, details); 3535 dictionary->AddNumberEntry(i, value, details);
3520 if (!maybe_result->ToObject(&result)) return maybe_result; 3536 if (!maybe_result->ToObject(&result)) return maybe_result;
3521 dictionary = SeededNumberDictionary::cast(result); 3537 dictionary = SeededNumberDictionary::cast(result);
3522 } 3538 }
(...skipping 466 matching lines...) Expand 10 before | Expand all | Expand 10 after
3989 if (IsJSProxy()) { 4005 if (IsJSProxy()) {
3990 return JSProxy::cast(this)->DeletePropertyWithHandler(name, mode); 4006 return JSProxy::cast(this)->DeletePropertyWithHandler(name, mode);
3991 } 4007 }
3992 return JSObject::cast(this)->DeleteProperty(name, mode); 4008 return JSObject::cast(this)->DeleteProperty(name, mode);
3993 } 4009 }
3994 4010
3995 4011
3996 bool JSObject::ReferencesObjectFromElements(FixedArray* elements, 4012 bool JSObject::ReferencesObjectFromElements(FixedArray* elements,
3997 ElementsKind kind, 4013 ElementsKind kind,
3998 Object* object) { 4014 Object* object) {
3999 ASSERT(kind == FAST_ELEMENTS || 4015 ASSERT(IsFastObjectElementsKind(kind) ||
4000 kind == DICTIONARY_ELEMENTS); 4016 kind == DICTIONARY_ELEMENTS);
4001 if (kind == FAST_ELEMENTS) { 4017 if (IsFastObjectElementsKind(kind)) {
4002 int length = IsJSArray() 4018 int length = IsJSArray()
4003 ? Smi::cast(JSArray::cast(this)->length())->value() 4019 ? Smi::cast(JSArray::cast(this)->length())->value()
4004 : elements->length(); 4020 : elements->length();
4005 for (int i = 0; i < length; ++i) { 4021 for (int i = 0; i < length; ++i) {
4006 Object* element = elements->get(i); 4022 Object* element = elements->get(i);
4007 if (!element->IsTheHole() && element == object) return true; 4023 if (!element->IsTheHole() && element == object) return true;
4008 } 4024 }
4009 } else { 4025 } else {
4010 Object* key = 4026 Object* key =
4011 SeededNumberDictionary::cast(elements)->SlowReverseLookup(object); 4027 SeededNumberDictionary::cast(elements)->SlowReverseLookup(object);
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
4043 case EXTERNAL_PIXEL_ELEMENTS: 4059 case EXTERNAL_PIXEL_ELEMENTS:
4044 case EXTERNAL_BYTE_ELEMENTS: 4060 case EXTERNAL_BYTE_ELEMENTS:
4045 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 4061 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
4046 case EXTERNAL_SHORT_ELEMENTS: 4062 case EXTERNAL_SHORT_ELEMENTS:
4047 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 4063 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
4048 case EXTERNAL_INT_ELEMENTS: 4064 case EXTERNAL_INT_ELEMENTS:
4049 case EXTERNAL_UNSIGNED_INT_ELEMENTS: 4065 case EXTERNAL_UNSIGNED_INT_ELEMENTS:
4050 case EXTERNAL_FLOAT_ELEMENTS: 4066 case EXTERNAL_FLOAT_ELEMENTS:
4051 case EXTERNAL_DOUBLE_ELEMENTS: 4067 case EXTERNAL_DOUBLE_ELEMENTS:
4052 case FAST_DOUBLE_ELEMENTS: 4068 case FAST_DOUBLE_ELEMENTS:
4069 case FAST_HOLEY_DOUBLE_ELEMENTS:
4053 // Raw pixels and external arrays do not reference other 4070 // Raw pixels and external arrays do not reference other
4054 // objects. 4071 // objects.
4055 break; 4072 break;
4056 case FAST_SMI_ONLY_ELEMENTS: 4073 case FAST_SMI_ELEMENTS:
4074 case FAST_HOLEY_SMI_ELEMENTS:
4057 break; 4075 break;
4058 case FAST_ELEMENTS: 4076 case FAST_ELEMENTS:
4077 case FAST_HOLEY_ELEMENTS:
4059 case DICTIONARY_ELEMENTS: { 4078 case DICTIONARY_ELEMENTS: {
4060 FixedArray* elements = FixedArray::cast(this->elements()); 4079 FixedArray* elements = FixedArray::cast(this->elements());
4061 if (ReferencesObjectFromElements(elements, kind, obj)) return true; 4080 if (ReferencesObjectFromElements(elements, kind, obj)) return true;
4062 break; 4081 break;
4063 } 4082 }
4064 case NON_STRICT_ARGUMENTS_ELEMENTS: { 4083 case NON_STRICT_ARGUMENTS_ELEMENTS: {
4065 FixedArray* parameter_map = FixedArray::cast(elements()); 4084 FixedArray* parameter_map = FixedArray::cast(elements());
4066 // Check the mapped parameters. 4085 // Check the mapped parameters.
4067 int length = parameter_map->length(); 4086 int length = parameter_map->length();
4068 for (int i = 2; i < length; ++i) { 4087 for (int i = 2; i < length; ++i) {
4069 Object* value = parameter_map->get(i); 4088 Object* value = parameter_map->get(i);
4070 if (!value->IsTheHole() && value == obj) return true; 4089 if (!value->IsTheHole() && value == obj) return true;
4071 } 4090 }
4072 // Check the arguments. 4091 // Check the arguments.
4073 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); 4092 FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
4074 kind = arguments->IsDictionary() ? DICTIONARY_ELEMENTS : FAST_ELEMENTS; 4093 kind = arguments->IsDictionary() ? DICTIONARY_ELEMENTS :
4094 FAST_HOLEY_ELEMENTS;
4075 if (ReferencesObjectFromElements(arguments, kind, obj)) return true; 4095 if (ReferencesObjectFromElements(arguments, kind, obj)) return true;
4076 break; 4096 break;
4077 } 4097 }
4078 } 4098 }
4079 4099
4080 // For functions check the context. 4100 // For functions check the context.
4081 if (IsJSFunction()) { 4101 if (IsJSFunction()) {
4082 // Get the constructor function for arguments array. 4102 // Get the constructor function for arguments array.
4083 JSObject* arguments_boilerplate = 4103 JSObject* arguments_boilerplate =
4084 heap->isolate()->context()->global_context()-> 4104 heap->isolate()->context()->global_context()->
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after
4298 for (Object* current = this; 4318 for (Object* current = this;
4299 current != heap->null_value(); 4319 current != heap->null_value();
4300 current = JSObject::cast(current)->GetPrototype()) { 4320 current = JSObject::cast(current)->GetPrototype()) {
4301 JSReceiver::cast(current)->LocalLookup(name, result); 4321 JSReceiver::cast(current)->LocalLookup(name, result);
4302 if (result->IsProperty()) return; 4322 if (result->IsProperty()) return;
4303 } 4323 }
4304 result->NotFound(); 4324 result->NotFound();
4305 } 4325 }
4306 4326
4307 4327
4308 // Search object and it's prototype chain for callback properties. 4328 // Search object and its prototype chain for callback properties.
4309 void JSObject::LookupCallback(String* name, LookupResult* result) { 4329 void JSObject::LookupCallback(String* name, LookupResult* result) {
4310 Heap* heap = GetHeap(); 4330 Heap* heap = GetHeap();
4311 for (Object* current = this; 4331 for (Object* current = this;
4312 current != heap->null_value() && current->IsJSObject(); 4332 current != heap->null_value() && current->IsJSObject();
4313 current = JSObject::cast(current)->GetPrototype()) { 4333 current = JSObject::cast(current)->GetPrototype()) {
4314 JSObject::cast(current)->LocalLookupRealNamedProperty(name, result); 4334 JSObject::cast(current)->LocalLookupRealNamedProperty(name, result);
4315 if (result->IsFound() && result->type() == CALLBACKS) return; 4335 if (result->IsFound() && result->type() == CALLBACKS) return;
4316 } 4336 }
4317 result->NotFound(); 4337 result->NotFound();
4318 } 4338 }
(...skipping 23 matching lines...) Expand all
4342 } 4362 }
4343 return false; 4363 return false;
4344 } 4364 }
4345 4365
4346 4366
4347 MaybeObject* JSObject::DefineElementAccessor(uint32_t index, 4367 MaybeObject* JSObject::DefineElementAccessor(uint32_t index,
4348 Object* getter, 4368 Object* getter,
4349 Object* setter, 4369 Object* setter,
4350 PropertyAttributes attributes) { 4370 PropertyAttributes attributes) {
4351 switch (GetElementsKind()) { 4371 switch (GetElementsKind()) {
4352 case FAST_SMI_ONLY_ELEMENTS: 4372 case FAST_SMI_ELEMENTS:
4353 case FAST_ELEMENTS: 4373 case FAST_ELEMENTS:
4354 case FAST_DOUBLE_ELEMENTS: 4374 case FAST_DOUBLE_ELEMENTS:
4375 case FAST_HOLEY_SMI_ELEMENTS:
4376 case FAST_HOLEY_ELEMENTS:
4377 case FAST_HOLEY_DOUBLE_ELEMENTS:
4355 break; 4378 break;
4356 case EXTERNAL_PIXEL_ELEMENTS: 4379 case EXTERNAL_PIXEL_ELEMENTS:
4357 case EXTERNAL_BYTE_ELEMENTS: 4380 case EXTERNAL_BYTE_ELEMENTS:
4358 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 4381 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
4359 case EXTERNAL_SHORT_ELEMENTS: 4382 case EXTERNAL_SHORT_ELEMENTS:
4360 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 4383 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
4361 case EXTERNAL_INT_ELEMENTS: 4384 case EXTERNAL_INT_ELEMENTS:
4362 case EXTERNAL_UNSIGNED_INT_ELEMENTS: 4385 case EXTERNAL_UNSIGNED_INT_ELEMENTS:
4363 case EXTERNAL_FLOAT_ELEMENTS: 4386 case EXTERNAL_FLOAT_ELEMENTS:
4364 case EXTERNAL_DOUBLE_ELEMENTS: 4387 case EXTERNAL_DOUBLE_ELEMENTS:
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
4434 accessors->SetComponents(getter, setter); 4457 accessors->SetComponents(getter, setter);
4435 return SetPropertyCallback(name, accessors, attributes); 4458 return SetPropertyCallback(name, accessors, attributes);
4436 } 4459 }
4437 4460
4438 4461
4439 bool JSObject::CanSetCallback(String* name) { 4462 bool JSObject::CanSetCallback(String* name) {
4440 ASSERT(!IsAccessCheckNeeded() || 4463 ASSERT(!IsAccessCheckNeeded() ||
4441 GetIsolate()->MayNamedAccess(this, name, v8::ACCESS_SET)); 4464 GetIsolate()->MayNamedAccess(this, name, v8::ACCESS_SET));
4442 4465
4443 // Check if there is an API defined callback object which prohibits 4466 // Check if there is an API defined callback object which prohibits
4444 // callback overwriting in this object or it's prototype chain. 4467 // callback overwriting in this object or its prototype chain.
4445 // This mechanism is needed for instance in a browser setting, where 4468 // This mechanism is needed for instance in a browser setting, where
4446 // certain accessors such as window.location should not be allowed 4469 // certain accessors such as window.location should not be allowed
4447 // to be overwritten because allowing overwriting could potentially 4470 // to be overwritten because allowing overwriting could potentially
4448 // cause security problems. 4471 // cause security problems.
4449 LookupResult callback_result(GetIsolate()); 4472 LookupResult callback_result(GetIsolate());
4450 LookupCallback(name, &callback_result); 4473 LookupCallback(name, &callback_result);
4451 if (callback_result.IsProperty()) { 4474 if (callback_result.IsProperty()) {
4452 Object* obj = callback_result.GetCallbackObject(); 4475 Object* obj = callback_result.GetCallbackObject();
4453 if (obj->IsAccessorInfo() && 4476 if (obj->IsAccessorInfo() &&
4454 AccessorInfo::cast(obj)->prohibits_overwriting()) { 4477 AccessorInfo::cast(obj)->prohibits_overwriting()) {
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
4605 } 4628 }
4606 4629
4607 uint32_t index = 0; 4630 uint32_t index = 0;
4608 bool is_element = name->AsArrayIndex(&index); 4631 bool is_element = name->AsArrayIndex(&index);
4609 4632
4610 if (is_element) { 4633 if (is_element) {
4611 if (IsJSArray()) return isolate->heap()->undefined_value(); 4634 if (IsJSArray()) return isolate->heap()->undefined_value();
4612 4635
4613 // Accessors overwrite previous callbacks (cf. with getters/setters). 4636 // Accessors overwrite previous callbacks (cf. with getters/setters).
4614 switch (GetElementsKind()) { 4637 switch (GetElementsKind()) {
4615 case FAST_SMI_ONLY_ELEMENTS: 4638 case FAST_SMI_ELEMENTS:
4616 case FAST_ELEMENTS: 4639 case FAST_ELEMENTS:
4617 case FAST_DOUBLE_ELEMENTS: 4640 case FAST_DOUBLE_ELEMENTS:
4641 case FAST_HOLEY_SMI_ELEMENTS:
4642 case FAST_HOLEY_ELEMENTS:
4643 case FAST_HOLEY_DOUBLE_ELEMENTS:
4618 break; 4644 break;
4619 case EXTERNAL_PIXEL_ELEMENTS: 4645 case EXTERNAL_PIXEL_ELEMENTS:
4620 case EXTERNAL_BYTE_ELEMENTS: 4646 case EXTERNAL_BYTE_ELEMENTS:
4621 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 4647 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
4622 case EXTERNAL_SHORT_ELEMENTS: 4648 case EXTERNAL_SHORT_ELEMENTS:
4623 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 4649 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
4624 case EXTERNAL_INT_ELEMENTS: 4650 case EXTERNAL_INT_ELEMENTS:
4625 case EXTERNAL_UNSIGNED_INT_ELEMENTS: 4651 case EXTERNAL_UNSIGNED_INT_ELEMENTS:
4626 case EXTERNAL_FLOAT_ELEMENTS: 4652 case EXTERNAL_FLOAT_ELEMENTS:
4627 case EXTERNAL_DOUBLE_ELEMENTS: 4653 case EXTERNAL_DOUBLE_ELEMENTS:
(...skipping 3811 matching lines...) Expand 10 before | Expand all | Expand 10 after
8439 PrintF("RelocInfo (size = %d)\n", relocation_size()); 8465 PrintF("RelocInfo (size = %d)\n", relocation_size());
8440 for (RelocIterator it(this); !it.done(); it.next()) it.rinfo()->Print(out); 8466 for (RelocIterator it(this); !it.done(); it.next()) it.rinfo()->Print(out);
8441 PrintF(out, "\n"); 8467 PrintF(out, "\n");
8442 } 8468 }
8443 #endif // ENABLE_DISASSEMBLER 8469 #endif // ENABLE_DISASSEMBLER
8444 8470
8445 8471
8446 MaybeObject* JSObject::SetFastElementsCapacityAndLength( 8472 MaybeObject* JSObject::SetFastElementsCapacityAndLength(
8447 int capacity, 8473 int capacity,
8448 int length, 8474 int length,
8449 SetFastElementsCapacityMode set_capacity_mode) { 8475 SetFastElementsCapacitySmiMode smi_mode) {
8450 Heap* heap = GetHeap(); 8476 Heap* heap = GetHeap();
8451 // We should never end in here with a pixel or external array. 8477 // We should never end in here with a pixel or external array.
8452 ASSERT(!HasExternalArrayElements()); 8478 ASSERT(!HasExternalArrayElements());
8453 8479
8454 // Allocate a new fast elements backing store. 8480 // Allocate a new fast elements backing store.
8455 FixedArray* new_elements; 8481 FixedArray* new_elements;
8456 { MaybeObject* maybe = heap->AllocateFixedArrayWithHoles(capacity); 8482 { MaybeObject* maybe = heap->AllocateFixedArrayWithHoles(capacity);
8457 if (!maybe->To(&new_elements)) return maybe; 8483 if (!maybe->To(&new_elements)) return maybe;
8458 } 8484 }
8459 8485
8460 // Find the new map to use for this object if there is a map change. 8486 ElementsKind elements_kind = GetElementsKind();
8461 Map* new_map = NULL; 8487 ElementsKind new_elements_kind;
8462 if (elements()->map() != heap->non_strict_arguments_elements_map()) { 8488 // The resized array has Smi-only elements if the capacity mode forces it, or
8463 // The resized array has FAST_SMI_ONLY_ELEMENTS if the capacity mode forces 8489 // if it's allowed and the old elements array contained only SMIs.
8464 // it, or if it's allowed and the old elements array contained only SMIs. 8490 bool has_fast_smi_elements =
8465 bool has_fast_smi_only_elements = 8491 (smi_mode == kForceSmiOnlyElements) ||
8466 (set_capacity_mode == kForceSmiOnlyElements) || 8492 ((smi_mode == kAllowSmiOnlyElements) && HasFastSmiElements());
8467 ((set_capacity_mode == kAllowSmiOnlyElements) && 8493 if (has_fast_smi_elements) {
8468 (elements()->map()->has_fast_smi_only_elements() || 8494 if (IsHoleyElementsKind(elements_kind)) {
8469 elements() == heap->empty_fixed_array())); 8495 new_elements_kind = FAST_HOLEY_SMI_ELEMENTS;
8470 ElementsKind elements_kind = has_fast_smi_only_elements 8496 } else {
8471 ? FAST_SMI_ONLY_ELEMENTS 8497 new_elements_kind = FAST_SMI_ELEMENTS;
8472 : FAST_ELEMENTS; 8498 }
8473 MaybeObject* maybe = GetElementsTransitionMap(GetIsolate(), elements_kind); 8499 } else {
8474 if (!maybe->To(&new_map)) return maybe; 8500 if (IsHoleyElementsKind(elements_kind)) {
8501 new_elements_kind = FAST_HOLEY_ELEMENTS;
8502 } else {
8503 new_elements_kind = FAST_ELEMENTS;
8504 }
8475 } 8505 }
8476
8477 FixedArrayBase* old_elements = elements(); 8506 FixedArrayBase* old_elements = elements();
8478 ElementsKind elements_kind = GetElementsKind();
8479 ElementsAccessor* accessor = ElementsAccessor::ForKind(elements_kind); 8507 ElementsAccessor* accessor = ElementsAccessor::ForKind(elements_kind);
8480 ElementsKind to_kind = (elements_kind == FAST_SMI_ONLY_ELEMENTS) 8508 accessor->CopyElements(this, new_elements, new_elements_kind);
fschneider 2012/05/09 11:30:33 Missing check for failure? CopyElements has a Mayb
8481 ? FAST_SMI_ONLY_ELEMENTS
8482 : FAST_ELEMENTS;
8483 // int copy_size = Min(old_elements_raw->length(), new_elements->length());
8484 accessor->CopyElements(this, new_elements, to_kind);
8485 if (elements_kind != NON_STRICT_ARGUMENTS_ELEMENTS) { 8509 if (elements_kind != NON_STRICT_ARGUMENTS_ELEMENTS) {
8510 Map* new_map = map();
8511 if (new_elements_kind != elements_kind) {
8512 MaybeObject* maybe =
8513 GetElementsTransitionMap(GetIsolate(), new_elements_kind);
8514 if (!maybe->To(&new_map)) return maybe;
8515 }
8516 #ifdef DEBUG
8517 ValidateElements();
8518 #endif
8486 set_map_and_elements(new_map, new_elements); 8519 set_map_and_elements(new_map, new_elements);
8487 } else { 8520 } else {
8488 FixedArray* parameter_map = FixedArray::cast(old_elements); 8521 FixedArray* parameter_map = FixedArray::cast(old_elements);
8489 parameter_map->set(1, new_elements); 8522 parameter_map->set(1, new_elements);
8490 } 8523 }
8491 8524
8492 if (FLAG_trace_elements_transitions) { 8525 if (FLAG_trace_elements_transitions) {
8493 PrintElementsTransition(stdout, elements_kind, old_elements, 8526 PrintElementsTransition(stdout, elements_kind, old_elements,
8494 GetElementsKind(), new_elements); 8527 GetElementsKind(), new_elements);
8495 } 8528 }
8496 8529
8497 // Update the length if necessary.
8498 if (IsJSArray()) { 8530 if (IsJSArray()) {
8499 JSArray::cast(this)->set_length(Smi::FromInt(length)); 8531 JSArray::cast(this)->set_length(Smi::FromInt(length));
8500 } 8532 }
8501
8502 return new_elements; 8533 return new_elements;
8503 } 8534 }
8504 8535
8505 8536
8506 MaybeObject* JSObject::SetFastDoubleElementsCapacityAndLength( 8537 MaybeObject* JSObject::SetFastDoubleElementsCapacityAndLength(
8507 int capacity, 8538 int capacity,
8508 int length) { 8539 int length) {
8509 Heap* heap = GetHeap(); 8540 Heap* heap = GetHeap();
8510 // We should never end in here with a pixel or external array. 8541 // We should never end in here with a pixel or external array.
8511 ASSERT(!HasExternalArrayElements()); 8542 ASSERT(!HasExternalArrayElements());
8512 8543
8513 FixedDoubleArray* elems; 8544 FixedDoubleArray* elems;
8514 { MaybeObject* maybe_obj = 8545 { MaybeObject* maybe_obj =
8515 heap->AllocateUninitializedFixedDoubleArray(capacity); 8546 heap->AllocateUninitializedFixedDoubleArray(capacity);
8516 if (!maybe_obj->To(&elems)) return maybe_obj; 8547 if (!maybe_obj->To(&elems)) return maybe_obj;
8517 } 8548 }
8518 8549
8550 ElementsKind elements_kind = GetElementsKind();
8551 ElementsKind new_elements_kind = elements_kind;
8552 if (IsHoleyElementsKind(elements_kind)) {
8553 new_elements_kind = FAST_HOLEY_DOUBLE_ELEMENTS;
8554 } else {
8555 new_elements_kind = FAST_DOUBLE_ELEMENTS;
8556 }
8557
8519 Map* new_map; 8558 Map* new_map;
8520 { MaybeObject* maybe_obj = 8559 { MaybeObject* maybe_obj =
8521 GetElementsTransitionMap(heap->isolate(), FAST_DOUBLE_ELEMENTS); 8560 GetElementsTransitionMap(heap->isolate(), new_elements_kind);
8522 if (!maybe_obj->To(&new_map)) return maybe_obj; 8561 if (!maybe_obj->To(&new_map)) return maybe_obj;
8523 } 8562 }
8524 8563
8525 FixedArrayBase* old_elements = elements(); 8564 FixedArrayBase* old_elements = elements();
8526 ElementsKind elements_kind = GetElementsKind();
8527 ElementsAccessor* accessor = ElementsAccessor::ForKind(elements_kind); 8565 ElementsAccessor* accessor = ElementsAccessor::ForKind(elements_kind);
8528 accessor->CopyElements(this, elems, FAST_DOUBLE_ELEMENTS); 8566 accessor->CopyElements(this, elems, FAST_DOUBLE_ELEMENTS);
8529 if (elements_kind != NON_STRICT_ARGUMENTS_ELEMENTS) { 8567 if (elements_kind != NON_STRICT_ARGUMENTS_ELEMENTS) {
8568 #ifdef DEBUG
8569 ValidateElements();
8570 #endif
8530 set_map_and_elements(new_map, elems); 8571 set_map_and_elements(new_map, elems);
8531 } else { 8572 } else {
8532 FixedArray* parameter_map = FixedArray::cast(old_elements); 8573 FixedArray* parameter_map = FixedArray::cast(old_elements);
8533 parameter_map->set(1, elems); 8574 parameter_map->set(1, elems);
8534 } 8575 }
8535 8576
8536 if (FLAG_trace_elements_transitions) { 8577 if (FLAG_trace_elements_transitions) {
8537 PrintElementsTransition(stdout, elements_kind, old_elements, 8578 PrintElementsTransition(stdout, elements_kind, old_elements,
8538 FAST_DOUBLE_ELEMENTS, elems); 8579 GetElementsKind(), elems);
8539 } 8580 }
8540 8581
8541 if (IsJSArray()) { 8582 if (IsJSArray()) {
8542 JSArray::cast(this)->set_length(Smi::FromInt(length)); 8583 JSArray::cast(this)->set_length(Smi::FromInt(length));
8543 } 8584 }
8544 8585
8545 return this; 8586 return this;
8546 } 8587 }
8547 8588
8548 8589
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after
8808 return HasElementWithInterceptor(this, index) ? INTERCEPTED_ELEMENT 8849 return HasElementWithInterceptor(this, index) ? INTERCEPTED_ELEMENT
8809 : UNDEFINED_ELEMENT; 8850 : UNDEFINED_ELEMENT;
8810 } 8851 }
8811 8852
8812 // Handle [] on String objects. 8853 // Handle [] on String objects.
8813 if (this->IsStringObjectWithCharacterAt(index)) { 8854 if (this->IsStringObjectWithCharacterAt(index)) {
8814 return STRING_CHARACTER_ELEMENT; 8855 return STRING_CHARACTER_ELEMENT;
8815 } 8856 }
8816 8857
8817 switch (GetElementsKind()) { 8858 switch (GetElementsKind()) {
8818 case FAST_SMI_ONLY_ELEMENTS: 8859 case FAST_SMI_ELEMENTS:
8819 case FAST_ELEMENTS: { 8860 case FAST_ELEMENTS:
8861 case FAST_HOLEY_SMI_ELEMENTS:
8862 case FAST_HOLEY_ELEMENTS: {
8820 uint32_t length = IsJSArray() ? 8863 uint32_t length = IsJSArray() ?
8821 static_cast<uint32_t> 8864 static_cast<uint32_t>
8822 (Smi::cast(JSArray::cast(this)->length())->value()) : 8865 (Smi::cast(JSArray::cast(this)->length())->value()) :
8823 static_cast<uint32_t>(FixedArray::cast(elements())->length()); 8866 static_cast<uint32_t>(FixedArray::cast(elements())->length());
8824 if ((index < length) && 8867 if ((index < length) &&
8825 !FixedArray::cast(elements())->get(index)->IsTheHole()) { 8868 !FixedArray::cast(elements())->get(index)->IsTheHole()) {
8826 return FAST_ELEMENT; 8869 return FAST_ELEMENT;
8827 } 8870 }
8828 break; 8871 break;
8829 } 8872 }
8830 case FAST_DOUBLE_ELEMENTS: { 8873 case FAST_DOUBLE_ELEMENTS:
8874 case FAST_HOLEY_DOUBLE_ELEMENTS: {
8831 uint32_t length = IsJSArray() ? 8875 uint32_t length = IsJSArray() ?
8832 static_cast<uint32_t> 8876 static_cast<uint32_t>
8833 (Smi::cast(JSArray::cast(this)->length())->value()) : 8877 (Smi::cast(JSArray::cast(this)->length())->value()) :
8834 static_cast<uint32_t>(FixedDoubleArray::cast(elements())->length()); 8878 static_cast<uint32_t>(FixedDoubleArray::cast(elements())->length());
8835 if ((index < length) && 8879 if ((index < length) &&
8836 !FixedDoubleArray::cast(elements())->is_the_hole(index)) { 8880 !FixedDoubleArray::cast(elements())->is_the_hole(index)) {
8837 return FAST_ELEMENT; 8881 return FAST_ELEMENT;
8838 } 8882 }
8839 break; 8883 break;
8840 } 8884 }
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after
9104 } 9148 }
9105 9149
9106 9150
9107 // Adding n elements in fast case is O(n*n). 9151 // Adding n elements in fast case is O(n*n).
9108 // Note: revisit design to have dual undefined values to capture absent 9152 // Note: revisit design to have dual undefined values to capture absent
9109 // elements. 9153 // elements.
9110 MaybeObject* JSObject::SetFastElement(uint32_t index, 9154 MaybeObject* JSObject::SetFastElement(uint32_t index,
9111 Object* value, 9155 Object* value,
9112 StrictModeFlag strict_mode, 9156 StrictModeFlag strict_mode,
9113 bool check_prototype) { 9157 bool check_prototype) {
9114 ASSERT(HasFastTypeElements() || 9158 ASSERT(HasFastSmiOrObjectElements() ||
9115 HasFastArgumentsElements()); 9159 HasFastArgumentsElements());
9116 9160
9117 FixedArray* backing_store = FixedArray::cast(elements()); 9161 FixedArray* backing_store = FixedArray::cast(elements());
9118 if (backing_store->map() == GetHeap()->non_strict_arguments_elements_map()) { 9162 if (backing_store->map() == GetHeap()->non_strict_arguments_elements_map()) {
9119 backing_store = FixedArray::cast(backing_store->get(1)); 9163 backing_store = FixedArray::cast(backing_store->get(1));
9120 } else { 9164 } else {
9121 MaybeObject* maybe = EnsureWritableFastElements(); 9165 MaybeObject* maybe = EnsureWritableFastElements();
9122 if (!maybe->To(&backing_store)) return maybe; 9166 if (!maybe->To(&backing_store)) return maybe;
9123 } 9167 }
9124 uint32_t capacity = static_cast<uint32_t>(backing_store->length()); 9168 uint32_t capacity = static_cast<uint32_t>(backing_store->length());
9125 9169
9126 if (check_prototype && 9170 if (check_prototype &&
9127 (index >= capacity || backing_store->get(index)->IsTheHole())) { 9171 (index >= capacity || backing_store->get(index)->IsTheHole())) {
9128 bool found; 9172 bool found;
9129 MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index, 9173 MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index,
9130 value, 9174 value,
9131 &found, 9175 &found,
9132 strict_mode); 9176 strict_mode);
9133 if (found) return result; 9177 if (found) return result;
9134 } 9178 }
9135 9179
9136 uint32_t new_capacity = capacity; 9180 uint32_t new_capacity = capacity;
9137 // Check if the length property of this object needs to be updated. 9181 // Check if the length property of this object needs to be updated.
9138 uint32_t array_length = 0; 9182 uint32_t array_length = 0;
9139 bool must_update_array_length = false; 9183 bool must_update_array_length = false;
9184 bool introduces_holes = true;
9140 if (IsJSArray()) { 9185 if (IsJSArray()) {
9141 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length)); 9186 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length));
9187 introduces_holes = index > array_length;
9142 if (index >= array_length) { 9188 if (index >= array_length) {
9143 must_update_array_length = true; 9189 must_update_array_length = true;
9144 array_length = index + 1; 9190 array_length = index + 1;
9145 } 9191 }
9192 } else {
9193 introduces_holes = index >= capacity;
9146 } 9194 }
9195
9196 // If the array is growing, and it's not growth by a single element at the
9197 // end, make sure that the ElementsKind is HOLEY.
9198 ElementsKind elements_kind = GetElementsKind();
9199 if (introduces_holes &&
9200 IsFastElementsKind(elements_kind) &&
9201 !IsFastHoleyElementsKind(elements_kind)) {
9202 ElementsKind transitioned_kind = GetHoleyElementsKind(elements_kind);
9203 MaybeObject* maybe = TransitionElementsKind(transitioned_kind);
9204 if (maybe->IsFailure()) return maybe;
9205 }
9206
9147 // Check if the capacity of the backing store needs to be increased, or if 9207 // Check if the capacity of the backing store needs to be increased, or if
9148 // a transition to slow elements is necessary. 9208 // a transition to slow elements is necessary.
9149 if (index >= capacity) { 9209 if (index >= capacity) {
9150 bool convert_to_slow = true; 9210 bool convert_to_slow = true;
9151 if ((index - capacity) < kMaxGap) { 9211 if ((index - capacity) < kMaxGap) {
9152 new_capacity = NewElementsCapacity(index + 1); 9212 new_capacity = NewElementsCapacity(index + 1);
9153 ASSERT(new_capacity > index); 9213 ASSERT(new_capacity > index);
9154 if (!ShouldConvertToSlowElements(new_capacity)) { 9214 if (!ShouldConvertToSlowElements(new_capacity)) {
9155 convert_to_slow = false; 9215 convert_to_slow = false;
9156 } 9216 }
9157 } 9217 }
9158 if (convert_to_slow) { 9218 if (convert_to_slow) {
9159 MaybeObject* result = NormalizeElements(); 9219 MaybeObject* result = NormalizeElements();
9160 if (result->IsFailure()) return result; 9220 if (result->IsFailure()) return result;
9161 return SetDictionaryElement(index, value, NONE, strict_mode, 9221 return SetDictionaryElement(index, value, NONE, strict_mode,
9162 check_prototype); 9222 check_prototype);
9163 } 9223 }
9164 } 9224 }
9165 // Convert to fast double elements if appropriate. 9225 // Convert to fast double elements if appropriate.
9166 if (HasFastSmiOnlyElements() && !value->IsSmi() && value->IsNumber()) { 9226 if (HasFastSmiElements() && !value->IsSmi() && value->IsNumber()) {
9167 MaybeObject* maybe = 9227 MaybeObject* maybe =
9168 SetFastDoubleElementsCapacityAndLength(new_capacity, array_length); 9228 SetFastDoubleElementsCapacityAndLength(new_capacity,
9229 array_length);
9169 if (maybe->IsFailure()) return maybe; 9230 if (maybe->IsFailure()) return maybe;
9170 FixedDoubleArray::cast(elements())->set(index, value->Number()); 9231 FixedDoubleArray::cast(elements())->set(index, value->Number());
9232 #if DEBUG
9233 ValidateElements();
9234 #endif
9171 return value; 9235 return value;
9172 } 9236 }
9173 // Change elements kind from SMI_ONLY to generic FAST if necessary. 9237 // Change elements kind from Smi-only to generic FAST if necessary.
9174 if (HasFastSmiOnlyElements() && !value->IsSmi()) { 9238 if (HasFastSmiElements() && !value->IsSmi()) {
9175 Map* new_map; 9239 Map* new_map;
9176 { MaybeObject* maybe_new_map = GetElementsTransitionMap(GetIsolate(), 9240 ElementsKind kind = HasFastHoleyElements()
9177 FAST_ELEMENTS); 9241 ? FAST_HOLEY_ELEMENTS
9178 if (!maybe_new_map->To(&new_map)) return maybe_new_map; 9242 : FAST_ELEMENTS;
9179 } 9243 MaybeObject* maybe_new_map = GetElementsTransitionMap(GetIsolate(),
9244 kind);
9245 if (!maybe_new_map->To(&new_map)) return maybe_new_map;
9246
9180 set_map(new_map); 9247 set_map(new_map);
9181 if (FLAG_trace_elements_transitions) {
9182 PrintElementsTransition(stdout, FAST_SMI_ONLY_ELEMENTS, elements(),
9183 FAST_ELEMENTS, elements());
9184 }
9185 } 9248 }
9186 // Increase backing store capacity if that's been decided previously. 9249 // Increase backing store capacity if that's been decided previously.
9187 if (new_capacity != capacity) { 9250 if (new_capacity != capacity) {
9188 FixedArray* new_elements; 9251 FixedArray* new_elements;
9189 SetFastElementsCapacityMode set_capacity_mode = 9252 SetFastElementsCapacitySmiMode smi_mode =
9190 value->IsSmi() && HasFastSmiOnlyElements() 9253 value->IsSmi() && HasFastSmiElements()
9191 ? kAllowSmiOnlyElements 9254 ? kAllowSmiOnlyElements
9192 : kDontAllowSmiOnlyElements; 9255 : kDontAllowSmiOnlyElements;
9193 { MaybeObject* maybe = 9256 { MaybeObject* maybe =
9194 SetFastElementsCapacityAndLength(new_capacity, 9257 SetFastElementsCapacityAndLength(new_capacity,
9195 array_length, 9258 array_length,
9196 set_capacity_mode); 9259 smi_mode);
9197 if (!maybe->To(&new_elements)) return maybe; 9260 if (!maybe->To(&new_elements)) return maybe;
9198 } 9261 }
9199 new_elements->set(index, value); 9262 new_elements->set(index, value);
9263 #if DEBUG
9264 ValidateElements();
9265 #endif
9200 return value; 9266 return value;
9201 } 9267 }
9268
9202 // Finally, set the new element and length. 9269 // Finally, set the new element and length.
9203 ASSERT(elements()->IsFixedArray()); 9270 ASSERT(elements()->IsFixedArray());
9204 backing_store->set(index, value); 9271 backing_store->set(index, value);
9205 if (must_update_array_length) { 9272 if (must_update_array_length) {
9206 JSArray::cast(this)->set_length(Smi::FromInt(array_length)); 9273 JSArray::cast(this)->set_length(Smi::FromInt(array_length));
9207 } 9274 }
9208 return value; 9275 return value;
9209 } 9276 }
9210 9277
9211 9278
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
9315 } 9382 }
9316 9383
9317 // Attempt to put this object back in fast case. 9384 // Attempt to put this object back in fast case.
9318 if (ShouldConvertToFastElements()) { 9385 if (ShouldConvertToFastElements()) {
9319 uint32_t new_length = 0; 9386 uint32_t new_length = 0;
9320 if (IsJSArray()) { 9387 if (IsJSArray()) {
9321 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&new_length)); 9388 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&new_length));
9322 } else { 9389 } else {
9323 new_length = dictionary->max_number_key() + 1; 9390 new_length = dictionary->max_number_key() + 1;
9324 } 9391 }
9325 SetFastElementsCapacityMode set_capacity_mode = FLAG_smi_only_arrays 9392 SetFastElementsCapacitySmiMode smi_mode = FLAG_smi_only_arrays
9326 ? kAllowSmiOnlyElements 9393 ? kAllowSmiOnlyElements
9327 : kDontAllowSmiOnlyElements; 9394 : kDontAllowSmiOnlyElements;
9328 bool has_smi_only_elements = false; 9395 bool has_smi_only_elements = false;
9329 bool should_convert_to_fast_double_elements = 9396 bool should_convert_to_fast_double_elements =
9330 ShouldConvertToFastDoubleElements(&has_smi_only_elements); 9397 ShouldConvertToFastDoubleElements(&has_smi_only_elements);
9331 if (has_smi_only_elements) { 9398 if (has_smi_only_elements) {
9332 set_capacity_mode = kForceSmiOnlyElements; 9399 smi_mode = kForceSmiOnlyElements;
9333 } 9400 }
9334 MaybeObject* result = should_convert_to_fast_double_elements 9401 MaybeObject* result = should_convert_to_fast_double_elements
9335 ? SetFastDoubleElementsCapacityAndLength(new_length, new_length) 9402 ? SetFastDoubleElementsCapacityAndLength(new_length,
9403 new_length)
9336 : SetFastElementsCapacityAndLength(new_length, 9404 : SetFastElementsCapacityAndLength(new_length,
9337 new_length, 9405 new_length,
9338 set_capacity_mode); 9406 smi_mode);
9407 #if DEBUG
9408 ValidateElements();
fschneider 2012/05/09 11:30:33 Maybe check result for failure before calling Vali
9409 #endif
9339 if (result->IsFailure()) return result; 9410 if (result->IsFailure()) return result;
9340 #ifdef DEBUG 9411 #ifdef DEBUG
9341 if (FLAG_trace_normalization) { 9412 if (FLAG_trace_normalization) {
9342 PrintF("Object elements are fast case again:\n"); 9413 PrintF("Object elements are fast case again:\n");
9343 Print(); 9414 Print();
9344 } 9415 }
9345 #endif 9416 #endif
9346 } 9417 }
9347 return value; 9418 return value;
9348 } 9419 }
(...skipping 18 matching lines...) Expand all
9367 MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index, 9438 MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index,
9368 value, 9439 value,
9369 &found, 9440 &found,
9370 strict_mode); 9441 strict_mode);
9371 if (found) return result; 9442 if (found) return result;
9372 } 9443 }
9373 9444
9374 // If the value object is not a heap number, switch to fast elements and try 9445 // If the value object is not a heap number, switch to fast elements and try
9375 // again. 9446 // again.
9376 bool value_is_smi = value->IsSmi(); 9447 bool value_is_smi = value->IsSmi();
9448 bool introduces_holes = true;
9449 uint32_t length = elms_length;
9450 if (IsJSArray()) {
9451 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length));
9452 introduces_holes = index > length;
9453 } else {
9454 introduces_holes = index >= elms_length;
9455 }
9456
9377 if (!value->IsNumber()) { 9457 if (!value->IsNumber()) {
9378 Object* obj;
9379 uint32_t length = elms_length;
9380 if (IsJSArray()) {
9381 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length));
9382 }
9383 MaybeObject* maybe_obj = SetFastElementsCapacityAndLength( 9458 MaybeObject* maybe_obj = SetFastElementsCapacityAndLength(
9384 elms_length, 9459 elms_length,
9385 length, 9460 length,
9386 kDontAllowSmiOnlyElements); 9461 kDontAllowSmiOnlyElements);
9387 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 9462 if (maybe_obj->IsFailure()) return maybe_obj;
9388 return SetFastElement(index, 9463 maybe_obj = SetFastElement(index, value, strict_mode, check_prototype);
9389 value, 9464 if (maybe_obj->IsFailure()) return maybe_obj;
9390 strict_mode, 9465 #if DEBUG
9391 check_prototype); 9466 ValidateElements();
9467 #endif
9468 return maybe_obj;
9392 } 9469 }
9393 9470
9394 double double_value = value_is_smi 9471 double double_value = value_is_smi
9395 ? static_cast<double>(Smi::cast(value)->value()) 9472 ? static_cast<double>(Smi::cast(value)->value())
9396 : HeapNumber::cast(value)->value(); 9473 : HeapNumber::cast(value)->value();
9397 9474
9475 // If the array is growing, and it's not growth by a single element at the
9476 // end, make sure that the ElementsKind is HOLEY.
9477 ElementsKind elements_kind = GetElementsKind();
9478 if (introduces_holes && !IsFastHoleyElementsKind(elements_kind)) {
9479 ElementsKind transitioned_kind = GetHoleyElementsKind(elements_kind);
9480 MaybeObject* maybe = TransitionElementsKind(transitioned_kind);
9481 if (maybe->IsFailure()) return maybe;
9482 }
9483
9398 // Check whether there is extra space in the fixed array. 9484 // Check whether there is extra space in the fixed array.
9399 if (index < elms_length) { 9485 if (index < elms_length) {
9400 FixedDoubleArray* elms = FixedDoubleArray::cast(elements()); 9486 FixedDoubleArray* elms = FixedDoubleArray::cast(elements());
9401 elms->set(index, double_value); 9487 elms->set(index, double_value);
9402 if (IsJSArray()) { 9488 if (IsJSArray()) {
9403 // Update the length of the array if needed. 9489 // Update the length of the array if needed.
9404 uint32_t array_length = 0; 9490 uint32_t array_length = 0;
9405 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length)); 9491 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length));
9406 if (index >= array_length) { 9492 if (index >= array_length) {
9407 JSArray::cast(this)->set_length(Smi::FromInt(index + 1)); 9493 JSArray::cast(this)->set_length(Smi::FromInt(index + 1));
9408 } 9494 }
9409 } 9495 }
9410 return value; 9496 return value;
9411 } 9497 }
9412 9498
9413 // Allow gap in fast case. 9499 // Allow gap in fast case.
9414 if ((index - elms_length) < kMaxGap) { 9500 if ((index - elms_length) < kMaxGap) {
9415 // Try allocating extra space. 9501 // Try allocating extra space.
9416 int new_capacity = NewElementsCapacity(index+1); 9502 int new_capacity = NewElementsCapacity(index+1);
9417 if (!ShouldConvertToSlowElements(new_capacity)) { 9503 if (!ShouldConvertToSlowElements(new_capacity)) {
9418 ASSERT(static_cast<uint32_t>(new_capacity) > index); 9504 ASSERT(static_cast<uint32_t>(new_capacity) > index);
9419 Object* obj; 9505 MaybeObject* maybe_obj =
9420 { MaybeObject* maybe_obj = 9506 SetFastDoubleElementsCapacityAndLength(new_capacity, index + 1);
9421 SetFastDoubleElementsCapacityAndLength(new_capacity, 9507 if (maybe_obj->IsFailure()) return maybe_obj;
9422 index + 1);
9423 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
9424 }
9425 FixedDoubleArray::cast(elements())->set(index, double_value); 9508 FixedDoubleArray::cast(elements())->set(index, double_value);
9509 #if DEBUG
9510 ValidateElements();
9511 #endif
9426 return value; 9512 return value;
9427 } 9513 }
9428 } 9514 }
9429 9515
9430 // Otherwise default to slow case. 9516 // Otherwise default to slow case.
9431 ASSERT(HasFastDoubleElements()); 9517 ASSERT(HasFastDoubleElements());
9432 ASSERT(map()->has_fast_double_elements()); 9518 ASSERT(map()->has_fast_double_elements());
9433 ASSERT(elements()->IsFixedDoubleArray()); 9519 ASSERT(elements()->IsFixedDoubleArray());
9434 Object* obj; 9520 Object* obj;
9435 { MaybeObject* maybe_obj = NormalizeElements(); 9521 { MaybeObject* maybe_obj = NormalizeElements();
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
9559 Object* value, 9645 Object* value,
9560 PropertyAttributes attr, 9646 PropertyAttributes attr,
9561 StrictModeFlag strict_mode, 9647 StrictModeFlag strict_mode,
9562 bool check_prototype, 9648 bool check_prototype,
9563 SetPropertyMode set_mode) { 9649 SetPropertyMode set_mode) {
9564 ASSERT(HasDictionaryElements() || 9650 ASSERT(HasDictionaryElements() ||
9565 HasDictionaryArgumentsElements() || 9651 HasDictionaryArgumentsElements() ||
9566 (attr & (DONT_DELETE | DONT_ENUM | READ_ONLY)) == 0); 9652 (attr & (DONT_DELETE | DONT_ENUM | READ_ONLY)) == 0);
9567 Isolate* isolate = GetIsolate(); 9653 Isolate* isolate = GetIsolate();
9568 switch (GetElementsKind()) { 9654 switch (GetElementsKind()) {
9569 case FAST_SMI_ONLY_ELEMENTS: 9655 case FAST_SMI_ELEMENTS:
9570 case FAST_ELEMENTS: 9656 case FAST_ELEMENTS:
9657 case FAST_HOLEY_SMI_ELEMENTS:
9658 case FAST_HOLEY_ELEMENTS:
9571 return SetFastElement(index, value, strict_mode, check_prototype); 9659 return SetFastElement(index, value, strict_mode, check_prototype);
9572 case FAST_DOUBLE_ELEMENTS: 9660 case FAST_DOUBLE_ELEMENTS:
9661 case FAST_HOLEY_DOUBLE_ELEMENTS:
9573 return SetFastDoubleElement(index, value, strict_mode, check_prototype); 9662 return SetFastDoubleElement(index, value, strict_mode, check_prototype);
9574 case EXTERNAL_PIXEL_ELEMENTS: { 9663 case EXTERNAL_PIXEL_ELEMENTS: {
9575 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements()); 9664 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements());
9576 return pixels->SetValue(index, value); 9665 return pixels->SetValue(index, value);
9577 } 9666 }
9578 case EXTERNAL_BYTE_ELEMENTS: { 9667 case EXTERNAL_BYTE_ELEMENTS: {
9579 ExternalByteArray* array = ExternalByteArray::cast(elements()); 9668 ExternalByteArray* array = ExternalByteArray::cast(elements());
9580 return array->SetValue(index, value); 9669 return array->SetValue(index, value);
9581 } 9670 }
9582 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: { 9671 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: {
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
9653 ElementsKind to_kind) { 9742 ElementsKind to_kind) {
9654 CALL_HEAP_FUNCTION(object->GetIsolate(), 9743 CALL_HEAP_FUNCTION(object->GetIsolate(),
9655 object->TransitionElementsKind(to_kind), 9744 object->TransitionElementsKind(to_kind),
9656 Object); 9745 Object);
9657 } 9746 }
9658 9747
9659 9748
9660 MaybeObject* JSObject::TransitionElementsKind(ElementsKind to_kind) { 9749 MaybeObject* JSObject::TransitionElementsKind(ElementsKind to_kind) {
9661 ElementsKind from_kind = map()->elements_kind(); 9750 ElementsKind from_kind = map()->elements_kind();
9662 9751
9752 if (IsFastHoleyElementsKind(from_kind)) {
9753 to_kind = GetHoleyElementsKind(to_kind);
9754 }
9755
9663 Isolate* isolate = GetIsolate(); 9756 Isolate* isolate = GetIsolate();
9664 if (from_kind == FAST_SMI_ONLY_ELEMENTS && 9757
9665 (to_kind == FAST_ELEMENTS || 9758 if (elements() == isolate->heap()->empty_fixed_array() ||
9666 elements() == isolate->heap()->empty_fixed_array())) { 9759 (IsFastSmiOrObjectElementsKind(from_kind) &&
9760 IsFastSmiOrObjectElementsKind(to_kind)) ||
9761 (from_kind == FAST_DOUBLE_ELEMENTS &&
9762 to_kind == FAST_HOLEY_DOUBLE_ELEMENTS)) {
9763 // No change is needed to the elements() buffer, the transition
9764 // only requires a map change.
9667 MaybeObject* maybe_new_map = GetElementsTransitionMap(isolate, to_kind); 9765 MaybeObject* maybe_new_map = GetElementsTransitionMap(isolate, to_kind);
9668 Map* new_map; 9766 Map* new_map;
9669 if (!maybe_new_map->To(&new_map)) return maybe_new_map; 9767 if (!maybe_new_map->To(&new_map)) return maybe_new_map;
9670 set_map(new_map); 9768 set_map(new_map);
9671 if (FLAG_trace_elements_transitions) { 9769 if (FLAG_trace_elements_transitions) {
9672 FixedArrayBase* elms = FixedArrayBase::cast(elements()); 9770 FixedArrayBase* elms = FixedArrayBase::cast(elements());
9673 PrintElementsTransition(stdout, from_kind, elms, to_kind, elms); 9771 PrintElementsTransition(stdout, from_kind, elms, to_kind, elms);
9674 } 9772 }
9675 return this; 9773 return this;
9676 } 9774 }
9677 9775
9678 FixedArrayBase* elms = FixedArrayBase::cast(elements()); 9776 FixedArrayBase* elms = FixedArrayBase::cast(elements());
9679 uint32_t capacity = static_cast<uint32_t>(elms->length()); 9777 uint32_t capacity = static_cast<uint32_t>(elms->length());
9680 uint32_t length = capacity; 9778 uint32_t length = capacity;
9681 9779
9682 if (IsJSArray()) { 9780 if (IsJSArray()) {
9683 Object* raw_length = JSArray::cast(this)->length(); 9781 Object* raw_length = JSArray::cast(this)->length();
9684 if (raw_length->IsUndefined()) { 9782 if (raw_length->IsUndefined()) {
9685 // If length is undefined, then JSArray is being initialized and has no 9783 // If length is undefined, then JSArray is being initialized and has no
9686 // elements, assume a length of zero. 9784 // elements, assume a length of zero.
9687 length = 0; 9785 length = 0;
9688 } else { 9786 } else {
9689 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length)); 9787 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length));
9690 } 9788 }
9691 } 9789 }
9692 9790
9693 if (from_kind == FAST_SMI_ONLY_ELEMENTS && 9791 if (IsFastSmiElementsKind(from_kind) &&
9694 to_kind == FAST_DOUBLE_ELEMENTS) { 9792 IsFastDoubleElementsKind(to_kind)) {
9695 MaybeObject* maybe_result = 9793 MaybeObject* maybe_result =
9696 SetFastDoubleElementsCapacityAndLength(capacity, length); 9794 SetFastDoubleElementsCapacityAndLength(capacity, length);
9697 if (maybe_result->IsFailure()) return maybe_result; 9795 if (maybe_result->IsFailure()) return maybe_result;
9796 #if DEBUG
9797 ValidateElements();
9798 #endif
9698 return this; 9799 return this;
9699 } 9800 }
9700 9801
9701 if (from_kind == FAST_DOUBLE_ELEMENTS && to_kind == FAST_ELEMENTS) { 9802 if (IsFastDoubleElementsKind(from_kind) &&
9803 IsFastObjectElementsKind(to_kind)) {
9702 MaybeObject* maybe_result = SetFastElementsCapacityAndLength( 9804 MaybeObject* maybe_result = SetFastElementsCapacityAndLength(
9703 capacity, length, kDontAllowSmiOnlyElements); 9805 capacity, length, kDontAllowSmiOnlyElements);
9704 if (maybe_result->IsFailure()) return maybe_result; 9806 if (maybe_result->IsFailure()) return maybe_result;
9807 #if DEBUG
9808 ValidateElements();
9809 #endif
9705 return this; 9810 return this;
9706 } 9811 }
9707 9812
9708 // This method should never be called for any other case than the ones 9813 // This method should never be called for any other case than the ones
9709 // handled above. 9814 // handled above.
9710 UNREACHABLE(); 9815 UNREACHABLE();
9711 return GetIsolate()->heap()->null_value(); 9816 return GetIsolate()->heap()->null_value();
9712 } 9817 }
9713 9818
9714 9819
9715 // static 9820 // static
9716 bool Map::IsValidElementsTransition(ElementsKind from_kind, 9821 bool Map::IsValidElementsTransition(ElementsKind from_kind,
9717 ElementsKind to_kind) { 9822 ElementsKind to_kind) {
9718 return 9823 // Transitions can't go backwards.
9719 (from_kind == FAST_SMI_ONLY_ELEMENTS && 9824 if (!IsMoreGeneralElementsKindTransition(from_kind, to_kind)) {
9720 (to_kind == FAST_DOUBLE_ELEMENTS || to_kind == FAST_ELEMENTS)) || 9825 return false;
9721 (from_kind == FAST_DOUBLE_ELEMENTS && to_kind == FAST_ELEMENTS); 9826 }
9827
9828 // Transitions from HOLEY -> PACKED are not allowed.
9829 return !IsFastHoleyElementsKind(from_kind) ||
9830 IsFastHoleyElementsKind(to_kind);
9722 } 9831 }
9723 9832
9724 9833
9725 MaybeObject* JSArray::JSArrayUpdateLengthFromIndex(uint32_t index, 9834 MaybeObject* JSArray::JSArrayUpdateLengthFromIndex(uint32_t index,
9726 Object* value) { 9835 Object* value) {
9727 uint32_t old_len = 0; 9836 uint32_t old_len = 0;
9728 CHECK(length()->ToArrayIndex(&old_len)); 9837 CHECK(length()->ToArrayIndex(&old_len));
9729 // Check to see if we need to update the length. For now, we make 9838 // Check to see if we need to update the length. For now, we make
9730 // sure that the length stays within 32-bits (unsigned). 9839 // sure that the length stays within 32-bits (unsigned).
9731 if (index >= old_len && index != 0xffffffff) { 9840 if (index >= old_len && index != 0xffffffff) {
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
9802 FixedArray::cast(FixedArray::cast(backing_store_base)->get(1)); 9911 FixedArray::cast(FixedArray::cast(backing_store_base)->get(1));
9803 backing_store = FixedArray::cast(backing_store_base); 9912 backing_store = FixedArray::cast(backing_store_base);
9804 if (backing_store->IsDictionary()) { 9913 if (backing_store->IsDictionary()) {
9805 SeededNumberDictionary* dictionary = 9914 SeededNumberDictionary* dictionary =
9806 SeededNumberDictionary::cast(backing_store); 9915 SeededNumberDictionary::cast(backing_store);
9807 *capacity = dictionary->Capacity(); 9916 *capacity = dictionary->Capacity();
9808 *used = dictionary->NumberOfElements(); 9917 *used = dictionary->NumberOfElements();
9809 break; 9918 break;
9810 } 9919 }
9811 // Fall through. 9920 // Fall through.
9812 case FAST_SMI_ONLY_ELEMENTS: 9921 case FAST_SMI_ELEMENTS:
9813 case FAST_ELEMENTS: 9922 case FAST_ELEMENTS:
9923 case FAST_HOLEY_SMI_ELEMENTS:
9924 case FAST_HOLEY_ELEMENTS:
9814 backing_store = FixedArray::cast(backing_store_base); 9925 backing_store = FixedArray::cast(backing_store_base);
9815 *capacity = backing_store->length(); 9926 *capacity = backing_store->length();
9816 for (int i = 0; i < *capacity; ++i) { 9927 for (int i = 0; i < *capacity; ++i) {
9817 if (!backing_store->get(i)->IsTheHole()) ++(*used); 9928 if (!backing_store->get(i)->IsTheHole()) ++(*used);
9818 } 9929 }
9819 break; 9930 break;
9820 case DICTIONARY_ELEMENTS: { 9931 case DICTIONARY_ELEMENTS: {
9821 SeededNumberDictionary* dictionary = 9932 SeededNumberDictionary* dictionary =
9822 SeededNumberDictionary::cast(FixedArray::cast(elements())); 9933 SeededNumberDictionary::cast(FixedArray::cast(elements()));
9823 *capacity = dictionary->Capacity(); 9934 *capacity = dictionary->Capacity();
9824 *used = dictionary->NumberOfElements(); 9935 *used = dictionary->NumberOfElements();
9825 break; 9936 break;
9826 } 9937 }
9827 case FAST_DOUBLE_ELEMENTS: { 9938 case FAST_DOUBLE_ELEMENTS:
9939 case FAST_HOLEY_DOUBLE_ELEMENTS: {
9828 FixedDoubleArray* elms = FixedDoubleArray::cast(elements()); 9940 FixedDoubleArray* elms = FixedDoubleArray::cast(elements());
9829 *capacity = elms->length(); 9941 *capacity = elms->length();
9830 for (int i = 0; i < *capacity; i++) { 9942 for (int i = 0; i < *capacity; i++) {
9831 if (!elms->is_the_hole(i)) ++(*used); 9943 if (!elms->is_the_hole(i)) ++(*used);
9832 } 9944 }
9833 break; 9945 break;
9834 } 9946 }
9835 case EXTERNAL_BYTE_ELEMENTS: 9947 case EXTERNAL_BYTE_ELEMENTS:
9836 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 9948 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
9837 case EXTERNAL_SHORT_ELEMENTS: 9949 case EXTERNAL_SHORT_ELEMENTS:
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after
10087 if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) { 10199 if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) {
10088 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS); 10200 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS);
10089 return false; 10201 return false;
10090 } 10202 }
10091 } 10203 }
10092 10204
10093 // Handle [] on String objects. 10205 // Handle [] on String objects.
10094 if (this->IsStringObjectWithCharacterAt(index)) return true; 10206 if (this->IsStringObjectWithCharacterAt(index)) return true;
10095 10207
10096 switch (GetElementsKind()) { 10208 switch (GetElementsKind()) {
10097 case FAST_SMI_ONLY_ELEMENTS: 10209 case FAST_SMI_ELEMENTS:
10098 case FAST_ELEMENTS: { 10210 case FAST_ELEMENTS:
10099 uint32_t length = IsJSArray() ? 10211 case FAST_HOLEY_SMI_ELEMENTS:
10212 case FAST_HOLEY_ELEMENTS: {
10213 uint32_t length = IsJSArray() ?
10100 static_cast<uint32_t>( 10214 static_cast<uint32_t>(
10101 Smi::cast(JSArray::cast(this)->length())->value()) : 10215 Smi::cast(JSArray::cast(this)->length())->value()) :
10102 static_cast<uint32_t>(FixedArray::cast(elements())->length()); 10216 static_cast<uint32_t>(FixedArray::cast(elements())->length());
10103 return (index < length) && 10217 return (index < length) &&
10104 !FixedArray::cast(elements())->get(index)->IsTheHole(); 10218 !FixedArray::cast(elements())->get(index)->IsTheHole();
10105 } 10219 }
10106 case FAST_DOUBLE_ELEMENTS: { 10220 case FAST_DOUBLE_ELEMENTS:
10221 case FAST_HOLEY_DOUBLE_ELEMENTS: {
10107 uint32_t length = IsJSArray() ? 10222 uint32_t length = IsJSArray() ?
10108 static_cast<uint32_t>( 10223 static_cast<uint32_t>(
10109 Smi::cast(JSArray::cast(this)->length())->value()) : 10224 Smi::cast(JSArray::cast(this)->length())->value()) :
10110 static_cast<uint32_t>(FixedDoubleArray::cast(elements())->length()); 10225 static_cast<uint32_t>(FixedDoubleArray::cast(elements())->length());
10111 return (index < length) && 10226 return (index < length) &&
10112 !FixedDoubleArray::cast(elements())->is_the_hole(index); 10227 !FixedDoubleArray::cast(elements())->is_the_hole(index);
10113 break; 10228 break;
10114 } 10229 }
10115 case EXTERNAL_PIXEL_ELEMENTS: { 10230 case EXTERNAL_PIXEL_ELEMENTS: {
10116 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements()); 10231 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements());
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after
10296 } 10411 }
10297 10412
10298 10413
10299 int JSObject::NumberOfLocalElements(PropertyAttributes filter) { 10414 int JSObject::NumberOfLocalElements(PropertyAttributes filter) {
10300 return GetLocalElementKeys(NULL, filter); 10415 return GetLocalElementKeys(NULL, filter);
10301 } 10416 }
10302 10417
10303 10418
10304 int JSObject::NumberOfEnumElements() { 10419 int JSObject::NumberOfEnumElements() {
10305 // Fast case for objects with no elements. 10420 // Fast case for objects with no elements.
10306 if (!IsJSValue() && HasFastElements()) { 10421 if (!IsJSValue() && HasFastObjectElements()) {
10307 uint32_t length = IsJSArray() ? 10422 uint32_t length = IsJSArray() ?
10308 static_cast<uint32_t>( 10423 static_cast<uint32_t>(
10309 Smi::cast(JSArray::cast(this)->length())->value()) : 10424 Smi::cast(JSArray::cast(this)->length())->value()) :
10310 static_cast<uint32_t>(FixedArray::cast(elements())->length()); 10425 static_cast<uint32_t>(FixedArray::cast(elements())->length());
10311 if (length == 0) return 0; 10426 if (length == 0) return 0;
10312 } 10427 }
10313 // Compute the number of enumerable elements. 10428 // Compute the number of enumerable elements.
10314 return NumberOfLocalElements(static_cast<PropertyAttributes>(DONT_ENUM)); 10429 return NumberOfLocalElements(static_cast<PropertyAttributes>(DONT_ENUM));
10315 } 10430 }
10316 10431
10317 10432
10318 int JSObject::GetLocalElementKeys(FixedArray* storage, 10433 int JSObject::GetLocalElementKeys(FixedArray* storage,
10319 PropertyAttributes filter) { 10434 PropertyAttributes filter) {
10320 int counter = 0; 10435 int counter = 0;
10321 switch (GetElementsKind()) { 10436 switch (GetElementsKind()) {
10322 case FAST_SMI_ONLY_ELEMENTS: 10437 case FAST_SMI_ELEMENTS:
10323 case FAST_ELEMENTS: { 10438 case FAST_ELEMENTS:
10439 case FAST_HOLEY_SMI_ELEMENTS:
10440 case FAST_HOLEY_ELEMENTS: {
10324 int length = IsJSArray() ? 10441 int length = IsJSArray() ?
10325 Smi::cast(JSArray::cast(this)->length())->value() : 10442 Smi::cast(JSArray::cast(this)->length())->value() :
10326 FixedArray::cast(elements())->length(); 10443 FixedArray::cast(elements())->length();
10327 for (int i = 0; i < length; i++) { 10444 for (int i = 0; i < length; i++) {
10328 if (!FixedArray::cast(elements())->get(i)->IsTheHole()) { 10445 if (!FixedArray::cast(elements())->get(i)->IsTheHole()) {
10329 if (storage != NULL) { 10446 if (storage != NULL) {
10330 storage->set(counter, Smi::FromInt(i)); 10447 storage->set(counter, Smi::FromInt(i));
10331 } 10448 }
10332 counter++; 10449 counter++;
10333 } 10450 }
10334 } 10451 }
10335 ASSERT(!storage || storage->length() >= counter); 10452 ASSERT(!storage || storage->length() >= counter);
10336 break; 10453 break;
10337 } 10454 }
10338 case FAST_DOUBLE_ELEMENTS: { 10455 case FAST_DOUBLE_ELEMENTS:
10456 case FAST_HOLEY_DOUBLE_ELEMENTS: {
10339 int length = IsJSArray() ? 10457 int length = IsJSArray() ?
10340 Smi::cast(JSArray::cast(this)->length())->value() : 10458 Smi::cast(JSArray::cast(this)->length())->value() :
10341 FixedDoubleArray::cast(elements())->length(); 10459 FixedDoubleArray::cast(elements())->length();
10342 for (int i = 0; i < length; i++) { 10460 for (int i = 0; i < length; i++) {
10343 if (!FixedDoubleArray::cast(elements())->is_the_hole(i)) { 10461 if (!FixedDoubleArray::cast(elements())->is_the_hole(i)) {
10344 if (storage != NULL) { 10462 if (storage != NULL) {
10345 storage->set(counter, Smi::FromInt(i)); 10463 storage->set(counter, Smi::FromInt(i));
10346 } 10464 }
10347 counter++; 10465 counter++;
10348 } 10466 }
(...skipping 912 matching lines...) Expand 10 before | Expand all | Expand 10 after
11261 // Convert to fast elements containing only the existing properties. 11379 // Convert to fast elements containing only the existing properties.
11262 // Ordering is irrelevant, since we are going to sort anyway. 11380 // Ordering is irrelevant, since we are going to sort anyway.
11263 SeededNumberDictionary* dict = element_dictionary(); 11381 SeededNumberDictionary* dict = element_dictionary();
11264 if (IsJSArray() || dict->requires_slow_elements() || 11382 if (IsJSArray() || dict->requires_slow_elements() ||
11265 dict->max_number_key() >= limit) { 11383 dict->max_number_key() >= limit) {
11266 return PrepareSlowElementsForSort(limit); 11384 return PrepareSlowElementsForSort(limit);
11267 } 11385 }
11268 // Convert to fast elements. 11386 // Convert to fast elements.
11269 11387
11270 Object* obj; 11388 Object* obj;
11271 { MaybeObject* maybe_obj = GetElementsTransitionMap(GetIsolate(), 11389 MaybeObject* maybe_obj = GetElementsTransitionMap(GetIsolate(),
11272 FAST_ELEMENTS); 11390 FAST_HOLEY_ELEMENTS);
11273 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 11391 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
11274 }
11275 Map* new_map = Map::cast(obj); 11392 Map* new_map = Map::cast(obj);
11276 11393
11277 PretenureFlag tenure = heap->InNewSpace(this) ? NOT_TENURED: TENURED; 11394 PretenureFlag tenure = heap->InNewSpace(this) ? NOT_TENURED: TENURED;
11278 Object* new_array; 11395 Object* new_array;
11279 { MaybeObject* maybe_new_array = 11396 { MaybeObject* maybe_new_array =
11280 heap->AllocateFixedArray(dict->NumberOfElements(), tenure); 11397 heap->AllocateFixedArray(dict->NumberOfElements(), tenure);
11281 if (!maybe_new_array->ToObject(&new_array)) return maybe_new_array; 11398 if (!maybe_new_array->ToObject(&new_array)) return maybe_new_array;
11282 } 11399 }
11283 FixedArray* fast_elements = FixedArray::cast(new_array); 11400 FixedArray* fast_elements = FixedArray::cast(new_array);
11284 dict->CopyValuesTo(fast_elements); 11401 dict->CopyValuesTo(fast_elements);
11285 11402
11286 set_map(new_map); 11403 #ifdef DEBUG
11287 set_elements(fast_elements); 11404 ValidateElements();
11405 #endif
11406 set_map_and_elements(new_map, fast_elements);
11288 } else if (HasExternalArrayElements()) { 11407 } else if (HasExternalArrayElements()) {
11289 // External arrays cannot have holes or undefined elements. 11408 // External arrays cannot have holes or undefined elements.
11290 return Smi::FromInt(ExternalArray::cast(elements())->length()); 11409 return Smi::FromInt(ExternalArray::cast(elements())->length());
11291 } else if (!HasFastDoubleElements()) { 11410 } else if (!HasFastDoubleElements()) {
11292 Object* obj; 11411 Object* obj;
11293 { MaybeObject* maybe_obj = EnsureWritableFastElements(); 11412 { MaybeObject* maybe_obj = EnsureWritableFastElements();
11294 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 11413 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
11295 } 11414 }
11296 } 11415 }
11297 ASSERT(HasFastTypeElements() || HasFastDoubleElements()); 11416 ASSERT(HasFastSmiOrObjectElements() || HasFastDoubleElements());
11298 11417
11299 // Collect holes at the end, undefined before that and the rest at the 11418 // Collect holes at the end, undefined before that and the rest at the
11300 // start, and return the number of non-hole, non-undefined values. 11419 // start, and return the number of non-hole, non-undefined values.
11301 11420
11302 FixedArrayBase* elements_base = FixedArrayBase::cast(this->elements()); 11421 FixedArrayBase* elements_base = FixedArrayBase::cast(this->elements());
11303 uint32_t elements_length = static_cast<uint32_t>(elements_base->length()); 11422 uint32_t elements_length = static_cast<uint32_t>(elements_base->length());
11304 if (limit > elements_length) { 11423 if (limit > elements_length) {
11305 limit = elements_length ; 11424 limit = elements_length ;
11306 } 11425 }
11307 if (limit == 0) { 11426 if (limit == 0) {
(...skipping 1656 matching lines...) Expand 10 before | Expand all | Expand 10 after
12964 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); 13083 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER);
12965 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); 13084 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER);
12966 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); 13085 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER);
12967 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); 13086 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER);
12968 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); 13087 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER);
12969 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); 13088 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER);
12970 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); 13089 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER);
12971 } 13090 }
12972 13091
12973 } } // namespace v8::internal 13092 } } // 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