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

Side by Side Diff: src/objects.cc

Issue 10170030: Implement tracking and optimizations of packed arrays (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Platforms ports and review feedback Created 8 years, 7 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
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 503 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 1114 matching lines...) Expand 10 before | Expand all | Expand 10 after
2195 2192
2196 2193
2197 template <class T> 2194 template <class T>
2198 static Handle<T> MaybeNull(T* p) { 2195 static Handle<T> MaybeNull(T* p) {
2199 if (p == NULL) return Handle<T>::null(); 2196 if (p == NULL) return Handle<T>::null();
2200 return Handle<T>(p); 2197 return Handle<T>(p);
2201 } 2198 }
2202 2199
2203 2200
2204 Handle<Map> Map::FindTransitionedMap(MapHandleList* candidates) { 2201 Handle<Map> Map::FindTransitionedMap(MapHandleList* candidates) {
2205 ElementsKind elms_kind = elements_kind(); 2202 ElementsKind kind = elements_kind();
2206 if (elms_kind == FAST_DOUBLE_ELEMENTS) { 2203 Handle<Map> transitioned_map = Handle<Map>::null();
2207 bool dummy = true; 2204 Handle<Map> current_map(this);
2208 Handle<Map> fast_map = 2205 bool packed = IsFastPackedElementsKind(kind);
2209 MaybeNull(LookupElementsTransitionMap(FAST_ELEMENTS, &dummy)); 2206 if (IsTransitionableFastElementsKind(kind)) {
2210 if (!fast_map.is_null() && ContainsMap(candidates, fast_map)) { 2207 while (CanTransitionToMoreGeneralFastElementsKind(kind, false)) {
2211 return fast_map; 2208 kind = GetNextMoreGeneralFastElementsKind(kind, false);
2209 bool dummy = true;
2210 Handle<Map> maybe_transitioned_map =
2211 MaybeNull(current_map->LookupElementsTransitionMap(kind, &dummy));
2212 if (maybe_transitioned_map.is_null()) break;
2213 if (ContainsMap(candidates, maybe_transitioned_map) &&
2214 (packed || !IsFastPackedElementsKind(kind))) {
2215 transitioned_map = maybe_transitioned_map;
2216 if (!IsFastPackedElementsKind(kind)) packed = false;
2217 }
2218 current_map = maybe_transitioned_map;
2212 } 2219 }
2213 return Handle<Map>::null();
2214 } 2220 }
2215 if (elms_kind == FAST_SMI_ONLY_ELEMENTS) { 2221 return transitioned_map;
2216 bool dummy = true;
2217 Handle<Map> double_map =
2218 MaybeNull(LookupElementsTransitionMap(FAST_DOUBLE_ELEMENTS, &dummy));
2219 // In the current implementation, if the DOUBLE map doesn't exist, the
2220 // FAST map can't exist either.
2221 if (double_map.is_null()) return Handle<Map>::null();
2222 Handle<Map> fast_map =
2223 MaybeNull(double_map->LookupElementsTransitionMap(FAST_ELEMENTS,
2224 &dummy));
2225 if (!fast_map.is_null() && ContainsMap(candidates, fast_map)) {
2226 return fast_map;
2227 }
2228 if (ContainsMap(candidates, double_map)) return double_map;
2229 }
2230 return Handle<Map>::null();
2231 } 2222 }
2232 2223
2224
2233 static Map* GetElementsTransitionMapFromDescriptor(Object* descriptor_contents, 2225 static Map* GetElementsTransitionMapFromDescriptor(Object* descriptor_contents,
2234 ElementsKind elements_kind) { 2226 ElementsKind elements_kind) {
2235 if (descriptor_contents->IsMap()) { 2227 if (descriptor_contents->IsMap()) {
2236 Map* map = Map::cast(descriptor_contents); 2228 Map* map = Map::cast(descriptor_contents);
2237 if (map->elements_kind() == elements_kind) { 2229 if (map->elements_kind() == elements_kind) {
2238 return map; 2230 return map;
2239 } 2231 }
2240 return NULL; 2232 return NULL;
2241 } 2233 }
2242 2234
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
2331 } else { 2323 } else {
2332 if (safe_to_add_transition != NULL) { 2324 if (safe_to_add_transition != NULL) {
2333 *safe_to_add_transition = false; 2325 *safe_to_add_transition = false;
2334 } 2326 }
2335 } 2327 }
2336 } 2328 }
2337 return NULL; 2329 return NULL;
2338 } 2330 }
2339 2331
2340 2332
2341 Map* Map::LookupElementsTransitionMap(ElementsKind elements_kind, 2333 Map* Map::LookupElementsTransitionMap(ElementsKind to_kind,
2342 bool* safe_to_add_transition) { 2334 bool* safe_to_add_transition) {
2343 // Special case: indirect SMI->FAST transition (cf. comment in 2335 ElementsKind from_kind = elements_kind();
2344 // AddElementsTransition()). 2336 if (IsFastElementsKind(from_kind) && IsFastElementsKind(to_kind)) {
2345 if (this->elements_kind() == FAST_SMI_ONLY_ELEMENTS && 2337 if (!IsMoreGeneralElementsKindTransition(from_kind, to_kind)) {
2346 elements_kind == FAST_ELEMENTS) { 2338 if (safe_to_add_transition) *safe_to_add_transition = false;
2347 Map* double_map = this->LookupElementsTransitionMap(FAST_DOUBLE_ELEMENTS, 2339 return NULL;
2348 safe_to_add_transition); 2340 }
2349 if (double_map == NULL) return double_map; 2341 ElementsKind transitioned_from_kind =
2350 return double_map->LookupElementsTransitionMap(FAST_ELEMENTS, 2342 GetNextMoreGeneralFastElementsKind(from_kind, false);
2343
2344
2345 // If the transition is a single step in the transition sequence, fall
2346 // through to looking it up and returning it. If it requires several steps,
2347 // divide and conquer.
2348 if (transitioned_from_kind != to_kind) {
2349 // If the transition is several steps in the lattice, divide and conquer.
2350 Map* from_map = LookupElementsTransitionMap(transitioned_from_kind,
2351 safe_to_add_transition);
2352 if (from_map == NULL) return NULL;
2353 return from_map->LookupElementsTransitionMap(to_kind,
2351 safe_to_add_transition); 2354 safe_to_add_transition);
2355 }
2352 } 2356 }
2353 Object* descriptor_contents = GetDescriptorContents( 2357 Object* descriptor_contents = GetDescriptorContents(
2354 elements_transition_sentinel_name(), safe_to_add_transition); 2358 elements_transition_sentinel_name(), safe_to_add_transition);
2355 if (descriptor_contents != NULL) { 2359 if (descriptor_contents != NULL) {
2356 Map* maybe_transition_map = 2360 Map* maybe_transition_map =
2357 GetElementsTransitionMapFromDescriptor(descriptor_contents, 2361 GetElementsTransitionMapFromDescriptor(descriptor_contents,
2358 elements_kind); 2362 to_kind);
2359 ASSERT(maybe_transition_map == NULL || maybe_transition_map->IsMap()); 2363 ASSERT(maybe_transition_map == NULL || maybe_transition_map->IsMap());
2360 return maybe_transition_map; 2364 return maybe_transition_map;
2361 } 2365 }
2362 return NULL; 2366 return NULL;
2363 } 2367 }
2364 2368
2365 2369
2366 MaybeObject* Map::AddElementsTransition(ElementsKind elements_kind, 2370 MaybeObject* Map::AddElementsTransition(ElementsKind to_kind,
2367 Map* transitioned_map) { 2371 Map* transitioned_map) {
2368 // The map transition graph should be a tree, therefore the transition 2372 ElementsKind from_kind = elements_kind();
2369 // from SMI to FAST elements is not done directly, but by going through 2373 if (IsFastElementsKind(from_kind) && IsFastElementsKind(to_kind)) {
2370 // DOUBLE elements first. 2374 ASSERT(IsMoreGeneralElementsKindTransition(from_kind, to_kind));
2371 if (this->elements_kind() == FAST_SMI_ONLY_ELEMENTS && 2375 ElementsKind transitioned_from_kind =
2372 elements_kind == FAST_ELEMENTS) { 2376 GetNextMoreGeneralFastElementsKind(from_kind, false);
2373 bool safe_to_add = true; 2377 // The map transitions graph should be a tree, therefore transitions to
2374 Map* double_map = this->LookupElementsTransitionMap( 2378 // ElementsKind that are not adjacent in the ElementsKind sequence are not
2375 FAST_DOUBLE_ELEMENTS, &safe_to_add); 2379 // done directly, but instead by going through intermediate ElementsKinds
2376 // This method is only called when safe_to_add_transition has been found 2380 // first.
2377 // to be true earlier. 2381 if (to_kind != transitioned_from_kind) {
2378 ASSERT(safe_to_add); 2382 bool safe_to_add = true;
2383 Map* intermediate_map = LookupElementsTransitionMap(
2384 transitioned_from_kind, &safe_to_add);
2385 // This method is only called when safe_to_add has been found to be true
2386 // earlier.
2387 ASSERT(safe_to_add);
2379 2388
2380 if (double_map == NULL) { 2389 if (intermediate_map == NULL) {
2381 MaybeObject* maybe_map = this->CopyDropTransitions(); 2390 MaybeObject* maybe_map = CopyDropTransitions();
2382 if (!maybe_map->To(&double_map)) return maybe_map; 2391 if (!maybe_map->To(&intermediate_map)) return maybe_map;
2383 double_map->set_elements_kind(FAST_DOUBLE_ELEMENTS); 2392 intermediate_map->set_elements_kind(transitioned_from_kind);
2384 MaybeObject* maybe_double_transition = this->AddElementsTransition( 2393 MaybeObject* maybe_transition = AddElementsTransition(
2385 FAST_DOUBLE_ELEMENTS, double_map); 2394 transitioned_from_kind, intermediate_map);
2386 if (maybe_double_transition->IsFailure()) return maybe_double_transition; 2395 if (maybe_transition->IsFailure()) return maybe_transition;
2396 }
2397 return intermediate_map->AddElementsTransition(to_kind, transitioned_map);
2387 } 2398 }
2388 return double_map->AddElementsTransition(FAST_ELEMENTS, transitioned_map);
2389 } 2399 }
2390 2400
2391 bool safe_to_add_transition = true; 2401 bool safe_to_add_transition = true;
2392 Object* descriptor_contents = GetDescriptorContents( 2402 Object* descriptor_contents = GetDescriptorContents(
2393 elements_transition_sentinel_name(), &safe_to_add_transition); 2403 elements_transition_sentinel_name(), &safe_to_add_transition);
2394 // This method is only called when safe_to_add_transition has been found 2404 // This method is only called when safe_to_add_transition has been found
2395 // to be true earlier. 2405 // to be true earlier.
2396 ASSERT(safe_to_add_transition); 2406 ASSERT(safe_to_add_transition);
2397 MaybeObject* maybe_new_contents = 2407 MaybeObject* maybe_new_contents =
2398 AddElementsTransitionMapToDescriptor(descriptor_contents, 2408 AddElementsTransitionMapToDescriptor(descriptor_contents,
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
2430 ElementsKind from_kind = current_map->elements_kind(); 2440 ElementsKind from_kind = current_map->elements_kind();
2431 2441
2432 if (from_kind == to_kind) return current_map; 2442 if (from_kind == to_kind) return current_map;
2433 2443
2434 // Only objects with FastProperties can have DescriptorArrays and can track 2444 // Only objects with FastProperties can have DescriptorArrays and can track
2435 // element-related maps. Also don't add descriptors to maps that are shared. 2445 // element-related maps. Also don't add descriptors to maps that are shared.
2436 bool safe_to_add_transition = HasFastProperties() && 2446 bool safe_to_add_transition = HasFastProperties() &&
2437 !current_map->IsUndefined() && 2447 !current_map->IsUndefined() &&
2438 !current_map->is_shared(); 2448 !current_map->is_shared();
2439 2449
2440 // Prevent long chains of DICTIONARY -> FAST_ELEMENTS maps caused by objects 2450 // Prevent long chains of DICTIONARY -> FAST_*_ELEMENTS maps caused by objects
2441 // with elements that switch back and forth between dictionary and fast 2451 // with elements that switch back and forth between dictionary and fast
2442 // element mode. 2452 // element modes.
2443 if (from_kind == DICTIONARY_ELEMENTS && to_kind == FAST_ELEMENTS) { 2453 if (from_kind == DICTIONARY_ELEMENTS &&
2454 IsFastElementsKind(to_kind)) {
2444 safe_to_add_transition = false; 2455 safe_to_add_transition = false;
2445 } 2456 }
2446 2457
2447 if (safe_to_add_transition) { 2458 if (safe_to_add_transition) {
2448 // It's only safe to manipulate the descriptor array if it would be 2459 // It's only safe to manipulate the descriptor array if it would be
2449 // safe to add a transition. 2460 // safe to add a transition.
2450 Map* maybe_transition_map = current_map->LookupElementsTransitionMap( 2461 Map* maybe_transition_map = current_map->LookupElementsTransitionMap(
2451 to_kind, &safe_to_add_transition); 2462 to_kind, &safe_to_add_transition);
2452 if (maybe_transition_map != NULL) { 2463 if (maybe_transition_map != NULL) {
2453 return maybe_transition_map; 2464 return maybe_transition_map;
(...skipping 1015 matching lines...) Expand 10 before | Expand all | Expand 10 after
3469 // Find the backing store. 3480 // Find the backing store.
3470 FixedArrayBase* array = FixedArrayBase::cast(elements()); 3481 FixedArrayBase* array = FixedArrayBase::cast(elements());
3471 Map* old_map = array->map(); 3482 Map* old_map = array->map();
3472 bool is_arguments = 3483 bool is_arguments =
3473 (old_map == old_map->GetHeap()->non_strict_arguments_elements_map()); 3484 (old_map == old_map->GetHeap()->non_strict_arguments_elements_map());
3474 if (is_arguments) { 3485 if (is_arguments) {
3475 array = FixedArrayBase::cast(FixedArray::cast(array)->get(1)); 3486 array = FixedArrayBase::cast(FixedArray::cast(array)->get(1));
3476 } 3487 }
3477 if (array->IsDictionary()) return array; 3488 if (array->IsDictionary()) return array;
3478 3489
3479 ASSERT(HasFastElements() || 3490 ASSERT(HasFastSmiOrObjectElements() ||
3480 HasFastSmiOnlyElements() ||
3481 HasFastDoubleElements() || 3491 HasFastDoubleElements() ||
3482 HasFastArgumentsElements()); 3492 HasFastArgumentsElements());
3483 // Compute the effective length and allocate a new backing store. 3493 // Compute the effective length and allocate a new backing store.
3484 int length = IsJSArray() 3494 int length = IsJSArray()
3485 ? Smi::cast(JSArray::cast(this)->length())->value() 3495 ? Smi::cast(JSArray::cast(this)->length())->value()
3486 : array->length(); 3496 : array->length();
3487 int old_capacity = 0; 3497 int old_capacity = 0;
3488 int used_elements = 0; 3498 int used_elements = 0;
3489 GetElementsCapacityAndUsage(&old_capacity, &used_elements); 3499 GetElementsCapacityAndUsage(&old_capacity, &used_elements);
3490 SeededNumberDictionary* dictionary = NULL; 3500 SeededNumberDictionary* dictionary = NULL;
(...skipping 14 matching lines...) Expand all
3505 } else { 3515 } else {
3506 // Objects must be allocated in the old object space, since the 3516 // Objects must be allocated in the old object space, since the
3507 // overall number of HeapNumbers needed for the conversion might 3517 // overall number of HeapNumbers needed for the conversion might
3508 // exceed the capacity of new space, and we would fail repeatedly 3518 // exceed the capacity of new space, and we would fail repeatedly
3509 // trying to convert the FixedDoubleArray. 3519 // trying to convert the FixedDoubleArray.
3510 MaybeObject* maybe_value_object = 3520 MaybeObject* maybe_value_object =
3511 GetHeap()->AllocateHeapNumber(double_array->get_scalar(i), TENURED); 3521 GetHeap()->AllocateHeapNumber(double_array->get_scalar(i), TENURED);
3512 if (!maybe_value_object->ToObject(&value)) return maybe_value_object; 3522 if (!maybe_value_object->ToObject(&value)) return maybe_value_object;
3513 } 3523 }
3514 } else { 3524 } else {
3515 ASSERT(old_map->has_fast_elements() || 3525 ASSERT(old_map->has_fast_smi_or_object_elements());
3516 old_map->has_fast_smi_only_elements());
3517 value = FixedArray::cast(array)->get(i); 3526 value = FixedArray::cast(array)->get(i);
3518 } 3527 }
3519 PropertyDetails details = PropertyDetails(NONE, NORMAL); 3528 PropertyDetails details = PropertyDetails(NONE, NORMAL);
3520 if (!value->IsTheHole()) { 3529 if (!value->IsTheHole()) {
3521 Object* result; 3530 Object* result;
3522 MaybeObject* maybe_result = 3531 MaybeObject* maybe_result =
3523 dictionary->AddNumberEntry(i, value, details); 3532 dictionary->AddNumberEntry(i, value, details);
3524 if (!maybe_result->ToObject(&result)) return maybe_result; 3533 if (!maybe_result->ToObject(&result)) return maybe_result;
3525 dictionary = SeededNumberDictionary::cast(result); 3534 dictionary = SeededNumberDictionary::cast(result);
3526 } 3535 }
(...skipping 466 matching lines...) Expand 10 before | Expand all | Expand 10 after
3993 if (IsJSProxy()) { 4002 if (IsJSProxy()) {
3994 return JSProxy::cast(this)->DeletePropertyWithHandler(name, mode); 4003 return JSProxy::cast(this)->DeletePropertyWithHandler(name, mode);
3995 } 4004 }
3996 return JSObject::cast(this)->DeleteProperty(name, mode); 4005 return JSObject::cast(this)->DeleteProperty(name, mode);
3997 } 4006 }
3998 4007
3999 4008
4000 bool JSObject::ReferencesObjectFromElements(FixedArray* elements, 4009 bool JSObject::ReferencesObjectFromElements(FixedArray* elements,
4001 ElementsKind kind, 4010 ElementsKind kind,
4002 Object* object) { 4011 Object* object) {
4003 ASSERT(kind == FAST_ELEMENTS || 4012 ASSERT(IsFastObjectElementsKind(kind) ||
4004 kind == DICTIONARY_ELEMENTS); 4013 kind == DICTIONARY_ELEMENTS);
4005 if (kind == FAST_ELEMENTS) { 4014 if (IsFastObjectElementsKind(kind)) {
4006 int length = IsJSArray() 4015 int length = IsJSArray()
4007 ? Smi::cast(JSArray::cast(this)->length())->value() 4016 ? Smi::cast(JSArray::cast(this)->length())->value()
4008 : elements->length(); 4017 : elements->length();
4009 for (int i = 0; i < length; ++i) { 4018 for (int i = 0; i < length; ++i) {
4010 Object* element = elements->get(i); 4019 Object* element = elements->get(i);
4011 if (!element->IsTheHole() && element == object) return true; 4020 if (!element->IsTheHole() && element == object) return true;
4012 } 4021 }
4013 } else { 4022 } else {
4014 Object* key = 4023 Object* key =
4015 SeededNumberDictionary::cast(elements)->SlowReverseLookup(object); 4024 SeededNumberDictionary::cast(elements)->SlowReverseLookup(object);
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
4047 case EXTERNAL_PIXEL_ELEMENTS: 4056 case EXTERNAL_PIXEL_ELEMENTS:
4048 case EXTERNAL_BYTE_ELEMENTS: 4057 case EXTERNAL_BYTE_ELEMENTS:
4049 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 4058 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
4050 case EXTERNAL_SHORT_ELEMENTS: 4059 case EXTERNAL_SHORT_ELEMENTS:
4051 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 4060 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
4052 case EXTERNAL_INT_ELEMENTS: 4061 case EXTERNAL_INT_ELEMENTS:
4053 case EXTERNAL_UNSIGNED_INT_ELEMENTS: 4062 case EXTERNAL_UNSIGNED_INT_ELEMENTS:
4054 case EXTERNAL_FLOAT_ELEMENTS: 4063 case EXTERNAL_FLOAT_ELEMENTS:
4055 case EXTERNAL_DOUBLE_ELEMENTS: 4064 case EXTERNAL_DOUBLE_ELEMENTS:
4056 case FAST_DOUBLE_ELEMENTS: 4065 case FAST_DOUBLE_ELEMENTS:
4066 case FAST_HOLEY_DOUBLE_ELEMENTS:
4057 // Raw pixels and external arrays do not reference other 4067 // Raw pixels and external arrays do not reference other
4058 // objects. 4068 // objects.
4059 break; 4069 break;
4060 case FAST_SMI_ONLY_ELEMENTS: 4070 case FAST_SMI_ELEMENTS:
4071 case FAST_HOLEY_SMI_ELEMENTS:
4061 break; 4072 break;
4062 case FAST_ELEMENTS: 4073 case FAST_ELEMENTS:
4074 case FAST_HOLEY_ELEMENTS:
4063 case DICTIONARY_ELEMENTS: { 4075 case DICTIONARY_ELEMENTS: {
4064 FixedArray* elements = FixedArray::cast(this->elements()); 4076 FixedArray* elements = FixedArray::cast(this->elements());
4065 if (ReferencesObjectFromElements(elements, kind, obj)) return true; 4077 if (ReferencesObjectFromElements(elements, kind, obj)) return true;
4066 break; 4078 break;
4067 } 4079 }
4068 case NON_STRICT_ARGUMENTS_ELEMENTS: { 4080 case NON_STRICT_ARGUMENTS_ELEMENTS: {
4069 FixedArray* parameter_map = FixedArray::cast(elements()); 4081 FixedArray* parameter_map = FixedArray::cast(elements());
4070 // Check the mapped parameters. 4082 // Check the mapped parameters.
4071 int length = parameter_map->length(); 4083 int length = parameter_map->length();
4072 for (int i = 2; i < length; ++i) { 4084 for (int i = 2; i < length; ++i) {
4073 Object* value = parameter_map->get(i); 4085 Object* value = parameter_map->get(i);
4074 if (!value->IsTheHole() && value == obj) return true; 4086 if (!value->IsTheHole() && value == obj) return true;
4075 } 4087 }
4076 // Check the arguments. 4088 // Check the arguments.
4077 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); 4089 FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
4078 kind = arguments->IsDictionary() ? DICTIONARY_ELEMENTS : FAST_ELEMENTS; 4090 kind = arguments->IsDictionary() ? DICTIONARY_ELEMENTS :
4091 FAST_HOLEY_ELEMENTS;
4079 if (ReferencesObjectFromElements(arguments, kind, obj)) return true; 4092 if (ReferencesObjectFromElements(arguments, kind, obj)) return true;
4080 break; 4093 break;
4081 } 4094 }
4082 } 4095 }
4083 4096
4084 // For functions check the context. 4097 // For functions check the context.
4085 if (IsJSFunction()) { 4098 if (IsJSFunction()) {
4086 // Get the constructor function for arguments array. 4099 // Get the constructor function for arguments array.
4087 JSObject* arguments_boilerplate = 4100 JSObject* arguments_boilerplate =
4088 heap->isolate()->context()->global_context()-> 4101 heap->isolate()->context()->global_context()->
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after
4302 for (Object* current = this; 4315 for (Object* current = this;
4303 current != heap->null_value(); 4316 current != heap->null_value();
4304 current = JSObject::cast(current)->GetPrototype()) { 4317 current = JSObject::cast(current)->GetPrototype()) {
4305 JSReceiver::cast(current)->LocalLookup(name, result); 4318 JSReceiver::cast(current)->LocalLookup(name, result);
4306 if (result->IsProperty()) return; 4319 if (result->IsProperty()) return;
4307 } 4320 }
4308 result->NotFound(); 4321 result->NotFound();
4309 } 4322 }
4310 4323
4311 4324
4312 // Search object and it's prototype chain for callback properties. 4325 // Search object and its prototype chain for callback properties.
4313 void JSObject::LookupCallback(String* name, LookupResult* result) { 4326 void JSObject::LookupCallback(String* name, LookupResult* result) {
4314 Heap* heap = GetHeap(); 4327 Heap* heap = GetHeap();
4315 for (Object* current = this; 4328 for (Object* current = this;
4316 current != heap->null_value() && current->IsJSObject(); 4329 current != heap->null_value() && current->IsJSObject();
4317 current = JSObject::cast(current)->GetPrototype()) { 4330 current = JSObject::cast(current)->GetPrototype()) {
4318 JSObject::cast(current)->LocalLookupRealNamedProperty(name, result); 4331 JSObject::cast(current)->LocalLookupRealNamedProperty(name, result);
4319 if (result->IsFound() && result->type() == CALLBACKS) return; 4332 if (result->IsFound() && result->type() == CALLBACKS) return;
4320 } 4333 }
4321 result->NotFound(); 4334 result->NotFound();
4322 } 4335 }
(...skipping 23 matching lines...) Expand all
4346 } 4359 }
4347 return false; 4360 return false;
4348 } 4361 }
4349 4362
4350 4363
4351 MaybeObject* JSObject::DefineElementAccessor(uint32_t index, 4364 MaybeObject* JSObject::DefineElementAccessor(uint32_t index,
4352 Object* getter, 4365 Object* getter,
4353 Object* setter, 4366 Object* setter,
4354 PropertyAttributes attributes) { 4367 PropertyAttributes attributes) {
4355 switch (GetElementsKind()) { 4368 switch (GetElementsKind()) {
4356 case FAST_SMI_ONLY_ELEMENTS: 4369 case FAST_SMI_ELEMENTS:
4357 case FAST_ELEMENTS: 4370 case FAST_ELEMENTS:
4358 case FAST_DOUBLE_ELEMENTS: 4371 case FAST_DOUBLE_ELEMENTS:
4372 case FAST_HOLEY_SMI_ELEMENTS:
4373 case FAST_HOLEY_ELEMENTS:
4374 case FAST_HOLEY_DOUBLE_ELEMENTS:
4359 break; 4375 break;
4360 case EXTERNAL_PIXEL_ELEMENTS: 4376 case EXTERNAL_PIXEL_ELEMENTS:
4361 case EXTERNAL_BYTE_ELEMENTS: 4377 case EXTERNAL_BYTE_ELEMENTS:
4362 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 4378 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
4363 case EXTERNAL_SHORT_ELEMENTS: 4379 case EXTERNAL_SHORT_ELEMENTS:
4364 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 4380 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
4365 case EXTERNAL_INT_ELEMENTS: 4381 case EXTERNAL_INT_ELEMENTS:
4366 case EXTERNAL_UNSIGNED_INT_ELEMENTS: 4382 case EXTERNAL_UNSIGNED_INT_ELEMENTS:
4367 case EXTERNAL_FLOAT_ELEMENTS: 4383 case EXTERNAL_FLOAT_ELEMENTS:
4368 case EXTERNAL_DOUBLE_ELEMENTS: 4384 case EXTERNAL_DOUBLE_ELEMENTS:
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
4465 accessors->SetComponents(getter, setter); 4481 accessors->SetComponents(getter, setter);
4466 return SetPropertyCallback(name, accessors, attributes); 4482 return SetPropertyCallback(name, accessors, attributes);
4467 } 4483 }
4468 4484
4469 4485
4470 bool JSObject::CanSetCallback(String* name) { 4486 bool JSObject::CanSetCallback(String* name) {
4471 ASSERT(!IsAccessCheckNeeded() || 4487 ASSERT(!IsAccessCheckNeeded() ||
4472 GetIsolate()->MayNamedAccess(this, name, v8::ACCESS_SET)); 4488 GetIsolate()->MayNamedAccess(this, name, v8::ACCESS_SET));
4473 4489
4474 // Check if there is an API defined callback object which prohibits 4490 // Check if there is an API defined callback object which prohibits
4475 // callback overwriting in this object or it's prototype chain. 4491 // callback overwriting in this object or its prototype chain.
4476 // This mechanism is needed for instance in a browser setting, where 4492 // This mechanism is needed for instance in a browser setting, where
4477 // certain accessors such as window.location should not be allowed 4493 // certain accessors such as window.location should not be allowed
4478 // to be overwritten because allowing overwriting could potentially 4494 // to be overwritten because allowing overwriting could potentially
4479 // cause security problems. 4495 // cause security problems.
4480 LookupResult callback_result(GetIsolate()); 4496 LookupResult callback_result(GetIsolate());
4481 LookupCallback(name, &callback_result); 4497 LookupCallback(name, &callback_result);
4482 if (callback_result.IsProperty()) { 4498 if (callback_result.IsProperty()) {
4483 Object* obj = callback_result.GetCallbackObject(); 4499 Object* obj = callback_result.GetCallbackObject();
4484 if (obj->IsAccessorInfo() && 4500 if (obj->IsAccessorInfo() &&
4485 AccessorInfo::cast(obj)->prohibits_overwriting()) { 4501 AccessorInfo::cast(obj)->prohibits_overwriting()) {
(...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after
4789 } 4805 }
4790 4806
4791 uint32_t index = 0; 4807 uint32_t index = 0;
4792 bool is_element = name->AsArrayIndex(&index); 4808 bool is_element = name->AsArrayIndex(&index);
4793 4809
4794 if (is_element) { 4810 if (is_element) {
4795 if (IsJSArray()) return isolate->heap()->undefined_value(); 4811 if (IsJSArray()) return isolate->heap()->undefined_value();
4796 4812
4797 // Accessors overwrite previous callbacks (cf. with getters/setters). 4813 // Accessors overwrite previous callbacks (cf. with getters/setters).
4798 switch (GetElementsKind()) { 4814 switch (GetElementsKind()) {
4799 case FAST_SMI_ONLY_ELEMENTS: 4815 case FAST_SMI_ELEMENTS:
4800 case FAST_ELEMENTS: 4816 case FAST_ELEMENTS:
4801 case FAST_DOUBLE_ELEMENTS: 4817 case FAST_DOUBLE_ELEMENTS:
4818 case FAST_HOLEY_SMI_ELEMENTS:
4819 case FAST_HOLEY_ELEMENTS:
4820 case FAST_HOLEY_DOUBLE_ELEMENTS:
4802 break; 4821 break;
4803 case EXTERNAL_PIXEL_ELEMENTS: 4822 case EXTERNAL_PIXEL_ELEMENTS:
4804 case EXTERNAL_BYTE_ELEMENTS: 4823 case EXTERNAL_BYTE_ELEMENTS:
4805 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 4824 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
4806 case EXTERNAL_SHORT_ELEMENTS: 4825 case EXTERNAL_SHORT_ELEMENTS:
4807 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 4826 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
4808 case EXTERNAL_INT_ELEMENTS: 4827 case EXTERNAL_INT_ELEMENTS:
4809 case EXTERNAL_UNSIGNED_INT_ELEMENTS: 4828 case EXTERNAL_UNSIGNED_INT_ELEMENTS:
4810 case EXTERNAL_FLOAT_ELEMENTS: 4829 case EXTERNAL_FLOAT_ELEMENTS:
4811 case EXTERNAL_DOUBLE_ELEMENTS: 4830 case EXTERNAL_DOUBLE_ELEMENTS:
(...skipping 3768 matching lines...) Expand 10 before | Expand all | Expand 10 after
8580 PrintF("RelocInfo (size = %d)\n", relocation_size()); 8599 PrintF("RelocInfo (size = %d)\n", relocation_size());
8581 for (RelocIterator it(this); !it.done(); it.next()) it.rinfo()->Print(out); 8600 for (RelocIterator it(this); !it.done(); it.next()) it.rinfo()->Print(out);
8582 PrintF(out, "\n"); 8601 PrintF(out, "\n");
8583 } 8602 }
8584 #endif // ENABLE_DISASSEMBLER 8603 #endif // ENABLE_DISASSEMBLER
8585 8604
8586 8605
8587 MaybeObject* JSObject::SetFastElementsCapacityAndLength( 8606 MaybeObject* JSObject::SetFastElementsCapacityAndLength(
8588 int capacity, 8607 int capacity,
8589 int length, 8608 int length,
8590 SetFastElementsCapacityMode set_capacity_mode) { 8609 SetFastElementsCapacitySmiMode smi_mode) {
8591 Heap* heap = GetHeap(); 8610 Heap* heap = GetHeap();
8592 // We should never end in here with a pixel or external array. 8611 // We should never end in here with a pixel or external array.
8593 ASSERT(!HasExternalArrayElements()); 8612 ASSERT(!HasExternalArrayElements());
8594 8613
8595 // Allocate a new fast elements backing store. 8614 // Allocate a new fast elements backing store.
8596 FixedArray* new_elements; 8615 FixedArray* new_elements;
8597 { MaybeObject* maybe = heap->AllocateFixedArrayWithHoles(capacity); 8616 { MaybeObject* maybe = heap->AllocateFixedArrayWithHoles(capacity);
8598 if (!maybe->To(&new_elements)) return maybe; 8617 if (!maybe->To(&new_elements)) return maybe;
8599 } 8618 }
8600 8619
8601 // Find the new map to use for this object if there is a map change. 8620 ElementsKind elements_kind = GetElementsKind();
8602 Map* new_map = NULL; 8621 ElementsKind new_elements_kind;
8603 if (elements()->map() != heap->non_strict_arguments_elements_map()) { 8622 // The resized array has FAST_*_SMI_ELEMENTS if the capacity mode forces it,
8604 // The resized array has FAST_SMI_ONLY_ELEMENTS if the capacity mode forces 8623 // or if it's allowed and the old elements array contained only SMIs.
8605 // it, or if it's allowed and the old elements array contained only SMIs. 8624 bool has_fast_smi_elements =
8606 bool has_fast_smi_only_elements = 8625 (smi_mode == kForceSmiElements) ||
8607 (set_capacity_mode == kForceSmiOnlyElements) || 8626 ((smi_mode == kAllowSmiElements) && HasFastSmiElements());
8608 ((set_capacity_mode == kAllowSmiOnlyElements) && 8627 if (has_fast_smi_elements) {
8609 (elements()->map()->has_fast_smi_only_elements() || 8628 if (IsHoleyElementsKind(elements_kind)) {
8610 elements() == heap->empty_fixed_array())); 8629 new_elements_kind = FAST_HOLEY_SMI_ELEMENTS;
8611 ElementsKind elements_kind = has_fast_smi_only_elements 8630 } else {
8612 ? FAST_SMI_ONLY_ELEMENTS 8631 new_elements_kind = FAST_SMI_ELEMENTS;
8613 : FAST_ELEMENTS; 8632 }
8614 MaybeObject* maybe = GetElementsTransitionMap(GetIsolate(), elements_kind); 8633 } else {
8615 if (!maybe->To(&new_map)) return maybe; 8634 if (IsHoleyElementsKind(elements_kind)) {
8635 new_elements_kind = FAST_HOLEY_ELEMENTS;
8636 } else {
8637 new_elements_kind = FAST_ELEMENTS;
8638 }
8616 } 8639 }
8617
8618 FixedArrayBase* old_elements = elements(); 8640 FixedArrayBase* old_elements = elements();
8619 ElementsKind elements_kind = GetElementsKind();
8620 ElementsAccessor* accessor = ElementsAccessor::ForKind(elements_kind); 8641 ElementsAccessor* accessor = ElementsAccessor::ForKind(elements_kind);
8621 ElementsKind to_kind = (elements_kind == FAST_SMI_ONLY_ELEMENTS)
8622 ? FAST_SMI_ONLY_ELEMENTS
8623 : FAST_ELEMENTS;
8624 { MaybeObject* maybe_obj = 8642 { MaybeObject* maybe_obj =
8625 accessor->CopyElements(this, new_elements, to_kind); 8643 accessor->CopyElements(this, new_elements, new_elements_kind);
8626 if (maybe_obj->IsFailure()) return maybe_obj; 8644 if (maybe_obj->IsFailure()) return maybe_obj;
8627 } 8645 }
8628 if (elements_kind != NON_STRICT_ARGUMENTS_ELEMENTS) { 8646 if (elements_kind != NON_STRICT_ARGUMENTS_ELEMENTS) {
8647 Map* new_map = map();
8648 if (new_elements_kind != elements_kind) {
8649 MaybeObject* maybe =
8650 GetElementsTransitionMap(GetIsolate(), new_elements_kind);
8651 if (!maybe->To(&new_map)) return maybe;
8652 }
8653 ValidateElements();
8629 set_map_and_elements(new_map, new_elements); 8654 set_map_and_elements(new_map, new_elements);
8630 } else { 8655 } else {
8631 FixedArray* parameter_map = FixedArray::cast(old_elements); 8656 FixedArray* parameter_map = FixedArray::cast(old_elements);
8632 parameter_map->set(1, new_elements); 8657 parameter_map->set(1, new_elements);
8633 } 8658 }
8634 8659
8635 if (FLAG_trace_elements_transitions) { 8660 if (FLAG_trace_elements_transitions) {
8636 PrintElementsTransition(stdout, elements_kind, old_elements, 8661 PrintElementsTransition(stdout, elements_kind, old_elements,
8637 GetElementsKind(), new_elements); 8662 GetElementsKind(), new_elements);
8638 } 8663 }
8639 8664
8640 // Update the length if necessary.
8641 if (IsJSArray()) { 8665 if (IsJSArray()) {
8642 JSArray::cast(this)->set_length(Smi::FromInt(length)); 8666 JSArray::cast(this)->set_length(Smi::FromInt(length));
8643 } 8667 }
8644
8645 return new_elements; 8668 return new_elements;
8646 } 8669 }
8647 8670
8648 8671
8649 MaybeObject* JSObject::SetFastDoubleElementsCapacityAndLength( 8672 MaybeObject* JSObject::SetFastDoubleElementsCapacityAndLength(
8650 int capacity, 8673 int capacity,
8651 int length) { 8674 int length) {
8652 Heap* heap = GetHeap(); 8675 Heap* heap = GetHeap();
8653 // We should never end in here with a pixel or external array. 8676 // We should never end in here with a pixel or external array.
8654 ASSERT(!HasExternalArrayElements()); 8677 ASSERT(!HasExternalArrayElements());
8655 8678
8656 FixedArrayBase* elems; 8679 FixedArrayBase* elems;
8657 { MaybeObject* maybe_obj = 8680 { MaybeObject* maybe_obj =
8658 heap->AllocateUninitializedFixedDoubleArray(capacity); 8681 heap->AllocateUninitializedFixedDoubleArray(capacity);
8659 if (!maybe_obj->To(&elems)) return maybe_obj; 8682 if (!maybe_obj->To(&elems)) return maybe_obj;
8660 } 8683 }
8661 8684
8685 ElementsKind elements_kind = GetElementsKind();
8686 ElementsKind new_elements_kind = elements_kind;
8687 if (IsHoleyElementsKind(elements_kind)) {
8688 new_elements_kind = FAST_HOLEY_DOUBLE_ELEMENTS;
8689 } else {
8690 new_elements_kind = FAST_DOUBLE_ELEMENTS;
8691 }
8692
8662 Map* new_map; 8693 Map* new_map;
8663 { MaybeObject* maybe_obj = 8694 { MaybeObject* maybe_obj =
8664 GetElementsTransitionMap(heap->isolate(), FAST_DOUBLE_ELEMENTS); 8695 GetElementsTransitionMap(heap->isolate(), new_elements_kind);
8665 if (!maybe_obj->To(&new_map)) return maybe_obj; 8696 if (!maybe_obj->To(&new_map)) return maybe_obj;
8666 } 8697 }
8667 8698
8668 FixedArrayBase* old_elements = elements(); 8699 FixedArrayBase* old_elements = elements();
8669 ElementsKind elements_kind = GetElementsKind();
8670 ElementsAccessor* accessor = ElementsAccessor::ForKind(elements_kind); 8700 ElementsAccessor* accessor = ElementsAccessor::ForKind(elements_kind);
8671 { MaybeObject* maybe_obj = 8701 { MaybeObject* maybe_obj =
8672 accessor->CopyElements(this, elems, FAST_DOUBLE_ELEMENTS); 8702 accessor->CopyElements(this, elems, FAST_DOUBLE_ELEMENTS);
8673 if (maybe_obj->IsFailure()) return maybe_obj; 8703 if (maybe_obj->IsFailure()) return maybe_obj;
8674 } 8704 }
8675 if (elements_kind != NON_STRICT_ARGUMENTS_ELEMENTS) { 8705 if (elements_kind != NON_STRICT_ARGUMENTS_ELEMENTS) {
8706 ValidateElements();
8676 set_map_and_elements(new_map, elems); 8707 set_map_and_elements(new_map, elems);
8677 } else { 8708 } else {
8678 FixedArray* parameter_map = FixedArray::cast(old_elements); 8709 FixedArray* parameter_map = FixedArray::cast(old_elements);
8679 parameter_map->set(1, elems); 8710 parameter_map->set(1, elems);
8680 } 8711 }
8681 8712
8682 if (FLAG_trace_elements_transitions) { 8713 if (FLAG_trace_elements_transitions) {
8683 PrintElementsTransition(stdout, elements_kind, old_elements, 8714 PrintElementsTransition(stdout, elements_kind, old_elements,
8684 FAST_DOUBLE_ELEMENTS, elems); 8715 GetElementsKind(), elems);
8685 } 8716 }
8686 8717
8687 if (IsJSArray()) { 8718 if (IsJSArray()) {
8688 JSArray::cast(this)->set_length(Smi::FromInt(length)); 8719 JSArray::cast(this)->set_length(Smi::FromInt(length));
8689 } 8720 }
8690 8721
8691 return this; 8722 return this;
8692 } 8723 }
8693 8724
8694 8725
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after
8954 return HasElementWithInterceptor(this, index) ? INTERCEPTED_ELEMENT 8985 return HasElementWithInterceptor(this, index) ? INTERCEPTED_ELEMENT
8955 : UNDEFINED_ELEMENT; 8986 : UNDEFINED_ELEMENT;
8956 } 8987 }
8957 8988
8958 // Handle [] on String objects. 8989 // Handle [] on String objects.
8959 if (this->IsStringObjectWithCharacterAt(index)) { 8990 if (this->IsStringObjectWithCharacterAt(index)) {
8960 return STRING_CHARACTER_ELEMENT; 8991 return STRING_CHARACTER_ELEMENT;
8961 } 8992 }
8962 8993
8963 switch (GetElementsKind()) { 8994 switch (GetElementsKind()) {
8964 case FAST_SMI_ONLY_ELEMENTS: 8995 case FAST_SMI_ELEMENTS:
8965 case FAST_ELEMENTS: { 8996 case FAST_ELEMENTS:
8997 case FAST_HOLEY_SMI_ELEMENTS:
8998 case FAST_HOLEY_ELEMENTS: {
8966 uint32_t length = IsJSArray() ? 8999 uint32_t length = IsJSArray() ?
8967 static_cast<uint32_t> 9000 static_cast<uint32_t>
8968 (Smi::cast(JSArray::cast(this)->length())->value()) : 9001 (Smi::cast(JSArray::cast(this)->length())->value()) :
8969 static_cast<uint32_t>(FixedArray::cast(elements())->length()); 9002 static_cast<uint32_t>(FixedArray::cast(elements())->length());
8970 if ((index < length) && 9003 if ((index < length) &&
8971 !FixedArray::cast(elements())->get(index)->IsTheHole()) { 9004 !FixedArray::cast(elements())->get(index)->IsTheHole()) {
8972 return FAST_ELEMENT; 9005 return FAST_ELEMENT;
8973 } 9006 }
8974 break; 9007 break;
8975 } 9008 }
8976 case FAST_DOUBLE_ELEMENTS: { 9009 case FAST_DOUBLE_ELEMENTS:
9010 case FAST_HOLEY_DOUBLE_ELEMENTS: {
8977 uint32_t length = IsJSArray() ? 9011 uint32_t length = IsJSArray() ?
8978 static_cast<uint32_t> 9012 static_cast<uint32_t>
8979 (Smi::cast(JSArray::cast(this)->length())->value()) : 9013 (Smi::cast(JSArray::cast(this)->length())->value()) :
8980 static_cast<uint32_t>(FixedDoubleArray::cast(elements())->length()); 9014 static_cast<uint32_t>(FixedDoubleArray::cast(elements())->length());
8981 if ((index < length) && 9015 if ((index < length) &&
8982 !FixedDoubleArray::cast(elements())->is_the_hole(index)) { 9016 !FixedDoubleArray::cast(elements())->is_the_hole(index)) {
8983 return FAST_ELEMENT; 9017 return FAST_ELEMENT;
8984 } 9018 }
8985 break; 9019 break;
8986 } 9020 }
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after
9250 } 9284 }
9251 9285
9252 9286
9253 // Adding n elements in fast case is O(n*n). 9287 // Adding n elements in fast case is O(n*n).
9254 // Note: revisit design to have dual undefined values to capture absent 9288 // Note: revisit design to have dual undefined values to capture absent
9255 // elements. 9289 // elements.
9256 MaybeObject* JSObject::SetFastElement(uint32_t index, 9290 MaybeObject* JSObject::SetFastElement(uint32_t index,
9257 Object* value, 9291 Object* value,
9258 StrictModeFlag strict_mode, 9292 StrictModeFlag strict_mode,
9259 bool check_prototype) { 9293 bool check_prototype) {
9260 ASSERT(HasFastTypeElements() || 9294 ASSERT(HasFastSmiOrObjectElements() ||
9261 HasFastArgumentsElements()); 9295 HasFastArgumentsElements());
9262 9296
9263 FixedArray* backing_store = FixedArray::cast(elements()); 9297 FixedArray* backing_store = FixedArray::cast(elements());
9264 if (backing_store->map() == GetHeap()->non_strict_arguments_elements_map()) { 9298 if (backing_store->map() == GetHeap()->non_strict_arguments_elements_map()) {
9265 backing_store = FixedArray::cast(backing_store->get(1)); 9299 backing_store = FixedArray::cast(backing_store->get(1));
9266 } else { 9300 } else {
9267 MaybeObject* maybe = EnsureWritableFastElements(); 9301 MaybeObject* maybe = EnsureWritableFastElements();
9268 if (!maybe->To(&backing_store)) return maybe; 9302 if (!maybe->To(&backing_store)) return maybe;
9269 } 9303 }
9270 uint32_t capacity = static_cast<uint32_t>(backing_store->length()); 9304 uint32_t capacity = static_cast<uint32_t>(backing_store->length());
9271 9305
9272 if (check_prototype && 9306 if (check_prototype &&
9273 (index >= capacity || backing_store->get(index)->IsTheHole())) { 9307 (index >= capacity || backing_store->get(index)->IsTheHole())) {
9274 bool found; 9308 bool found;
9275 MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index, 9309 MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index,
9276 value, 9310 value,
9277 &found, 9311 &found,
9278 strict_mode); 9312 strict_mode);
9279 if (found) return result; 9313 if (found) return result;
9280 } 9314 }
9281 9315
9282 uint32_t new_capacity = capacity; 9316 uint32_t new_capacity = capacity;
9283 // Check if the length property of this object needs to be updated. 9317 // Check if the length property of this object needs to be updated.
9284 uint32_t array_length = 0; 9318 uint32_t array_length = 0;
9285 bool must_update_array_length = false; 9319 bool must_update_array_length = false;
9320 bool introduces_holes = true;
9286 if (IsJSArray()) { 9321 if (IsJSArray()) {
9287 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length)); 9322 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length));
9323 introduces_holes = index > array_length;
9288 if (index >= array_length) { 9324 if (index >= array_length) {
9289 must_update_array_length = true; 9325 must_update_array_length = true;
9290 array_length = index + 1; 9326 array_length = index + 1;
9291 } 9327 }
9328 } else {
9329 introduces_holes = index >= capacity;
9292 } 9330 }
9331
9332 // If the array is growing, and it's not growth by a single element at the
9333 // end, make sure that the ElementsKind is HOLEY.
9334 ElementsKind elements_kind = GetElementsKind();
9335 if (introduces_holes &&
9336 IsFastElementsKind(elements_kind) &&
9337 !IsFastHoleyElementsKind(elements_kind)) {
9338 ElementsKind transitioned_kind = GetHoleyElementsKind(elements_kind);
9339 MaybeObject* maybe = TransitionElementsKind(transitioned_kind);
9340 if (maybe->IsFailure()) return maybe;
9341 }
9342
9293 // Check if the capacity of the backing store needs to be increased, or if 9343 // Check if the capacity of the backing store needs to be increased, or if
9294 // a transition to slow elements is necessary. 9344 // a transition to slow elements is necessary.
9295 if (index >= capacity) { 9345 if (index >= capacity) {
9296 bool convert_to_slow = true; 9346 bool convert_to_slow = true;
9297 if ((index - capacity) < kMaxGap) { 9347 if ((index - capacity) < kMaxGap) {
9298 new_capacity = NewElementsCapacity(index + 1); 9348 new_capacity = NewElementsCapacity(index + 1);
9299 ASSERT(new_capacity > index); 9349 ASSERT(new_capacity > index);
9300 if (!ShouldConvertToSlowElements(new_capacity)) { 9350 if (!ShouldConvertToSlowElements(new_capacity)) {
9301 convert_to_slow = false; 9351 convert_to_slow = false;
9302 } 9352 }
9303 } 9353 }
9304 if (convert_to_slow) { 9354 if (convert_to_slow) {
9305 MaybeObject* result = NormalizeElements(); 9355 MaybeObject* result = NormalizeElements();
9306 if (result->IsFailure()) return result; 9356 if (result->IsFailure()) return result;
9307 return SetDictionaryElement(index, value, NONE, strict_mode, 9357 return SetDictionaryElement(index, value, NONE, strict_mode,
9308 check_prototype); 9358 check_prototype);
9309 } 9359 }
9310 } 9360 }
9311 // Convert to fast double elements if appropriate. 9361 // Convert to fast double elements if appropriate.
9312 if (HasFastSmiOnlyElements() && !value->IsSmi() && value->IsNumber()) { 9362 if (HasFastSmiElements() && !value->IsSmi() && value->IsNumber()) {
9313 MaybeObject* maybe = 9363 MaybeObject* maybe =
9314 SetFastDoubleElementsCapacityAndLength(new_capacity, array_length); 9364 SetFastDoubleElementsCapacityAndLength(new_capacity, array_length);
9315 if (maybe->IsFailure()) return maybe; 9365 if (maybe->IsFailure()) return maybe;
9316 FixedDoubleArray::cast(elements())->set(index, value->Number()); 9366 FixedDoubleArray::cast(elements())->set(index, value->Number());
9367 ValidateElements();
9317 return value; 9368 return value;
9318 } 9369 }
9319 // Change elements kind from SMI_ONLY to generic FAST if necessary. 9370 // Change elements kind from Smi-only to generic FAST if necessary.
9320 if (HasFastSmiOnlyElements() && !value->IsSmi()) { 9371 if (HasFastSmiElements() && !value->IsSmi()) {
9321 Map* new_map; 9372 Map* new_map;
9322 { MaybeObject* maybe_new_map = GetElementsTransitionMap(GetIsolate(), 9373 ElementsKind kind = HasFastHoleyElements()
9323 FAST_ELEMENTS); 9374 ? FAST_HOLEY_ELEMENTS
9324 if (!maybe_new_map->To(&new_map)) return maybe_new_map; 9375 : FAST_ELEMENTS;
9325 } 9376 MaybeObject* maybe_new_map = GetElementsTransitionMap(GetIsolate(),
9377 kind);
9378 if (!maybe_new_map->To(&new_map)) return maybe_new_map;
9379
9326 set_map(new_map); 9380 set_map(new_map);
9327 if (FLAG_trace_elements_transitions) {
9328 PrintElementsTransition(stdout, FAST_SMI_ONLY_ELEMENTS, elements(),
9329 FAST_ELEMENTS, elements());
9330 }
9331 } 9381 }
9332 // Increase backing store capacity if that's been decided previously. 9382 // Increase backing store capacity if that's been decided previously.
9333 if (new_capacity != capacity) { 9383 if (new_capacity != capacity) {
9334 FixedArray* new_elements; 9384 FixedArray* new_elements;
9335 SetFastElementsCapacityMode set_capacity_mode = 9385 SetFastElementsCapacitySmiMode smi_mode =
9336 value->IsSmi() && HasFastSmiOnlyElements() 9386 value->IsSmi() && HasFastSmiElements()
9337 ? kAllowSmiOnlyElements 9387 ? kAllowSmiElements
9338 : kDontAllowSmiOnlyElements; 9388 : kDontAllowSmiElements;
9339 { MaybeObject* maybe = 9389 { MaybeObject* maybe =
9340 SetFastElementsCapacityAndLength(new_capacity, 9390 SetFastElementsCapacityAndLength(new_capacity,
9341 array_length, 9391 array_length,
9342 set_capacity_mode); 9392 smi_mode);
9343 if (!maybe->To(&new_elements)) return maybe; 9393 if (!maybe->To(&new_elements)) return maybe;
9344 } 9394 }
9345 new_elements->set(index, value); 9395 new_elements->set(index, value);
9396 ValidateElements();
9346 return value; 9397 return value;
9347 } 9398 }
9399
9348 // Finally, set the new element and length. 9400 // Finally, set the new element and length.
9349 ASSERT(elements()->IsFixedArray()); 9401 ASSERT(elements()->IsFixedArray());
9350 backing_store->set(index, value); 9402 backing_store->set(index, value);
9351 if (must_update_array_length) { 9403 if (must_update_array_length) {
9352 JSArray::cast(this)->set_length(Smi::FromInt(array_length)); 9404 JSArray::cast(this)->set_length(Smi::FromInt(array_length));
9353 } 9405 }
9354 return value; 9406 return value;
9355 } 9407 }
9356 9408
9357 9409
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
9461 } 9513 }
9462 9514
9463 // Attempt to put this object back in fast case. 9515 // Attempt to put this object back in fast case.
9464 if (ShouldConvertToFastElements()) { 9516 if (ShouldConvertToFastElements()) {
9465 uint32_t new_length = 0; 9517 uint32_t new_length = 0;
9466 if (IsJSArray()) { 9518 if (IsJSArray()) {
9467 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&new_length)); 9519 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&new_length));
9468 } else { 9520 } else {
9469 new_length = dictionary->max_number_key() + 1; 9521 new_length = dictionary->max_number_key() + 1;
9470 } 9522 }
9471 SetFastElementsCapacityMode set_capacity_mode = FLAG_smi_only_arrays 9523 SetFastElementsCapacitySmiMode smi_mode = FLAG_smi_only_arrays
9472 ? kAllowSmiOnlyElements 9524 ? kAllowSmiElements
9473 : kDontAllowSmiOnlyElements; 9525 : kDontAllowSmiElements;
9474 bool has_smi_only_elements = false; 9526 bool has_smi_only_elements = false;
9475 bool should_convert_to_fast_double_elements = 9527 bool should_convert_to_fast_double_elements =
9476 ShouldConvertToFastDoubleElements(&has_smi_only_elements); 9528 ShouldConvertToFastDoubleElements(&has_smi_only_elements);
9477 if (has_smi_only_elements) { 9529 if (has_smi_only_elements) {
9478 set_capacity_mode = kForceSmiOnlyElements; 9530 smi_mode = kForceSmiElements;
9479 } 9531 }
9480 MaybeObject* result = should_convert_to_fast_double_elements 9532 MaybeObject* result = should_convert_to_fast_double_elements
9481 ? SetFastDoubleElementsCapacityAndLength(new_length, new_length) 9533 ? SetFastDoubleElementsCapacityAndLength(new_length, new_length)
9482 : SetFastElementsCapacityAndLength(new_length, 9534 : SetFastElementsCapacityAndLength(new_length,
9483 new_length, 9535 new_length,
9484 set_capacity_mode); 9536 smi_mode);
9537 ValidateElements();
9485 if (result->IsFailure()) return result; 9538 if (result->IsFailure()) return result;
9486 #ifdef DEBUG 9539 #ifdef DEBUG
9487 if (FLAG_trace_normalization) { 9540 if (FLAG_trace_normalization) {
9488 PrintF("Object elements are fast case again:\n"); 9541 PrintF("Object elements are fast case again:\n");
9489 Print(); 9542 Print();
9490 } 9543 }
9491 #endif 9544 #endif
9492 } 9545 }
9493 return value; 9546 return value;
9494 } 9547 }
(...skipping 18 matching lines...) Expand all
9513 MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index, 9566 MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index,
9514 value, 9567 value,
9515 &found, 9568 &found,
9516 strict_mode); 9569 strict_mode);
9517 if (found) return result; 9570 if (found) return result;
9518 } 9571 }
9519 9572
9520 // If the value object is not a heap number, switch to fast elements and try 9573 // If the value object is not a heap number, switch to fast elements and try
9521 // again. 9574 // again.
9522 bool value_is_smi = value->IsSmi(); 9575 bool value_is_smi = value->IsSmi();
9576 bool introduces_holes = true;
9577 uint32_t length = elms_length;
9578 if (IsJSArray()) {
9579 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length));
9580 introduces_holes = index > length;
9581 } else {
9582 introduces_holes = index >= elms_length;
9583 }
9584
9523 if (!value->IsNumber()) { 9585 if (!value->IsNumber()) {
9524 Object* obj;
9525 uint32_t length = elms_length;
9526 if (IsJSArray()) {
9527 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length));
9528 }
9529 MaybeObject* maybe_obj = SetFastElementsCapacityAndLength( 9586 MaybeObject* maybe_obj = SetFastElementsCapacityAndLength(
9530 elms_length, 9587 elms_length,
9531 length, 9588 length,
9532 kDontAllowSmiOnlyElements); 9589 kDontAllowSmiElements);
9533 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 9590 if (maybe_obj->IsFailure()) return maybe_obj;
9534 return SetFastElement(index, 9591 maybe_obj = SetFastElement(index, value, strict_mode, check_prototype);
9535 value, 9592 if (maybe_obj->IsFailure()) return maybe_obj;
9536 strict_mode, 9593 ValidateElements();
9537 check_prototype); 9594 return maybe_obj;
9538 } 9595 }
9539 9596
9540 double double_value = value_is_smi 9597 double double_value = value_is_smi
9541 ? static_cast<double>(Smi::cast(value)->value()) 9598 ? static_cast<double>(Smi::cast(value)->value())
9542 : HeapNumber::cast(value)->value(); 9599 : HeapNumber::cast(value)->value();
9543 9600
9601 // If the array is growing, and it's not growth by a single element at the
9602 // end, make sure that the ElementsKind is HOLEY.
9603 ElementsKind elements_kind = GetElementsKind();
9604 if (introduces_holes && !IsFastHoleyElementsKind(elements_kind)) {
9605 ElementsKind transitioned_kind = GetHoleyElementsKind(elements_kind);
9606 MaybeObject* maybe = TransitionElementsKind(transitioned_kind);
9607 if (maybe->IsFailure()) return maybe;
9608 }
9609
9544 // Check whether there is extra space in the fixed array. 9610 // Check whether there is extra space in the fixed array.
9545 if (index < elms_length) { 9611 if (index < elms_length) {
9546 FixedDoubleArray* elms = FixedDoubleArray::cast(elements()); 9612 FixedDoubleArray* elms = FixedDoubleArray::cast(elements());
9547 elms->set(index, double_value); 9613 elms->set(index, double_value);
9548 if (IsJSArray()) { 9614 if (IsJSArray()) {
9549 // Update the length of the array if needed. 9615 // Update the length of the array if needed.
9550 uint32_t array_length = 0; 9616 uint32_t array_length = 0;
9551 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length)); 9617 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length));
9552 if (index >= array_length) { 9618 if (index >= array_length) {
9553 JSArray::cast(this)->set_length(Smi::FromInt(index + 1)); 9619 JSArray::cast(this)->set_length(Smi::FromInt(index + 1));
9554 } 9620 }
9555 } 9621 }
9556 return value; 9622 return value;
9557 } 9623 }
9558 9624
9559 // Allow gap in fast case. 9625 // Allow gap in fast case.
9560 if ((index - elms_length) < kMaxGap) { 9626 if ((index - elms_length) < kMaxGap) {
9561 // Try allocating extra space. 9627 // Try allocating extra space.
9562 int new_capacity = NewElementsCapacity(index+1); 9628 int new_capacity = NewElementsCapacity(index+1);
9563 if (!ShouldConvertToSlowElements(new_capacity)) { 9629 if (!ShouldConvertToSlowElements(new_capacity)) {
9564 ASSERT(static_cast<uint32_t>(new_capacity) > index); 9630 ASSERT(static_cast<uint32_t>(new_capacity) > index);
9565 Object* obj; 9631 MaybeObject* maybe_obj =
9566 { MaybeObject* maybe_obj = 9632 SetFastDoubleElementsCapacityAndLength(new_capacity, index + 1);
9567 SetFastDoubleElementsCapacityAndLength(new_capacity, 9633 if (maybe_obj->IsFailure()) return maybe_obj;
9568 index + 1);
9569 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
9570 }
9571 FixedDoubleArray::cast(elements())->set(index, double_value); 9634 FixedDoubleArray::cast(elements())->set(index, double_value);
9635 ValidateElements();
9572 return value; 9636 return value;
9573 } 9637 }
9574 } 9638 }
9575 9639
9576 // Otherwise default to slow case. 9640 // Otherwise default to slow case.
9577 ASSERT(HasFastDoubleElements()); 9641 ASSERT(HasFastDoubleElements());
9578 ASSERT(map()->has_fast_double_elements()); 9642 ASSERT(map()->has_fast_double_elements());
9579 ASSERT(elements()->IsFixedDoubleArray()); 9643 ASSERT(elements()->IsFixedDoubleArray());
9580 Object* obj; 9644 Object* obj;
9581 { MaybeObject* maybe_obj = NormalizeElements(); 9645 { MaybeObject* maybe_obj = NormalizeElements();
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
9705 Object* value, 9769 Object* value,
9706 PropertyAttributes attr, 9770 PropertyAttributes attr,
9707 StrictModeFlag strict_mode, 9771 StrictModeFlag strict_mode,
9708 bool check_prototype, 9772 bool check_prototype,
9709 SetPropertyMode set_mode) { 9773 SetPropertyMode set_mode) {
9710 ASSERT(HasDictionaryElements() || 9774 ASSERT(HasDictionaryElements() ||
9711 HasDictionaryArgumentsElements() || 9775 HasDictionaryArgumentsElements() ||
9712 (attr & (DONT_DELETE | DONT_ENUM | READ_ONLY)) == 0); 9776 (attr & (DONT_DELETE | DONT_ENUM | READ_ONLY)) == 0);
9713 Isolate* isolate = GetIsolate(); 9777 Isolate* isolate = GetIsolate();
9714 switch (GetElementsKind()) { 9778 switch (GetElementsKind()) {
9715 case FAST_SMI_ONLY_ELEMENTS: 9779 case FAST_SMI_ELEMENTS:
9716 case FAST_ELEMENTS: 9780 case FAST_ELEMENTS:
9781 case FAST_HOLEY_SMI_ELEMENTS:
9782 case FAST_HOLEY_ELEMENTS:
9717 return SetFastElement(index, value, strict_mode, check_prototype); 9783 return SetFastElement(index, value, strict_mode, check_prototype);
9718 case FAST_DOUBLE_ELEMENTS: 9784 case FAST_DOUBLE_ELEMENTS:
9785 case FAST_HOLEY_DOUBLE_ELEMENTS:
9719 return SetFastDoubleElement(index, value, strict_mode, check_prototype); 9786 return SetFastDoubleElement(index, value, strict_mode, check_prototype);
9720 case EXTERNAL_PIXEL_ELEMENTS: { 9787 case EXTERNAL_PIXEL_ELEMENTS: {
9721 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements()); 9788 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements());
9722 return pixels->SetValue(index, value); 9789 return pixels->SetValue(index, value);
9723 } 9790 }
9724 case EXTERNAL_BYTE_ELEMENTS: { 9791 case EXTERNAL_BYTE_ELEMENTS: {
9725 ExternalByteArray* array = ExternalByteArray::cast(elements()); 9792 ExternalByteArray* array = ExternalByteArray::cast(elements());
9726 return array->SetValue(index, value); 9793 return array->SetValue(index, value);
9727 } 9794 }
9728 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: { 9795 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: {
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
9799 ElementsKind to_kind) { 9866 ElementsKind to_kind) {
9800 CALL_HEAP_FUNCTION(object->GetIsolate(), 9867 CALL_HEAP_FUNCTION(object->GetIsolate(),
9801 object->TransitionElementsKind(to_kind), 9868 object->TransitionElementsKind(to_kind),
9802 Object); 9869 Object);
9803 } 9870 }
9804 9871
9805 9872
9806 MaybeObject* JSObject::TransitionElementsKind(ElementsKind to_kind) { 9873 MaybeObject* JSObject::TransitionElementsKind(ElementsKind to_kind) {
9807 ElementsKind from_kind = map()->elements_kind(); 9874 ElementsKind from_kind = map()->elements_kind();
9808 9875
9876 if (IsFastHoleyElementsKind(from_kind)) {
9877 to_kind = GetHoleyElementsKind(to_kind);
9878 }
9879
9809 Isolate* isolate = GetIsolate(); 9880 Isolate* isolate = GetIsolate();
9810 if ((from_kind == FAST_SMI_ONLY_ELEMENTS || 9881 if (elements() == isolate->heap()->empty_fixed_array() ||
9811 elements() == isolate->heap()->empty_fixed_array()) && 9882 (IsFastSmiOrObjectElementsKind(from_kind) &&
9812 to_kind == FAST_ELEMENTS) { 9883 IsFastSmiOrObjectElementsKind(to_kind)) ||
9813 ASSERT(from_kind != FAST_ELEMENTS); 9884 (from_kind == FAST_DOUBLE_ELEMENTS &&
9885 to_kind == FAST_HOLEY_DOUBLE_ELEMENTS)) {
9886 ASSERT(from_kind != TERMINAL_FAST_ELEMENTS_KIND);
9887 // No change is needed to the elements() buffer, the transition
9888 // only requires a map change.
9814 MaybeObject* maybe_new_map = GetElementsTransitionMap(isolate, to_kind); 9889 MaybeObject* maybe_new_map = GetElementsTransitionMap(isolate, to_kind);
9815 Map* new_map; 9890 Map* new_map;
9816 if (!maybe_new_map->To(&new_map)) return maybe_new_map; 9891 if (!maybe_new_map->To(&new_map)) return maybe_new_map;
9817 set_map(new_map); 9892 set_map(new_map);
9818 if (FLAG_trace_elements_transitions) { 9893 if (FLAG_trace_elements_transitions) {
9819 FixedArrayBase* elms = FixedArrayBase::cast(elements()); 9894 FixedArrayBase* elms = FixedArrayBase::cast(elements());
9820 PrintElementsTransition(stdout, from_kind, elms, to_kind, elms); 9895 PrintElementsTransition(stdout, from_kind, elms, to_kind, elms);
9821 } 9896 }
9822 return this; 9897 return this;
9823 } 9898 }
9824 9899
9825 FixedArrayBase* elms = FixedArrayBase::cast(elements()); 9900 FixedArrayBase* elms = FixedArrayBase::cast(elements());
9826 uint32_t capacity = static_cast<uint32_t>(elms->length()); 9901 uint32_t capacity = static_cast<uint32_t>(elms->length());
9827 uint32_t length = capacity; 9902 uint32_t length = capacity;
9828 9903
9829 if (IsJSArray()) { 9904 if (IsJSArray()) {
9830 Object* raw_length = JSArray::cast(this)->length(); 9905 Object* raw_length = JSArray::cast(this)->length();
9831 if (raw_length->IsUndefined()) { 9906 if (raw_length->IsUndefined()) {
9832 // If length is undefined, then JSArray is being initialized and has no 9907 // If length is undefined, then JSArray is being initialized and has no
9833 // elements, assume a length of zero. 9908 // elements, assume a length of zero.
9834 length = 0; 9909 length = 0;
9835 } else { 9910 } else {
9836 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length)); 9911 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length));
9837 } 9912 }
9838 } 9913 }
9839 9914
9840 if (from_kind == FAST_SMI_ONLY_ELEMENTS && 9915 if (IsFastSmiElementsKind(from_kind) &&
9841 to_kind == FAST_DOUBLE_ELEMENTS) { 9916 IsFastDoubleElementsKind(to_kind)) {
9842 MaybeObject* maybe_result = 9917 MaybeObject* maybe_result =
9843 SetFastDoubleElementsCapacityAndLength(capacity, length); 9918 SetFastDoubleElementsCapacityAndLength(capacity, length);
9844 if (maybe_result->IsFailure()) return maybe_result; 9919 if (maybe_result->IsFailure()) return maybe_result;
9920 ValidateElements();
9845 return this; 9921 return this;
9846 } 9922 }
9847 9923
9848 if (from_kind == FAST_DOUBLE_ELEMENTS && to_kind == FAST_ELEMENTS) { 9924 if (IsFastDoubleElementsKind(from_kind) &&
9925 IsFastObjectElementsKind(to_kind)) {
9849 MaybeObject* maybe_result = SetFastElementsCapacityAndLength( 9926 MaybeObject* maybe_result = SetFastElementsCapacityAndLength(
9850 capacity, length, kDontAllowSmiOnlyElements); 9927 capacity, length, kDontAllowSmiElements);
9851 if (maybe_result->IsFailure()) return maybe_result; 9928 if (maybe_result->IsFailure()) return maybe_result;
9929 ValidateElements();
9852 return this; 9930 return this;
9853 } 9931 }
9854 9932
9855 // This method should never be called for any other case than the ones 9933 // This method should never be called for any other case than the ones
9856 // handled above. 9934 // handled above.
9857 UNREACHABLE(); 9935 UNREACHABLE();
9858 return GetIsolate()->heap()->null_value(); 9936 return GetIsolate()->heap()->null_value();
9859 } 9937 }
9860 9938
9861 9939
9862 // static 9940 // static
9863 bool Map::IsValidElementsTransition(ElementsKind from_kind, 9941 bool Map::IsValidElementsTransition(ElementsKind from_kind,
9864 ElementsKind to_kind) { 9942 ElementsKind to_kind) {
9865 return 9943 // Transitions can't go backwards.
9866 (from_kind == FAST_SMI_ONLY_ELEMENTS && 9944 if (!IsMoreGeneralElementsKindTransition(from_kind, to_kind)) {
9867 (to_kind == FAST_DOUBLE_ELEMENTS || to_kind == FAST_ELEMENTS)) || 9945 return false;
9868 (from_kind == FAST_DOUBLE_ELEMENTS && to_kind == FAST_ELEMENTS); 9946 }
9947
9948 // Transitions from HOLEY -> PACKED are not allowed.
9949 return !IsFastHoleyElementsKind(from_kind) ||
9950 IsFastHoleyElementsKind(to_kind);
9869 } 9951 }
9870 9952
9871 9953
9872 MaybeObject* JSArray::JSArrayUpdateLengthFromIndex(uint32_t index, 9954 MaybeObject* JSArray::JSArrayUpdateLengthFromIndex(uint32_t index,
9873 Object* value) { 9955 Object* value) {
9874 uint32_t old_len = 0; 9956 uint32_t old_len = 0;
9875 CHECK(length()->ToArrayIndex(&old_len)); 9957 CHECK(length()->ToArrayIndex(&old_len));
9876 // Check to see if we need to update the length. For now, we make 9958 // Check to see if we need to update the length. For now, we make
9877 // sure that the length stays within 32-bits (unsigned). 9959 // sure that the length stays within 32-bits (unsigned).
9878 if (index >= old_len && index != 0xffffffff) { 9960 if (index >= old_len && index != 0xffffffff) {
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
9949 FixedArray::cast(FixedArray::cast(backing_store_base)->get(1)); 10031 FixedArray::cast(FixedArray::cast(backing_store_base)->get(1));
9950 backing_store = FixedArray::cast(backing_store_base); 10032 backing_store = FixedArray::cast(backing_store_base);
9951 if (backing_store->IsDictionary()) { 10033 if (backing_store->IsDictionary()) {
9952 SeededNumberDictionary* dictionary = 10034 SeededNumberDictionary* dictionary =
9953 SeededNumberDictionary::cast(backing_store); 10035 SeededNumberDictionary::cast(backing_store);
9954 *capacity = dictionary->Capacity(); 10036 *capacity = dictionary->Capacity();
9955 *used = dictionary->NumberOfElements(); 10037 *used = dictionary->NumberOfElements();
9956 break; 10038 break;
9957 } 10039 }
9958 // Fall through. 10040 // Fall through.
9959 case FAST_SMI_ONLY_ELEMENTS: 10041 case FAST_SMI_ELEMENTS:
9960 case FAST_ELEMENTS: 10042 case FAST_ELEMENTS:
10043 case FAST_HOLEY_SMI_ELEMENTS:
10044 case FAST_HOLEY_ELEMENTS:
9961 backing_store = FixedArray::cast(backing_store_base); 10045 backing_store = FixedArray::cast(backing_store_base);
9962 *capacity = backing_store->length(); 10046 *capacity = backing_store->length();
9963 for (int i = 0; i < *capacity; ++i) { 10047 for (int i = 0; i < *capacity; ++i) {
9964 if (!backing_store->get(i)->IsTheHole()) ++(*used); 10048 if (!backing_store->get(i)->IsTheHole()) ++(*used);
9965 } 10049 }
9966 break; 10050 break;
9967 case DICTIONARY_ELEMENTS: { 10051 case DICTIONARY_ELEMENTS: {
9968 SeededNumberDictionary* dictionary = 10052 SeededNumberDictionary* dictionary =
9969 SeededNumberDictionary::cast(FixedArray::cast(elements())); 10053 SeededNumberDictionary::cast(FixedArray::cast(elements()));
9970 *capacity = dictionary->Capacity(); 10054 *capacity = dictionary->Capacity();
9971 *used = dictionary->NumberOfElements(); 10055 *used = dictionary->NumberOfElements();
9972 break; 10056 break;
9973 } 10057 }
9974 case FAST_DOUBLE_ELEMENTS: { 10058 case FAST_DOUBLE_ELEMENTS:
10059 case FAST_HOLEY_DOUBLE_ELEMENTS: {
9975 FixedDoubleArray* elms = FixedDoubleArray::cast(elements()); 10060 FixedDoubleArray* elms = FixedDoubleArray::cast(elements());
9976 *capacity = elms->length(); 10061 *capacity = elms->length();
9977 for (int i = 0; i < *capacity; i++) { 10062 for (int i = 0; i < *capacity; i++) {
9978 if (!elms->is_the_hole(i)) ++(*used); 10063 if (!elms->is_the_hole(i)) ++(*used);
9979 } 10064 }
9980 break; 10065 break;
9981 } 10066 }
9982 case EXTERNAL_BYTE_ELEMENTS: 10067 case EXTERNAL_BYTE_ELEMENTS:
9983 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 10068 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
9984 case EXTERNAL_SHORT_ELEMENTS: 10069 case EXTERNAL_SHORT_ELEMENTS:
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after
10234 if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) { 10319 if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) {
10235 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS); 10320 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS);
10236 return false; 10321 return false;
10237 } 10322 }
10238 } 10323 }
10239 10324
10240 // Handle [] on String objects. 10325 // Handle [] on String objects.
10241 if (this->IsStringObjectWithCharacterAt(index)) return true; 10326 if (this->IsStringObjectWithCharacterAt(index)) return true;
10242 10327
10243 switch (GetElementsKind()) { 10328 switch (GetElementsKind()) {
10244 case FAST_SMI_ONLY_ELEMENTS: 10329 case FAST_SMI_ELEMENTS:
10245 case FAST_ELEMENTS: { 10330 case FAST_ELEMENTS:
10246 uint32_t length = IsJSArray() ? 10331 case FAST_HOLEY_SMI_ELEMENTS:
10332 case FAST_HOLEY_ELEMENTS: {
10333 uint32_t length = IsJSArray() ?
10247 static_cast<uint32_t>( 10334 static_cast<uint32_t>(
10248 Smi::cast(JSArray::cast(this)->length())->value()) : 10335 Smi::cast(JSArray::cast(this)->length())->value()) :
10249 static_cast<uint32_t>(FixedArray::cast(elements())->length()); 10336 static_cast<uint32_t>(FixedArray::cast(elements())->length());
10250 return (index < length) && 10337 return (index < length) &&
10251 !FixedArray::cast(elements())->get(index)->IsTheHole(); 10338 !FixedArray::cast(elements())->get(index)->IsTheHole();
10252 } 10339 }
10253 case FAST_DOUBLE_ELEMENTS: { 10340 case FAST_DOUBLE_ELEMENTS:
10341 case FAST_HOLEY_DOUBLE_ELEMENTS: {
10254 uint32_t length = IsJSArray() ? 10342 uint32_t length = IsJSArray() ?
10255 static_cast<uint32_t>( 10343 static_cast<uint32_t>(
10256 Smi::cast(JSArray::cast(this)->length())->value()) : 10344 Smi::cast(JSArray::cast(this)->length())->value()) :
10257 static_cast<uint32_t>(FixedDoubleArray::cast(elements())->length()); 10345 static_cast<uint32_t>(FixedDoubleArray::cast(elements())->length());
10258 return (index < length) && 10346 return (index < length) &&
10259 !FixedDoubleArray::cast(elements())->is_the_hole(index); 10347 !FixedDoubleArray::cast(elements())->is_the_hole(index);
10260 break; 10348 break;
10261 } 10349 }
10262 case EXTERNAL_PIXEL_ELEMENTS: { 10350 case EXTERNAL_PIXEL_ELEMENTS: {
10263 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements()); 10351 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements());
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after
10443 } 10531 }
10444 10532
10445 10533
10446 int JSObject::NumberOfLocalElements(PropertyAttributes filter) { 10534 int JSObject::NumberOfLocalElements(PropertyAttributes filter) {
10447 return GetLocalElementKeys(NULL, filter); 10535 return GetLocalElementKeys(NULL, filter);
10448 } 10536 }
10449 10537
10450 10538
10451 int JSObject::NumberOfEnumElements() { 10539 int JSObject::NumberOfEnumElements() {
10452 // Fast case for objects with no elements. 10540 // Fast case for objects with no elements.
10453 if (!IsJSValue() && HasFastElements()) { 10541 if (!IsJSValue() && HasFastObjectElements()) {
10454 uint32_t length = IsJSArray() ? 10542 uint32_t length = IsJSArray() ?
10455 static_cast<uint32_t>( 10543 static_cast<uint32_t>(
10456 Smi::cast(JSArray::cast(this)->length())->value()) : 10544 Smi::cast(JSArray::cast(this)->length())->value()) :
10457 static_cast<uint32_t>(FixedArray::cast(elements())->length()); 10545 static_cast<uint32_t>(FixedArray::cast(elements())->length());
10458 if (length == 0) return 0; 10546 if (length == 0) return 0;
10459 } 10547 }
10460 // Compute the number of enumerable elements. 10548 // Compute the number of enumerable elements.
10461 return NumberOfLocalElements(static_cast<PropertyAttributes>(DONT_ENUM)); 10549 return NumberOfLocalElements(static_cast<PropertyAttributes>(DONT_ENUM));
10462 } 10550 }
10463 10551
10464 10552
10465 int JSObject::GetLocalElementKeys(FixedArray* storage, 10553 int JSObject::GetLocalElementKeys(FixedArray* storage,
10466 PropertyAttributes filter) { 10554 PropertyAttributes filter) {
10467 int counter = 0; 10555 int counter = 0;
10468 switch (GetElementsKind()) { 10556 switch (GetElementsKind()) {
10469 case FAST_SMI_ONLY_ELEMENTS: 10557 case FAST_SMI_ELEMENTS:
10470 case FAST_ELEMENTS: { 10558 case FAST_ELEMENTS:
10559 case FAST_HOLEY_SMI_ELEMENTS:
10560 case FAST_HOLEY_ELEMENTS: {
10471 int length = IsJSArray() ? 10561 int length = IsJSArray() ?
10472 Smi::cast(JSArray::cast(this)->length())->value() : 10562 Smi::cast(JSArray::cast(this)->length())->value() :
10473 FixedArray::cast(elements())->length(); 10563 FixedArray::cast(elements())->length();
10474 for (int i = 0; i < length; i++) { 10564 for (int i = 0; i < length; i++) {
10475 if (!FixedArray::cast(elements())->get(i)->IsTheHole()) { 10565 if (!FixedArray::cast(elements())->get(i)->IsTheHole()) {
10476 if (storage != NULL) { 10566 if (storage != NULL) {
10477 storage->set(counter, Smi::FromInt(i)); 10567 storage->set(counter, Smi::FromInt(i));
10478 } 10568 }
10479 counter++; 10569 counter++;
10480 } 10570 }
10481 } 10571 }
10482 ASSERT(!storage || storage->length() >= counter); 10572 ASSERT(!storage || storage->length() >= counter);
10483 break; 10573 break;
10484 } 10574 }
10485 case FAST_DOUBLE_ELEMENTS: { 10575 case FAST_DOUBLE_ELEMENTS:
10576 case FAST_HOLEY_DOUBLE_ELEMENTS: {
10486 int length = IsJSArray() ? 10577 int length = IsJSArray() ?
10487 Smi::cast(JSArray::cast(this)->length())->value() : 10578 Smi::cast(JSArray::cast(this)->length())->value() :
10488 FixedDoubleArray::cast(elements())->length(); 10579 FixedDoubleArray::cast(elements())->length();
10489 for (int i = 0; i < length; i++) { 10580 for (int i = 0; i < length; i++) {
10490 if (!FixedDoubleArray::cast(elements())->is_the_hole(i)) { 10581 if (!FixedDoubleArray::cast(elements())->is_the_hole(i)) {
10491 if (storage != NULL) { 10582 if (storage != NULL) {
10492 storage->set(counter, Smi::FromInt(i)); 10583 storage->set(counter, Smi::FromInt(i));
10493 } 10584 }
10494 counter++; 10585 counter++;
10495 } 10586 }
(...skipping 912 matching lines...) Expand 10 before | Expand all | Expand 10 after
11408 // Convert to fast elements containing only the existing properties. 11499 // Convert to fast elements containing only the existing properties.
11409 // Ordering is irrelevant, since we are going to sort anyway. 11500 // Ordering is irrelevant, since we are going to sort anyway.
11410 SeededNumberDictionary* dict = element_dictionary(); 11501 SeededNumberDictionary* dict = element_dictionary();
11411 if (IsJSArray() || dict->requires_slow_elements() || 11502 if (IsJSArray() || dict->requires_slow_elements() ||
11412 dict->max_number_key() >= limit) { 11503 dict->max_number_key() >= limit) {
11413 return PrepareSlowElementsForSort(limit); 11504 return PrepareSlowElementsForSort(limit);
11414 } 11505 }
11415 // Convert to fast elements. 11506 // Convert to fast elements.
11416 11507
11417 Object* obj; 11508 Object* obj;
11418 { MaybeObject* maybe_obj = GetElementsTransitionMap(GetIsolate(), 11509 MaybeObject* maybe_obj = GetElementsTransitionMap(GetIsolate(),
11419 FAST_ELEMENTS); 11510 FAST_HOLEY_ELEMENTS);
11420 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 11511 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
11421 }
11422 Map* new_map = Map::cast(obj); 11512 Map* new_map = Map::cast(obj);
11423 11513
11424 PretenureFlag tenure = heap->InNewSpace(this) ? NOT_TENURED: TENURED; 11514 PretenureFlag tenure = heap->InNewSpace(this) ? NOT_TENURED: TENURED;
11425 Object* new_array; 11515 Object* new_array;
11426 { MaybeObject* maybe_new_array = 11516 { MaybeObject* maybe_new_array =
11427 heap->AllocateFixedArray(dict->NumberOfElements(), tenure); 11517 heap->AllocateFixedArray(dict->NumberOfElements(), tenure);
11428 if (!maybe_new_array->ToObject(&new_array)) return maybe_new_array; 11518 if (!maybe_new_array->ToObject(&new_array)) return maybe_new_array;
11429 } 11519 }
11430 FixedArray* fast_elements = FixedArray::cast(new_array); 11520 FixedArray* fast_elements = FixedArray::cast(new_array);
11431 dict->CopyValuesTo(fast_elements); 11521 dict->CopyValuesTo(fast_elements);
11522 ValidateElements();
11432 11523
11433 set_map(new_map); 11524 set_map_and_elements(new_map, fast_elements);
11434 set_elements(fast_elements);
11435 } else if (HasExternalArrayElements()) { 11525 } else if (HasExternalArrayElements()) {
11436 // External arrays cannot have holes or undefined elements. 11526 // External arrays cannot have holes or undefined elements.
11437 return Smi::FromInt(ExternalArray::cast(elements())->length()); 11527 return Smi::FromInt(ExternalArray::cast(elements())->length());
11438 } else if (!HasFastDoubleElements()) { 11528 } else if (!HasFastDoubleElements()) {
11439 Object* obj; 11529 Object* obj;
11440 { MaybeObject* maybe_obj = EnsureWritableFastElements(); 11530 { MaybeObject* maybe_obj = EnsureWritableFastElements();
11441 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 11531 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
11442 } 11532 }
11443 } 11533 }
11444 ASSERT(HasFastTypeElements() || HasFastDoubleElements()); 11534 ASSERT(HasFastSmiOrObjectElements() || HasFastDoubleElements());
11445 11535
11446 // Collect holes at the end, undefined before that and the rest at the 11536 // Collect holes at the end, undefined before that and the rest at the
11447 // start, and return the number of non-hole, non-undefined values. 11537 // start, and return the number of non-hole, non-undefined values.
11448 11538
11449 FixedArrayBase* elements_base = FixedArrayBase::cast(this->elements()); 11539 FixedArrayBase* elements_base = FixedArrayBase::cast(this->elements());
11450 uint32_t elements_length = static_cast<uint32_t>(elements_base->length()); 11540 uint32_t elements_length = static_cast<uint32_t>(elements_base->length());
11451 if (limit > elements_length) { 11541 if (limit > elements_length) {
11452 limit = elements_length ; 11542 limit = elements_length ;
11453 } 11543 }
11454 if (limit == 0) { 11544 if (limit == 0) {
(...skipping 1656 matching lines...) Expand 10 before | Expand all | Expand 10 after
13111 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); 13201 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER);
13112 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); 13202 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER);
13113 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); 13203 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER);
13114 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); 13204 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER);
13115 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); 13205 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER);
13116 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); 13206 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER);
13117 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); 13207 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER);
13118 } 13208 }
13119 13209
13120 } } // namespace v8::internal 13210 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698