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

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: 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
« 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 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 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
4438 accessors->SetComponents(getter, setter); 4454 accessors->SetComponents(getter, setter);
4439 return SetPropertyCallback(name, accessors, attributes); 4455 return SetPropertyCallback(name, accessors, attributes);
4440 } 4456 }
4441 4457
4442 4458
4443 bool JSObject::CanSetCallback(String* name) { 4459 bool JSObject::CanSetCallback(String* name) {
4444 ASSERT(!IsAccessCheckNeeded() || 4460 ASSERT(!IsAccessCheckNeeded() ||
4445 GetIsolate()->MayNamedAccess(this, name, v8::ACCESS_SET)); 4461 GetIsolate()->MayNamedAccess(this, name, v8::ACCESS_SET));
4446 4462
4447 // Check if there is an API defined callback object which prohibits 4463 // Check if there is an API defined callback object which prohibits
4448 // callback overwriting in this object or it's prototype chain. 4464 // callback overwriting in this object or its prototype chain.
4449 // This mechanism is needed for instance in a browser setting, where 4465 // This mechanism is needed for instance in a browser setting, where
4450 // certain accessors such as window.location should not be allowed 4466 // certain accessors such as window.location should not be allowed
4451 // to be overwritten because allowing overwriting could potentially 4467 // to be overwritten because allowing overwriting could potentially
4452 // cause security problems. 4468 // cause security problems.
4453 LookupResult callback_result(GetIsolate()); 4469 LookupResult callback_result(GetIsolate());
4454 LookupCallback(name, &callback_result); 4470 LookupCallback(name, &callback_result);
4455 if (callback_result.IsProperty()) { 4471 if (callback_result.IsProperty()) {
4456 Object* obj = callback_result.GetCallbackObject(); 4472 Object* obj = callback_result.GetCallbackObject();
4457 if (obj->IsAccessorInfo() && 4473 if (obj->IsAccessorInfo() &&
4458 AccessorInfo::cast(obj)->prohibits_overwriting()) { 4474 AccessorInfo::cast(obj)->prohibits_overwriting()) {
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
4609 } 4625 }
4610 4626
4611 uint32_t index = 0; 4627 uint32_t index = 0;
4612 bool is_element = name->AsArrayIndex(&index); 4628 bool is_element = name->AsArrayIndex(&index);
4613 4629
4614 if (is_element) { 4630 if (is_element) {
4615 if (IsJSArray()) return isolate->heap()->undefined_value(); 4631 if (IsJSArray()) return isolate->heap()->undefined_value();
4616 4632
4617 // Accessors overwrite previous callbacks (cf. with getters/setters). 4633 // Accessors overwrite previous callbacks (cf. with getters/setters).
4618 switch (GetElementsKind()) { 4634 switch (GetElementsKind()) {
4619 case FAST_SMI_ONLY_ELEMENTS: 4635 case FAST_SMI_ELEMENTS:
4620 case FAST_ELEMENTS: 4636 case FAST_ELEMENTS:
4621 case FAST_DOUBLE_ELEMENTS: 4637 case FAST_DOUBLE_ELEMENTS:
4638 case FAST_HOLEY_SMI_ELEMENTS:
4639 case FAST_HOLEY_ELEMENTS:
4640 case FAST_HOLEY_DOUBLE_ELEMENTS:
4622 break; 4641 break;
4623 case EXTERNAL_PIXEL_ELEMENTS: 4642 case EXTERNAL_PIXEL_ELEMENTS:
4624 case EXTERNAL_BYTE_ELEMENTS: 4643 case EXTERNAL_BYTE_ELEMENTS:
4625 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 4644 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
4626 case EXTERNAL_SHORT_ELEMENTS: 4645 case EXTERNAL_SHORT_ELEMENTS:
4627 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 4646 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
4628 case EXTERNAL_INT_ELEMENTS: 4647 case EXTERNAL_INT_ELEMENTS:
4629 case EXTERNAL_UNSIGNED_INT_ELEMENTS: 4648 case EXTERNAL_UNSIGNED_INT_ELEMENTS:
4630 case EXTERNAL_FLOAT_ELEMENTS: 4649 case EXTERNAL_FLOAT_ELEMENTS:
4631 case EXTERNAL_DOUBLE_ELEMENTS: 4650 case EXTERNAL_DOUBLE_ELEMENTS:
(...skipping 3768 matching lines...) Expand 10 before | Expand all | Expand 10 after
8400 PrintF("RelocInfo (size = %d)\n", relocation_size()); 8419 PrintF("RelocInfo (size = %d)\n", relocation_size());
8401 for (RelocIterator it(this); !it.done(); it.next()) it.rinfo()->Print(out); 8420 for (RelocIterator it(this); !it.done(); it.next()) it.rinfo()->Print(out);
8402 PrintF(out, "\n"); 8421 PrintF(out, "\n");
8403 } 8422 }
8404 #endif // ENABLE_DISASSEMBLER 8423 #endif // ENABLE_DISASSEMBLER
8405 8424
8406 8425
8407 MaybeObject* JSObject::SetFastElementsCapacityAndLength( 8426 MaybeObject* JSObject::SetFastElementsCapacityAndLength(
8408 int capacity, 8427 int capacity,
8409 int length, 8428 int length,
8410 SetFastElementsCapacityMode set_capacity_mode) { 8429 SetFastElementsCapacitySmiMode smi_mode) {
8411 Heap* heap = GetHeap(); 8430 Heap* heap = GetHeap();
8412 // We should never end in here with a pixel or external array. 8431 // We should never end in here with a pixel or external array.
8413 ASSERT(!HasExternalArrayElements()); 8432 ASSERT(!HasExternalArrayElements());
8414 8433
8415 // Allocate a new fast elements backing store. 8434 // Allocate a new fast elements backing store.
8416 FixedArray* new_elements; 8435 FixedArray* new_elements;
8417 { MaybeObject* maybe = heap->AllocateFixedArrayWithHoles(capacity); 8436 { MaybeObject* maybe = heap->AllocateFixedArrayWithHoles(capacity);
8418 if (!maybe->To(&new_elements)) return maybe; 8437 if (!maybe->To(&new_elements)) return maybe;
8419 } 8438 }
8420 8439
8421 // Find the new map to use for this object if there is a map change. 8440 ElementsKind elements_kind = GetElementsKind();
8422 Map* new_map = NULL; 8441 ElementsKind new_elements_kind;
8423 if (elements()->map() != heap->non_strict_arguments_elements_map()) { 8442 // The resized array has FAST_*_SMI_ELEMENTS if the capacity mode forces it,
8424 // The resized array has FAST_SMI_ONLY_ELEMENTS if the capacity mode forces 8443 // or if it's allowed and the old elements array contained only SMIs.
8425 // it, or if it's allowed and the old elements array contained only SMIs. 8444 bool has_fast_smi_elements =
8426 bool has_fast_smi_only_elements = 8445 (smi_mode == kForceSmiElements) ||
8427 (set_capacity_mode == kForceSmiOnlyElements) || 8446 ((smi_mode == kAllowSmiElements) && HasFastSmiElements());
8428 ((set_capacity_mode == kAllowSmiOnlyElements) && 8447 if (has_fast_smi_elements) {
8429 (elements()->map()->has_fast_smi_only_elements() || 8448 if (IsHoleyElementsKind(elements_kind)) {
8430 elements() == heap->empty_fixed_array())); 8449 new_elements_kind = FAST_HOLEY_SMI_ELEMENTS;
8431 ElementsKind elements_kind = has_fast_smi_only_elements 8450 } else {
8432 ? FAST_SMI_ONLY_ELEMENTS 8451 new_elements_kind = FAST_SMI_ELEMENTS;
8433 : FAST_ELEMENTS; 8452 }
8434 MaybeObject* maybe = GetElementsTransitionMap(GetIsolate(), elements_kind); 8453 } else {
8435 if (!maybe->To(&new_map)) return maybe; 8454 if (IsHoleyElementsKind(elements_kind)) {
8455 new_elements_kind = FAST_HOLEY_ELEMENTS;
8456 } else {
8457 new_elements_kind = FAST_ELEMENTS;
8458 }
8436 } 8459 }
8437
8438 FixedArrayBase* old_elements = elements(); 8460 FixedArrayBase* old_elements = elements();
8439 ElementsKind elements_kind = GetElementsKind();
8440 ElementsAccessor* accessor = ElementsAccessor::ForKind(elements_kind); 8461 ElementsAccessor* accessor = ElementsAccessor::ForKind(elements_kind);
8441 ElementsKind to_kind = (elements_kind == FAST_SMI_ONLY_ELEMENTS)
8442 ? FAST_SMI_ONLY_ELEMENTS
8443 : FAST_ELEMENTS;
8444 { MaybeObject* maybe_obj = 8462 { MaybeObject* maybe_obj =
8445 accessor->CopyElements(this, new_elements, to_kind); 8463 accessor->CopyElements(this, new_elements, new_elements_kind);
8446 if (maybe_obj->IsFailure()) return maybe_obj; 8464 if (maybe_obj->IsFailure()) return maybe_obj;
8447 } 8465 }
8448 if (elements_kind != NON_STRICT_ARGUMENTS_ELEMENTS) { 8466 if (elements_kind != NON_STRICT_ARGUMENTS_ELEMENTS) {
8467 Map* new_map = map();
8468 if (new_elements_kind != elements_kind) {
8469 MaybeObject* maybe =
8470 GetElementsTransitionMap(GetIsolate(), new_elements_kind);
8471 if (!maybe->To(&new_map)) return maybe;
8472 }
8473 ValidateElements();
8449 set_map_and_elements(new_map, new_elements); 8474 set_map_and_elements(new_map, new_elements);
8450 } else { 8475 } else {
8451 FixedArray* parameter_map = FixedArray::cast(old_elements); 8476 FixedArray* parameter_map = FixedArray::cast(old_elements);
8452 parameter_map->set(1, new_elements); 8477 parameter_map->set(1, new_elements);
8453 } 8478 }
8454 8479
8455 if (FLAG_trace_elements_transitions) { 8480 if (FLAG_trace_elements_transitions) {
8456 PrintElementsTransition(stdout, elements_kind, old_elements, 8481 PrintElementsTransition(stdout, elements_kind, old_elements,
8457 GetElementsKind(), new_elements); 8482 GetElementsKind(), new_elements);
8458 } 8483 }
8459 8484
8460 // Update the length if necessary.
8461 if (IsJSArray()) { 8485 if (IsJSArray()) {
8462 JSArray::cast(this)->set_length(Smi::FromInt(length)); 8486 JSArray::cast(this)->set_length(Smi::FromInt(length));
8463 } 8487 }
8464
8465 return new_elements; 8488 return new_elements;
8466 } 8489 }
8467 8490
8468 8491
8469 MaybeObject* JSObject::SetFastDoubleElementsCapacityAndLength( 8492 MaybeObject* JSObject::SetFastDoubleElementsCapacityAndLength(
8470 int capacity, 8493 int capacity,
8471 int length) { 8494 int length) {
8472 Heap* heap = GetHeap(); 8495 Heap* heap = GetHeap();
8473 // We should never end in here with a pixel or external array. 8496 // We should never end in here with a pixel or external array.
8474 ASSERT(!HasExternalArrayElements()); 8497 ASSERT(!HasExternalArrayElements());
8475 8498
8476 FixedArrayBase* elems; 8499 FixedArrayBase* elems;
8477 { MaybeObject* maybe_obj = 8500 { MaybeObject* maybe_obj =
8478 heap->AllocateUninitializedFixedDoubleArray(capacity); 8501 heap->AllocateUninitializedFixedDoubleArray(capacity);
8479 if (!maybe_obj->To(&elems)) return maybe_obj; 8502 if (!maybe_obj->To(&elems)) return maybe_obj;
8480 } 8503 }
8481 8504
8505 ElementsKind elements_kind = GetElementsKind();
8506 ElementsKind new_elements_kind = elements_kind;
8507 if (IsHoleyElementsKind(elements_kind)) {
8508 new_elements_kind = FAST_HOLEY_DOUBLE_ELEMENTS;
8509 } else {
8510 new_elements_kind = FAST_DOUBLE_ELEMENTS;
8511 }
8512
8482 Map* new_map; 8513 Map* new_map;
8483 { MaybeObject* maybe_obj = 8514 { MaybeObject* maybe_obj =
8484 GetElementsTransitionMap(heap->isolate(), FAST_DOUBLE_ELEMENTS); 8515 GetElementsTransitionMap(heap->isolate(), new_elements_kind);
8485 if (!maybe_obj->To(&new_map)) return maybe_obj; 8516 if (!maybe_obj->To(&new_map)) return maybe_obj;
8486 } 8517 }
8487 8518
8488 FixedArrayBase* old_elements = elements(); 8519 FixedArrayBase* old_elements = elements();
8489 ElementsKind elements_kind = GetElementsKind();
8490 ElementsAccessor* accessor = ElementsAccessor::ForKind(elements_kind); 8520 ElementsAccessor* accessor = ElementsAccessor::ForKind(elements_kind);
8491 { MaybeObject* maybe_obj = 8521 { MaybeObject* maybe_obj =
8492 accessor->CopyElements(this, elems, FAST_DOUBLE_ELEMENTS); 8522 accessor->CopyElements(this, elems, FAST_DOUBLE_ELEMENTS);
8493 if (maybe_obj->IsFailure()) return maybe_obj; 8523 if (maybe_obj->IsFailure()) return maybe_obj;
8494 } 8524 }
8495 if (elements_kind != NON_STRICT_ARGUMENTS_ELEMENTS) { 8525 if (elements_kind != NON_STRICT_ARGUMENTS_ELEMENTS) {
8526 ValidateElements();
8496 set_map_and_elements(new_map, elems); 8527 set_map_and_elements(new_map, elems);
8497 } else { 8528 } else {
8498 FixedArray* parameter_map = FixedArray::cast(old_elements); 8529 FixedArray* parameter_map = FixedArray::cast(old_elements);
8499 parameter_map->set(1, elems); 8530 parameter_map->set(1, elems);
8500 } 8531 }
8501 8532
8502 if (FLAG_trace_elements_transitions) { 8533 if (FLAG_trace_elements_transitions) {
8503 PrintElementsTransition(stdout, elements_kind, old_elements, 8534 PrintElementsTransition(stdout, elements_kind, old_elements,
8504 FAST_DOUBLE_ELEMENTS, elems); 8535 GetElementsKind(), elems);
8505 } 8536 }
8506 8537
8507 if (IsJSArray()) { 8538 if (IsJSArray()) {
8508 JSArray::cast(this)->set_length(Smi::FromInt(length)); 8539 JSArray::cast(this)->set_length(Smi::FromInt(length));
8509 } 8540 }
8510 8541
8511 return this; 8542 return this;
8512 } 8543 }
8513 8544
8514 8545
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after
8774 return HasElementWithInterceptor(this, index) ? INTERCEPTED_ELEMENT 8805 return HasElementWithInterceptor(this, index) ? INTERCEPTED_ELEMENT
8775 : UNDEFINED_ELEMENT; 8806 : UNDEFINED_ELEMENT;
8776 } 8807 }
8777 8808
8778 // Handle [] on String objects. 8809 // Handle [] on String objects.
8779 if (this->IsStringObjectWithCharacterAt(index)) { 8810 if (this->IsStringObjectWithCharacterAt(index)) {
8780 return STRING_CHARACTER_ELEMENT; 8811 return STRING_CHARACTER_ELEMENT;
8781 } 8812 }
8782 8813
8783 switch (GetElementsKind()) { 8814 switch (GetElementsKind()) {
8784 case FAST_SMI_ONLY_ELEMENTS: 8815 case FAST_SMI_ELEMENTS:
8785 case FAST_ELEMENTS: { 8816 case FAST_ELEMENTS:
8817 case FAST_HOLEY_SMI_ELEMENTS:
8818 case FAST_HOLEY_ELEMENTS: {
8786 uint32_t length = IsJSArray() ? 8819 uint32_t length = IsJSArray() ?
8787 static_cast<uint32_t> 8820 static_cast<uint32_t>
8788 (Smi::cast(JSArray::cast(this)->length())->value()) : 8821 (Smi::cast(JSArray::cast(this)->length())->value()) :
8789 static_cast<uint32_t>(FixedArray::cast(elements())->length()); 8822 static_cast<uint32_t>(FixedArray::cast(elements())->length());
8790 if ((index < length) && 8823 if ((index < length) &&
8791 !FixedArray::cast(elements())->get(index)->IsTheHole()) { 8824 !FixedArray::cast(elements())->get(index)->IsTheHole()) {
8792 return FAST_ELEMENT; 8825 return FAST_ELEMENT;
8793 } 8826 }
8794 break; 8827 break;
8795 } 8828 }
8796 case FAST_DOUBLE_ELEMENTS: { 8829 case FAST_DOUBLE_ELEMENTS:
8830 case FAST_HOLEY_DOUBLE_ELEMENTS: {
8797 uint32_t length = IsJSArray() ? 8831 uint32_t length = IsJSArray() ?
8798 static_cast<uint32_t> 8832 static_cast<uint32_t>
8799 (Smi::cast(JSArray::cast(this)->length())->value()) : 8833 (Smi::cast(JSArray::cast(this)->length())->value()) :
8800 static_cast<uint32_t>(FixedDoubleArray::cast(elements())->length()); 8834 static_cast<uint32_t>(FixedDoubleArray::cast(elements())->length());
8801 if ((index < length) && 8835 if ((index < length) &&
8802 !FixedDoubleArray::cast(elements())->is_the_hole(index)) { 8836 !FixedDoubleArray::cast(elements())->is_the_hole(index)) {
8803 return FAST_ELEMENT; 8837 return FAST_ELEMENT;
8804 } 8838 }
8805 break; 8839 break;
8806 } 8840 }
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after
9070 } 9104 }
9071 9105
9072 9106
9073 // Adding n elements in fast case is O(n*n). 9107 // Adding n elements in fast case is O(n*n).
9074 // Note: revisit design to have dual undefined values to capture absent 9108 // Note: revisit design to have dual undefined values to capture absent
9075 // elements. 9109 // elements.
9076 MaybeObject* JSObject::SetFastElement(uint32_t index, 9110 MaybeObject* JSObject::SetFastElement(uint32_t index,
9077 Object* value, 9111 Object* value,
9078 StrictModeFlag strict_mode, 9112 StrictModeFlag strict_mode,
9079 bool check_prototype) { 9113 bool check_prototype) {
9080 ASSERT(HasFastTypeElements() || 9114 ASSERT(HasFastSmiOrObjectElements() ||
9081 HasFastArgumentsElements()); 9115 HasFastArgumentsElements());
9082 9116
9083 FixedArray* backing_store = FixedArray::cast(elements()); 9117 FixedArray* backing_store = FixedArray::cast(elements());
9084 if (backing_store->map() == GetHeap()->non_strict_arguments_elements_map()) { 9118 if (backing_store->map() == GetHeap()->non_strict_arguments_elements_map()) {
9085 backing_store = FixedArray::cast(backing_store->get(1)); 9119 backing_store = FixedArray::cast(backing_store->get(1));
9086 } else { 9120 } else {
9087 MaybeObject* maybe = EnsureWritableFastElements(); 9121 MaybeObject* maybe = EnsureWritableFastElements();
9088 if (!maybe->To(&backing_store)) return maybe; 9122 if (!maybe->To(&backing_store)) return maybe;
9089 } 9123 }
9090 uint32_t capacity = static_cast<uint32_t>(backing_store->length()); 9124 uint32_t capacity = static_cast<uint32_t>(backing_store->length());
9091 9125
9092 if (check_prototype && 9126 if (check_prototype &&
9093 (index >= capacity || backing_store->get(index)->IsTheHole())) { 9127 (index >= capacity || backing_store->get(index)->IsTheHole())) {
9094 bool found; 9128 bool found;
9095 MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index, 9129 MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index,
9096 value, 9130 value,
9097 &found, 9131 &found,
9098 strict_mode); 9132 strict_mode);
9099 if (found) return result; 9133 if (found) return result;
9100 } 9134 }
9101 9135
9102 uint32_t new_capacity = capacity; 9136 uint32_t new_capacity = capacity;
9103 // Check if the length property of this object needs to be updated. 9137 // Check if the length property of this object needs to be updated.
9104 uint32_t array_length = 0; 9138 uint32_t array_length = 0;
9105 bool must_update_array_length = false; 9139 bool must_update_array_length = false;
9140 bool introduces_holes = true;
9106 if (IsJSArray()) { 9141 if (IsJSArray()) {
9107 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length)); 9142 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length));
9143 introduces_holes = index > array_length;
9108 if (index >= array_length) { 9144 if (index >= array_length) {
9109 must_update_array_length = true; 9145 must_update_array_length = true;
9110 array_length = index + 1; 9146 array_length = index + 1;
9111 } 9147 }
9148 } else {
9149 introduces_holes = index >= capacity;
9112 } 9150 }
9151
9152 // If the array is growing, and it's not growth by a single element at the
9153 // end, make sure that the ElementsKind is HOLEY.
9154 ElementsKind elements_kind = GetElementsKind();
9155 if (introduces_holes &&
9156 IsFastElementsKind(elements_kind) &&
9157 !IsFastHoleyElementsKind(elements_kind)) {
9158 ElementsKind transitioned_kind = GetHoleyElementsKind(elements_kind);
9159 MaybeObject* maybe = TransitionElementsKind(transitioned_kind);
9160 if (maybe->IsFailure()) return maybe;
9161 }
9162
9113 // Check if the capacity of the backing store needs to be increased, or if 9163 // Check if the capacity of the backing store needs to be increased, or if
9114 // a transition to slow elements is necessary. 9164 // a transition to slow elements is necessary.
9115 if (index >= capacity) { 9165 if (index >= capacity) {
9116 bool convert_to_slow = true; 9166 bool convert_to_slow = true;
9117 if ((index - capacity) < kMaxGap) { 9167 if ((index - capacity) < kMaxGap) {
9118 new_capacity = NewElementsCapacity(index + 1); 9168 new_capacity = NewElementsCapacity(index + 1);
9119 ASSERT(new_capacity > index); 9169 ASSERT(new_capacity > index);
9120 if (!ShouldConvertToSlowElements(new_capacity)) { 9170 if (!ShouldConvertToSlowElements(new_capacity)) {
9121 convert_to_slow = false; 9171 convert_to_slow = false;
9122 } 9172 }
9123 } 9173 }
9124 if (convert_to_slow) { 9174 if (convert_to_slow) {
9125 MaybeObject* result = NormalizeElements(); 9175 MaybeObject* result = NormalizeElements();
9126 if (result->IsFailure()) return result; 9176 if (result->IsFailure()) return result;
9127 return SetDictionaryElement(index, value, NONE, strict_mode, 9177 return SetDictionaryElement(index, value, NONE, strict_mode,
9128 check_prototype); 9178 check_prototype);
9129 } 9179 }
9130 } 9180 }
9131 // Convert to fast double elements if appropriate. 9181 // Convert to fast double elements if appropriate.
9132 if (HasFastSmiOnlyElements() && !value->IsSmi() && value->IsNumber()) { 9182 if (HasFastSmiElements() && !value->IsSmi() && value->IsNumber()) {
9133 MaybeObject* maybe = 9183 MaybeObject* maybe =
9134 SetFastDoubleElementsCapacityAndLength(new_capacity, array_length); 9184 SetFastDoubleElementsCapacityAndLength(new_capacity, array_length);
9135 if (maybe->IsFailure()) return maybe; 9185 if (maybe->IsFailure()) return maybe;
9136 FixedDoubleArray::cast(elements())->set(index, value->Number()); 9186 FixedDoubleArray::cast(elements())->set(index, value->Number());
9187 ValidateElements();
9137 return value; 9188 return value;
9138 } 9189 }
9139 // Change elements kind from SMI_ONLY to generic FAST if necessary. 9190 // Change elements kind from Smi-only to generic FAST if necessary.
9140 if (HasFastSmiOnlyElements() && !value->IsSmi()) { 9191 if (HasFastSmiElements() && !value->IsSmi()) {
9141 Map* new_map; 9192 Map* new_map;
9142 { MaybeObject* maybe_new_map = GetElementsTransitionMap(GetIsolate(), 9193 ElementsKind kind = HasFastHoleyElements()
9143 FAST_ELEMENTS); 9194 ? FAST_HOLEY_ELEMENTS
9144 if (!maybe_new_map->To(&new_map)) return maybe_new_map; 9195 : FAST_ELEMENTS;
9145 } 9196 MaybeObject* maybe_new_map = GetElementsTransitionMap(GetIsolate(),
9197 kind);
9198 if (!maybe_new_map->To(&new_map)) return maybe_new_map;
9199
9146 set_map(new_map); 9200 set_map(new_map);
9147 if (FLAG_trace_elements_transitions) {
9148 PrintElementsTransition(stdout, FAST_SMI_ONLY_ELEMENTS, elements(),
9149 FAST_ELEMENTS, elements());
9150 }
9151 } 9201 }
9152 // Increase backing store capacity if that's been decided previously. 9202 // Increase backing store capacity if that's been decided previously.
9153 if (new_capacity != capacity) { 9203 if (new_capacity != capacity) {
9154 FixedArray* new_elements; 9204 FixedArray* new_elements;
9155 SetFastElementsCapacityMode set_capacity_mode = 9205 SetFastElementsCapacitySmiMode smi_mode =
9156 value->IsSmi() && HasFastSmiOnlyElements() 9206 value->IsSmi() && HasFastSmiElements()
9157 ? kAllowSmiOnlyElements 9207 ? kAllowSmiElements
9158 : kDontAllowSmiOnlyElements; 9208 : kDontAllowSmiElements;
9159 { MaybeObject* maybe = 9209 { MaybeObject* maybe =
9160 SetFastElementsCapacityAndLength(new_capacity, 9210 SetFastElementsCapacityAndLength(new_capacity,
9161 array_length, 9211 array_length,
9162 set_capacity_mode); 9212 smi_mode);
9163 if (!maybe->To(&new_elements)) return maybe; 9213 if (!maybe->To(&new_elements)) return maybe;
9164 } 9214 }
9165 new_elements->set(index, value); 9215 new_elements->set(index, value);
9216 ValidateElements();
9166 return value; 9217 return value;
9167 } 9218 }
9219
9168 // Finally, set the new element and length. 9220 // Finally, set the new element and length.
9169 ASSERT(elements()->IsFixedArray()); 9221 ASSERT(elements()->IsFixedArray());
9170 backing_store->set(index, value); 9222 backing_store->set(index, value);
9171 if (must_update_array_length) { 9223 if (must_update_array_length) {
9172 JSArray::cast(this)->set_length(Smi::FromInt(array_length)); 9224 JSArray::cast(this)->set_length(Smi::FromInt(array_length));
9173 } 9225 }
9174 return value; 9226 return value;
9175 } 9227 }
9176 9228
9177 9229
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
9281 } 9333 }
9282 9334
9283 // Attempt to put this object back in fast case. 9335 // Attempt to put this object back in fast case.
9284 if (ShouldConvertToFastElements()) { 9336 if (ShouldConvertToFastElements()) {
9285 uint32_t new_length = 0; 9337 uint32_t new_length = 0;
9286 if (IsJSArray()) { 9338 if (IsJSArray()) {
9287 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&new_length)); 9339 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&new_length));
9288 } else { 9340 } else {
9289 new_length = dictionary->max_number_key() + 1; 9341 new_length = dictionary->max_number_key() + 1;
9290 } 9342 }
9291 SetFastElementsCapacityMode set_capacity_mode = FLAG_smi_only_arrays 9343 SetFastElementsCapacitySmiMode smi_mode = FLAG_smi_only_arrays
9292 ? kAllowSmiOnlyElements 9344 ? kAllowSmiElements
9293 : kDontAllowSmiOnlyElements; 9345 : kDontAllowSmiElements;
9294 bool has_smi_only_elements = false; 9346 bool has_smi_only_elements = false;
9295 bool should_convert_to_fast_double_elements = 9347 bool should_convert_to_fast_double_elements =
9296 ShouldConvertToFastDoubleElements(&has_smi_only_elements); 9348 ShouldConvertToFastDoubleElements(&has_smi_only_elements);
9297 if (has_smi_only_elements) { 9349 if (has_smi_only_elements) {
9298 set_capacity_mode = kForceSmiOnlyElements; 9350 smi_mode = kForceSmiElements;
9299 } 9351 }
9300 MaybeObject* result = should_convert_to_fast_double_elements 9352 MaybeObject* result = should_convert_to_fast_double_elements
9301 ? SetFastDoubleElementsCapacityAndLength(new_length, new_length) 9353 ? SetFastDoubleElementsCapacityAndLength(new_length, new_length)
9302 : SetFastElementsCapacityAndLength(new_length, 9354 : SetFastElementsCapacityAndLength(new_length,
9303 new_length, 9355 new_length,
9304 set_capacity_mode); 9356 smi_mode);
9357 ValidateElements();
9305 if (result->IsFailure()) return result; 9358 if (result->IsFailure()) return result;
9306 #ifdef DEBUG 9359 #ifdef DEBUG
9307 if (FLAG_trace_normalization) { 9360 if (FLAG_trace_normalization) {
9308 PrintF("Object elements are fast case again:\n"); 9361 PrintF("Object elements are fast case again:\n");
9309 Print(); 9362 Print();
9310 } 9363 }
9311 #endif 9364 #endif
9312 } 9365 }
9313 return value; 9366 return value;
9314 } 9367 }
(...skipping 18 matching lines...) Expand all
9333 MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index, 9386 MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index,
9334 value, 9387 value,
9335 &found, 9388 &found,
9336 strict_mode); 9389 strict_mode);
9337 if (found) return result; 9390 if (found) return result;
9338 } 9391 }
9339 9392
9340 // If the value object is not a heap number, switch to fast elements and try 9393 // If the value object is not a heap number, switch to fast elements and try
9341 // again. 9394 // again.
9342 bool value_is_smi = value->IsSmi(); 9395 bool value_is_smi = value->IsSmi();
9396 bool introduces_holes = true;
9397 uint32_t length = elms_length;
9398 if (IsJSArray()) {
9399 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length));
9400 introduces_holes = index > length;
9401 } else {
9402 introduces_holes = index >= elms_length;
9403 }
9404
9343 if (!value->IsNumber()) { 9405 if (!value->IsNumber()) {
9344 Object* obj;
9345 uint32_t length = elms_length;
9346 if (IsJSArray()) {
9347 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length));
9348 }
9349 MaybeObject* maybe_obj = SetFastElementsCapacityAndLength( 9406 MaybeObject* maybe_obj = SetFastElementsCapacityAndLength(
9350 elms_length, 9407 elms_length,
9351 length, 9408 length,
9352 kDontAllowSmiOnlyElements); 9409 kDontAllowSmiElements);
9353 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 9410 if (maybe_obj->IsFailure()) return maybe_obj;
9354 return SetFastElement(index, 9411 maybe_obj = SetFastElement(index, value, strict_mode, check_prototype);
9355 value, 9412 if (maybe_obj->IsFailure()) return maybe_obj;
9356 strict_mode, 9413 ValidateElements();
9357 check_prototype); 9414 return maybe_obj;
9358 } 9415 }
9359 9416
9360 double double_value = value_is_smi 9417 double double_value = value_is_smi
9361 ? static_cast<double>(Smi::cast(value)->value()) 9418 ? static_cast<double>(Smi::cast(value)->value())
9362 : HeapNumber::cast(value)->value(); 9419 : HeapNumber::cast(value)->value();
9363 9420
9421 // If the array is growing, and it's not growth by a single element at the
9422 // end, make sure that the ElementsKind is HOLEY.
9423 ElementsKind elements_kind = GetElementsKind();
9424 if (introduces_holes && !IsFastHoleyElementsKind(elements_kind)) {
9425 ElementsKind transitioned_kind = GetHoleyElementsKind(elements_kind);
9426 MaybeObject* maybe = TransitionElementsKind(transitioned_kind);
9427 if (maybe->IsFailure()) return maybe;
9428 }
9429
9364 // Check whether there is extra space in the fixed array. 9430 // Check whether there is extra space in the fixed array.
9365 if (index < elms_length) { 9431 if (index < elms_length) {
9366 FixedDoubleArray* elms = FixedDoubleArray::cast(elements()); 9432 FixedDoubleArray* elms = FixedDoubleArray::cast(elements());
9367 elms->set(index, double_value); 9433 elms->set(index, double_value);
9368 if (IsJSArray()) { 9434 if (IsJSArray()) {
9369 // Update the length of the array if needed. 9435 // Update the length of the array if needed.
9370 uint32_t array_length = 0; 9436 uint32_t array_length = 0;
9371 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length)); 9437 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length));
9372 if (index >= array_length) { 9438 if (index >= array_length) {
9373 JSArray::cast(this)->set_length(Smi::FromInt(index + 1)); 9439 JSArray::cast(this)->set_length(Smi::FromInt(index + 1));
9374 } 9440 }
9375 } 9441 }
9376 return value; 9442 return value;
9377 } 9443 }
9378 9444
9379 // Allow gap in fast case. 9445 // Allow gap in fast case.
9380 if ((index - elms_length) < kMaxGap) { 9446 if ((index - elms_length) < kMaxGap) {
9381 // Try allocating extra space. 9447 // Try allocating extra space.
9382 int new_capacity = NewElementsCapacity(index+1); 9448 int new_capacity = NewElementsCapacity(index+1);
9383 if (!ShouldConvertToSlowElements(new_capacity)) { 9449 if (!ShouldConvertToSlowElements(new_capacity)) {
9384 ASSERT(static_cast<uint32_t>(new_capacity) > index); 9450 ASSERT(static_cast<uint32_t>(new_capacity) > index);
9385 Object* obj; 9451 MaybeObject* maybe_obj =
9386 { MaybeObject* maybe_obj = 9452 SetFastDoubleElementsCapacityAndLength(new_capacity, index + 1);
9387 SetFastDoubleElementsCapacityAndLength(new_capacity, 9453 if (maybe_obj->IsFailure()) return maybe_obj;
9388 index + 1);
9389 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
9390 }
9391 FixedDoubleArray::cast(elements())->set(index, double_value); 9454 FixedDoubleArray::cast(elements())->set(index, double_value);
9455 ValidateElements();
9392 return value; 9456 return value;
9393 } 9457 }
9394 } 9458 }
9395 9459
9396 // Otherwise default to slow case. 9460 // Otherwise default to slow case.
9397 ASSERT(HasFastDoubleElements()); 9461 ASSERT(HasFastDoubleElements());
9398 ASSERT(map()->has_fast_double_elements()); 9462 ASSERT(map()->has_fast_double_elements());
9399 ASSERT(elements()->IsFixedDoubleArray()); 9463 ASSERT(elements()->IsFixedDoubleArray());
9400 Object* obj; 9464 Object* obj;
9401 { MaybeObject* maybe_obj = NormalizeElements(); 9465 { MaybeObject* maybe_obj = NormalizeElements();
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
9525 Object* value, 9589 Object* value,
9526 PropertyAttributes attr, 9590 PropertyAttributes attr,
9527 StrictModeFlag strict_mode, 9591 StrictModeFlag strict_mode,
9528 bool check_prototype, 9592 bool check_prototype,
9529 SetPropertyMode set_mode) { 9593 SetPropertyMode set_mode) {
9530 ASSERT(HasDictionaryElements() || 9594 ASSERT(HasDictionaryElements() ||
9531 HasDictionaryArgumentsElements() || 9595 HasDictionaryArgumentsElements() ||
9532 (attr & (DONT_DELETE | DONT_ENUM | READ_ONLY)) == 0); 9596 (attr & (DONT_DELETE | DONT_ENUM | READ_ONLY)) == 0);
9533 Isolate* isolate = GetIsolate(); 9597 Isolate* isolate = GetIsolate();
9534 switch (GetElementsKind()) { 9598 switch (GetElementsKind()) {
9535 case FAST_SMI_ONLY_ELEMENTS: 9599 case FAST_SMI_ELEMENTS:
9536 case FAST_ELEMENTS: 9600 case FAST_ELEMENTS:
9601 case FAST_HOLEY_SMI_ELEMENTS:
9602 case FAST_HOLEY_ELEMENTS:
9537 return SetFastElement(index, value, strict_mode, check_prototype); 9603 return SetFastElement(index, value, strict_mode, check_prototype);
9538 case FAST_DOUBLE_ELEMENTS: 9604 case FAST_DOUBLE_ELEMENTS:
9605 case FAST_HOLEY_DOUBLE_ELEMENTS:
9539 return SetFastDoubleElement(index, value, strict_mode, check_prototype); 9606 return SetFastDoubleElement(index, value, strict_mode, check_prototype);
9540 case EXTERNAL_PIXEL_ELEMENTS: { 9607 case EXTERNAL_PIXEL_ELEMENTS: {
9541 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements()); 9608 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements());
9542 return pixels->SetValue(index, value); 9609 return pixels->SetValue(index, value);
9543 } 9610 }
9544 case EXTERNAL_BYTE_ELEMENTS: { 9611 case EXTERNAL_BYTE_ELEMENTS: {
9545 ExternalByteArray* array = ExternalByteArray::cast(elements()); 9612 ExternalByteArray* array = ExternalByteArray::cast(elements());
9546 return array->SetValue(index, value); 9613 return array->SetValue(index, value);
9547 } 9614 }
9548 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: { 9615 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: {
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
9619 ElementsKind to_kind) { 9686 ElementsKind to_kind) {
9620 CALL_HEAP_FUNCTION(object->GetIsolate(), 9687 CALL_HEAP_FUNCTION(object->GetIsolate(),
9621 object->TransitionElementsKind(to_kind), 9688 object->TransitionElementsKind(to_kind),
9622 Object); 9689 Object);
9623 } 9690 }
9624 9691
9625 9692
9626 MaybeObject* JSObject::TransitionElementsKind(ElementsKind to_kind) { 9693 MaybeObject* JSObject::TransitionElementsKind(ElementsKind to_kind) {
9627 ElementsKind from_kind = map()->elements_kind(); 9694 ElementsKind from_kind = map()->elements_kind();
9628 9695
9696 if (IsFastHoleyElementsKind(from_kind)) {
9697 to_kind = GetHoleyElementsKind(to_kind);
9698 }
9699
9629 Isolate* isolate = GetIsolate(); 9700 Isolate* isolate = GetIsolate();
9630 if ((from_kind == FAST_SMI_ONLY_ELEMENTS || 9701 if (elements() == isolate->heap()->empty_fixed_array() ||
9631 elements() == isolate->heap()->empty_fixed_array()) && 9702 (IsFastSmiOrObjectElementsKind(from_kind) &&
9632 to_kind == FAST_ELEMENTS) { 9703 IsFastSmiOrObjectElementsKind(to_kind)) ||
9633 ASSERT(from_kind != FAST_ELEMENTS); 9704 (from_kind == FAST_DOUBLE_ELEMENTS &&
9705 to_kind == FAST_HOLEY_DOUBLE_ELEMENTS)) {
9706 ASSERT(from_kind != TERMINAL_FAST_ELEMENTS_KIND);
9707 // No change is needed to the elements() buffer, the transition
9708 // only requires a map change.
9634 MaybeObject* maybe_new_map = GetElementsTransitionMap(isolate, to_kind); 9709 MaybeObject* maybe_new_map = GetElementsTransitionMap(isolate, to_kind);
9635 Map* new_map; 9710 Map* new_map;
9636 if (!maybe_new_map->To(&new_map)) return maybe_new_map; 9711 if (!maybe_new_map->To(&new_map)) return maybe_new_map;
9637 set_map(new_map); 9712 set_map(new_map);
9638 if (FLAG_trace_elements_transitions) { 9713 if (FLAG_trace_elements_transitions) {
9639 FixedArrayBase* elms = FixedArrayBase::cast(elements()); 9714 FixedArrayBase* elms = FixedArrayBase::cast(elements());
9640 PrintElementsTransition(stdout, from_kind, elms, to_kind, elms); 9715 PrintElementsTransition(stdout, from_kind, elms, to_kind, elms);
9641 } 9716 }
9642 return this; 9717 return this;
9643 } 9718 }
9644 9719
9645 FixedArrayBase* elms = FixedArrayBase::cast(elements()); 9720 FixedArrayBase* elms = FixedArrayBase::cast(elements());
9646 uint32_t capacity = static_cast<uint32_t>(elms->length()); 9721 uint32_t capacity = static_cast<uint32_t>(elms->length());
9647 uint32_t length = capacity; 9722 uint32_t length = capacity;
9648 9723
9649 if (IsJSArray()) { 9724 if (IsJSArray()) {
9650 Object* raw_length = JSArray::cast(this)->length(); 9725 Object* raw_length = JSArray::cast(this)->length();
9651 if (raw_length->IsUndefined()) { 9726 if (raw_length->IsUndefined()) {
9652 // If length is undefined, then JSArray is being initialized and has no 9727 // If length is undefined, then JSArray is being initialized and has no
9653 // elements, assume a length of zero. 9728 // elements, assume a length of zero.
9654 length = 0; 9729 length = 0;
9655 } else { 9730 } else {
9656 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length)); 9731 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length));
9657 } 9732 }
9658 } 9733 }
9659 9734
9660 if (from_kind == FAST_SMI_ONLY_ELEMENTS && 9735 if (IsFastSmiElementsKind(from_kind) &&
9661 to_kind == FAST_DOUBLE_ELEMENTS) { 9736 IsFastDoubleElementsKind(to_kind)) {
9662 MaybeObject* maybe_result = 9737 MaybeObject* maybe_result =
9663 SetFastDoubleElementsCapacityAndLength(capacity, length); 9738 SetFastDoubleElementsCapacityAndLength(capacity, length);
9664 if (maybe_result->IsFailure()) return maybe_result; 9739 if (maybe_result->IsFailure()) return maybe_result;
9740 ValidateElements();
9665 return this; 9741 return this;
9666 } 9742 }
9667 9743
9668 if (from_kind == FAST_DOUBLE_ELEMENTS && to_kind == FAST_ELEMENTS) { 9744 if (IsFastDoubleElementsKind(from_kind) &&
9745 IsFastObjectElementsKind(to_kind)) {
9669 MaybeObject* maybe_result = SetFastElementsCapacityAndLength( 9746 MaybeObject* maybe_result = SetFastElementsCapacityAndLength(
9670 capacity, length, kDontAllowSmiOnlyElements); 9747 capacity, length, kDontAllowSmiElements);
9671 if (maybe_result->IsFailure()) return maybe_result; 9748 if (maybe_result->IsFailure()) return maybe_result;
9749 ValidateElements();
9672 return this; 9750 return this;
9673 } 9751 }
9674 9752
9675 // This method should never be called for any other case than the ones 9753 // This method should never be called for any other case than the ones
9676 // handled above. 9754 // handled above.
9677 UNREACHABLE(); 9755 UNREACHABLE();
9678 return GetIsolate()->heap()->null_value(); 9756 return GetIsolate()->heap()->null_value();
9679 } 9757 }
9680 9758
9681 9759
9682 // static 9760 // static
9683 bool Map::IsValidElementsTransition(ElementsKind from_kind, 9761 bool Map::IsValidElementsTransition(ElementsKind from_kind,
9684 ElementsKind to_kind) { 9762 ElementsKind to_kind) {
9685 return 9763 // Transitions can't go backwards.
9686 (from_kind == FAST_SMI_ONLY_ELEMENTS && 9764 if (!IsMoreGeneralElementsKindTransition(from_kind, to_kind)) {
9687 (to_kind == FAST_DOUBLE_ELEMENTS || to_kind == FAST_ELEMENTS)) || 9765 return false;
9688 (from_kind == FAST_DOUBLE_ELEMENTS && to_kind == FAST_ELEMENTS); 9766 }
9767
9768 // Transitions from HOLEY -> PACKED are not allowed.
9769 return !IsFastHoleyElementsKind(from_kind) ||
9770 IsFastHoleyElementsKind(to_kind);
9689 } 9771 }
9690 9772
9691 9773
9692 MaybeObject* JSArray::JSArrayUpdateLengthFromIndex(uint32_t index, 9774 MaybeObject* JSArray::JSArrayUpdateLengthFromIndex(uint32_t index,
9693 Object* value) { 9775 Object* value) {
9694 uint32_t old_len = 0; 9776 uint32_t old_len = 0;
9695 CHECK(length()->ToArrayIndex(&old_len)); 9777 CHECK(length()->ToArrayIndex(&old_len));
9696 // Check to see if we need to update the length. For now, we make 9778 // Check to see if we need to update the length. For now, we make
9697 // sure that the length stays within 32-bits (unsigned). 9779 // sure that the length stays within 32-bits (unsigned).
9698 if (index >= old_len && index != 0xffffffff) { 9780 if (index >= old_len && index != 0xffffffff) {
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
9769 FixedArray::cast(FixedArray::cast(backing_store_base)->get(1)); 9851 FixedArray::cast(FixedArray::cast(backing_store_base)->get(1));
9770 backing_store = FixedArray::cast(backing_store_base); 9852 backing_store = FixedArray::cast(backing_store_base);
9771 if (backing_store->IsDictionary()) { 9853 if (backing_store->IsDictionary()) {
9772 SeededNumberDictionary* dictionary = 9854 SeededNumberDictionary* dictionary =
9773 SeededNumberDictionary::cast(backing_store); 9855 SeededNumberDictionary::cast(backing_store);
9774 *capacity = dictionary->Capacity(); 9856 *capacity = dictionary->Capacity();
9775 *used = dictionary->NumberOfElements(); 9857 *used = dictionary->NumberOfElements();
9776 break; 9858 break;
9777 } 9859 }
9778 // Fall through. 9860 // Fall through.
9779 case FAST_SMI_ONLY_ELEMENTS: 9861 case FAST_SMI_ELEMENTS:
9780 case FAST_ELEMENTS: 9862 case FAST_ELEMENTS:
9863 case FAST_HOLEY_SMI_ELEMENTS:
9864 case FAST_HOLEY_ELEMENTS:
9781 backing_store = FixedArray::cast(backing_store_base); 9865 backing_store = FixedArray::cast(backing_store_base);
9782 *capacity = backing_store->length(); 9866 *capacity = backing_store->length();
9783 for (int i = 0; i < *capacity; ++i) { 9867 for (int i = 0; i < *capacity; ++i) {
9784 if (!backing_store->get(i)->IsTheHole()) ++(*used); 9868 if (!backing_store->get(i)->IsTheHole()) ++(*used);
9785 } 9869 }
9786 break; 9870 break;
9787 case DICTIONARY_ELEMENTS: { 9871 case DICTIONARY_ELEMENTS: {
9788 SeededNumberDictionary* dictionary = 9872 SeededNumberDictionary* dictionary =
9789 SeededNumberDictionary::cast(FixedArray::cast(elements())); 9873 SeededNumberDictionary::cast(FixedArray::cast(elements()));
9790 *capacity = dictionary->Capacity(); 9874 *capacity = dictionary->Capacity();
9791 *used = dictionary->NumberOfElements(); 9875 *used = dictionary->NumberOfElements();
9792 break; 9876 break;
9793 } 9877 }
9794 case FAST_DOUBLE_ELEMENTS: { 9878 case FAST_DOUBLE_ELEMENTS:
9879 case FAST_HOLEY_DOUBLE_ELEMENTS: {
9795 FixedDoubleArray* elms = FixedDoubleArray::cast(elements()); 9880 FixedDoubleArray* elms = FixedDoubleArray::cast(elements());
9796 *capacity = elms->length(); 9881 *capacity = elms->length();
9797 for (int i = 0; i < *capacity; i++) { 9882 for (int i = 0; i < *capacity; i++) {
9798 if (!elms->is_the_hole(i)) ++(*used); 9883 if (!elms->is_the_hole(i)) ++(*used);
9799 } 9884 }
9800 break; 9885 break;
9801 } 9886 }
9802 case EXTERNAL_BYTE_ELEMENTS: 9887 case EXTERNAL_BYTE_ELEMENTS:
9803 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 9888 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
9804 case EXTERNAL_SHORT_ELEMENTS: 9889 case EXTERNAL_SHORT_ELEMENTS:
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after
10054 if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) { 10139 if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) {
10055 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS); 10140 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS);
10056 return false; 10141 return false;
10057 } 10142 }
10058 } 10143 }
10059 10144
10060 // Handle [] on String objects. 10145 // Handle [] on String objects.
10061 if (this->IsStringObjectWithCharacterAt(index)) return true; 10146 if (this->IsStringObjectWithCharacterAt(index)) return true;
10062 10147
10063 switch (GetElementsKind()) { 10148 switch (GetElementsKind()) {
10064 case FAST_SMI_ONLY_ELEMENTS: 10149 case FAST_SMI_ELEMENTS:
10065 case FAST_ELEMENTS: { 10150 case FAST_ELEMENTS:
10066 uint32_t length = IsJSArray() ? 10151 case FAST_HOLEY_SMI_ELEMENTS:
10152 case FAST_HOLEY_ELEMENTS: {
10153 uint32_t length = IsJSArray() ?
10067 static_cast<uint32_t>( 10154 static_cast<uint32_t>(
10068 Smi::cast(JSArray::cast(this)->length())->value()) : 10155 Smi::cast(JSArray::cast(this)->length())->value()) :
10069 static_cast<uint32_t>(FixedArray::cast(elements())->length()); 10156 static_cast<uint32_t>(FixedArray::cast(elements())->length());
10070 return (index < length) && 10157 return (index < length) &&
10071 !FixedArray::cast(elements())->get(index)->IsTheHole(); 10158 !FixedArray::cast(elements())->get(index)->IsTheHole();
10072 } 10159 }
10073 case FAST_DOUBLE_ELEMENTS: { 10160 case FAST_DOUBLE_ELEMENTS:
10161 case FAST_HOLEY_DOUBLE_ELEMENTS: {
10074 uint32_t length = IsJSArray() ? 10162 uint32_t length = IsJSArray() ?
10075 static_cast<uint32_t>( 10163 static_cast<uint32_t>(
10076 Smi::cast(JSArray::cast(this)->length())->value()) : 10164 Smi::cast(JSArray::cast(this)->length())->value()) :
10077 static_cast<uint32_t>(FixedDoubleArray::cast(elements())->length()); 10165 static_cast<uint32_t>(FixedDoubleArray::cast(elements())->length());
10078 return (index < length) && 10166 return (index < length) &&
10079 !FixedDoubleArray::cast(elements())->is_the_hole(index); 10167 !FixedDoubleArray::cast(elements())->is_the_hole(index);
10080 break; 10168 break;
10081 } 10169 }
10082 case EXTERNAL_PIXEL_ELEMENTS: { 10170 case EXTERNAL_PIXEL_ELEMENTS: {
10083 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements()); 10171 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements());
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after
10263 } 10351 }
10264 10352
10265 10353
10266 int JSObject::NumberOfLocalElements(PropertyAttributes filter) { 10354 int JSObject::NumberOfLocalElements(PropertyAttributes filter) {
10267 return GetLocalElementKeys(NULL, filter); 10355 return GetLocalElementKeys(NULL, filter);
10268 } 10356 }
10269 10357
10270 10358
10271 int JSObject::NumberOfEnumElements() { 10359 int JSObject::NumberOfEnumElements() {
10272 // Fast case for objects with no elements. 10360 // Fast case for objects with no elements.
10273 if (!IsJSValue() && HasFastElements()) { 10361 if (!IsJSValue() && HasFastObjectElements()) {
10274 uint32_t length = IsJSArray() ? 10362 uint32_t length = IsJSArray() ?
10275 static_cast<uint32_t>( 10363 static_cast<uint32_t>(
10276 Smi::cast(JSArray::cast(this)->length())->value()) : 10364 Smi::cast(JSArray::cast(this)->length())->value()) :
10277 static_cast<uint32_t>(FixedArray::cast(elements())->length()); 10365 static_cast<uint32_t>(FixedArray::cast(elements())->length());
10278 if (length == 0) return 0; 10366 if (length == 0) return 0;
10279 } 10367 }
10280 // Compute the number of enumerable elements. 10368 // Compute the number of enumerable elements.
10281 return NumberOfLocalElements(static_cast<PropertyAttributes>(DONT_ENUM)); 10369 return NumberOfLocalElements(static_cast<PropertyAttributes>(DONT_ENUM));
10282 } 10370 }
10283 10371
10284 10372
10285 int JSObject::GetLocalElementKeys(FixedArray* storage, 10373 int JSObject::GetLocalElementKeys(FixedArray* storage,
10286 PropertyAttributes filter) { 10374 PropertyAttributes filter) {
10287 int counter = 0; 10375 int counter = 0;
10288 switch (GetElementsKind()) { 10376 switch (GetElementsKind()) {
10289 case FAST_SMI_ONLY_ELEMENTS: 10377 case FAST_SMI_ELEMENTS:
10290 case FAST_ELEMENTS: { 10378 case FAST_ELEMENTS:
10379 case FAST_HOLEY_SMI_ELEMENTS:
10380 case FAST_HOLEY_ELEMENTS: {
10291 int length = IsJSArray() ? 10381 int length = IsJSArray() ?
10292 Smi::cast(JSArray::cast(this)->length())->value() : 10382 Smi::cast(JSArray::cast(this)->length())->value() :
10293 FixedArray::cast(elements())->length(); 10383 FixedArray::cast(elements())->length();
10294 for (int i = 0; i < length; i++) { 10384 for (int i = 0; i < length; i++) {
10295 if (!FixedArray::cast(elements())->get(i)->IsTheHole()) { 10385 if (!FixedArray::cast(elements())->get(i)->IsTheHole()) {
10296 if (storage != NULL) { 10386 if (storage != NULL) {
10297 storage->set(counter, Smi::FromInt(i)); 10387 storage->set(counter, Smi::FromInt(i));
10298 } 10388 }
10299 counter++; 10389 counter++;
10300 } 10390 }
10301 } 10391 }
10302 ASSERT(!storage || storage->length() >= counter); 10392 ASSERT(!storage || storage->length() >= counter);
10303 break; 10393 break;
10304 } 10394 }
10305 case FAST_DOUBLE_ELEMENTS: { 10395 case FAST_DOUBLE_ELEMENTS:
10396 case FAST_HOLEY_DOUBLE_ELEMENTS: {
10306 int length = IsJSArray() ? 10397 int length = IsJSArray() ?
10307 Smi::cast(JSArray::cast(this)->length())->value() : 10398 Smi::cast(JSArray::cast(this)->length())->value() :
10308 FixedDoubleArray::cast(elements())->length(); 10399 FixedDoubleArray::cast(elements())->length();
10309 for (int i = 0; i < length; i++) { 10400 for (int i = 0; i < length; i++) {
10310 if (!FixedDoubleArray::cast(elements())->is_the_hole(i)) { 10401 if (!FixedDoubleArray::cast(elements())->is_the_hole(i)) {
10311 if (storage != NULL) { 10402 if (storage != NULL) {
10312 storage->set(counter, Smi::FromInt(i)); 10403 storage->set(counter, Smi::FromInt(i));
10313 } 10404 }
10314 counter++; 10405 counter++;
10315 } 10406 }
(...skipping 912 matching lines...) Expand 10 before | Expand all | Expand 10 after
11228 // Convert to fast elements containing only the existing properties. 11319 // Convert to fast elements containing only the existing properties.
11229 // Ordering is irrelevant, since we are going to sort anyway. 11320 // Ordering is irrelevant, since we are going to sort anyway.
11230 SeededNumberDictionary* dict = element_dictionary(); 11321 SeededNumberDictionary* dict = element_dictionary();
11231 if (IsJSArray() || dict->requires_slow_elements() || 11322 if (IsJSArray() || dict->requires_slow_elements() ||
11232 dict->max_number_key() >= limit) { 11323 dict->max_number_key() >= limit) {
11233 return PrepareSlowElementsForSort(limit); 11324 return PrepareSlowElementsForSort(limit);
11234 } 11325 }
11235 // Convert to fast elements. 11326 // Convert to fast elements.
11236 11327
11237 Object* obj; 11328 Object* obj;
11238 { MaybeObject* maybe_obj = GetElementsTransitionMap(GetIsolate(), 11329 MaybeObject* maybe_obj = GetElementsTransitionMap(GetIsolate(),
11239 FAST_ELEMENTS); 11330 FAST_HOLEY_ELEMENTS);
11240 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 11331 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
11241 }
11242 Map* new_map = Map::cast(obj); 11332 Map* new_map = Map::cast(obj);
11243 11333
11244 PretenureFlag tenure = heap->InNewSpace(this) ? NOT_TENURED: TENURED; 11334 PretenureFlag tenure = heap->InNewSpace(this) ? NOT_TENURED: TENURED;
11245 Object* new_array; 11335 Object* new_array;
11246 { MaybeObject* maybe_new_array = 11336 { MaybeObject* maybe_new_array =
11247 heap->AllocateFixedArray(dict->NumberOfElements(), tenure); 11337 heap->AllocateFixedArray(dict->NumberOfElements(), tenure);
11248 if (!maybe_new_array->ToObject(&new_array)) return maybe_new_array; 11338 if (!maybe_new_array->ToObject(&new_array)) return maybe_new_array;
11249 } 11339 }
11250 FixedArray* fast_elements = FixedArray::cast(new_array); 11340 FixedArray* fast_elements = FixedArray::cast(new_array);
11251 dict->CopyValuesTo(fast_elements); 11341 dict->CopyValuesTo(fast_elements);
11342 ValidateElements();
11252 11343
11253 set_map(new_map); 11344 set_map_and_elements(new_map, fast_elements);
11254 set_elements(fast_elements);
11255 } else if (HasExternalArrayElements()) { 11345 } else if (HasExternalArrayElements()) {
11256 // External arrays cannot have holes or undefined elements. 11346 // External arrays cannot have holes or undefined elements.
11257 return Smi::FromInt(ExternalArray::cast(elements())->length()); 11347 return Smi::FromInt(ExternalArray::cast(elements())->length());
11258 } else if (!HasFastDoubleElements()) { 11348 } else if (!HasFastDoubleElements()) {
11259 Object* obj; 11349 Object* obj;
11260 { MaybeObject* maybe_obj = EnsureWritableFastElements(); 11350 { MaybeObject* maybe_obj = EnsureWritableFastElements();
11261 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 11351 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
11262 } 11352 }
11263 } 11353 }
11264 ASSERT(HasFastTypeElements() || HasFastDoubleElements()); 11354 ASSERT(HasFastSmiOrObjectElements() || HasFastDoubleElements());
11265 11355
11266 // Collect holes at the end, undefined before that and the rest at the 11356 // Collect holes at the end, undefined before that and the rest at the
11267 // start, and return the number of non-hole, non-undefined values. 11357 // start, and return the number of non-hole, non-undefined values.
11268 11358
11269 FixedArrayBase* elements_base = FixedArrayBase::cast(this->elements()); 11359 FixedArrayBase* elements_base = FixedArrayBase::cast(this->elements());
11270 uint32_t elements_length = static_cast<uint32_t>(elements_base->length()); 11360 uint32_t elements_length = static_cast<uint32_t>(elements_base->length());
11271 if (limit > elements_length) { 11361 if (limit > elements_length) {
11272 limit = elements_length ; 11362 limit = elements_length ;
11273 } 11363 }
11274 if (limit == 0) { 11364 if (limit == 0) {
(...skipping 1656 matching lines...) Expand 10 before | Expand all | Expand 10 after
12931 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); 13021 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER);
12932 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); 13022 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER);
12933 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); 13023 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER);
12934 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); 13024 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER);
12935 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); 13025 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER);
12936 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); 13026 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER);
12937 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); 13027 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER);
12938 } 13028 }
12939 13029
12940 } } // namespace v8::internal 13030 } } // 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