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

Side by Side Diff: src/objects.cc

Issue 10442015: Rollback of r11638, r11636 on trunk branch. (Closed) Base URL: https://v8.googlecode.com/svn/trunk
Patch Set: Created 8 years, 6 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
59 64
60 MUST_USE_RESULT static MaybeObject* CreateJSValue(JSFunction* constructor, 65 MUST_USE_RESULT static MaybeObject* CreateJSValue(JSFunction* constructor,
61 Object* value) { 66 Object* value) {
62 Object* result; 67 Object* result;
63 { MaybeObject* maybe_result = 68 { MaybeObject* maybe_result =
64 constructor->GetHeap()->AllocateJSObject(constructor); 69 constructor->GetHeap()->AllocateJSObject(constructor);
65 if (!maybe_result->ToObject(&result)) return maybe_result; 70 if (!maybe_result->ToObject(&result)) return maybe_result;
66 } 71 }
67 JSValue::cast(result)->set_value(value); 72 JSValue::cast(result)->set_value(value);
68 return result; 73 return result;
(...skipping 462 matching lines...) Expand 10 before | Expand all | Expand 10 after
531 bool JSObject::IsDirty() { 536 bool JSObject::IsDirty() {
532 Object* cons_obj = map()->constructor(); 537 Object* cons_obj = map()->constructor();
533 if (!cons_obj->IsJSFunction()) 538 if (!cons_obj->IsJSFunction())
534 return true; 539 return true;
535 JSFunction* fun = JSFunction::cast(cons_obj); 540 JSFunction* fun = JSFunction::cast(cons_obj);
536 if (!fun->shared()->IsApiFunction()) 541 if (!fun->shared()->IsApiFunction())
537 return true; 542 return true;
538 // If the object is fully fast case and has the same map it was 543 // If the object is fully fast case and has the same map it was
539 // created with then no changes can have been made to it. 544 // created with then no changes can have been made to it.
540 return map() != fun->initial_map() 545 return map() != fun->initial_map()
541 || !HasFastObjectElements() 546 || !HasFastElements()
542 || !HasFastProperties(); 547 || !HasFastProperties();
543 } 548 }
544 549
545 550
546 Handle<Object> Object::GetProperty(Handle<Object> object, 551 Handle<Object> Object::GetProperty(Handle<Object> object,
547 Handle<Object> receiver, 552 Handle<Object> receiver,
548 LookupResult* result, 553 LookupResult* result,
549 Handle<String> key, 554 Handle<String> key,
550 PropertyAttributes* attributes) { 555 PropertyAttributes* attributes) {
551 Isolate* isolate = object->IsHeapObject() 556 Isolate* isolate = object->IsHeapObject()
(...skipping 503 matching lines...) Expand 10 before | Expand all | Expand 10 after
1055 } 1060 }
1056 accumulator->Put('>'); 1061 accumulator->Put('>');
1057 } 1062 }
1058 return; 1063 return;
1059 } 1064 }
1060 1065
1061 1066
1062 void JSObject::JSObjectShortPrint(StringStream* accumulator) { 1067 void JSObject::JSObjectShortPrint(StringStream* accumulator) {
1063 switch (map()->instance_type()) { 1068 switch (map()->instance_type()) {
1064 case JS_ARRAY_TYPE: { 1069 case JS_ARRAY_TYPE: {
1065 double length = JSArray::cast(this)->length()->IsUndefined() 1070 double length = JSArray::cast(this)->length()->Number();
1066 ? 0
1067 : JSArray::cast(this)->length()->Number();
1068 accumulator->Add("<JS Array[%u]>", static_cast<uint32_t>(length)); 1071 accumulator->Add("<JS Array[%u]>", static_cast<uint32_t>(length));
1069 break; 1072 break;
1070 } 1073 }
1071 case JS_WEAK_MAP_TYPE: { 1074 case JS_WEAK_MAP_TYPE: {
1072 accumulator->Add("<JS WeakMap>"); 1075 accumulator->Add("<JS WeakMap>");
1073 break; 1076 break;
1074 } 1077 }
1075 case JS_REGEXP_TYPE: { 1078 case JS_REGEXP_TYPE: {
1076 accumulator->Add("<JS RegExp>"); 1079 accumulator->Add("<JS RegExp>");
1077 break; 1080 break;
(...skipping 1114 matching lines...) Expand 10 before | Expand all | Expand 10 after
2192 2195
2193 2196
2194 template <class T> 2197 template <class T>
2195 static Handle<T> MaybeNull(T* p) { 2198 static Handle<T> MaybeNull(T* p) {
2196 if (p == NULL) return Handle<T>::null(); 2199 if (p == NULL) return Handle<T>::null();
2197 return Handle<T>(p); 2200 return Handle<T>(p);
2198 } 2201 }
2199 2202
2200 2203
2201 Handle<Map> Map::FindTransitionedMap(MapHandleList* candidates) { 2204 Handle<Map> Map::FindTransitionedMap(MapHandleList* candidates) {
2202 ElementsKind kind = elements_kind(); 2205 ElementsKind elms_kind = elements_kind();
2203 Handle<Map> transitioned_map = Handle<Map>::null(); 2206 if (elms_kind == FAST_DOUBLE_ELEMENTS) {
2204 Handle<Map> current_map(this); 2207 bool dummy = true;
2205 bool packed = IsFastPackedElementsKind(kind); 2208 Handle<Map> fast_map =
2206 if (IsTransitionableFastElementsKind(kind)) { 2209 MaybeNull(LookupElementsTransitionMap(FAST_ELEMENTS, &dummy));
2207 while (CanTransitionToMoreGeneralFastElementsKind(kind, false)) { 2210 if (!fast_map.is_null() && ContainsMap(candidates, fast_map)) {
2208 kind = GetNextMoreGeneralFastElementsKind(kind, false); 2211 return fast_map;
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;
2219 } 2212 }
2213 return Handle<Map>::null();
2220 } 2214 }
2221 return transitioned_map; 2215 if (elms_kind == FAST_SMI_ONLY_ELEMENTS) {
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();
2222 } 2231 }
2223 2232
2224
2225 static Map* GetElementsTransitionMapFromDescriptor(Object* descriptor_contents, 2233 static Map* GetElementsTransitionMapFromDescriptor(Object* descriptor_contents,
2226 ElementsKind elements_kind) { 2234 ElementsKind elements_kind) {
2227 if (descriptor_contents->IsMap()) { 2235 if (descriptor_contents->IsMap()) {
2228 Map* map = Map::cast(descriptor_contents); 2236 Map* map = Map::cast(descriptor_contents);
2229 if (map->elements_kind() == elements_kind) { 2237 if (map->elements_kind() == elements_kind) {
2230 return map; 2238 return map;
2231 } 2239 }
2232 return NULL; 2240 return NULL;
2233 } 2241 }
2234 2242
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
2323 } else { 2331 } else {
2324 if (safe_to_add_transition != NULL) { 2332 if (safe_to_add_transition != NULL) {
2325 *safe_to_add_transition = false; 2333 *safe_to_add_transition = false;
2326 } 2334 }
2327 } 2335 }
2328 } 2336 }
2329 return NULL; 2337 return NULL;
2330 } 2338 }
2331 2339
2332 2340
2333 Map* Map::LookupElementsTransitionMap(ElementsKind to_kind, 2341 Map* Map::LookupElementsTransitionMap(ElementsKind elements_kind,
2334 bool* safe_to_add_transition) { 2342 bool* safe_to_add_transition) {
2335 ElementsKind from_kind = elements_kind(); 2343 // Special case: indirect SMI->FAST transition (cf. comment in
2336 if (IsFastElementsKind(from_kind) && IsFastElementsKind(to_kind)) { 2344 // AddElementsTransition()).
2337 if (!IsMoreGeneralElementsKindTransition(from_kind, to_kind)) { 2345 if (this->elements_kind() == FAST_SMI_ONLY_ELEMENTS &&
2338 if (safe_to_add_transition) *safe_to_add_transition = false; 2346 elements_kind == FAST_ELEMENTS) {
2339 return NULL; 2347 Map* double_map = this->LookupElementsTransitionMap(FAST_DOUBLE_ELEMENTS,
2340 } 2348 safe_to_add_transition);
2341 ElementsKind transitioned_from_kind = 2349 if (double_map == NULL) return double_map;
2342 GetNextMoreGeneralFastElementsKind(from_kind, false); 2350 return double_map->LookupElementsTransitionMap(FAST_ELEMENTS,
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,
2354 safe_to_add_transition); 2351 safe_to_add_transition);
2355 }
2356 } 2352 }
2357 Object* descriptor_contents = GetDescriptorContents( 2353 Object* descriptor_contents = GetDescriptorContents(
2358 elements_transition_sentinel_name(), safe_to_add_transition); 2354 elements_transition_sentinel_name(), safe_to_add_transition);
2359 if (descriptor_contents != NULL) { 2355 if (descriptor_contents != NULL) {
2360 Map* maybe_transition_map = 2356 Map* maybe_transition_map =
2361 GetElementsTransitionMapFromDescriptor(descriptor_contents, 2357 GetElementsTransitionMapFromDescriptor(descriptor_contents,
2362 to_kind); 2358 elements_kind);
2363 ASSERT(maybe_transition_map == NULL || maybe_transition_map->IsMap()); 2359 ASSERT(maybe_transition_map == NULL || maybe_transition_map->IsMap());
2364 return maybe_transition_map; 2360 return maybe_transition_map;
2365 } 2361 }
2366 return NULL; 2362 return NULL;
2367 } 2363 }
2368 2364
2369 2365
2370 MaybeObject* Map::AddElementsTransition(ElementsKind to_kind, 2366 MaybeObject* Map::AddElementsTransition(ElementsKind elements_kind,
2371 Map* transitioned_map) { 2367 Map* transitioned_map) {
2372 ElementsKind from_kind = elements_kind(); 2368 // The map transition graph should be a tree, therefore the transition
2373 if (IsFastElementsKind(from_kind) && IsFastElementsKind(to_kind)) { 2369 // from SMI to FAST elements is not done directly, but by going through
2374 ASSERT(IsMoreGeneralElementsKindTransition(from_kind, to_kind)); 2370 // DOUBLE elements first.
2375 ElementsKind transitioned_from_kind = 2371 if (this->elements_kind() == FAST_SMI_ONLY_ELEMENTS &&
2376 GetNextMoreGeneralFastElementsKind(from_kind, false); 2372 elements_kind == FAST_ELEMENTS) {
2377 // The map transitions graph should be a tree, therefore transitions to 2373 bool safe_to_add = true;
2378 // ElementsKind that are not adjacent in the ElementsKind sequence are not 2374 Map* double_map = this->LookupElementsTransitionMap(
2379 // done directly, but instead by going through intermediate ElementsKinds 2375 FAST_DOUBLE_ELEMENTS, &safe_to_add);
2380 // first. 2376 // This method is only called when safe_to_add_transition has been found
2381 if (to_kind != transitioned_from_kind) { 2377 // to be true earlier.
2382 bool safe_to_add = true; 2378 ASSERT(safe_to_add);
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);
2388 2379
2389 if (intermediate_map == NULL) { 2380 if (double_map == NULL) {
2390 MaybeObject* maybe_map = CopyDropTransitions(); 2381 MaybeObject* maybe_map = this->CopyDropTransitions();
2391 if (!maybe_map->To(&intermediate_map)) return maybe_map; 2382 if (!maybe_map->To(&double_map)) return maybe_map;
2392 intermediate_map->set_elements_kind(transitioned_from_kind); 2383 double_map->set_elements_kind(FAST_DOUBLE_ELEMENTS);
2393 MaybeObject* maybe_transition = AddElementsTransition( 2384 MaybeObject* maybe_double_transition = this->AddElementsTransition(
2394 transitioned_from_kind, intermediate_map); 2385 FAST_DOUBLE_ELEMENTS, double_map);
2395 if (maybe_transition->IsFailure()) return maybe_transition; 2386 if (maybe_double_transition->IsFailure()) return maybe_double_transition;
2396 }
2397 return intermediate_map->AddElementsTransition(to_kind, transitioned_map);
2398 } 2387 }
2388 return double_map->AddElementsTransition(FAST_ELEMENTS, transitioned_map);
2399 } 2389 }
2400 2390
2401 bool safe_to_add_transition = true; 2391 bool safe_to_add_transition = true;
2402 Object* descriptor_contents = GetDescriptorContents( 2392 Object* descriptor_contents = GetDescriptorContents(
2403 elements_transition_sentinel_name(), &safe_to_add_transition); 2393 elements_transition_sentinel_name(), &safe_to_add_transition);
2404 // This method is only called when safe_to_add_transition has been found 2394 // This method is only called when safe_to_add_transition has been found
2405 // to be true earlier. 2395 // to be true earlier.
2406 ASSERT(safe_to_add_transition); 2396 ASSERT(safe_to_add_transition);
2407 MaybeObject* maybe_new_contents = 2397 MaybeObject* maybe_new_contents =
2408 AddElementsTransitionMapToDescriptor(descriptor_contents, 2398 AddElementsTransitionMapToDescriptor(descriptor_contents,
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
2440 ElementsKind from_kind = current_map->elements_kind(); 2430 ElementsKind from_kind = current_map->elements_kind();
2441 2431
2442 if (from_kind == to_kind) return current_map; 2432 if (from_kind == to_kind) return current_map;
2443 2433
2444 // Only objects with FastProperties can have DescriptorArrays and can track 2434 // Only objects with FastProperties can have DescriptorArrays and can track
2445 // element-related maps. Also don't add descriptors to maps that are shared. 2435 // element-related maps. Also don't add descriptors to maps that are shared.
2446 bool safe_to_add_transition = HasFastProperties() && 2436 bool safe_to_add_transition = HasFastProperties() &&
2447 !current_map->IsUndefined() && 2437 !current_map->IsUndefined() &&
2448 !current_map->is_shared(); 2438 !current_map->is_shared();
2449 2439
2450 // Prevent long chains of DICTIONARY -> FAST_*_ELEMENTS maps caused by objects 2440 // Prevent long chains of DICTIONARY -> FAST_ELEMENTS maps caused by objects
2451 // with elements that switch back and forth between dictionary and fast 2441 // with elements that switch back and forth between dictionary and fast
2452 // element modes. 2442 // element mode.
2453 if (from_kind == DICTIONARY_ELEMENTS && 2443 if (from_kind == DICTIONARY_ELEMENTS && to_kind == FAST_ELEMENTS) {
2454 IsFastElementsKind(to_kind)) {
2455 safe_to_add_transition = false; 2444 safe_to_add_transition = false;
2456 } 2445 }
2457 2446
2458 if (safe_to_add_transition) { 2447 if (safe_to_add_transition) {
2459 // It's only safe to manipulate the descriptor array if it would be 2448 // It's only safe to manipulate the descriptor array if it would be
2460 // safe to add a transition. 2449 // safe to add a transition.
2461 Map* maybe_transition_map = current_map->LookupElementsTransitionMap( 2450 Map* maybe_transition_map = current_map->LookupElementsTransitionMap(
2462 to_kind, &safe_to_add_transition); 2451 to_kind, &safe_to_add_transition);
2463 if (maybe_transition_map != NULL) { 2452 if (maybe_transition_map != NULL) {
2464 return maybe_transition_map; 2453 return maybe_transition_map;
(...skipping 1015 matching lines...) Expand 10 before | Expand all | Expand 10 after
3480 // Find the backing store. 3469 // Find the backing store.
3481 FixedArrayBase* array = FixedArrayBase::cast(elements()); 3470 FixedArrayBase* array = FixedArrayBase::cast(elements());
3482 Map* old_map = array->map(); 3471 Map* old_map = array->map();
3483 bool is_arguments = 3472 bool is_arguments =
3484 (old_map == old_map->GetHeap()->non_strict_arguments_elements_map()); 3473 (old_map == old_map->GetHeap()->non_strict_arguments_elements_map());
3485 if (is_arguments) { 3474 if (is_arguments) {
3486 array = FixedArrayBase::cast(FixedArray::cast(array)->get(1)); 3475 array = FixedArrayBase::cast(FixedArray::cast(array)->get(1));
3487 } 3476 }
3488 if (array->IsDictionary()) return array; 3477 if (array->IsDictionary()) return array;
3489 3478
3490 ASSERT(HasFastSmiOrObjectElements() || 3479 ASSERT(HasFastElements() ||
3480 HasFastSmiOnlyElements() ||
3491 HasFastDoubleElements() || 3481 HasFastDoubleElements() ||
3492 HasFastArgumentsElements()); 3482 HasFastArgumentsElements());
3493 // Compute the effective length and allocate a new backing store. 3483 // Compute the effective length and allocate a new backing store.
3494 int length = IsJSArray() 3484 int length = IsJSArray()
3495 ? Smi::cast(JSArray::cast(this)->length())->value() 3485 ? Smi::cast(JSArray::cast(this)->length())->value()
3496 : array->length(); 3486 : array->length();
3497 int old_capacity = 0; 3487 int old_capacity = 0;
3498 int used_elements = 0; 3488 int used_elements = 0;
3499 GetElementsCapacityAndUsage(&old_capacity, &used_elements); 3489 GetElementsCapacityAndUsage(&old_capacity, &used_elements);
3500 SeededNumberDictionary* dictionary = NULL; 3490 SeededNumberDictionary* dictionary = NULL;
(...skipping 14 matching lines...) Expand all
3515 } else { 3505 } else {
3516 // Objects must be allocated in the old object space, since the 3506 // Objects must be allocated in the old object space, since the
3517 // overall number of HeapNumbers needed for the conversion might 3507 // overall number of HeapNumbers needed for the conversion might
3518 // exceed the capacity of new space, and we would fail repeatedly 3508 // exceed the capacity of new space, and we would fail repeatedly
3519 // trying to convert the FixedDoubleArray. 3509 // trying to convert the FixedDoubleArray.
3520 MaybeObject* maybe_value_object = 3510 MaybeObject* maybe_value_object =
3521 GetHeap()->AllocateHeapNumber(double_array->get_scalar(i), TENURED); 3511 GetHeap()->AllocateHeapNumber(double_array->get_scalar(i), TENURED);
3522 if (!maybe_value_object->ToObject(&value)) return maybe_value_object; 3512 if (!maybe_value_object->ToObject(&value)) return maybe_value_object;
3523 } 3513 }
3524 } else { 3514 } else {
3525 ASSERT(old_map->has_fast_smi_or_object_elements()); 3515 ASSERT(old_map->has_fast_elements() ||
3516 old_map->has_fast_smi_only_elements());
3526 value = FixedArray::cast(array)->get(i); 3517 value = FixedArray::cast(array)->get(i);
3527 } 3518 }
3528 PropertyDetails details = PropertyDetails(NONE, NORMAL); 3519 PropertyDetails details = PropertyDetails(NONE, NORMAL);
3529 if (!value->IsTheHole()) { 3520 if (!value->IsTheHole()) {
3530 Object* result; 3521 Object* result;
3531 MaybeObject* maybe_result = 3522 MaybeObject* maybe_result =
3532 dictionary->AddNumberEntry(i, value, details); 3523 dictionary->AddNumberEntry(i, value, details);
3533 if (!maybe_result->ToObject(&result)) return maybe_result; 3524 if (!maybe_result->ToObject(&result)) return maybe_result;
3534 dictionary = SeededNumberDictionary::cast(result); 3525 dictionary = SeededNumberDictionary::cast(result);
3535 } 3526 }
(...skipping 466 matching lines...) Expand 10 before | Expand all | Expand 10 after
4002 if (IsJSProxy()) { 3993 if (IsJSProxy()) {
4003 return JSProxy::cast(this)->DeletePropertyWithHandler(name, mode); 3994 return JSProxy::cast(this)->DeletePropertyWithHandler(name, mode);
4004 } 3995 }
4005 return JSObject::cast(this)->DeleteProperty(name, mode); 3996 return JSObject::cast(this)->DeleteProperty(name, mode);
4006 } 3997 }
4007 3998
4008 3999
4009 bool JSObject::ReferencesObjectFromElements(FixedArray* elements, 4000 bool JSObject::ReferencesObjectFromElements(FixedArray* elements,
4010 ElementsKind kind, 4001 ElementsKind kind,
4011 Object* object) { 4002 Object* object) {
4012 ASSERT(IsFastObjectElementsKind(kind) || 4003 ASSERT(kind == FAST_ELEMENTS ||
4013 kind == DICTIONARY_ELEMENTS); 4004 kind == DICTIONARY_ELEMENTS);
4014 if (IsFastObjectElementsKind(kind)) { 4005 if (kind == FAST_ELEMENTS) {
4015 int length = IsJSArray() 4006 int length = IsJSArray()
4016 ? Smi::cast(JSArray::cast(this)->length())->value() 4007 ? Smi::cast(JSArray::cast(this)->length())->value()
4017 : elements->length(); 4008 : elements->length();
4018 for (int i = 0; i < length; ++i) { 4009 for (int i = 0; i < length; ++i) {
4019 Object* element = elements->get(i); 4010 Object* element = elements->get(i);
4020 if (!element->IsTheHole() && element == object) return true; 4011 if (!element->IsTheHole() && element == object) return true;
4021 } 4012 }
4022 } else { 4013 } else {
4023 Object* key = 4014 Object* key =
4024 SeededNumberDictionary::cast(elements)->SlowReverseLookup(object); 4015 SeededNumberDictionary::cast(elements)->SlowReverseLookup(object);
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
4056 case EXTERNAL_PIXEL_ELEMENTS: 4047 case EXTERNAL_PIXEL_ELEMENTS:
4057 case EXTERNAL_BYTE_ELEMENTS: 4048 case EXTERNAL_BYTE_ELEMENTS:
4058 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 4049 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
4059 case EXTERNAL_SHORT_ELEMENTS: 4050 case EXTERNAL_SHORT_ELEMENTS:
4060 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 4051 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
4061 case EXTERNAL_INT_ELEMENTS: 4052 case EXTERNAL_INT_ELEMENTS:
4062 case EXTERNAL_UNSIGNED_INT_ELEMENTS: 4053 case EXTERNAL_UNSIGNED_INT_ELEMENTS:
4063 case EXTERNAL_FLOAT_ELEMENTS: 4054 case EXTERNAL_FLOAT_ELEMENTS:
4064 case EXTERNAL_DOUBLE_ELEMENTS: 4055 case EXTERNAL_DOUBLE_ELEMENTS:
4065 case FAST_DOUBLE_ELEMENTS: 4056 case FAST_DOUBLE_ELEMENTS:
4066 case FAST_HOLEY_DOUBLE_ELEMENTS:
4067 // Raw pixels and external arrays do not reference other 4057 // Raw pixels and external arrays do not reference other
4068 // objects. 4058 // objects.
4069 break; 4059 break;
4070 case FAST_SMI_ELEMENTS: 4060 case FAST_SMI_ONLY_ELEMENTS:
4071 case FAST_HOLEY_SMI_ELEMENTS:
4072 break; 4061 break;
4073 case FAST_ELEMENTS: 4062 case FAST_ELEMENTS:
4074 case FAST_HOLEY_ELEMENTS:
4075 case DICTIONARY_ELEMENTS: { 4063 case DICTIONARY_ELEMENTS: {
4076 FixedArray* elements = FixedArray::cast(this->elements()); 4064 FixedArray* elements = FixedArray::cast(this->elements());
4077 if (ReferencesObjectFromElements(elements, kind, obj)) return true; 4065 if (ReferencesObjectFromElements(elements, kind, obj)) return true;
4078 break; 4066 break;
4079 } 4067 }
4080 case NON_STRICT_ARGUMENTS_ELEMENTS: { 4068 case NON_STRICT_ARGUMENTS_ELEMENTS: {
4081 FixedArray* parameter_map = FixedArray::cast(elements()); 4069 FixedArray* parameter_map = FixedArray::cast(elements());
4082 // Check the mapped parameters. 4070 // Check the mapped parameters.
4083 int length = parameter_map->length(); 4071 int length = parameter_map->length();
4084 for (int i = 2; i < length; ++i) { 4072 for (int i = 2; i < length; ++i) {
4085 Object* value = parameter_map->get(i); 4073 Object* value = parameter_map->get(i);
4086 if (!value->IsTheHole() && value == obj) return true; 4074 if (!value->IsTheHole() && value == obj) return true;
4087 } 4075 }
4088 // Check the arguments. 4076 // Check the arguments.
4089 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); 4077 FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
4090 kind = arguments->IsDictionary() ? DICTIONARY_ELEMENTS : 4078 kind = arguments->IsDictionary() ? DICTIONARY_ELEMENTS : FAST_ELEMENTS;
4091 FAST_HOLEY_ELEMENTS;
4092 if (ReferencesObjectFromElements(arguments, kind, obj)) return true; 4079 if (ReferencesObjectFromElements(arguments, kind, obj)) return true;
4093 break; 4080 break;
4094 } 4081 }
4095 } 4082 }
4096 4083
4097 // For functions check the context. 4084 // For functions check the context.
4098 if (IsJSFunction()) { 4085 if (IsJSFunction()) {
4099 // Get the constructor function for arguments array. 4086 // Get the constructor function for arguments array.
4100 JSObject* arguments_boilerplate = 4087 JSObject* arguments_boilerplate =
4101 heap->isolate()->context()->global_context()-> 4088 heap->isolate()->context()->global_context()->
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after
4315 for (Object* current = this; 4302 for (Object* current = this;
4316 current != heap->null_value(); 4303 current != heap->null_value();
4317 current = JSObject::cast(current)->GetPrototype()) { 4304 current = JSObject::cast(current)->GetPrototype()) {
4318 JSReceiver::cast(current)->LocalLookup(name, result); 4305 JSReceiver::cast(current)->LocalLookup(name, result);
4319 if (result->IsProperty()) return; 4306 if (result->IsProperty()) return;
4320 } 4307 }
4321 result->NotFound(); 4308 result->NotFound();
4322 } 4309 }
4323 4310
4324 4311
4325 // Search object and its prototype chain for callback properties. 4312 // Search object and it's prototype chain for callback properties.
4326 void JSObject::LookupCallback(String* name, LookupResult* result) { 4313 void JSObject::LookupCallback(String* name, LookupResult* result) {
4327 Heap* heap = GetHeap(); 4314 Heap* heap = GetHeap();
4328 for (Object* current = this; 4315 for (Object* current = this;
4329 current != heap->null_value() && current->IsJSObject(); 4316 current != heap->null_value() && current->IsJSObject();
4330 current = JSObject::cast(current)->GetPrototype()) { 4317 current = JSObject::cast(current)->GetPrototype()) {
4331 JSObject::cast(current)->LocalLookupRealNamedProperty(name, result); 4318 JSObject::cast(current)->LocalLookupRealNamedProperty(name, result);
4332 if (result->IsFound() && result->type() == CALLBACKS) return; 4319 if (result->IsFound() && result->type() == CALLBACKS) return;
4333 } 4320 }
4334 result->NotFound(); 4321 result->NotFound();
4335 } 4322 }
(...skipping 23 matching lines...) Expand all
4359 } 4346 }
4360 return false; 4347 return false;
4361 } 4348 }
4362 4349
4363 4350
4364 MaybeObject* JSObject::DefineElementAccessor(uint32_t index, 4351 MaybeObject* JSObject::DefineElementAccessor(uint32_t index,
4365 Object* getter, 4352 Object* getter,
4366 Object* setter, 4353 Object* setter,
4367 PropertyAttributes attributes) { 4354 PropertyAttributes attributes) {
4368 switch (GetElementsKind()) { 4355 switch (GetElementsKind()) {
4369 case FAST_SMI_ELEMENTS: 4356 case FAST_SMI_ONLY_ELEMENTS:
4370 case FAST_ELEMENTS: 4357 case FAST_ELEMENTS:
4371 case FAST_DOUBLE_ELEMENTS: 4358 case FAST_DOUBLE_ELEMENTS:
4372 case FAST_HOLEY_SMI_ELEMENTS:
4373 case FAST_HOLEY_ELEMENTS:
4374 case FAST_HOLEY_DOUBLE_ELEMENTS:
4375 break; 4359 break;
4376 case EXTERNAL_PIXEL_ELEMENTS: 4360 case EXTERNAL_PIXEL_ELEMENTS:
4377 case EXTERNAL_BYTE_ELEMENTS: 4361 case EXTERNAL_BYTE_ELEMENTS:
4378 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 4362 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
4379 case EXTERNAL_SHORT_ELEMENTS: 4363 case EXTERNAL_SHORT_ELEMENTS:
4380 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 4364 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
4381 case EXTERNAL_INT_ELEMENTS: 4365 case EXTERNAL_INT_ELEMENTS:
4382 case EXTERNAL_UNSIGNED_INT_ELEMENTS: 4366 case EXTERNAL_UNSIGNED_INT_ELEMENTS:
4383 case EXTERNAL_FLOAT_ELEMENTS: 4367 case EXTERNAL_FLOAT_ELEMENTS:
4384 case EXTERNAL_DOUBLE_ELEMENTS: 4368 case EXTERNAL_DOUBLE_ELEMENTS:
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
4454 accessors->SetComponents(getter, setter); 4438 accessors->SetComponents(getter, setter);
4455 return SetPropertyCallback(name, accessors, attributes); 4439 return SetPropertyCallback(name, accessors, attributes);
4456 } 4440 }
4457 4441
4458 4442
4459 bool JSObject::CanSetCallback(String* name) { 4443 bool JSObject::CanSetCallback(String* name) {
4460 ASSERT(!IsAccessCheckNeeded() || 4444 ASSERT(!IsAccessCheckNeeded() ||
4461 GetIsolate()->MayNamedAccess(this, name, v8::ACCESS_SET)); 4445 GetIsolate()->MayNamedAccess(this, name, v8::ACCESS_SET));
4462 4446
4463 // Check if there is an API defined callback object which prohibits 4447 // Check if there is an API defined callback object which prohibits
4464 // callback overwriting in this object or its prototype chain. 4448 // callback overwriting in this object or it's prototype chain.
4465 // This mechanism is needed for instance in a browser setting, where 4449 // This mechanism is needed for instance in a browser setting, where
4466 // certain accessors such as window.location should not be allowed 4450 // certain accessors such as window.location should not be allowed
4467 // to be overwritten because allowing overwriting could potentially 4451 // to be overwritten because allowing overwriting could potentially
4468 // cause security problems. 4452 // cause security problems.
4469 LookupResult callback_result(GetIsolate()); 4453 LookupResult callback_result(GetIsolate());
4470 LookupCallback(name, &callback_result); 4454 LookupCallback(name, &callback_result);
4471 if (callback_result.IsProperty()) { 4455 if (callback_result.IsProperty()) {
4472 Object* obj = callback_result.GetCallbackObject(); 4456 Object* obj = callback_result.GetCallbackObject();
4473 if (obj->IsAccessorInfo() && 4457 if (obj->IsAccessorInfo() &&
4474 AccessorInfo::cast(obj)->prohibits_overwriting()) { 4458 AccessorInfo::cast(obj)->prohibits_overwriting()) {
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
4625 } 4609 }
4626 4610
4627 uint32_t index = 0; 4611 uint32_t index = 0;
4628 bool is_element = name->AsArrayIndex(&index); 4612 bool is_element = name->AsArrayIndex(&index);
4629 4613
4630 if (is_element) { 4614 if (is_element) {
4631 if (IsJSArray()) return isolate->heap()->undefined_value(); 4615 if (IsJSArray()) return isolate->heap()->undefined_value();
4632 4616
4633 // Accessors overwrite previous callbacks (cf. with getters/setters). 4617 // Accessors overwrite previous callbacks (cf. with getters/setters).
4634 switch (GetElementsKind()) { 4618 switch (GetElementsKind()) {
4635 case FAST_SMI_ELEMENTS: 4619 case FAST_SMI_ONLY_ELEMENTS:
4636 case FAST_ELEMENTS: 4620 case FAST_ELEMENTS:
4637 case FAST_DOUBLE_ELEMENTS: 4621 case FAST_DOUBLE_ELEMENTS:
4638 case FAST_HOLEY_SMI_ELEMENTS:
4639 case FAST_HOLEY_ELEMENTS:
4640 case FAST_HOLEY_DOUBLE_ELEMENTS:
4641 break; 4622 break;
4642 case EXTERNAL_PIXEL_ELEMENTS: 4623 case EXTERNAL_PIXEL_ELEMENTS:
4643 case EXTERNAL_BYTE_ELEMENTS: 4624 case EXTERNAL_BYTE_ELEMENTS:
4644 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 4625 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
4645 case EXTERNAL_SHORT_ELEMENTS: 4626 case EXTERNAL_SHORT_ELEMENTS:
4646 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 4627 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
4647 case EXTERNAL_INT_ELEMENTS: 4628 case EXTERNAL_INT_ELEMENTS:
4648 case EXTERNAL_UNSIGNED_INT_ELEMENTS: 4629 case EXTERNAL_UNSIGNED_INT_ELEMENTS:
4649 case EXTERNAL_FLOAT_ELEMENTS: 4630 case EXTERNAL_FLOAT_ELEMENTS:
4650 case EXTERNAL_DOUBLE_ELEMENTS: 4631 case EXTERNAL_DOUBLE_ELEMENTS:
(...skipping 3768 matching lines...) Expand 10 before | Expand all | Expand 10 after
8419 PrintF("RelocInfo (size = %d)\n", relocation_size()); 8400 PrintF("RelocInfo (size = %d)\n", relocation_size());
8420 for (RelocIterator it(this); !it.done(); it.next()) it.rinfo()->Print(out); 8401 for (RelocIterator it(this); !it.done(); it.next()) it.rinfo()->Print(out);
8421 PrintF(out, "\n"); 8402 PrintF(out, "\n");
8422 } 8403 }
8423 #endif // ENABLE_DISASSEMBLER 8404 #endif // ENABLE_DISASSEMBLER
8424 8405
8425 8406
8426 MaybeObject* JSObject::SetFastElementsCapacityAndLength( 8407 MaybeObject* JSObject::SetFastElementsCapacityAndLength(
8427 int capacity, 8408 int capacity,
8428 int length, 8409 int length,
8429 SetFastElementsCapacitySmiMode smi_mode) { 8410 SetFastElementsCapacityMode set_capacity_mode) {
8430 Heap* heap = GetHeap(); 8411 Heap* heap = GetHeap();
8431 // We should never end in here with a pixel or external array. 8412 // We should never end in here with a pixel or external array.
8432 ASSERT(!HasExternalArrayElements()); 8413 ASSERT(!HasExternalArrayElements());
8433 8414
8434 // Allocate a new fast elements backing store. 8415 // Allocate a new fast elements backing store.
8435 FixedArray* new_elements; 8416 FixedArray* new_elements;
8436 { MaybeObject* maybe = heap->AllocateFixedArrayWithHoles(capacity); 8417 { MaybeObject* maybe = heap->AllocateFixedArrayWithHoles(capacity);
8437 if (!maybe->To(&new_elements)) return maybe; 8418 if (!maybe->To(&new_elements)) return maybe;
8438 } 8419 }
8439 8420
8421 // Find the new map to use for this object if there is a map change.
8422 Map* new_map = NULL;
8423 if (elements()->map() != heap->non_strict_arguments_elements_map()) {
8424 // The resized array has FAST_SMI_ONLY_ELEMENTS if the capacity mode forces
8425 // it, or if it's allowed and the old elements array contained only SMIs.
8426 bool has_fast_smi_only_elements =
8427 (set_capacity_mode == kForceSmiOnlyElements) ||
8428 ((set_capacity_mode == kAllowSmiOnlyElements) &&
8429 (elements()->map()->has_fast_smi_only_elements() ||
8430 elements() == heap->empty_fixed_array()));
8431 ElementsKind elements_kind = has_fast_smi_only_elements
8432 ? FAST_SMI_ONLY_ELEMENTS
8433 : FAST_ELEMENTS;
8434 MaybeObject* maybe = GetElementsTransitionMap(GetIsolate(), elements_kind);
8435 if (!maybe->To(&new_map)) return maybe;
8436 }
8437
8438 FixedArrayBase* old_elements = elements();
8440 ElementsKind elements_kind = GetElementsKind(); 8439 ElementsKind elements_kind = GetElementsKind();
8441 ElementsKind new_elements_kind;
8442 // The resized array has FAST_*_SMI_ELEMENTS if the capacity mode forces it,
8443 // or if it's allowed and the old elements array contained only SMIs.
8444 bool has_fast_smi_elements =
8445 (smi_mode == kForceSmiElements) ||
8446 ((smi_mode == kAllowSmiElements) && HasFastSmiElements());
8447 if (has_fast_smi_elements) {
8448 if (IsHoleyElementsKind(elements_kind)) {
8449 new_elements_kind = FAST_HOLEY_SMI_ELEMENTS;
8450 } else {
8451 new_elements_kind = FAST_SMI_ELEMENTS;
8452 }
8453 } else {
8454 if (IsHoleyElementsKind(elements_kind)) {
8455 new_elements_kind = FAST_HOLEY_ELEMENTS;
8456 } else {
8457 new_elements_kind = FAST_ELEMENTS;
8458 }
8459 }
8460 FixedArrayBase* old_elements = elements();
8461 ElementsAccessor* accessor = ElementsAccessor::ForKind(elements_kind); 8440 ElementsAccessor* accessor = ElementsAccessor::ForKind(elements_kind);
8441 ElementsKind to_kind = (elements_kind == FAST_SMI_ONLY_ELEMENTS)
8442 ? FAST_SMI_ONLY_ELEMENTS
8443 : FAST_ELEMENTS;
8462 { MaybeObject* maybe_obj = 8444 { MaybeObject* maybe_obj =
8463 accessor->CopyElements(this, new_elements, new_elements_kind); 8445 accessor->CopyElements(this, new_elements, to_kind);
8464 if (maybe_obj->IsFailure()) return maybe_obj; 8446 if (maybe_obj->IsFailure()) return maybe_obj;
8465 } 8447 }
8466 if (elements_kind != NON_STRICT_ARGUMENTS_ELEMENTS) { 8448 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();
8474 set_map_and_elements(new_map, new_elements); 8449 set_map_and_elements(new_map, new_elements);
8475 } else { 8450 } else {
8476 FixedArray* parameter_map = FixedArray::cast(old_elements); 8451 FixedArray* parameter_map = FixedArray::cast(old_elements);
8477 parameter_map->set(1, new_elements); 8452 parameter_map->set(1, new_elements);
8478 } 8453 }
8479 8454
8480 if (FLAG_trace_elements_transitions) { 8455 if (FLAG_trace_elements_transitions) {
8481 PrintElementsTransition(stdout, elements_kind, old_elements, 8456 PrintElementsTransition(stdout, elements_kind, old_elements,
8482 GetElementsKind(), new_elements); 8457 GetElementsKind(), new_elements);
8483 } 8458 }
8484 8459
8460 // Update the length if necessary.
8485 if (IsJSArray()) { 8461 if (IsJSArray()) {
8486 JSArray::cast(this)->set_length(Smi::FromInt(length)); 8462 JSArray::cast(this)->set_length(Smi::FromInt(length));
8487 } 8463 }
8464
8488 return new_elements; 8465 return new_elements;
8489 } 8466 }
8490 8467
8491 8468
8492 MaybeObject* JSObject::SetFastDoubleElementsCapacityAndLength( 8469 MaybeObject* JSObject::SetFastDoubleElementsCapacityAndLength(
8493 int capacity, 8470 int capacity,
8494 int length) { 8471 int length) {
8495 Heap* heap = GetHeap(); 8472 Heap* heap = GetHeap();
8496 // We should never end in here with a pixel or external array. 8473 // We should never end in here with a pixel or external array.
8497 ASSERT(!HasExternalArrayElements()); 8474 ASSERT(!HasExternalArrayElements());
8498 8475
8499 FixedArrayBase* elems; 8476 FixedArrayBase* elems;
8500 { MaybeObject* maybe_obj = 8477 { MaybeObject* maybe_obj =
8501 heap->AllocateUninitializedFixedDoubleArray(capacity); 8478 heap->AllocateUninitializedFixedDoubleArray(capacity);
8502 if (!maybe_obj->To(&elems)) return maybe_obj; 8479 if (!maybe_obj->To(&elems)) return maybe_obj;
8503 } 8480 }
8504 8481
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
8513 Map* new_map; 8482 Map* new_map;
8514 { MaybeObject* maybe_obj = 8483 { MaybeObject* maybe_obj =
8515 GetElementsTransitionMap(heap->isolate(), new_elements_kind); 8484 GetElementsTransitionMap(heap->isolate(), FAST_DOUBLE_ELEMENTS);
8516 if (!maybe_obj->To(&new_map)) return maybe_obj; 8485 if (!maybe_obj->To(&new_map)) return maybe_obj;
8517 } 8486 }
8518 8487
8519 FixedArrayBase* old_elements = elements(); 8488 FixedArrayBase* old_elements = elements();
8489 ElementsKind elements_kind = GetElementsKind();
8520 ElementsAccessor* accessor = ElementsAccessor::ForKind(elements_kind); 8490 ElementsAccessor* accessor = ElementsAccessor::ForKind(elements_kind);
8521 { MaybeObject* maybe_obj = 8491 { MaybeObject* maybe_obj =
8522 accessor->CopyElements(this, elems, FAST_DOUBLE_ELEMENTS); 8492 accessor->CopyElements(this, elems, FAST_DOUBLE_ELEMENTS);
8523 if (maybe_obj->IsFailure()) return maybe_obj; 8493 if (maybe_obj->IsFailure()) return maybe_obj;
8524 } 8494 }
8525 if (elements_kind != NON_STRICT_ARGUMENTS_ELEMENTS) { 8495 if (elements_kind != NON_STRICT_ARGUMENTS_ELEMENTS) {
8526 ValidateElements();
8527 set_map_and_elements(new_map, elems); 8496 set_map_and_elements(new_map, elems);
8528 } else { 8497 } else {
8529 FixedArray* parameter_map = FixedArray::cast(old_elements); 8498 FixedArray* parameter_map = FixedArray::cast(old_elements);
8530 parameter_map->set(1, elems); 8499 parameter_map->set(1, elems);
8531 } 8500 }
8532 8501
8533 if (FLAG_trace_elements_transitions) { 8502 if (FLAG_trace_elements_transitions) {
8534 PrintElementsTransition(stdout, elements_kind, old_elements, 8503 PrintElementsTransition(stdout, elements_kind, old_elements,
8535 GetElementsKind(), elems); 8504 FAST_DOUBLE_ELEMENTS, elems);
8536 } 8505 }
8537 8506
8538 if (IsJSArray()) { 8507 if (IsJSArray()) {
8539 JSArray::cast(this)->set_length(Smi::FromInt(length)); 8508 JSArray::cast(this)->set_length(Smi::FromInt(length));
8540 } 8509 }
8541 8510
8542 return this; 8511 return this;
8543 } 8512 }
8544 8513
8545 8514
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after
8805 return HasElementWithInterceptor(this, index) ? INTERCEPTED_ELEMENT 8774 return HasElementWithInterceptor(this, index) ? INTERCEPTED_ELEMENT
8806 : UNDEFINED_ELEMENT; 8775 : UNDEFINED_ELEMENT;
8807 } 8776 }
8808 8777
8809 // Handle [] on String objects. 8778 // Handle [] on String objects.
8810 if (this->IsStringObjectWithCharacterAt(index)) { 8779 if (this->IsStringObjectWithCharacterAt(index)) {
8811 return STRING_CHARACTER_ELEMENT; 8780 return STRING_CHARACTER_ELEMENT;
8812 } 8781 }
8813 8782
8814 switch (GetElementsKind()) { 8783 switch (GetElementsKind()) {
8815 case FAST_SMI_ELEMENTS: 8784 case FAST_SMI_ONLY_ELEMENTS:
8816 case FAST_ELEMENTS: 8785 case FAST_ELEMENTS: {
8817 case FAST_HOLEY_SMI_ELEMENTS:
8818 case FAST_HOLEY_ELEMENTS: {
8819 uint32_t length = IsJSArray() ? 8786 uint32_t length = IsJSArray() ?
8820 static_cast<uint32_t> 8787 static_cast<uint32_t>
8821 (Smi::cast(JSArray::cast(this)->length())->value()) : 8788 (Smi::cast(JSArray::cast(this)->length())->value()) :
8822 static_cast<uint32_t>(FixedArray::cast(elements())->length()); 8789 static_cast<uint32_t>(FixedArray::cast(elements())->length());
8823 if ((index < length) && 8790 if ((index < length) &&
8824 !FixedArray::cast(elements())->get(index)->IsTheHole()) { 8791 !FixedArray::cast(elements())->get(index)->IsTheHole()) {
8825 return FAST_ELEMENT; 8792 return FAST_ELEMENT;
8826 } 8793 }
8827 break; 8794 break;
8828 } 8795 }
8829 case FAST_DOUBLE_ELEMENTS: 8796 case FAST_DOUBLE_ELEMENTS: {
8830 case FAST_HOLEY_DOUBLE_ELEMENTS: {
8831 uint32_t length = IsJSArray() ? 8797 uint32_t length = IsJSArray() ?
8832 static_cast<uint32_t> 8798 static_cast<uint32_t>
8833 (Smi::cast(JSArray::cast(this)->length())->value()) : 8799 (Smi::cast(JSArray::cast(this)->length())->value()) :
8834 static_cast<uint32_t>(FixedDoubleArray::cast(elements())->length()); 8800 static_cast<uint32_t>(FixedDoubleArray::cast(elements())->length());
8835 if ((index < length) && 8801 if ((index < length) &&
8836 !FixedDoubleArray::cast(elements())->is_the_hole(index)) { 8802 !FixedDoubleArray::cast(elements())->is_the_hole(index)) {
8837 return FAST_ELEMENT; 8803 return FAST_ELEMENT;
8838 } 8804 }
8839 break; 8805 break;
8840 } 8806 }
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after
9104 } 9070 }
9105 9071
9106 9072
9107 // Adding n elements in fast case is O(n*n). 9073 // Adding n elements in fast case is O(n*n).
9108 // Note: revisit design to have dual undefined values to capture absent 9074 // Note: revisit design to have dual undefined values to capture absent
9109 // elements. 9075 // elements.
9110 MaybeObject* JSObject::SetFastElement(uint32_t index, 9076 MaybeObject* JSObject::SetFastElement(uint32_t index,
9111 Object* value, 9077 Object* value,
9112 StrictModeFlag strict_mode, 9078 StrictModeFlag strict_mode,
9113 bool check_prototype) { 9079 bool check_prototype) {
9114 ASSERT(HasFastSmiOrObjectElements() || 9080 ASSERT(HasFastTypeElements() ||
9115 HasFastArgumentsElements()); 9081 HasFastArgumentsElements());
9116 9082
9117 FixedArray* backing_store = FixedArray::cast(elements()); 9083 FixedArray* backing_store = FixedArray::cast(elements());
9118 if (backing_store->map() == GetHeap()->non_strict_arguments_elements_map()) { 9084 if (backing_store->map() == GetHeap()->non_strict_arguments_elements_map()) {
9119 backing_store = FixedArray::cast(backing_store->get(1)); 9085 backing_store = FixedArray::cast(backing_store->get(1));
9120 } else { 9086 } else {
9121 MaybeObject* maybe = EnsureWritableFastElements(); 9087 MaybeObject* maybe = EnsureWritableFastElements();
9122 if (!maybe->To(&backing_store)) return maybe; 9088 if (!maybe->To(&backing_store)) return maybe;
9123 } 9089 }
9124 uint32_t capacity = static_cast<uint32_t>(backing_store->length()); 9090 uint32_t capacity = static_cast<uint32_t>(backing_store->length());
9125 9091
9126 if (check_prototype && 9092 if (check_prototype &&
9127 (index >= capacity || backing_store->get(index)->IsTheHole())) { 9093 (index >= capacity || backing_store->get(index)->IsTheHole())) {
9128 bool found; 9094 bool found;
9129 MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index, 9095 MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index,
9130 value, 9096 value,
9131 &found, 9097 &found,
9132 strict_mode); 9098 strict_mode);
9133 if (found) return result; 9099 if (found) return result;
9134 } 9100 }
9135 9101
9136 uint32_t new_capacity = capacity; 9102 uint32_t new_capacity = capacity;
9137 // Check if the length property of this object needs to be updated. 9103 // Check if the length property of this object needs to be updated.
9138 uint32_t array_length = 0; 9104 uint32_t array_length = 0;
9139 bool must_update_array_length = false; 9105 bool must_update_array_length = false;
9140 bool introduces_holes = true;
9141 if (IsJSArray()) { 9106 if (IsJSArray()) {
9142 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length)); 9107 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length));
9143 introduces_holes = index > array_length;
9144 if (index >= array_length) { 9108 if (index >= array_length) {
9145 must_update_array_length = true; 9109 must_update_array_length = true;
9146 array_length = index + 1; 9110 array_length = index + 1;
9147 } 9111 }
9148 } else {
9149 introduces_holes = index >= capacity;
9150 } 9112 }
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
9163 // Check if the capacity of the backing store needs to be increased, or if 9113 // Check if the capacity of the backing store needs to be increased, or if
9164 // a transition to slow elements is necessary. 9114 // a transition to slow elements is necessary.
9165 if (index >= capacity) { 9115 if (index >= capacity) {
9166 bool convert_to_slow = true; 9116 bool convert_to_slow = true;
9167 if ((index - capacity) < kMaxGap) { 9117 if ((index - capacity) < kMaxGap) {
9168 new_capacity = NewElementsCapacity(index + 1); 9118 new_capacity = NewElementsCapacity(index + 1);
9169 ASSERT(new_capacity > index); 9119 ASSERT(new_capacity > index);
9170 if (!ShouldConvertToSlowElements(new_capacity)) { 9120 if (!ShouldConvertToSlowElements(new_capacity)) {
9171 convert_to_slow = false; 9121 convert_to_slow = false;
9172 } 9122 }
9173 } 9123 }
9174 if (convert_to_slow) { 9124 if (convert_to_slow) {
9175 MaybeObject* result = NormalizeElements(); 9125 MaybeObject* result = NormalizeElements();
9176 if (result->IsFailure()) return result; 9126 if (result->IsFailure()) return result;
9177 return SetDictionaryElement(index, value, NONE, strict_mode, 9127 return SetDictionaryElement(index, value, NONE, strict_mode,
9178 check_prototype); 9128 check_prototype);
9179 } 9129 }
9180 } 9130 }
9181 // Convert to fast double elements if appropriate. 9131 // Convert to fast double elements if appropriate.
9182 if (HasFastSmiElements() && !value->IsSmi() && value->IsNumber()) { 9132 if (HasFastSmiOnlyElements() && !value->IsSmi() && value->IsNumber()) {
9183 MaybeObject* maybe = 9133 MaybeObject* maybe =
9184 SetFastDoubleElementsCapacityAndLength(new_capacity, array_length); 9134 SetFastDoubleElementsCapacityAndLength(new_capacity, array_length);
9185 if (maybe->IsFailure()) return maybe; 9135 if (maybe->IsFailure()) return maybe;
9186 FixedDoubleArray::cast(elements())->set(index, value->Number()); 9136 FixedDoubleArray::cast(elements())->set(index, value->Number());
9187 ValidateElements();
9188 return value; 9137 return value;
9189 } 9138 }
9190 // Change elements kind from Smi-only to generic FAST if necessary. 9139 // Change elements kind from SMI_ONLY to generic FAST if necessary.
9191 if (HasFastSmiElements() && !value->IsSmi()) { 9140 if (HasFastSmiOnlyElements() && !value->IsSmi()) {
9192 Map* new_map; 9141 Map* new_map;
9193 ElementsKind kind = HasFastHoleyElements() 9142 { MaybeObject* maybe_new_map = GetElementsTransitionMap(GetIsolate(),
9194 ? FAST_HOLEY_ELEMENTS 9143 FAST_ELEMENTS);
9195 : FAST_ELEMENTS; 9144 if (!maybe_new_map->To(&new_map)) return maybe_new_map;
9196 MaybeObject* maybe_new_map = GetElementsTransitionMap(GetIsolate(), 9145 }
9197 kind);
9198 if (!maybe_new_map->To(&new_map)) return maybe_new_map;
9199
9200 set_map(new_map); 9146 set_map(new_map);
9147 if (FLAG_trace_elements_transitions) {
9148 PrintElementsTransition(stdout, FAST_SMI_ONLY_ELEMENTS, elements(),
9149 FAST_ELEMENTS, elements());
9150 }
9201 } 9151 }
9202 // Increase backing store capacity if that's been decided previously. 9152 // Increase backing store capacity if that's been decided previously.
9203 if (new_capacity != capacity) { 9153 if (new_capacity != capacity) {
9204 FixedArray* new_elements; 9154 FixedArray* new_elements;
9205 SetFastElementsCapacitySmiMode smi_mode = 9155 SetFastElementsCapacityMode set_capacity_mode =
9206 value->IsSmi() && HasFastSmiElements() 9156 value->IsSmi() && HasFastSmiOnlyElements()
9207 ? kAllowSmiElements 9157 ? kAllowSmiOnlyElements
9208 : kDontAllowSmiElements; 9158 : kDontAllowSmiOnlyElements;
9209 { MaybeObject* maybe = 9159 { MaybeObject* maybe =
9210 SetFastElementsCapacityAndLength(new_capacity, 9160 SetFastElementsCapacityAndLength(new_capacity,
9211 array_length, 9161 array_length,
9212 smi_mode); 9162 set_capacity_mode);
9213 if (!maybe->To(&new_elements)) return maybe; 9163 if (!maybe->To(&new_elements)) return maybe;
9214 } 9164 }
9215 new_elements->set(index, value); 9165 new_elements->set(index, value);
9216 ValidateElements();
9217 return value; 9166 return value;
9218 } 9167 }
9219
9220 // Finally, set the new element and length. 9168 // Finally, set the new element and length.
9221 ASSERT(elements()->IsFixedArray()); 9169 ASSERT(elements()->IsFixedArray());
9222 backing_store->set(index, value); 9170 backing_store->set(index, value);
9223 if (must_update_array_length) { 9171 if (must_update_array_length) {
9224 JSArray::cast(this)->set_length(Smi::FromInt(array_length)); 9172 JSArray::cast(this)->set_length(Smi::FromInt(array_length));
9225 } 9173 }
9226 return value; 9174 return value;
9227 } 9175 }
9228 9176
9229 9177
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
9333 } 9281 }
9334 9282
9335 // Attempt to put this object back in fast case. 9283 // Attempt to put this object back in fast case.
9336 if (ShouldConvertToFastElements()) { 9284 if (ShouldConvertToFastElements()) {
9337 uint32_t new_length = 0; 9285 uint32_t new_length = 0;
9338 if (IsJSArray()) { 9286 if (IsJSArray()) {
9339 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&new_length)); 9287 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&new_length));
9340 } else { 9288 } else {
9341 new_length = dictionary->max_number_key() + 1; 9289 new_length = dictionary->max_number_key() + 1;
9342 } 9290 }
9343 SetFastElementsCapacitySmiMode smi_mode = FLAG_smi_only_arrays 9291 SetFastElementsCapacityMode set_capacity_mode = FLAG_smi_only_arrays
9344 ? kAllowSmiElements 9292 ? kAllowSmiOnlyElements
9345 : kDontAllowSmiElements; 9293 : kDontAllowSmiOnlyElements;
9346 bool has_smi_only_elements = false; 9294 bool has_smi_only_elements = false;
9347 bool should_convert_to_fast_double_elements = 9295 bool should_convert_to_fast_double_elements =
9348 ShouldConvertToFastDoubleElements(&has_smi_only_elements); 9296 ShouldConvertToFastDoubleElements(&has_smi_only_elements);
9349 if (has_smi_only_elements) { 9297 if (has_smi_only_elements) {
9350 smi_mode = kForceSmiElements; 9298 set_capacity_mode = kForceSmiOnlyElements;
9351 } 9299 }
9352 MaybeObject* result = should_convert_to_fast_double_elements 9300 MaybeObject* result = should_convert_to_fast_double_elements
9353 ? SetFastDoubleElementsCapacityAndLength(new_length, new_length) 9301 ? SetFastDoubleElementsCapacityAndLength(new_length, new_length)
9354 : SetFastElementsCapacityAndLength(new_length, 9302 : SetFastElementsCapacityAndLength(new_length,
9355 new_length, 9303 new_length,
9356 smi_mode); 9304 set_capacity_mode);
9357 ValidateElements();
9358 if (result->IsFailure()) return result; 9305 if (result->IsFailure()) return result;
9359 #ifdef DEBUG 9306 #ifdef DEBUG
9360 if (FLAG_trace_normalization) { 9307 if (FLAG_trace_normalization) {
9361 PrintF("Object elements are fast case again:\n"); 9308 PrintF("Object elements are fast case again:\n");
9362 Print(); 9309 Print();
9363 } 9310 }
9364 #endif 9311 #endif
9365 } 9312 }
9366 return value; 9313 return value;
9367 } 9314 }
(...skipping 18 matching lines...) Expand all
9386 MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index, 9333 MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index,
9387 value, 9334 value,
9388 &found, 9335 &found,
9389 strict_mode); 9336 strict_mode);
9390 if (found) return result; 9337 if (found) return result;
9391 } 9338 }
9392 9339
9393 // If the value object is not a heap number, switch to fast elements and try 9340 // If the value object is not a heap number, switch to fast elements and try
9394 // again. 9341 // again.
9395 bool value_is_smi = value->IsSmi(); 9342 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
9405 if (!value->IsNumber()) { 9343 if (!value->IsNumber()) {
9344 Object* obj;
9345 uint32_t length = elms_length;
9346 if (IsJSArray()) {
9347 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length));
9348 }
9406 MaybeObject* maybe_obj = SetFastElementsCapacityAndLength( 9349 MaybeObject* maybe_obj = SetFastElementsCapacityAndLength(
9407 elms_length, 9350 elms_length,
9408 length, 9351 length,
9409 kDontAllowSmiElements); 9352 kDontAllowSmiOnlyElements);
9410 if (maybe_obj->IsFailure()) return maybe_obj; 9353 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
9411 maybe_obj = SetFastElement(index, value, strict_mode, check_prototype); 9354 return SetFastElement(index,
9412 if (maybe_obj->IsFailure()) return maybe_obj; 9355 value,
9413 ValidateElements(); 9356 strict_mode,
9414 return maybe_obj; 9357 check_prototype);
9415 } 9358 }
9416 9359
9417 double double_value = value_is_smi 9360 double double_value = value_is_smi
9418 ? static_cast<double>(Smi::cast(value)->value()) 9361 ? static_cast<double>(Smi::cast(value)->value())
9419 : HeapNumber::cast(value)->value(); 9362 : HeapNumber::cast(value)->value();
9420 9363
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
9430 // Check whether there is extra space in the fixed array. 9364 // Check whether there is extra space in the fixed array.
9431 if (index < elms_length) { 9365 if (index < elms_length) {
9432 FixedDoubleArray* elms = FixedDoubleArray::cast(elements()); 9366 FixedDoubleArray* elms = FixedDoubleArray::cast(elements());
9433 elms->set(index, double_value); 9367 elms->set(index, double_value);
9434 if (IsJSArray()) { 9368 if (IsJSArray()) {
9435 // Update the length of the array if needed. 9369 // Update the length of the array if needed.
9436 uint32_t array_length = 0; 9370 uint32_t array_length = 0;
9437 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length)); 9371 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length));
9438 if (index >= array_length) { 9372 if (index >= array_length) {
9439 JSArray::cast(this)->set_length(Smi::FromInt(index + 1)); 9373 JSArray::cast(this)->set_length(Smi::FromInt(index + 1));
9440 } 9374 }
9441 } 9375 }
9442 return value; 9376 return value;
9443 } 9377 }
9444 9378
9445 // Allow gap in fast case. 9379 // Allow gap in fast case.
9446 if ((index - elms_length) < kMaxGap) { 9380 if ((index - elms_length) < kMaxGap) {
9447 // Try allocating extra space. 9381 // Try allocating extra space.
9448 int new_capacity = NewElementsCapacity(index+1); 9382 int new_capacity = NewElementsCapacity(index+1);
9449 if (!ShouldConvertToSlowElements(new_capacity)) { 9383 if (!ShouldConvertToSlowElements(new_capacity)) {
9450 ASSERT(static_cast<uint32_t>(new_capacity) > index); 9384 ASSERT(static_cast<uint32_t>(new_capacity) > index);
9451 MaybeObject* maybe_obj = 9385 Object* obj;
9452 SetFastDoubleElementsCapacityAndLength(new_capacity, index + 1); 9386 { MaybeObject* maybe_obj =
9453 if (maybe_obj->IsFailure()) return maybe_obj; 9387 SetFastDoubleElementsCapacityAndLength(new_capacity,
9388 index + 1);
9389 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
9390 }
9454 FixedDoubleArray::cast(elements())->set(index, double_value); 9391 FixedDoubleArray::cast(elements())->set(index, double_value);
9455 ValidateElements();
9456 return value; 9392 return value;
9457 } 9393 }
9458 } 9394 }
9459 9395
9460 // Otherwise default to slow case. 9396 // Otherwise default to slow case.
9461 ASSERT(HasFastDoubleElements()); 9397 ASSERT(HasFastDoubleElements());
9462 ASSERT(map()->has_fast_double_elements()); 9398 ASSERT(map()->has_fast_double_elements());
9463 ASSERT(elements()->IsFixedDoubleArray()); 9399 ASSERT(elements()->IsFixedDoubleArray());
9464 Object* obj; 9400 Object* obj;
9465 { MaybeObject* maybe_obj = NormalizeElements(); 9401 { MaybeObject* maybe_obj = NormalizeElements();
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
9589 Object* value, 9525 Object* value,
9590 PropertyAttributes attr, 9526 PropertyAttributes attr,
9591 StrictModeFlag strict_mode, 9527 StrictModeFlag strict_mode,
9592 bool check_prototype, 9528 bool check_prototype,
9593 SetPropertyMode set_mode) { 9529 SetPropertyMode set_mode) {
9594 ASSERT(HasDictionaryElements() || 9530 ASSERT(HasDictionaryElements() ||
9595 HasDictionaryArgumentsElements() || 9531 HasDictionaryArgumentsElements() ||
9596 (attr & (DONT_DELETE | DONT_ENUM | READ_ONLY)) == 0); 9532 (attr & (DONT_DELETE | DONT_ENUM | READ_ONLY)) == 0);
9597 Isolate* isolate = GetIsolate(); 9533 Isolate* isolate = GetIsolate();
9598 switch (GetElementsKind()) { 9534 switch (GetElementsKind()) {
9599 case FAST_SMI_ELEMENTS: 9535 case FAST_SMI_ONLY_ELEMENTS:
9600 case FAST_ELEMENTS: 9536 case FAST_ELEMENTS:
9601 case FAST_HOLEY_SMI_ELEMENTS:
9602 case FAST_HOLEY_ELEMENTS:
9603 return SetFastElement(index, value, strict_mode, check_prototype); 9537 return SetFastElement(index, value, strict_mode, check_prototype);
9604 case FAST_DOUBLE_ELEMENTS: 9538 case FAST_DOUBLE_ELEMENTS:
9605 case FAST_HOLEY_DOUBLE_ELEMENTS:
9606 return SetFastDoubleElement(index, value, strict_mode, check_prototype); 9539 return SetFastDoubleElement(index, value, strict_mode, check_prototype);
9607 case EXTERNAL_PIXEL_ELEMENTS: { 9540 case EXTERNAL_PIXEL_ELEMENTS: {
9608 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements()); 9541 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements());
9609 return pixels->SetValue(index, value); 9542 return pixels->SetValue(index, value);
9610 } 9543 }
9611 case EXTERNAL_BYTE_ELEMENTS: { 9544 case EXTERNAL_BYTE_ELEMENTS: {
9612 ExternalByteArray* array = ExternalByteArray::cast(elements()); 9545 ExternalByteArray* array = ExternalByteArray::cast(elements());
9613 return array->SetValue(index, value); 9546 return array->SetValue(index, value);
9614 } 9547 }
9615 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: { 9548 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: {
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
9686 ElementsKind to_kind) { 9619 ElementsKind to_kind) {
9687 CALL_HEAP_FUNCTION(object->GetIsolate(), 9620 CALL_HEAP_FUNCTION(object->GetIsolate(),
9688 object->TransitionElementsKind(to_kind), 9621 object->TransitionElementsKind(to_kind),
9689 Object); 9622 Object);
9690 } 9623 }
9691 9624
9692 9625
9693 MaybeObject* JSObject::TransitionElementsKind(ElementsKind to_kind) { 9626 MaybeObject* JSObject::TransitionElementsKind(ElementsKind to_kind) {
9694 ElementsKind from_kind = map()->elements_kind(); 9627 ElementsKind from_kind = map()->elements_kind();
9695 9628
9696 if (IsFastHoleyElementsKind(from_kind)) {
9697 to_kind = GetHoleyElementsKind(to_kind);
9698 }
9699
9700 Isolate* isolate = GetIsolate(); 9629 Isolate* isolate = GetIsolate();
9701 if (elements() == isolate->heap()->empty_fixed_array() || 9630 if ((from_kind == FAST_SMI_ONLY_ELEMENTS ||
9702 (IsFastSmiOrObjectElementsKind(from_kind) && 9631 elements() == isolate->heap()->empty_fixed_array()) &&
9703 IsFastSmiOrObjectElementsKind(to_kind)) || 9632 to_kind == FAST_ELEMENTS) {
9704 (from_kind == FAST_DOUBLE_ELEMENTS && 9633 ASSERT(from_kind != FAST_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.
9709 MaybeObject* maybe_new_map = GetElementsTransitionMap(isolate, to_kind); 9634 MaybeObject* maybe_new_map = GetElementsTransitionMap(isolate, to_kind);
9710 Map* new_map; 9635 Map* new_map;
9711 if (!maybe_new_map->To(&new_map)) return maybe_new_map; 9636 if (!maybe_new_map->To(&new_map)) return maybe_new_map;
9712 set_map(new_map); 9637 set_map(new_map);
9713 if (FLAG_trace_elements_transitions) { 9638 if (FLAG_trace_elements_transitions) {
9714 FixedArrayBase* elms = FixedArrayBase::cast(elements()); 9639 FixedArrayBase* elms = FixedArrayBase::cast(elements());
9715 PrintElementsTransition(stdout, from_kind, elms, to_kind, elms); 9640 PrintElementsTransition(stdout, from_kind, elms, to_kind, elms);
9716 } 9641 }
9717 return this; 9642 return this;
9718 } 9643 }
9719 9644
9720 FixedArrayBase* elms = FixedArrayBase::cast(elements()); 9645 FixedArrayBase* elms = FixedArrayBase::cast(elements());
9721 uint32_t capacity = static_cast<uint32_t>(elms->length()); 9646 uint32_t capacity = static_cast<uint32_t>(elms->length());
9722 uint32_t length = capacity; 9647 uint32_t length = capacity;
9723 9648
9724 if (IsJSArray()) { 9649 if (IsJSArray()) {
9725 Object* raw_length = JSArray::cast(this)->length(); 9650 Object* raw_length = JSArray::cast(this)->length();
9726 if (raw_length->IsUndefined()) { 9651 if (raw_length->IsUndefined()) {
9727 // If length is undefined, then JSArray is being initialized and has no 9652 // If length is undefined, then JSArray is being initialized and has no
9728 // elements, assume a length of zero. 9653 // elements, assume a length of zero.
9729 length = 0; 9654 length = 0;
9730 } else { 9655 } else {
9731 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length)); 9656 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length));
9732 } 9657 }
9733 } 9658 }
9734 9659
9735 if (IsFastSmiElementsKind(from_kind) && 9660 if (from_kind == FAST_SMI_ONLY_ELEMENTS &&
9736 IsFastDoubleElementsKind(to_kind)) { 9661 to_kind == FAST_DOUBLE_ELEMENTS) {
9737 MaybeObject* maybe_result = 9662 MaybeObject* maybe_result =
9738 SetFastDoubleElementsCapacityAndLength(capacity, length); 9663 SetFastDoubleElementsCapacityAndLength(capacity, length);
9739 if (maybe_result->IsFailure()) return maybe_result; 9664 if (maybe_result->IsFailure()) return maybe_result;
9740 ValidateElements();
9741 return this; 9665 return this;
9742 } 9666 }
9743 9667
9744 if (IsFastDoubleElementsKind(from_kind) && 9668 if (from_kind == FAST_DOUBLE_ELEMENTS && to_kind == FAST_ELEMENTS) {
9745 IsFastObjectElementsKind(to_kind)) {
9746 MaybeObject* maybe_result = SetFastElementsCapacityAndLength( 9669 MaybeObject* maybe_result = SetFastElementsCapacityAndLength(
9747 capacity, length, kDontAllowSmiElements); 9670 capacity, length, kDontAllowSmiOnlyElements);
9748 if (maybe_result->IsFailure()) return maybe_result; 9671 if (maybe_result->IsFailure()) return maybe_result;
9749 ValidateElements();
9750 return this; 9672 return this;
9751 } 9673 }
9752 9674
9753 // This method should never be called for any other case than the ones 9675 // This method should never be called for any other case than the ones
9754 // handled above. 9676 // handled above.
9755 UNREACHABLE(); 9677 UNREACHABLE();
9756 return GetIsolate()->heap()->null_value(); 9678 return GetIsolate()->heap()->null_value();
9757 } 9679 }
9758 9680
9759 9681
9760 // static 9682 // static
9761 bool Map::IsValidElementsTransition(ElementsKind from_kind, 9683 bool Map::IsValidElementsTransition(ElementsKind from_kind,
9762 ElementsKind to_kind) { 9684 ElementsKind to_kind) {
9763 // Transitions can't go backwards. 9685 return
9764 if (!IsMoreGeneralElementsKindTransition(from_kind, to_kind)) { 9686 (from_kind == FAST_SMI_ONLY_ELEMENTS &&
9765 return false; 9687 (to_kind == FAST_DOUBLE_ELEMENTS || to_kind == FAST_ELEMENTS)) ||
9766 } 9688 (from_kind == FAST_DOUBLE_ELEMENTS && to_kind == FAST_ELEMENTS);
9767
9768 // Transitions from HOLEY -> PACKED are not allowed.
9769 return !IsFastHoleyElementsKind(from_kind) ||
9770 IsFastHoleyElementsKind(to_kind);
9771 } 9689 }
9772 9690
9773 9691
9774 MaybeObject* JSArray::JSArrayUpdateLengthFromIndex(uint32_t index, 9692 MaybeObject* JSArray::JSArrayUpdateLengthFromIndex(uint32_t index,
9775 Object* value) { 9693 Object* value) {
9776 uint32_t old_len = 0; 9694 uint32_t old_len = 0;
9777 CHECK(length()->ToArrayIndex(&old_len)); 9695 CHECK(length()->ToArrayIndex(&old_len));
9778 // Check to see if we need to update the length. For now, we make 9696 // Check to see if we need to update the length. For now, we make
9779 // sure that the length stays within 32-bits (unsigned). 9697 // sure that the length stays within 32-bits (unsigned).
9780 if (index >= old_len && index != 0xffffffff) { 9698 if (index >= old_len && index != 0xffffffff) {
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
9851 FixedArray::cast(FixedArray::cast(backing_store_base)->get(1)); 9769 FixedArray::cast(FixedArray::cast(backing_store_base)->get(1));
9852 backing_store = FixedArray::cast(backing_store_base); 9770 backing_store = FixedArray::cast(backing_store_base);
9853 if (backing_store->IsDictionary()) { 9771 if (backing_store->IsDictionary()) {
9854 SeededNumberDictionary* dictionary = 9772 SeededNumberDictionary* dictionary =
9855 SeededNumberDictionary::cast(backing_store); 9773 SeededNumberDictionary::cast(backing_store);
9856 *capacity = dictionary->Capacity(); 9774 *capacity = dictionary->Capacity();
9857 *used = dictionary->NumberOfElements(); 9775 *used = dictionary->NumberOfElements();
9858 break; 9776 break;
9859 } 9777 }
9860 // Fall through. 9778 // Fall through.
9861 case FAST_SMI_ELEMENTS: 9779 case FAST_SMI_ONLY_ELEMENTS:
9862 case FAST_ELEMENTS: 9780 case FAST_ELEMENTS:
9863 case FAST_HOLEY_SMI_ELEMENTS:
9864 case FAST_HOLEY_ELEMENTS:
9865 backing_store = FixedArray::cast(backing_store_base); 9781 backing_store = FixedArray::cast(backing_store_base);
9866 *capacity = backing_store->length(); 9782 *capacity = backing_store->length();
9867 for (int i = 0; i < *capacity; ++i) { 9783 for (int i = 0; i < *capacity; ++i) {
9868 if (!backing_store->get(i)->IsTheHole()) ++(*used); 9784 if (!backing_store->get(i)->IsTheHole()) ++(*used);
9869 } 9785 }
9870 break; 9786 break;
9871 case DICTIONARY_ELEMENTS: { 9787 case DICTIONARY_ELEMENTS: {
9872 SeededNumberDictionary* dictionary = 9788 SeededNumberDictionary* dictionary =
9873 SeededNumberDictionary::cast(FixedArray::cast(elements())); 9789 SeededNumberDictionary::cast(FixedArray::cast(elements()));
9874 *capacity = dictionary->Capacity(); 9790 *capacity = dictionary->Capacity();
9875 *used = dictionary->NumberOfElements(); 9791 *used = dictionary->NumberOfElements();
9876 break; 9792 break;
9877 } 9793 }
9878 case FAST_DOUBLE_ELEMENTS: 9794 case FAST_DOUBLE_ELEMENTS: {
9879 case FAST_HOLEY_DOUBLE_ELEMENTS: {
9880 FixedDoubleArray* elms = FixedDoubleArray::cast(elements()); 9795 FixedDoubleArray* elms = FixedDoubleArray::cast(elements());
9881 *capacity = elms->length(); 9796 *capacity = elms->length();
9882 for (int i = 0; i < *capacity; i++) { 9797 for (int i = 0; i < *capacity; i++) {
9883 if (!elms->is_the_hole(i)) ++(*used); 9798 if (!elms->is_the_hole(i)) ++(*used);
9884 } 9799 }
9885 break; 9800 break;
9886 } 9801 }
9887 case EXTERNAL_BYTE_ELEMENTS: 9802 case EXTERNAL_BYTE_ELEMENTS:
9888 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 9803 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
9889 case EXTERNAL_SHORT_ELEMENTS: 9804 case EXTERNAL_SHORT_ELEMENTS:
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after
10139 if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) { 10054 if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) {
10140 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS); 10055 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS);
10141 return false; 10056 return false;
10142 } 10057 }
10143 } 10058 }
10144 10059
10145 // Handle [] on String objects. 10060 // Handle [] on String objects.
10146 if (this->IsStringObjectWithCharacterAt(index)) return true; 10061 if (this->IsStringObjectWithCharacterAt(index)) return true;
10147 10062
10148 switch (GetElementsKind()) { 10063 switch (GetElementsKind()) {
10149 case FAST_SMI_ELEMENTS: 10064 case FAST_SMI_ONLY_ELEMENTS:
10150 case FAST_ELEMENTS: 10065 case FAST_ELEMENTS: {
10151 case FAST_HOLEY_SMI_ELEMENTS: 10066 uint32_t length = IsJSArray() ?
10152 case FAST_HOLEY_ELEMENTS: {
10153 uint32_t length = IsJSArray() ?
10154 static_cast<uint32_t>( 10067 static_cast<uint32_t>(
10155 Smi::cast(JSArray::cast(this)->length())->value()) : 10068 Smi::cast(JSArray::cast(this)->length())->value()) :
10156 static_cast<uint32_t>(FixedArray::cast(elements())->length()); 10069 static_cast<uint32_t>(FixedArray::cast(elements())->length());
10157 return (index < length) && 10070 return (index < length) &&
10158 !FixedArray::cast(elements())->get(index)->IsTheHole(); 10071 !FixedArray::cast(elements())->get(index)->IsTheHole();
10159 } 10072 }
10160 case FAST_DOUBLE_ELEMENTS: 10073 case FAST_DOUBLE_ELEMENTS: {
10161 case FAST_HOLEY_DOUBLE_ELEMENTS: {
10162 uint32_t length = IsJSArray() ? 10074 uint32_t length = IsJSArray() ?
10163 static_cast<uint32_t>( 10075 static_cast<uint32_t>(
10164 Smi::cast(JSArray::cast(this)->length())->value()) : 10076 Smi::cast(JSArray::cast(this)->length())->value()) :
10165 static_cast<uint32_t>(FixedDoubleArray::cast(elements())->length()); 10077 static_cast<uint32_t>(FixedDoubleArray::cast(elements())->length());
10166 return (index < length) && 10078 return (index < length) &&
10167 !FixedDoubleArray::cast(elements())->is_the_hole(index); 10079 !FixedDoubleArray::cast(elements())->is_the_hole(index);
10168 break; 10080 break;
10169 } 10081 }
10170 case EXTERNAL_PIXEL_ELEMENTS: { 10082 case EXTERNAL_PIXEL_ELEMENTS: {
10171 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements()); 10083 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements());
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after
10351 } 10263 }
10352 10264
10353 10265
10354 int JSObject::NumberOfLocalElements(PropertyAttributes filter) { 10266 int JSObject::NumberOfLocalElements(PropertyAttributes filter) {
10355 return GetLocalElementKeys(NULL, filter); 10267 return GetLocalElementKeys(NULL, filter);
10356 } 10268 }
10357 10269
10358 10270
10359 int JSObject::NumberOfEnumElements() { 10271 int JSObject::NumberOfEnumElements() {
10360 // Fast case for objects with no elements. 10272 // Fast case for objects with no elements.
10361 if (!IsJSValue() && HasFastObjectElements()) { 10273 if (!IsJSValue() && HasFastElements()) {
10362 uint32_t length = IsJSArray() ? 10274 uint32_t length = IsJSArray() ?
10363 static_cast<uint32_t>( 10275 static_cast<uint32_t>(
10364 Smi::cast(JSArray::cast(this)->length())->value()) : 10276 Smi::cast(JSArray::cast(this)->length())->value()) :
10365 static_cast<uint32_t>(FixedArray::cast(elements())->length()); 10277 static_cast<uint32_t>(FixedArray::cast(elements())->length());
10366 if (length == 0) return 0; 10278 if (length == 0) return 0;
10367 } 10279 }
10368 // Compute the number of enumerable elements. 10280 // Compute the number of enumerable elements.
10369 return NumberOfLocalElements(static_cast<PropertyAttributes>(DONT_ENUM)); 10281 return NumberOfLocalElements(static_cast<PropertyAttributes>(DONT_ENUM));
10370 } 10282 }
10371 10283
10372 10284
10373 int JSObject::GetLocalElementKeys(FixedArray* storage, 10285 int JSObject::GetLocalElementKeys(FixedArray* storage,
10374 PropertyAttributes filter) { 10286 PropertyAttributes filter) {
10375 int counter = 0; 10287 int counter = 0;
10376 switch (GetElementsKind()) { 10288 switch (GetElementsKind()) {
10377 case FAST_SMI_ELEMENTS: 10289 case FAST_SMI_ONLY_ELEMENTS:
10378 case FAST_ELEMENTS: 10290 case FAST_ELEMENTS: {
10379 case FAST_HOLEY_SMI_ELEMENTS:
10380 case FAST_HOLEY_ELEMENTS: {
10381 int length = IsJSArray() ? 10291 int length = IsJSArray() ?
10382 Smi::cast(JSArray::cast(this)->length())->value() : 10292 Smi::cast(JSArray::cast(this)->length())->value() :
10383 FixedArray::cast(elements())->length(); 10293 FixedArray::cast(elements())->length();
10384 for (int i = 0; i < length; i++) { 10294 for (int i = 0; i < length; i++) {
10385 if (!FixedArray::cast(elements())->get(i)->IsTheHole()) { 10295 if (!FixedArray::cast(elements())->get(i)->IsTheHole()) {
10386 if (storage != NULL) { 10296 if (storage != NULL) {
10387 storage->set(counter, Smi::FromInt(i)); 10297 storage->set(counter, Smi::FromInt(i));
10388 } 10298 }
10389 counter++; 10299 counter++;
10390 } 10300 }
10391 } 10301 }
10392 ASSERT(!storage || storage->length() >= counter); 10302 ASSERT(!storage || storage->length() >= counter);
10393 break; 10303 break;
10394 } 10304 }
10395 case FAST_DOUBLE_ELEMENTS: 10305 case FAST_DOUBLE_ELEMENTS: {
10396 case FAST_HOLEY_DOUBLE_ELEMENTS: {
10397 int length = IsJSArray() ? 10306 int length = IsJSArray() ?
10398 Smi::cast(JSArray::cast(this)->length())->value() : 10307 Smi::cast(JSArray::cast(this)->length())->value() :
10399 FixedDoubleArray::cast(elements())->length(); 10308 FixedDoubleArray::cast(elements())->length();
10400 for (int i = 0; i < length; i++) { 10309 for (int i = 0; i < length; i++) {
10401 if (!FixedDoubleArray::cast(elements())->is_the_hole(i)) { 10310 if (!FixedDoubleArray::cast(elements())->is_the_hole(i)) {
10402 if (storage != NULL) { 10311 if (storage != NULL) {
10403 storage->set(counter, Smi::FromInt(i)); 10312 storage->set(counter, Smi::FromInt(i));
10404 } 10313 }
10405 counter++; 10314 counter++;
10406 } 10315 }
(...skipping 912 matching lines...) Expand 10 before | Expand all | Expand 10 after
11319 // Convert to fast elements containing only the existing properties. 11228 // Convert to fast elements containing only the existing properties.
11320 // Ordering is irrelevant, since we are going to sort anyway. 11229 // Ordering is irrelevant, since we are going to sort anyway.
11321 SeededNumberDictionary* dict = element_dictionary(); 11230 SeededNumberDictionary* dict = element_dictionary();
11322 if (IsJSArray() || dict->requires_slow_elements() || 11231 if (IsJSArray() || dict->requires_slow_elements() ||
11323 dict->max_number_key() >= limit) { 11232 dict->max_number_key() >= limit) {
11324 return PrepareSlowElementsForSort(limit); 11233 return PrepareSlowElementsForSort(limit);
11325 } 11234 }
11326 // Convert to fast elements. 11235 // Convert to fast elements.
11327 11236
11328 Object* obj; 11237 Object* obj;
11329 MaybeObject* maybe_obj = GetElementsTransitionMap(GetIsolate(), 11238 { MaybeObject* maybe_obj = GetElementsTransitionMap(GetIsolate(),
11330 FAST_HOLEY_ELEMENTS); 11239 FAST_ELEMENTS);
11331 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 11240 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
11241 }
11332 Map* new_map = Map::cast(obj); 11242 Map* new_map = Map::cast(obj);
11333 11243
11334 PretenureFlag tenure = heap->InNewSpace(this) ? NOT_TENURED: TENURED; 11244 PretenureFlag tenure = heap->InNewSpace(this) ? NOT_TENURED: TENURED;
11335 Object* new_array; 11245 Object* new_array;
11336 { MaybeObject* maybe_new_array = 11246 { MaybeObject* maybe_new_array =
11337 heap->AllocateFixedArray(dict->NumberOfElements(), tenure); 11247 heap->AllocateFixedArray(dict->NumberOfElements(), tenure);
11338 if (!maybe_new_array->ToObject(&new_array)) return maybe_new_array; 11248 if (!maybe_new_array->ToObject(&new_array)) return maybe_new_array;
11339 } 11249 }
11340 FixedArray* fast_elements = FixedArray::cast(new_array); 11250 FixedArray* fast_elements = FixedArray::cast(new_array);
11341 dict->CopyValuesTo(fast_elements); 11251 dict->CopyValuesTo(fast_elements);
11342 ValidateElements();
11343 11252
11344 set_map_and_elements(new_map, fast_elements); 11253 set_map(new_map);
11254 set_elements(fast_elements);
11345 } else if (HasExternalArrayElements()) { 11255 } else if (HasExternalArrayElements()) {
11346 // External arrays cannot have holes or undefined elements. 11256 // External arrays cannot have holes or undefined elements.
11347 return Smi::FromInt(ExternalArray::cast(elements())->length()); 11257 return Smi::FromInt(ExternalArray::cast(elements())->length());
11348 } else if (!HasFastDoubleElements()) { 11258 } else if (!HasFastDoubleElements()) {
11349 Object* obj; 11259 Object* obj;
11350 { MaybeObject* maybe_obj = EnsureWritableFastElements(); 11260 { MaybeObject* maybe_obj = EnsureWritableFastElements();
11351 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 11261 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
11352 } 11262 }
11353 } 11263 }
11354 ASSERT(HasFastSmiOrObjectElements() || HasFastDoubleElements()); 11264 ASSERT(HasFastTypeElements() || HasFastDoubleElements());
11355 11265
11356 // Collect holes at the end, undefined before that and the rest at the 11266 // Collect holes at the end, undefined before that and the rest at the
11357 // start, and return the number of non-hole, non-undefined values. 11267 // start, and return the number of non-hole, non-undefined values.
11358 11268
11359 FixedArrayBase* elements_base = FixedArrayBase::cast(this->elements()); 11269 FixedArrayBase* elements_base = FixedArrayBase::cast(this->elements());
11360 uint32_t elements_length = static_cast<uint32_t>(elements_base->length()); 11270 uint32_t elements_length = static_cast<uint32_t>(elements_base->length());
11361 if (limit > elements_length) { 11271 if (limit > elements_length) {
11362 limit = elements_length ; 11272 limit = elements_length ;
11363 } 11273 }
11364 if (limit == 0) { 11274 if (limit == 0) {
(...skipping 1656 matching lines...) Expand 10 before | Expand all | Expand 10 after
13021 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); 12931 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER);
13022 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); 12932 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER);
13023 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); 12933 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER);
13024 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); 12934 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER);
13025 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); 12935 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER);
13026 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); 12936 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER);
13027 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); 12937 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER);
13028 } 12938 }
13029 12939
13030 } } // namespace v8::internal 12940 } } // 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