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

Side by Side Diff: src/objects.cc

Issue 159263: - A prototype which allows to expose CanvasPixelArray functionality... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 11 years, 4 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 2006-2009 the V8 project authors. All rights reserved. 1 // Copyright 2006-2009 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 988 matching lines...) Expand 10 before | Expand all | Expand 10 after
999 switch (map()->instance_type()) { 999 switch (map()->instance_type()) {
1000 case MAP_TYPE: 1000 case MAP_TYPE:
1001 accumulator->Add("<Map>"); 1001 accumulator->Add("<Map>");
1002 break; 1002 break;
1003 case FIXED_ARRAY_TYPE: 1003 case FIXED_ARRAY_TYPE:
1004 accumulator->Add("<FixedArray[%u]>", FixedArray::cast(this)->length()); 1004 accumulator->Add("<FixedArray[%u]>", FixedArray::cast(this)->length());
1005 break; 1005 break;
1006 case BYTE_ARRAY_TYPE: 1006 case BYTE_ARRAY_TYPE:
1007 accumulator->Add("<ByteArray[%u]>", ByteArray::cast(this)->length()); 1007 accumulator->Add("<ByteArray[%u]>", ByteArray::cast(this)->length());
1008 break; 1008 break;
1009 case PIXEL_ARRAY_TYPE:
1010 accumulator->Add("<PixelArray[%u]>", PixelArray::cast(this)->length());
1011 break;
1009 case SHARED_FUNCTION_INFO_TYPE: 1012 case SHARED_FUNCTION_INFO_TYPE:
1010 accumulator->Add("<SharedFunctionInfo>"); 1013 accumulator->Add("<SharedFunctionInfo>");
1011 break; 1014 break;
1012 #define MAKE_STRUCT_CASE(NAME, Name, name) \ 1015 #define MAKE_STRUCT_CASE(NAME, Name, name) \
1013 case NAME##_TYPE: \ 1016 case NAME##_TYPE: \
1014 accumulator->Put('<'); \ 1017 accumulator->Put('<'); \
1015 accumulator->Add(#Name); \ 1018 accumulator->Add(#Name); \
1016 accumulator->Put('>'); \ 1019 accumulator->Put('>'); \
1017 break; 1020 break;
1018 STRUCT_LIST(MAKE_STRUCT_CASE) 1021 STRUCT_LIST(MAKE_STRUCT_CASE)
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
1140 case CODE_TYPE: 1143 case CODE_TYPE:
1141 reinterpret_cast<Code*>(this)->CodeIterateBody(v); 1144 reinterpret_cast<Code*>(this)->CodeIterateBody(v);
1142 break; 1145 break;
1143 case JS_GLOBAL_PROPERTY_CELL_TYPE: 1146 case JS_GLOBAL_PROPERTY_CELL_TYPE:
1144 reinterpret_cast<JSGlobalPropertyCell*>(this) 1147 reinterpret_cast<JSGlobalPropertyCell*>(this)
1145 ->JSGlobalPropertyCellIterateBody(v); 1148 ->JSGlobalPropertyCellIterateBody(v);
1146 break; 1149 break;
1147 case HEAP_NUMBER_TYPE: 1150 case HEAP_NUMBER_TYPE:
1148 case FILLER_TYPE: 1151 case FILLER_TYPE:
1149 case BYTE_ARRAY_TYPE: 1152 case BYTE_ARRAY_TYPE:
1153 case PIXEL_ARRAY_TYPE:
1150 break; 1154 break;
1151 case SHARED_FUNCTION_INFO_TYPE: { 1155 case SHARED_FUNCTION_INFO_TYPE: {
1152 SharedFunctionInfo* shared = reinterpret_cast<SharedFunctionInfo*>(this); 1156 SharedFunctionInfo* shared = reinterpret_cast<SharedFunctionInfo*>(this);
1153 shared->SharedFunctionInfoIterateBody(v); 1157 shared->SharedFunctionInfoIterateBody(v);
1154 break; 1158 break;
1155 } 1159 }
1156 #define MAKE_STRUCT_CASE(NAME, Name, name) \ 1160 #define MAKE_STRUCT_CASE(NAME, Name, name) \
1157 case NAME##_TYPE: 1161 case NAME##_TYPE:
1158 STRUCT_LIST(MAKE_STRUCT_CASE) 1162 STRUCT_LIST(MAKE_STRUCT_CASE)
1159 #undef MAKE_STRUCT_CASE 1163 #undef MAKE_STRUCT_CASE
(...skipping 502 matching lines...) Expand 10 before | Expand all | Expand 10 after
1662 } 1666 }
1663 } 1667 }
1664 result->NotFound(); 1668 result->NotFound();
1665 } 1669 }
1666 1670
1667 1671
1668 Object* JSObject::LookupCallbackSetterInPrototypes(uint32_t index) { 1672 Object* JSObject::LookupCallbackSetterInPrototypes(uint32_t index) {
1669 for (Object* pt = GetPrototype(); 1673 for (Object* pt = GetPrototype();
1670 pt != Heap::null_value(); 1674 pt != Heap::null_value();
1671 pt = pt->GetPrototype()) { 1675 pt = pt->GetPrototype()) {
1672 if (JSObject::cast(pt)->HasFastElements()) continue; 1676 if (!JSObject::cast(pt)->HasDictionaryElements()) {
1677 continue;
1678 }
1673 NumberDictionary* dictionary = JSObject::cast(pt)->element_dictionary(); 1679 NumberDictionary* dictionary = JSObject::cast(pt)->element_dictionary();
1674 int entry = dictionary->FindEntry(index); 1680 int entry = dictionary->FindEntry(index);
1675 if (entry != NumberDictionary::kNotFound) { 1681 if (entry != NumberDictionary::kNotFound) {
1676 Object* element = dictionary->ValueAt(entry); 1682 Object* element = dictionary->ValueAt(entry);
1677 PropertyDetails details = dictionary->DetailsAt(entry); 1683 PropertyDetails details = dictionary->DetailsAt(entry);
1678 if (details.type() == CALLBACKS) { 1684 if (details.type() == CALLBACKS) {
1679 // Only accessors allowed as elements. 1685 // Only accessors allowed as elements.
1680 return FixedArray::cast(element)->get(kSetterIndex); 1686 return FixedArray::cast(element)->get(kSetterIndex);
1681 } 1687 }
1682 } 1688 }
(...skipping 541 matching lines...) Expand 10 before | Expand all | Expand 10 after
2224 2230
2225 Object* JSObject::TransformToFastProperties(int unused_property_fields) { 2231 Object* JSObject::TransformToFastProperties(int unused_property_fields) {
2226 if (HasFastProperties()) return this; 2232 if (HasFastProperties()) return this;
2227 ASSERT(!IsGlobalObject()); 2233 ASSERT(!IsGlobalObject());
2228 return property_dictionary()-> 2234 return property_dictionary()->
2229 TransformPropertiesToFastFor(this, unused_property_fields); 2235 TransformPropertiesToFastFor(this, unused_property_fields);
2230 } 2236 }
2231 2237
2232 2238
2233 Object* JSObject::NormalizeElements() { 2239 Object* JSObject::NormalizeElements() {
2234 if (!HasFastElements()) return this; 2240 ASSERT(!HasPixelElements());
2241 if (HasDictionaryElements()) return this;
2235 2242
2236 // Get number of entries. 2243 // Get number of entries.
2237 FixedArray* array = FixedArray::cast(elements()); 2244 FixedArray* array = FixedArray::cast(elements());
2238 2245
2239 // Compute the effective length. 2246 // Compute the effective length.
2240 int length = IsJSArray() ? 2247 int length = IsJSArray() ?
2241 Smi::cast(JSArray::cast(this)->length())->value() : 2248 Smi::cast(JSArray::cast(this)->length())->value() :
2242 array->length(); 2249 array->length();
2243 Object* obj = NumberDictionary::Allocate(length); 2250 Object* obj = NumberDictionary::Allocate(length);
2244 if (obj->IsFailure()) return obj; 2251 if (obj->IsFailure()) return obj;
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
2310 } 2317 }
2311 Object* raw_result = 2318 Object* raw_result =
2312 this_handle->DeletePropertyPostInterceptor(*name_handle, NORMAL_DELETION); 2319 this_handle->DeletePropertyPostInterceptor(*name_handle, NORMAL_DELETION);
2313 RETURN_IF_SCHEDULED_EXCEPTION(); 2320 RETURN_IF_SCHEDULED_EXCEPTION();
2314 return raw_result; 2321 return raw_result;
2315 } 2322 }
2316 2323
2317 2324
2318 Object* JSObject::DeleteElementPostInterceptor(uint32_t index, 2325 Object* JSObject::DeleteElementPostInterceptor(uint32_t index,
2319 DeleteMode mode) { 2326 DeleteMode mode) {
2320 if (HasFastElements()) { 2327 ASSERT(!HasPixelElements());
2321 uint32_t length = IsJSArray() ? 2328 switch (GetElementsKind()) {
2329 case FAST_ELEMENTS: {
2330 uint32_t length = IsJSArray() ?
2322 static_cast<uint32_t>(Smi::cast(JSArray::cast(this)->length())->value()) : 2331 static_cast<uint32_t>(Smi::cast(JSArray::cast(this)->length())->value()) :
2323 static_cast<uint32_t>(FixedArray::cast(elements())->length()); 2332 static_cast<uint32_t>(FixedArray::cast(elements())->length());
2324 if (index < length) { 2333 if (index < length) {
2325 FixedArray::cast(elements())->set_the_hole(index); 2334 FixedArray::cast(elements())->set_the_hole(index);
2335 }
2336 break;
2326 } 2337 }
2327 return Heap::true_value(); 2338 case DICTIONARY_ELEMENTS: {
2328 } 2339 NumberDictionary* dictionary = element_dictionary();
2329 ASSERT(!HasFastElements()); 2340 int entry = dictionary->FindEntry(index);
2330 NumberDictionary* dictionary = element_dictionary(); 2341 if (entry != NumberDictionary::kNotFound) {
2331 int entry = dictionary->FindEntry(index); 2342 return dictionary->DeleteProperty(entry, mode);
2332 if (entry != NumberDictionary::kNotFound) { 2343 }
2333 return dictionary->DeleteProperty(entry, mode); 2344 break;
2345 }
2346 default:
2347 UNREACHABLE();
2348 break;
2334 } 2349 }
2335 return Heap::true_value(); 2350 return Heap::true_value();
2336 } 2351 }
2337 2352
2338 2353
2339 Object* JSObject::DeleteElementWithInterceptor(uint32_t index) { 2354 Object* JSObject::DeleteElementWithInterceptor(uint32_t index) {
2340 // Make sure that the top context does not change when doing 2355 // Make sure that the top context does not change when doing
2341 // callbacks or interceptor calls. 2356 // callbacks or interceptor calls.
2342 AssertNoContextChange ncc; 2357 AssertNoContextChange ncc;
2343 HandleScope scope; 2358 HandleScope scope;
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
2385 } 2400 }
2386 2401
2387 if (HasIndexedInterceptor()) { 2402 if (HasIndexedInterceptor()) {
2388 // Skip interceptor if forcing deletion. 2403 // Skip interceptor if forcing deletion.
2389 if (mode == FORCE_DELETION) { 2404 if (mode == FORCE_DELETION) {
2390 return DeleteElementPostInterceptor(index, mode); 2405 return DeleteElementPostInterceptor(index, mode);
2391 } 2406 }
2392 return DeleteElementWithInterceptor(index); 2407 return DeleteElementWithInterceptor(index);
2393 } 2408 }
2394 2409
2395 if (HasFastElements()) { 2410 switch (GetElementsKind()) {
2396 uint32_t length = IsJSArray() ? 2411 case FAST_ELEMENTS: {
2412 uint32_t length = IsJSArray() ?
2397 static_cast<uint32_t>(Smi::cast(JSArray::cast(this)->length())->value()) : 2413 static_cast<uint32_t>(Smi::cast(JSArray::cast(this)->length())->value()) :
2398 static_cast<uint32_t>(FixedArray::cast(elements())->length()); 2414 static_cast<uint32_t>(FixedArray::cast(elements())->length());
2399 if (index < length) { 2415 if (index < length) {
2400 FixedArray::cast(elements())->set_the_hole(index); 2416 FixedArray::cast(elements())->set_the_hole(index);
2417 }
2418 break;
2401 } 2419 }
2402 return Heap::true_value(); 2420 case PIXEL_ELEMENTS: {
2403 } else { 2421 // Pixel elements cannot be deleted. Just silently ignore here.
2404 NumberDictionary* dictionary = element_dictionary(); 2422 break;
2405 int entry = dictionary->FindEntry(index);
2406 if (entry != NumberDictionary::kNotFound) {
2407 return dictionary->DeleteProperty(entry, mode);
2408 } 2423 }
2424 case DICTIONARY_ELEMENTS: {
2425 NumberDictionary* dictionary = element_dictionary();
2426 int entry = dictionary->FindEntry(index);
2427 if (entry != NumberDictionary::kNotFound) {
2428 return dictionary->DeleteProperty(entry, mode);
2429 }
2430 break;
2431 }
2432 default:
2433 UNREACHABLE();
2434 break;
2409 } 2435 }
2410 return Heap::true_value(); 2436 return Heap::true_value();
2411 } 2437 }
2412 2438
2413 2439
2414 Object* JSObject::DeleteProperty(String* name, DeleteMode mode) { 2440 Object* JSObject::DeleteProperty(String* name, DeleteMode mode) {
2415 // ECMA-262, 3rd, 8.6.2.5 2441 // ECMA-262, 3rd, 8.6.2.5
2416 ASSERT(name->IsString()); 2442 ASSERT(name->IsString());
2417 2443
2418 // Check access rights if needed. 2444 // Check access rights if needed.
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
2476 return true; 2502 return true;
2477 } 2503 }
2478 2504
2479 // Check if the object is among the named properties. 2505 // Check if the object is among the named properties.
2480 Object* key = SlowReverseLookup(obj); 2506 Object* key = SlowReverseLookup(obj);
2481 if (key != Heap::undefined_value()) { 2507 if (key != Heap::undefined_value()) {
2482 return true; 2508 return true;
2483 } 2509 }
2484 2510
2485 // Check if the object is among the indexed properties. 2511 // Check if the object is among the indexed properties.
2486 if (HasFastElements()) { 2512 switch (GetElementsKind()) {
2487 int length = IsJSArray() 2513 case PIXEL_ELEMENTS:
2488 ? Smi::cast(JSArray::cast(this)->length())->value() 2514 // Raw pixels do not reference other objects.
2489 : FixedArray::cast(elements())->length(); 2515 break;
2490 for (int i = 0; i < length; i++) { 2516 case FAST_ELEMENTS: {
2491 Object* element = FixedArray::cast(elements())->get(i); 2517 int length = IsJSArray() ?
2492 if (!element->IsTheHole() && element == obj) { 2518 Smi::cast(JSArray::cast(this)->length())->value() :
2519 FixedArray::cast(elements())->length();
2520 for (int i = 0; i < length; i++) {
2521 Object* element = FixedArray::cast(elements())->get(i);
2522 if (!element->IsTheHole() && element == obj) {
2523 return true;
2524 }
2525 }
2526 break;
2527 }
2528 case DICTIONARY_ELEMENTS: {
2529 key = element_dictionary()->SlowReverseLookup(obj);
2530 if (key != Heap::undefined_value()) {
2493 return true; 2531 return true;
2494 } 2532 }
2533 break;
2495 } 2534 }
2496 } else { 2535 default:
2497 key = element_dictionary()->SlowReverseLookup(obj); 2536 UNREACHABLE();
2498 if (key != Heap::undefined_value()) { 2537 break;
2499 return true;
2500 }
2501 } 2538 }
2502 2539
2503 // For functions check the context. Boilerplate functions do 2540 // For functions check the context. Boilerplate functions do
2504 // not have to be traversed since they have no real context. 2541 // not have to be traversed since they have no real context.
2505 if (IsJSFunction() && !JSFunction::cast(this)->IsBoilerplate()) { 2542 if (IsJSFunction() && !JSFunction::cast(this)->IsBoilerplate()) {
2506 // Get the constructor function for arguments array. 2543 // Get the constructor function for arguments array.
2507 JSObject* arguments_boilerplate = 2544 JSObject* arguments_boilerplate =
2508 Top::context()->global_context()->arguments_boilerplate(); 2545 Top::context()->global_context()->arguments_boilerplate();
2509 JSFunction* arguments_function = 2546 JSFunction* arguments_function =
2510 JSFunction::cast(arguments_boilerplate->map()->constructor()); 2547 JSFunction::cast(arguments_boilerplate->map()->constructor());
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after
2708 AccessorInfo::cast(obj)->prohibits_overwriting()) { 2745 AccessorInfo::cast(obj)->prohibits_overwriting()) {
2709 return Heap::undefined_value(); 2746 return Heap::undefined_value();
2710 } 2747 }
2711 } 2748 }
2712 2749
2713 uint32_t index; 2750 uint32_t index;
2714 bool is_element = name->AsArrayIndex(&index); 2751 bool is_element = name->AsArrayIndex(&index);
2715 if (is_element && IsJSArray()) return Heap::undefined_value(); 2752 if (is_element && IsJSArray()) return Heap::undefined_value();
2716 2753
2717 if (is_element) { 2754 if (is_element) {
2718 // Lookup the index. 2755 switch (GetElementsKind()) {
2719 if (!HasFastElements()) { 2756 case FAST_ELEMENTS:
2720 NumberDictionary* dictionary = element_dictionary(); 2757 break;
2721 int entry = dictionary->FindEntry(index); 2758 case PIXEL_ELEMENTS:
2722 if (entry != NumberDictionary::kNotFound) { 2759 // Ignore getters and setters on pixel elements.
2723 Object* result = dictionary->ValueAt(entry); 2760 return Heap::undefined_value();
2724 PropertyDetails details = dictionary->DetailsAt(entry); 2761 case DICTIONARY_ELEMENTS: {
2725 if (details.IsReadOnly()) return Heap::undefined_value(); 2762 // Lookup the index.
2726 if (details.type() == CALLBACKS) { 2763 NumberDictionary* dictionary = element_dictionary();
2727 // Only accessors allowed as elements. 2764 int entry = dictionary->FindEntry(index);
2728 ASSERT(result->IsFixedArray()); 2765 if (entry != NumberDictionary::kNotFound) {
2729 return result; 2766 Object* result = dictionary->ValueAt(entry);
2767 PropertyDetails details = dictionary->DetailsAt(entry);
2768 if (details.IsReadOnly()) return Heap::undefined_value();
2769 if (details.type() == CALLBACKS) {
2770 // Only accessors allowed as elements.
2771 ASSERT(result->IsFixedArray());
2772 return result;
2773 }
2730 } 2774 }
2775 break;
2731 } 2776 }
2777 default:
2778 UNREACHABLE();
2779 break;
2732 } 2780 }
2733 } else { 2781 } else {
2734 // Lookup the name. 2782 // Lookup the name.
2735 LookupResult result; 2783 LookupResult result;
2736 LocalLookup(name, &result); 2784 LocalLookup(name, &result);
2737 if (result.IsValid()) { 2785 if (result.IsValid()) {
2738 if (result.IsReadOnly()) return Heap::undefined_value(); 2786 if (result.IsReadOnly()) return Heap::undefined_value();
2739 if (result.type() == CALLBACKS) { 2787 if (result.type() == CALLBACKS) {
2740 Object* obj = result.GetCallbackObject(); 2788 Object* obj = result.GetCallbackObject();
2741 if (obj->IsFixedArray()) return obj; 2789 if (obj->IsFixedArray()) return obj;
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
2820 return Heap::undefined_value(); 2868 return Heap::undefined_value();
2821 } 2869 }
2822 2870
2823 // Make the lookup and include prototypes. 2871 // Make the lookup and include prototypes.
2824 int accessor_index = is_getter ? kGetterIndex : kSetterIndex; 2872 int accessor_index = is_getter ? kGetterIndex : kSetterIndex;
2825 uint32_t index; 2873 uint32_t index;
2826 if (name->AsArrayIndex(&index)) { 2874 if (name->AsArrayIndex(&index)) {
2827 for (Object* obj = this; 2875 for (Object* obj = this;
2828 obj != Heap::null_value(); 2876 obj != Heap::null_value();
2829 obj = JSObject::cast(obj)->GetPrototype()) { 2877 obj = JSObject::cast(obj)->GetPrototype()) {
2830 JSObject* jsObject = JSObject::cast(obj); 2878 JSObject* js_object = JSObject::cast(obj);
2831 if (!jsObject->HasFastElements()) { 2879 if (js_object->HasDictionaryElements()) {
2832 NumberDictionary* dictionary = jsObject->element_dictionary(); 2880 NumberDictionary* dictionary = js_object->element_dictionary();
2833 int entry = dictionary->FindEntry(index); 2881 int entry = dictionary->FindEntry(index);
2834 if (entry != NumberDictionary::kNotFound) { 2882 if (entry != NumberDictionary::kNotFound) {
2835 Object* element = dictionary->ValueAt(entry); 2883 Object* element = dictionary->ValueAt(entry);
2836 PropertyDetails details = dictionary->DetailsAt(entry); 2884 PropertyDetails details = dictionary->DetailsAt(entry);
2837 if (details.type() == CALLBACKS) { 2885 if (details.type() == CALLBACKS) {
2838 // Only accessors allowed as elements. 2886 // Only accessors allowed as elements.
2839 return FixedArray::cast(element)->get(accessor_index); 2887 return FixedArray::cast(element)->get(accessor_index);
2840 } 2888 }
2841 } 2889 }
2842 } 2890 }
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after
3022 if (element->IsString() && 3070 if (element->IsString() &&
3023 key->IsString() && String::cast(element)->Equals(String::cast(key))) { 3071 key->IsString() && String::cast(element)->Equals(String::cast(key))) {
3024 return true; 3072 return true;
3025 } 3073 }
3026 } 3074 }
3027 return false; 3075 return false;
3028 } 3076 }
3029 3077
3030 3078
3031 Object* FixedArray::AddKeysFromJSArray(JSArray* array) { 3079 Object* FixedArray::AddKeysFromJSArray(JSArray* array) {
3032 if (array->HasFastElements()) { 3080 ASSERT(!array->HasPixelElements());
3033 return UnionOfKeys(array->elements()); 3081 switch (array->GetElementsKind()) {
3082 case JSObject::FAST_ELEMENTS:
3083 return UnionOfKeys(FixedArray::cast(array->elements()));
3084 case JSObject::DICTIONARY_ELEMENTS: {
3085 NumberDictionary* dict = array->element_dictionary();
3086 int size = dict->NumberOfElements();
3087
3088 // Allocate a temporary fixed array.
3089 Object* object = Heap::AllocateFixedArray(size);
3090 if (object->IsFailure()) return object;
3091 FixedArray* key_array = FixedArray::cast(object);
3092
3093 int capacity = dict->Capacity();
3094 int pos = 0;
3095 // Copy the elements from the JSArray to the temporary fixed array.
3096 for (int i = 0; i < capacity; i++) {
3097 if (dict->IsKey(dict->KeyAt(i))) {
3098 key_array->set(pos++, dict->ValueAt(i));
3099 }
3100 }
3101 // Compute the union of this and the temporary fixed array.
3102 return UnionOfKeys(key_array);
3103 }
3104 default:
3105 UNREACHABLE();
3034 } 3106 }
3035 ASSERT(!array->HasFastElements()); 3107 UNREACHABLE();
3036 NumberDictionary* dict = array->element_dictionary(); 3108 return Heap::null_value(); // Failure case needs to "return" a value.
3037 int size = dict->NumberOfElements();
3038
3039 // Allocate a temporary fixed array.
3040 Object* object = Heap::AllocateFixedArray(size);
3041 if (object->IsFailure()) return object;
3042 FixedArray* key_array = FixedArray::cast(object);
3043
3044 int capacity = dict->Capacity();
3045 int pos = 0;
3046 // Copy the elements from the JSArray to the temporary fixed array.
3047 for (int i = 0; i < capacity; i++) {
3048 if (dict->IsKey(dict->KeyAt(i))) {
3049 key_array->set(pos++, dict->ValueAt(i));
3050 }
3051 }
3052 // Compute the union of this and the temporary fixed array.
3053 return UnionOfKeys(key_array);
3054 } 3109 }
3055 3110
3056 3111
3057 Object* FixedArray::UnionOfKeys(FixedArray* other) { 3112 Object* FixedArray::UnionOfKeys(FixedArray* other) {
3058 int len0 = length(); 3113 int len0 = length();
3059 int len1 = other->length(); 3114 int len1 = other->length();
3060 // Optimize if either is empty. 3115 // Optimize if either is empty.
3061 if (len0 == 0) return other; 3116 if (len0 == 0) return other;
3062 if (len1 == 0) return this; 3117 if (len1 == 0) return this;
3063 3118
(...skipping 2018 matching lines...) Expand 10 before | Expand all | Expand 10 after
5082 5137
5083 PrintF("RelocInfo (size = %d)\n", relocation_size()); 5138 PrintF("RelocInfo (size = %d)\n", relocation_size());
5084 for (RelocIterator it(this); !it.done(); it.next()) 5139 for (RelocIterator it(this); !it.done(); it.next())
5085 it.rinfo()->Print(); 5140 it.rinfo()->Print();
5086 PrintF("\n"); 5141 PrintF("\n");
5087 } 5142 }
5088 #endif // ENABLE_DISASSEMBLER 5143 #endif // ENABLE_DISASSEMBLER
5089 5144
5090 5145
5091 void JSObject::SetFastElements(FixedArray* elems) { 5146 void JSObject::SetFastElements(FixedArray* elems) {
5147 // We should never end in here with a pixel array.
5148 ASSERT(!HasPixelElements());
5092 #ifdef DEBUG 5149 #ifdef DEBUG
5093 // Check the provided array is filled with the_hole. 5150 // Check the provided array is filled with the_hole.
5094 uint32_t len = static_cast<uint32_t>(elems->length()); 5151 uint32_t len = static_cast<uint32_t>(elems->length());
5095 for (uint32_t i = 0; i < len; i++) ASSERT(elems->get(i)->IsTheHole()); 5152 for (uint32_t i = 0; i < len; i++) ASSERT(elems->get(i)->IsTheHole());
5096 #endif 5153 #endif
5097 WriteBarrierMode mode = elems->GetWriteBarrierMode(); 5154 WriteBarrierMode mode = elems->GetWriteBarrierMode();
5098 if (HasFastElements()) { 5155 switch (GetElementsKind()) {
5099 FixedArray* old_elements = FixedArray::cast(elements()); 5156 case FAST_ELEMENTS: {
5100 uint32_t old_length = static_cast<uint32_t>(old_elements->length()); 5157 FixedArray* old_elements = FixedArray::cast(elements());
5101 // Fill out the new array with this content and array holes. 5158 uint32_t old_length = static_cast<uint32_t>(old_elements->length());
5102 for (uint32_t i = 0; i < old_length; i++) { 5159 // Fill out the new array with this content and array holes.
5103 elems->set(i, old_elements->get(i), mode); 5160 for (uint32_t i = 0; i < old_length; i++) {
5161 elems->set(i, old_elements->get(i), mode);
5162 }
5163 break;
5104 } 5164 }
5105 } else { 5165 case DICTIONARY_ELEMENTS: {
5106 NumberDictionary* dictionary = NumberDictionary::cast(elements()); 5166 NumberDictionary* dictionary = NumberDictionary::cast(elements());
5107 for (int i = 0; i < dictionary->Capacity(); i++) { 5167 for (int i = 0; i < dictionary->Capacity(); i++) {
5108 Object* key = dictionary->KeyAt(i); 5168 Object* key = dictionary->KeyAt(i);
5109 if (key->IsNumber()) { 5169 if (key->IsNumber()) {
5110 uint32_t entry = static_cast<uint32_t>(key->Number()); 5170 uint32_t entry = static_cast<uint32_t>(key->Number());
5111 elems->set(entry, dictionary->ValueAt(i), mode); 5171 elems->set(entry, dictionary->ValueAt(i), mode);
5172 }
5112 } 5173 }
5174 break;
5113 } 5175 }
5176 default:
5177 UNREACHABLE();
5178 break;
5114 } 5179 }
5115 set_elements(elems); 5180 set_elements(elems);
5116 } 5181 }
5117 5182
5118 5183
5119 Object* JSObject::SetSlowElements(Object* len) { 5184 Object* JSObject::SetSlowElements(Object* len) {
5185 // We should never end in here with a pixel array.
5186 ASSERT(!HasPixelElements());
5187
5120 uint32_t new_length = static_cast<uint32_t>(len->Number()); 5188 uint32_t new_length = static_cast<uint32_t>(len->Number());
5121 5189
5122 if (!HasFastElements()) { 5190 switch (GetElementsKind()) {
5123 if (IsJSArray()) { 5191 case FAST_ELEMENTS: {
5124 uint32_t old_length = 5192 // Make sure we never try to shrink dense arrays into sparse arrays.
5125 static_cast<uint32_t>(JSArray::cast(this)->length()->Number()); 5193 ASSERT(static_cast<uint32_t>(FixedArray::cast(elements())->length()) <=
5126 element_dictionary()->RemoveNumberEntries(new_length, old_length), 5194 new_length);
5127 JSArray::cast(this)->set_length(len); 5195 Object* obj = NormalizeElements();
5196 if (obj->IsFailure()) return obj;
5197
5198 // Update length for JSArrays.
5199 if (IsJSArray()) JSArray::cast(this)->set_length(len);
5200 break;
5128 } 5201 }
5129 return this; 5202 case DICTIONARY_ELEMENTS: {
5203 if (IsJSArray()) {
5204 uint32_t old_length =
5205 static_cast<uint32_t>(JSArray::cast(this)->length()->Number());
5206 element_dictionary()->RemoveNumberEntries(new_length, old_length),
5207 JSArray::cast(this)->set_length(len);
5208 }
5209 break;
5210 }
5211 default:
5212 UNREACHABLE();
5213 break;
5130 } 5214 }
5131
5132 // Make sure we never try to shrink dense arrays into sparse arrays.
5133 ASSERT(static_cast<uint32_t>(FixedArray::cast(elements())->length()) <=
5134 new_length);
5135 Object* obj = NormalizeElements();
5136 if (obj->IsFailure()) return obj;
5137
5138 // Update length for JSArrays.
5139 if (IsJSArray()) JSArray::cast(this)->set_length(len);
5140 return this; 5215 return this;
5141 } 5216 }
5142 5217
5143 5218
5144 Object* JSArray::Initialize(int capacity) { 5219 Object* JSArray::Initialize(int capacity) {
5145 ASSERT(capacity >= 0); 5220 ASSERT(capacity >= 0);
5146 set_length(Smi::FromInt(0), SKIP_WRITE_BARRIER); 5221 set_length(Smi::FromInt(0), SKIP_WRITE_BARRIER);
5147 FixedArray* new_elements; 5222 FixedArray* new_elements;
5148 if (capacity == 0) { 5223 if (capacity == 0) {
5149 new_elements = Heap::empty_fixed_array(); 5224 new_elements = Heap::empty_fixed_array();
5150 } else { 5225 } else {
5151 Object* obj = Heap::AllocateFixedArrayWithHoles(capacity); 5226 Object* obj = Heap::AllocateFixedArrayWithHoles(capacity);
5152 if (obj->IsFailure()) return obj; 5227 if (obj->IsFailure()) return obj;
5153 new_elements = FixedArray::cast(obj); 5228 new_elements = FixedArray::cast(obj);
5154 } 5229 }
5155 set_elements(new_elements); 5230 set_elements(new_elements);
5156 return this; 5231 return this;
5157 } 5232 }
5158 5233
5159 5234
5160 void JSArray::Expand(int required_size) { 5235 void JSArray::Expand(int required_size) {
5161 Handle<JSArray> self(this); 5236 Handle<JSArray> self(this);
5162 Handle<FixedArray> old_backing(elements()); 5237 Handle<FixedArray> old_backing(FixedArray::cast(elements()));
5163 int old_size = old_backing->length(); 5238 int old_size = old_backing->length();
5164 // Doubling in size would be overkill, but leave some slack to avoid 5239 // Doubling in size would be overkill, but leave some slack to avoid
5165 // constantly growing. 5240 // constantly growing.
5166 int new_size = required_size + (required_size >> 3); 5241 int new_size = required_size + (required_size >> 3);
5167 Handle<FixedArray> new_backing = Factory::NewFixedArray(new_size); 5242 Handle<FixedArray> new_backing = Factory::NewFixedArray(new_size);
5168 // Can't use this any more now because we may have had a GC! 5243 // Can't use this any more now because we may have had a GC!
5169 for (int i = 0; i < old_size; i++) new_backing->set(i, old_backing->get(i)); 5244 for (int i = 0; i < old_size; i++) new_backing->set(i, old_backing->get(i));
5170 self->SetContent(*new_backing); 5245 self->SetContent(*new_backing);
5171 } 5246 }
5172 5247
5173 5248
5174 // Computes the new capacity when expanding the elements of a JSObject. 5249 // Computes the new capacity when expanding the elements of a JSObject.
5175 static int NewElementsCapacity(int old_capacity) { 5250 static int NewElementsCapacity(int old_capacity) {
5176 // (old_capacity + 50%) + 16 5251 // (old_capacity + 50%) + 16
5177 return old_capacity + (old_capacity >> 1) + 16; 5252 return old_capacity + (old_capacity >> 1) + 16;
5178 } 5253 }
5179 5254
5180 5255
5181 static Object* ArrayLengthRangeError() { 5256 static Object* ArrayLengthRangeError() {
5182 HandleScope scope; 5257 HandleScope scope;
5183 return Top::Throw(*Factory::NewRangeError("invalid_array_length", 5258 return Top::Throw(*Factory::NewRangeError("invalid_array_length",
5184 HandleVector<Object>(NULL, 0))); 5259 HandleVector<Object>(NULL, 0)));
5185 } 5260 }
5186 5261
5187 5262
5188 Object* JSObject::SetElementsLength(Object* len) { 5263 Object* JSObject::SetElementsLength(Object* len) {
5264 // We should never end in here with a pixel array.
5265 ASSERT(!HasPixelElements());
5266
5189 Object* smi_length = len->ToSmi(); 5267 Object* smi_length = len->ToSmi();
5190 if (smi_length->IsSmi()) { 5268 if (smi_length->IsSmi()) {
5191 int value = Smi::cast(smi_length)->value(); 5269 int value = Smi::cast(smi_length)->value();
5192 if (value < 0) return ArrayLengthRangeError(); 5270 if (value < 0) return ArrayLengthRangeError();
5193 if (HasFastElements()) { 5271 switch (GetElementsKind()) {
5194 int old_capacity = FixedArray::cast(elements())->length(); 5272 case FAST_ELEMENTS: {
5195 if (value <= old_capacity) { 5273 int old_capacity = FixedArray::cast(elements())->length();
5274 if (value <= old_capacity) {
5275 if (IsJSArray()) {
5276 int old_length = FastD2I(JSArray::cast(this)->length()->Number());
5277 // NOTE: We may be able to optimize this by removing the
5278 // last part of the elements backing storage array and
5279 // setting the capacity to the new size.
5280 for (int i = value; i < old_length; i++) {
5281 FixedArray::cast(elements())->set_the_hole(i);
5282 }
5283 JSArray::cast(this)->set_length(smi_length, SKIP_WRITE_BARRIER);
5284 }
5285 return this;
5286 }
5287 int min = NewElementsCapacity(old_capacity);
5288 int new_capacity = value > min ? value : min;
5289 if (new_capacity <= kMaxFastElementsLength ||
5290 !ShouldConvertToSlowElements(new_capacity)) {
5291 Object* obj = Heap::AllocateFixedArrayWithHoles(new_capacity);
5292 if (obj->IsFailure()) return obj;
5293 if (IsJSArray()) JSArray::cast(this)->set_length(smi_length,
5294 SKIP_WRITE_BARRIER);
5295 SetFastElements(FixedArray::cast(obj));
5296 return this;
5297 }
5298 break;
5299 }
5300 case DICTIONARY_ELEMENTS: {
5196 if (IsJSArray()) { 5301 if (IsJSArray()) {
5197 int old_length = FastD2I(JSArray::cast(this)->length()->Number()); 5302 if (value == 0) {
5198 // NOTE: We may be able to optimize this by removing the 5303 // If the length of a slow array is reset to zero, we clear
5199 // last part of the elements backing storage array and 5304 // the array and flush backing storage. This has the added
5200 // setting the capacity to the new size. 5305 // benefit that the array returns to fast mode.
5201 for (int i = value; i < old_length; i++) { 5306 initialize_elements();
5202 FixedArray::cast(elements())->set_the_hole(i); 5307 } else {
5308 // Remove deleted elements.
5309 uint32_t old_length =
5310 static_cast<uint32_t>(JSArray::cast(this)->length()->Number());
5311 element_dictionary()->RemoveNumberEntries(value, old_length);
5203 } 5312 }
5204 JSArray::cast(this)->set_length(smi_length, SKIP_WRITE_BARRIER); 5313 JSArray::cast(this)->set_length(smi_length, SKIP_WRITE_BARRIER);
5205 } 5314 }
5206 return this; 5315 return this;
5207 } 5316 }
5208 int min = NewElementsCapacity(old_capacity); 5317 default:
5209 int new_capacity = value > min ? value : min; 5318 UNREACHABLE();
5210 if (new_capacity <= kMaxFastElementsLength || 5319 break;
5211 !ShouldConvertToSlowElements(new_capacity)) {
5212 Object* obj = Heap::AllocateFixedArrayWithHoles(new_capacity);
5213 if (obj->IsFailure()) return obj;
5214 if (IsJSArray()) JSArray::cast(this)->set_length(smi_length,
5215 SKIP_WRITE_BARRIER);
5216 SetFastElements(FixedArray::cast(obj));
5217 return this;
5218 }
5219 } else {
5220 if (IsJSArray()) {
5221 if (value == 0) {
5222 // If the length of a slow array is reset to zero, we clear
5223 // the array and flush backing storage. This has the added
5224 // benefit that the array returns to fast mode.
5225 initialize_elements();
5226 } else {
5227 // Remove deleted elements.
5228 uint32_t old_length =
5229 static_cast<uint32_t>(JSArray::cast(this)->length()->Number());
5230 element_dictionary()->RemoveNumberEntries(value, old_length);
5231 }
5232 JSArray::cast(this)->set_length(smi_length, SKIP_WRITE_BARRIER);
5233 }
5234 return this;
5235 } 5320 }
5236 } 5321 }
5237 5322
5238 // General slow case. 5323 // General slow case.
5239 if (len->IsNumber()) { 5324 if (len->IsNumber()) {
5240 uint32_t length; 5325 uint32_t length;
5241 if (Array::IndexFromObject(len, &length)) { 5326 if (Array::IndexFromObject(len, &length)) {
5242 return SetSlowElements(len); 5327 return SetSlowElements(len);
5243 } else { 5328 } else {
5244 return ArrayLengthRangeError(); 5329 return ArrayLengthRangeError();
5245 } 5330 }
5246 } 5331 }
5247 5332
5248 // len is not a number so make the array size one and 5333 // len is not a number so make the array size one and
5249 // set only element to len. 5334 // set only element to len.
5250 Object* obj = Heap::AllocateFixedArray(1); 5335 Object* obj = Heap::AllocateFixedArray(1);
5251 if (obj->IsFailure()) return obj; 5336 if (obj->IsFailure()) return obj;
5252 FixedArray::cast(obj)->set(0, len); 5337 FixedArray::cast(obj)->set(0, len);
5253 if (IsJSArray()) JSArray::cast(this)->set_length(Smi::FromInt(1), 5338 if (IsJSArray()) JSArray::cast(this)->set_length(Smi::FromInt(1),
5254 SKIP_WRITE_BARRIER); 5339 SKIP_WRITE_BARRIER);
5255 set_elements(FixedArray::cast(obj)); 5340 set_elements(FixedArray::cast(obj));
5256 return this; 5341 return this;
5257 } 5342 }
5258 5343
5259 5344
5260 bool JSObject::HasElementPostInterceptor(JSObject* receiver, uint32_t index) { 5345 bool JSObject::HasElementPostInterceptor(JSObject* receiver, uint32_t index) {
5261 if (HasFastElements()) { 5346 switch (GetElementsKind()) {
5262 uint32_t length = IsJSArray() ? 5347 case FAST_ELEMENTS: {
5263 static_cast<uint32_t>( 5348 uint32_t length = IsJSArray() ?
5264 Smi::cast(JSArray::cast(this)->length())->value()) : 5349 static_cast<uint32_t>
5265 static_cast<uint32_t>(FixedArray::cast(elements())->length()); 5350 (Smi::cast(JSArray::cast(this)->length())->value()) :
5266 if ((index < length) && 5351 static_cast<uint32_t>(FixedArray::cast(elements())->length());
5267 !FixedArray::cast(elements())->get(index)->IsTheHole()) { 5352 if ((index < length) &&
5268 return true; 5353 !FixedArray::cast(elements())->get(index)->IsTheHole()) {
5354 return true;
5355 }
5356 break;
5269 } 5357 }
5270 } else { 5358 case PIXEL_ELEMENTS: {
5271 if (element_dictionary()->FindEntry(index) 5359 // TODO(iposva): Add testcase.
5272 != NumberDictionary::kNotFound) { 5360 PixelArray* pixels = PixelArray::cast(elements());
5273 return true; 5361 if (index < static_cast<uint32_t>(pixels->length())) {
5362 return true;
5363 }
5364 break;
5274 } 5365 }
5366 case DICTIONARY_ELEMENTS: {
5367 if (element_dictionary()->FindEntry(index)
5368 != NumberDictionary::kNotFound) {
5369 return true;
5370 }
5371 break;
5372 }
5373 default:
5374 UNREACHABLE();
5375 break;
5275 } 5376 }
5276 5377
5277 // Handle [] on String objects. 5378 // Handle [] on String objects.
5278 if (this->IsStringObjectWithCharacterAt(index)) return true; 5379 if (this->IsStringObjectWithCharacterAt(index)) return true;
5279 5380
5280 Object* pt = GetPrototype(); 5381 Object* pt = GetPrototype();
5281 if (pt == Heap::null_value()) return false; 5382 if (pt == Heap::null_value()) return false;
5282 return JSObject::cast(pt)->HasElementWithReceiver(receiver, index); 5383 return JSObject::cast(pt)->HasElementWithReceiver(receiver, index);
5283 } 5384 }
5284 5385
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
5331 } 5432 }
5332 5433
5333 // Check for lookup interceptor 5434 // Check for lookup interceptor
5334 if (HasIndexedInterceptor()) { 5435 if (HasIndexedInterceptor()) {
5335 return HasElementWithInterceptor(this, index); 5436 return HasElementWithInterceptor(this, index);
5336 } 5437 }
5337 5438
5338 // Handle [] on String objects. 5439 // Handle [] on String objects.
5339 if (this->IsStringObjectWithCharacterAt(index)) return true; 5440 if (this->IsStringObjectWithCharacterAt(index)) return true;
5340 5441
5341 if (HasFastElements()) { 5442 switch (GetElementsKind()) {
5342 uint32_t length = IsJSArray() ? 5443 case FAST_ELEMENTS: {
5343 static_cast<uint32_t>( 5444 uint32_t length = IsJSArray() ?
5344 Smi::cast(JSArray::cast(this)->length())->value()) : 5445 static_cast<uint32_t>
5345 static_cast<uint32_t>(FixedArray::cast(elements())->length()); 5446 (Smi::cast(JSArray::cast(this)->length())->value()) :
5346 return (index < length) && 5447 static_cast<uint32_t>(FixedArray::cast(elements())->length());
5347 !FixedArray::cast(elements())->get(index)->IsTheHole(); 5448 return (index < length) &&
5348 } else { 5449 !FixedArray::cast(elements())->get(index)->IsTheHole();
5349 return element_dictionary()->FindEntry(index) 5450 }
5350 != NumberDictionary::kNotFound; 5451 case PIXEL_ELEMENTS: {
5452 PixelArray* pixels = PixelArray::cast(elements());
5453 return (index < static_cast<uint32_t>(pixels->length()));
5454 }
5455 case DICTIONARY_ELEMENTS: {
5456 return element_dictionary()->FindEntry(index)
5457 != NumberDictionary::kNotFound;
5458 }
5459 default:
5460 UNREACHABLE();
5461 break;
5351 } 5462 }
5463 UNREACHABLE();
5464 return Heap::null_value();
5352 } 5465 }
5353 5466
5354 5467
5355 bool JSObject::HasElementWithReceiver(JSObject* receiver, uint32_t index) { 5468 bool JSObject::HasElementWithReceiver(JSObject* receiver, uint32_t index) {
5356 // Check access rights if needed. 5469 // Check access rights if needed.
5357 if (IsAccessCheckNeeded() && 5470 if (IsAccessCheckNeeded() &&
5358 !Top::MayIndexedAccess(this, index, v8::ACCESS_HAS)) { 5471 !Top::MayIndexedAccess(this, index, v8::ACCESS_HAS)) {
5359 Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS); 5472 Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS);
5360 return false; 5473 return false;
5361 } 5474 }
5362 5475
5363 // Check for lookup interceptor 5476 // Check for lookup interceptor
5364 if (HasIndexedInterceptor()) { 5477 if (HasIndexedInterceptor()) {
5365 return HasElementWithInterceptor(receiver, index); 5478 return HasElementWithInterceptor(receiver, index);
5366 } 5479 }
5367 5480
5368 if (HasFastElements()) { 5481 switch (GetElementsKind()) {
5369 uint32_t length = IsJSArray() ? 5482 case FAST_ELEMENTS: {
5370 static_cast<uint32_t>( 5483 uint32_t length = IsJSArray() ?
5371 Smi::cast(JSArray::cast(this)->length())->value()) : 5484 static_cast<uint32_t>
5372 static_cast<uint32_t>(FixedArray::cast(elements())->length()); 5485 (Smi::cast(JSArray::cast(this)->length())->value()) :
5373 if ((index < length) && 5486 static_cast<uint32_t>(FixedArray::cast(elements())->length());
5374 !FixedArray::cast(elements())->get(index)->IsTheHole()) return true; 5487 if ((index < length) &&
5375 } else { 5488 !FixedArray::cast(elements())->get(index)->IsTheHole()) return true;
5376 if (element_dictionary()->FindEntry(index) 5489 break;
5377 != NumberDictionary::kNotFound) {
5378 return true;
5379 } 5490 }
5491 case PIXEL_ELEMENTS: {
5492 PixelArray* pixels = PixelArray::cast(elements());
5493 if (index < static_cast<uint32_t>(pixels->length())) {
5494 return true;
5495 }
5496 break;
5497 }
5498 case DICTIONARY_ELEMENTS: {
5499 if (element_dictionary()->FindEntry(index)
5500 != NumberDictionary::kNotFound) {
5501 return true;
5502 }
5503 break;
5504 }
5505 default:
5506 UNREACHABLE();
5507 break;
5380 } 5508 }
5381 5509
5382 // Handle [] on String objects. 5510 // Handle [] on String objects.
5383 if (this->IsStringObjectWithCharacterAt(index)) return true; 5511 if (this->IsStringObjectWithCharacterAt(index)) return true;
5384 5512
5385 Object* pt = GetPrototype(); 5513 Object* pt = GetPrototype();
5386 if (pt == Heap::null_value()) return false; 5514 if (pt == Heap::null_value()) return false;
5387 return JSObject::cast(pt)->HasElementWithReceiver(receiver, index); 5515 return JSObject::cast(pt)->HasElementWithReceiver(receiver, index);
5388 } 5516 }
5389 5517
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
5465 if (IsJSArray()) JSArray::cast(this)->set_length(Smi::FromInt(index + 1), 5593 if (IsJSArray()) JSArray::cast(this)->set_length(Smi::FromInt(index + 1),
5466 SKIP_WRITE_BARRIER); 5594 SKIP_WRITE_BARRIER);
5467 FixedArray::cast(elements())->set(index, value); 5595 FixedArray::cast(elements())->set(index, value);
5468 return value; 5596 return value;
5469 } 5597 }
5470 } 5598 }
5471 5599
5472 // Otherwise default to slow case. 5600 // Otherwise default to slow case.
5473 Object* obj = NormalizeElements(); 5601 Object* obj = NormalizeElements();
5474 if (obj->IsFailure()) return obj; 5602 if (obj->IsFailure()) return obj;
5475 ASSERT(!HasFastElements()); 5603 ASSERT(HasDictionaryElements());
5476 return SetElement(index, value); 5604 return SetElement(index, value);
5477 } 5605 }
5478 5606
5479 Object* JSObject::SetElement(uint32_t index, Object* value) { 5607 Object* JSObject::SetElement(uint32_t index, Object* value) {
5480 // Check access rights if needed. 5608 // Check access rights if needed.
5481 if (IsAccessCheckNeeded() && 5609 if (IsAccessCheckNeeded() &&
5482 !Top::MayIndexedAccess(this, index, v8::ACCESS_SET)) { 5610 !Top::MayIndexedAccess(this, index, v8::ACCESS_SET)) {
5483 Top::ReportFailedAccessCheck(this, v8::ACCESS_SET); 5611 Top::ReportFailedAccessCheck(this, v8::ACCESS_SET);
5484 return value; 5612 return value;
5485 } 5613 }
5486 5614
5487 if (IsJSGlobalProxy()) { 5615 if (IsJSGlobalProxy()) {
5488 Object* proto = GetPrototype(); 5616 Object* proto = GetPrototype();
5489 if (proto->IsNull()) return value; 5617 if (proto->IsNull()) return value;
5490 ASSERT(proto->IsJSGlobalObject()); 5618 ASSERT(proto->IsJSGlobalObject());
5491 return JSObject::cast(proto)->SetElement(index, value); 5619 return JSObject::cast(proto)->SetElement(index, value);
5492 } 5620 }
5493 5621
5494 // Check for lookup interceptor 5622 // Check for lookup interceptor
5495 if (HasIndexedInterceptor()) { 5623 if (HasIndexedInterceptor()) {
5496 return SetElementWithInterceptor(index, value); 5624 return SetElementWithInterceptor(index, value);
5497 } 5625 }
5498 5626
5499 return SetElementWithoutInterceptor(index, value); 5627 return SetElementWithoutInterceptor(index, value);
5500 } 5628 }
5501 5629
5502 5630
5503 Object* JSObject::SetElementWithoutInterceptor(uint32_t index, Object* value) { 5631 Object* JSObject::SetElementWithoutInterceptor(uint32_t index, Object* value) {
5504 // Fast case. 5632 switch (GetElementsKind()) {
5505 if (HasFastElements()) return SetFastElement(index, value); 5633 case FAST_ELEMENTS:
5506 5634 // Fast case.
5507 // Dictionary case. 5635 return SetFastElement(index, value);
5508 ASSERT(!HasFastElements()); 5636 case PIXEL_ELEMENTS: {
5509 5637 PixelArray* pixels = PixelArray::cast(elements());
5510 // Insert element in the dictionary. 5638 return pixels->SetValue(index, value);
5511 FixedArray* elms = FixedArray::cast(elements()); 5639 }
5512 NumberDictionary* dictionary = NumberDictionary::cast(elms); 5640 case DICTIONARY_ELEMENTS: {
5513 5641 // Insert element in the dictionary.
5514 int entry = dictionary->FindEntry(index); 5642 FixedArray* elms = FixedArray::cast(elements());
5515 if (entry != NumberDictionary::kNotFound) { 5643 NumberDictionary* dictionary = NumberDictionary::cast(elms);
5516 Object* element = dictionary->ValueAt(entry); 5644
5517 PropertyDetails details = dictionary->DetailsAt(entry); 5645 int entry = dictionary->FindEntry(index);
5518 if (details.type() == CALLBACKS) { 5646 if (entry != NumberDictionary::kNotFound) {
5519 // Only accessors allowed as elements. 5647 Object* element = dictionary->ValueAt(entry);
5520 FixedArray* structure = FixedArray::cast(element); 5648 PropertyDetails details = dictionary->DetailsAt(entry);
5521 if (structure->get(kSetterIndex)->IsJSFunction()) { 5649 if (details.type() == CALLBACKS) {
5522 JSFunction* setter = JSFunction::cast(structure->get(kSetterIndex)); 5650 // Only accessors allowed as elements.
5523 return SetPropertyWithDefinedSetter(setter, value); 5651 FixedArray* structure = FixedArray::cast(element);
5652 if (structure->get(kSetterIndex)->IsJSFunction()) {
5653 JSFunction* setter = JSFunction::cast(structure->get(kSetterIndex));
5654 return SetPropertyWithDefinedSetter(setter, value);
5655 } else {
5656 Handle<Object> self(this);
5657 Handle<Object> key(Factory::NewNumberFromUint(index));
5658 Handle<Object> args[2] = { key, self };
5659 return Top::Throw(*Factory::NewTypeError("no_setter_in_callback",
5660 HandleVector(args, 2)));
5661 }
5662 } else {
5663 dictionary->UpdateMaxNumberKey(index);
5664 dictionary->ValueAtPut(entry, value);
5665 }
5524 } else { 5666 } else {
5525 Handle<Object> self(this); 5667 // Index not already used. Look for an accessor in the prototype chain.
5526 Handle<Object> key(Factory::NewNumberFromUint(index)); 5668 if (!IsJSArray()) {
5527 Handle<Object> args[2] = { key, self }; 5669 Object* setter = LookupCallbackSetterInPrototypes(index);
5528 return Top::Throw(*Factory::NewTypeError("no_setter_in_callback", 5670 if (setter->IsJSFunction()) {
5529 HandleVector(args, 2))); 5671 return SetPropertyWithDefinedSetter(JSFunction::cast(setter),
5672 value);
5673 }
5674 }
5675 Object* result = dictionary->AtNumberPut(index, value);
5676 if (result->IsFailure()) return result;
5677 if (elms != FixedArray::cast(result)) {
5678 set_elements(FixedArray::cast(result));
5679 }
5530 } 5680 }
5531 } else { 5681
5532 dictionary->UpdateMaxNumberKey(index); 5682 // Update the array length if this JSObject is an array.
5533 dictionary->ValueAtPut(entry, value); 5683 if (IsJSArray()) {
5684 JSArray* array = JSArray::cast(this);
5685 Object* return_value = array->JSArrayUpdateLengthFromIndex(index,
5686 value);
5687 if (return_value->IsFailure()) return return_value;
5688 }
5689
5690 // Attempt to put this object back in fast case.
5691 if (ShouldConvertToFastElements()) {
5692 uint32_t new_length = 0;
5693 if (IsJSArray()) {
5694 CHECK(Array::IndexFromObject(JSArray::cast(this)->length(),
5695 &new_length));
5696 JSArray::cast(this)->set_length(Smi::FromInt(new_length));
5697 } else {
5698 new_length = NumberDictionary::cast(elements())->max_number_key() + 1;
5699 }
5700 Object* obj = Heap::AllocateFixedArrayWithHoles(new_length);
5701 if (obj->IsFailure()) return obj;
5702 SetFastElements(FixedArray::cast(obj));
5703 #ifdef DEBUG
5704 if (FLAG_trace_normalization) {
5705 PrintF("Object elements are fast case again:\n");
5706 Print();
5707 }
5708 #endif
5709 }
5710
5711 return value;
5534 } 5712 }
5535 } else { 5713 default:
5536 // Index not already used. Look for an accessor in the prototype chain. 5714 UNREACHABLE();
5537 if (!IsJSArray()) { 5715 break;
5538 Object* setter = LookupCallbackSetterInPrototypes(index);
5539 if (setter->IsJSFunction()) {
5540 return SetPropertyWithDefinedSetter(JSFunction::cast(setter), value);
5541 }
5542 }
5543 Object* result = dictionary->AtNumberPut(index, value);
5544 if (result->IsFailure()) return result;
5545 if (elms != FixedArray::cast(result)) {
5546 set_elements(FixedArray::cast(result));
5547 }
5548 } 5716 }
5549 5717 // All possible cases have been handled above. Add a return to avoid the
5550 // Update the array length if this JSObject is an array. 5718 // complaints from the compiler.
5551 if (IsJSArray()) { 5719 UNREACHABLE();
5552 JSArray* array = JSArray::cast(this); 5720 return Heap::null_value();
5553 Object* return_value = array->JSArrayUpdateLengthFromIndex(index, value);
5554 if (return_value->IsFailure()) return return_value;
5555 }
5556
5557 // Attempt to put this object back in fast case.
5558 if (ShouldConvertToFastElements()) {
5559 uint32_t new_length = 0;
5560 if (IsJSArray()) {
5561 CHECK(Array::IndexFromObject(JSArray::cast(this)->length(), &new_length));
5562 JSArray::cast(this)->set_length(Smi::FromInt(new_length));
5563 } else {
5564 new_length = NumberDictionary::cast(elements())->max_number_key() + 1;
5565 }
5566 Object* obj = Heap::AllocateFixedArrayWithHoles(new_length);
5567 if (obj->IsFailure()) return obj;
5568 SetFastElements(FixedArray::cast(obj));
5569 #ifdef DEBUG
5570 if (FLAG_trace_normalization) {
5571 PrintF("Object elements are fast case again:\n");
5572 Print();
5573 }
5574 #endif
5575 }
5576
5577 return value;
5578 } 5721 }
5579 5722
5580 5723
5581 Object* JSArray::JSArrayUpdateLengthFromIndex(uint32_t index, Object* value) { 5724 Object* JSArray::JSArrayUpdateLengthFromIndex(uint32_t index, Object* value) {
5582 uint32_t old_len = 0; 5725 uint32_t old_len = 0;
5583 CHECK(Array::IndexFromObject(length(), &old_len)); 5726 CHECK(Array::IndexFromObject(length(), &old_len));
5584 // Check to see if we need to update the length. For now, we make 5727 // Check to see if we need to update the length. For now, we make
5585 // sure that the length stays within 32-bits (unsigned). 5728 // sure that the length stays within 32-bits (unsigned).
5586 if (index >= old_len && index != 0xffffffff) { 5729 if (index >= old_len && index != 0xffffffff) {
5587 Object* len = 5730 Object* len =
5588 Heap::NumberFromDouble(static_cast<double>(index) + 1); 5731 Heap::NumberFromDouble(static_cast<double>(index) + 1);
5589 if (len->IsFailure()) return len; 5732 if (len->IsFailure()) return len;
5590 set_length(len); 5733 set_length(len);
5591 } 5734 }
5592 return value; 5735 return value;
5593 } 5736 }
5594 5737
5595 5738
5596 Object* JSObject::GetElementPostInterceptor(JSObject* receiver, 5739 Object* JSObject::GetElementPostInterceptor(JSObject* receiver,
5597 uint32_t index) { 5740 uint32_t index) {
5598 // Get element works for both JSObject and JSArray since 5741 // Get element works for both JSObject and JSArray since
5599 // JSArray::length cannot change. 5742 // JSArray::length cannot change.
5600 if (HasFastElements()) { 5743 switch (GetElementsKind()) {
5601 FixedArray* elms = FixedArray::cast(elements()); 5744 case FAST_ELEMENTS: {
5602 if (index < static_cast<uint32_t>(elms->length())) { 5745 FixedArray* elms = FixedArray::cast(elements());
5603 Object* value = elms->get(index); 5746 if (index < static_cast<uint32_t>(elms->length())) {
5604 if (!value->IsTheHole()) return value; 5747 Object* value = elms->get(index);
5748 if (!value->IsTheHole()) return value;
5749 }
5750 break;
5605 } 5751 }
5606 } else { 5752 case PIXEL_ELEMENTS: {
5607 NumberDictionary* dictionary = element_dictionary(); 5753 // TODO(iposva): Add testcase and implement.
5608 int entry = dictionary->FindEntry(index); 5754 UNIMPLEMENTED();
5609 if (entry != NumberDictionary::kNotFound) { 5755 break;
5610 Object* element = dictionary->ValueAt(entry); 5756 }
5611 PropertyDetails details = dictionary->DetailsAt(entry); 5757 case DICTIONARY_ELEMENTS: {
5612 if (details.type() == CALLBACKS) { 5758 NumberDictionary* dictionary = element_dictionary();
5613 // Only accessors allowed as elements. 5759 int entry = dictionary->FindEntry(index);
5614 FixedArray* structure = FixedArray::cast(element); 5760 if (entry != NumberDictionary::kNotFound) {
5615 Object* getter = structure->get(kGetterIndex); 5761 Object* element = dictionary->ValueAt(entry);
5616 if (getter->IsJSFunction()) { 5762 PropertyDetails details = dictionary->DetailsAt(entry);
5617 return GetPropertyWithDefinedGetter(receiver, 5763 if (details.type() == CALLBACKS) {
5618 JSFunction::cast(getter)); 5764 // Only accessors allowed as elements.
5619 } else { 5765 FixedArray* structure = FixedArray::cast(element);
5620 // Getter is not a function. 5766 Object* getter = structure->get(kGetterIndex);
5621 return Heap::undefined_value(); 5767 if (getter->IsJSFunction()) {
5768 return GetPropertyWithDefinedGetter(receiver,
5769 JSFunction::cast(getter));
5770 } else {
5771 // Getter is not a function.
5772 return Heap::undefined_value();
5773 }
5622 } 5774 }
5775 return element;
5623 } 5776 }
5624 return element; 5777 break;
5625 } 5778 }
5779 default:
5780 UNREACHABLE();
5781 break;
5626 } 5782 }
5627 5783
5628 // Continue searching via the prototype chain. 5784 // Continue searching via the prototype chain.
5629 Object* pt = GetPrototype(); 5785 Object* pt = GetPrototype();
5630 if (pt == Heap::null_value()) return Heap::undefined_value(); 5786 if (pt == Heap::null_value()) return Heap::undefined_value();
5631 return pt->GetElementWithReceiver(receiver, index); 5787 return pt->GetElementWithReceiver(receiver, index);
5632 } 5788 }
5633 5789
5634 5790
5635 Object* JSObject::GetElementWithInterceptor(JSObject* receiver, 5791 Object* JSObject::GetElementWithInterceptor(JSObject* receiver,
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
5674 Top::ReportFailedAccessCheck(this, v8::ACCESS_GET); 5830 Top::ReportFailedAccessCheck(this, v8::ACCESS_GET);
5675 return Heap::undefined_value(); 5831 return Heap::undefined_value();
5676 } 5832 }
5677 5833
5678 if (HasIndexedInterceptor()) { 5834 if (HasIndexedInterceptor()) {
5679 return GetElementWithInterceptor(receiver, index); 5835 return GetElementWithInterceptor(receiver, index);
5680 } 5836 }
5681 5837
5682 // Get element works for both JSObject and JSArray since 5838 // Get element works for both JSObject and JSArray since
5683 // JSArray::length cannot change. 5839 // JSArray::length cannot change.
5684 if (HasFastElements()) { 5840 switch (GetElementsKind()) {
5685 FixedArray* elms = FixedArray::cast(elements()); 5841 case FAST_ELEMENTS: {
5686 if (index < static_cast<uint32_t>(elms->length())) { 5842 FixedArray* elms = FixedArray::cast(elements());
5687 Object* value = elms->get(index); 5843 if (index < static_cast<uint32_t>(elms->length())) {
5688 if (!value->IsTheHole()) return value; 5844 Object* value = elms->get(index);
5845 if (!value->IsTheHole()) return value;
5846 }
5847 break;
5689 } 5848 }
5690 } else { 5849 case PIXEL_ELEMENTS: {
5691 NumberDictionary* dictionary = element_dictionary(); 5850 PixelArray* pixels = PixelArray::cast(elements());
5692 int entry = dictionary->FindEntry(index); 5851 if (index < static_cast<uint32_t>(pixels->length())) {
5693 if (entry != NumberDictionary::kNotFound) { 5852 uint8_t value = pixels->get(index);
5694 Object* element = dictionary->ValueAt(entry); 5853 return Smi::FromInt(value);
5695 PropertyDetails details = dictionary->DetailsAt(entry); 5854 }
5696 if (details.type() == CALLBACKS) { 5855 break;
5697 // Only accessors allowed as elements. 5856 }
5698 FixedArray* structure = FixedArray::cast(element); 5857 case DICTIONARY_ELEMENTS: {
5699 Object* getter = structure->get(kGetterIndex); 5858 NumberDictionary* dictionary = element_dictionary();
5700 if (getter->IsJSFunction()) { 5859 int entry = dictionary->FindEntry(index);
5701 return GetPropertyWithDefinedGetter(receiver, 5860 if (entry != NumberDictionary::kNotFound) {
5702 JSFunction::cast(getter)); 5861 Object* element = dictionary->ValueAt(entry);
5703 } else { 5862 PropertyDetails details = dictionary->DetailsAt(entry);
5704 // Getter is not a function. 5863 if (details.type() == CALLBACKS) {
5705 return Heap::undefined_value(); 5864 // Only accessors allowed as elements.
5865 FixedArray* structure = FixedArray::cast(element);
5866 Object* getter = structure->get(kGetterIndex);
5867 if (getter->IsJSFunction()) {
5868 return GetPropertyWithDefinedGetter(receiver,
5869 JSFunction::cast(getter));
5870 } else {
5871 // Getter is not a function.
5872 return Heap::undefined_value();
5873 }
5706 } 5874 }
5875 return element;
5707 } 5876 }
5708 return element; 5877 break;
5709 } 5878 }
5710 } 5879 }
5711 5880
5712 Object* pt = GetPrototype(); 5881 Object* pt = GetPrototype();
5713 if (pt == Heap::null_value()) return Heap::undefined_value(); 5882 if (pt == Heap::null_value()) return Heap::undefined_value();
5714 return pt->GetElementWithReceiver(receiver, index); 5883 return pt->GetElementWithReceiver(receiver, index);
5715 } 5884 }
5716 5885
5717 5886
5718 bool JSObject::HasDenseElements() { 5887 bool JSObject::HasDenseElements() {
5719 int capacity = 0; 5888 int capacity = 0;
5720 int number_of_elements = 0; 5889 int number_of_elements = 0;
5721 5890
5722 if (HasFastElements()) { 5891 switch (GetElementsKind()) {
5723 FixedArray* elms = FixedArray::cast(elements()); 5892 case FAST_ELEMENTS: {
5724 capacity = elms->length(); 5893 FixedArray* elms = FixedArray::cast(elements());
5725 for (int i = 0; i < capacity; i++) { 5894 capacity = elms->length();
5726 if (!elms->get(i)->IsTheHole()) number_of_elements++; 5895 for (int i = 0; i < capacity; i++) {
5896 if (!elms->get(i)->IsTheHole()) number_of_elements++;
5897 }
5898 break;
5727 } 5899 }
5728 } else { 5900 case PIXEL_ELEMENTS: {
5729 NumberDictionary* dictionary = NumberDictionary::cast(elements()); 5901 return true;
5730 capacity = dictionary->Capacity(); 5902 }
5731 number_of_elements = dictionary->NumberOfElements(); 5903 case DICTIONARY_ELEMENTS: {
5904 NumberDictionary* dictionary = NumberDictionary::cast(elements());
5905 capacity = dictionary->Capacity();
5906 number_of_elements = dictionary->NumberOfElements();
5907 break;
5908 }
5909 default:
5910 UNREACHABLE();
5911 break;
5732 } 5912 }
5733 5913
5734 if (capacity == 0) return true; 5914 if (capacity == 0) return true;
5735 return (number_of_elements > (capacity / 2)); 5915 return (number_of_elements > (capacity / 2));
5736 } 5916 }
5737 5917
5738 5918
5739 bool JSObject::ShouldConvertToSlowElements(int new_capacity) { 5919 bool JSObject::ShouldConvertToSlowElements(int new_capacity) {
5740 ASSERT(HasFastElements()); 5920 ASSERT(HasFastElements());
5741 // Keep the array in fast case if the current backing storage is 5921 // Keep the array in fast case if the current backing storage is
5742 // almost filled and if the new capacity is no more than twice the 5922 // almost filled and if the new capacity is no more than twice the
5743 // old capacity. 5923 // old capacity.
5744 int elements_length = FixedArray::cast(elements())->length(); 5924 int elements_length = FixedArray::cast(elements())->length();
5745 return !HasDenseElements() || ((new_capacity / 2) > elements_length); 5925 return !HasDenseElements() || ((new_capacity / 2) > elements_length);
5746 } 5926 }
5747 5927
5748 5928
5749 bool JSObject::ShouldConvertToFastElements() { 5929 bool JSObject::ShouldConvertToFastElements() {
5750 ASSERT(!HasFastElements()); 5930 ASSERT(HasDictionaryElements());
5751 NumberDictionary* dictionary = NumberDictionary::cast(elements()); 5931 NumberDictionary* dictionary = NumberDictionary::cast(elements());
5752 // If the elements are sparse, we should not go back to fast case. 5932 // If the elements are sparse, we should not go back to fast case.
5753 if (!HasDenseElements()) return false; 5933 if (!HasDenseElements()) return false;
5754 // If an element has been added at a very high index in the elements 5934 // If an element has been added at a very high index in the elements
5755 // dictionary, we cannot go back to fast case. 5935 // dictionary, we cannot go back to fast case.
5756 if (dictionary->requires_slow_elements()) return false; 5936 if (dictionary->requires_slow_elements()) return false;
5757 // An object requiring access checks is never allowed to have fast 5937 // An object requiring access checks is never allowed to have fast
5758 // elements. If it had fast elements we would skip security checks. 5938 // elements. If it had fast elements we would skip security checks.
5759 if (IsAccessCheckNeeded()) return false; 5939 if (IsAccessCheckNeeded()) return false;
5760 // If the dictionary backing storage takes up roughly half as much 5940 // If the dictionary backing storage takes up roughly half as much
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after
5994 // Check access rights if needed. 6174 // Check access rights if needed.
5995 if (IsAccessCheckNeeded() && 6175 if (IsAccessCheckNeeded() &&
5996 !Top::MayIndexedAccess(this, index, v8::ACCESS_HAS)) { 6176 !Top::MayIndexedAccess(this, index, v8::ACCESS_HAS)) {
5997 Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS); 6177 Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS);
5998 return false; 6178 return false;
5999 } 6179 }
6000 6180
6001 // Handle [] on String objects. 6181 // Handle [] on String objects.
6002 if (this->IsStringObjectWithCharacterAt(index)) return true; 6182 if (this->IsStringObjectWithCharacterAt(index)) return true;
6003 6183
6004 if (HasFastElements()) { 6184 switch (GetElementsKind()) {
6005 uint32_t length = IsJSArray() ? 6185 case FAST_ELEMENTS: {
6006 static_cast<uint32_t>( 6186 uint32_t length = IsJSArray() ?
6007 Smi::cast(JSArray::cast(this)->length())->value()) : 6187 static_cast<uint32_t>(
6008 static_cast<uint32_t>(FixedArray::cast(elements())->length()); 6188 Smi::cast(JSArray::cast(this)->length())->value()) :
6009 return (index < length) && 6189 static_cast<uint32_t>(FixedArray::cast(elements())->length());
6010 !FixedArray::cast(elements())->get(index)->IsTheHole(); 6190 return (index < length) &&
6191 !FixedArray::cast(elements())->get(index)->IsTheHole();
6192 }
6193 case PIXEL_ELEMENTS: {
6194 PixelArray* pixels = PixelArray::cast(elements());
6195 return index < static_cast<uint32_t>(pixels->length());
6196 }
6197 case DICTIONARY_ELEMENTS: {
6198 return element_dictionary()->FindEntry(index)
6199 != NumberDictionary::kNotFound;
6200 }
6201 default:
6202 UNREACHABLE();
6203 break;
6011 } 6204 }
6012 return element_dictionary()->FindEntry(index) 6205 // All possibilities have been handled above already.
6013 != NumberDictionary::kNotFound; 6206 UNREACHABLE();
6207 return Heap::null_value();
6014 } 6208 }
6015 6209
6016 6210
6017 bool JSObject::HasRealNamedCallbackProperty(String* key) { 6211 bool JSObject::HasRealNamedCallbackProperty(String* key) {
6018 // Check access rights if needed. 6212 // Check access rights if needed.
6019 if (IsAccessCheckNeeded() && 6213 if (IsAccessCheckNeeded() &&
6020 !Top::MayNamedAccess(this, key, v8::ACCESS_HAS)) { 6214 !Top::MayNamedAccess(this, key, v8::ACCESS_HAS)) {
6021 Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS); 6215 Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS);
6022 return false; 6216 return false;
6023 } 6217 }
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
6186 6380
6187 6381
6188 int JSObject::NumberOfEnumElements() { 6382 int JSObject::NumberOfEnumElements() {
6189 return NumberOfLocalElements(static_cast<PropertyAttributes>(DONT_ENUM)); 6383 return NumberOfLocalElements(static_cast<PropertyAttributes>(DONT_ENUM));
6190 } 6384 }
6191 6385
6192 6386
6193 int JSObject::GetLocalElementKeys(FixedArray* storage, 6387 int JSObject::GetLocalElementKeys(FixedArray* storage,
6194 PropertyAttributes filter) { 6388 PropertyAttributes filter) {
6195 int counter = 0; 6389 int counter = 0;
6196 if (HasFastElements()) { 6390 switch (GetElementsKind()) {
6197 int length = IsJSArray() 6391 case FAST_ELEMENTS: {
6198 ? Smi::cast(JSArray::cast(this)->length())->value() 6392 int length = IsJSArray() ?
6199 : FixedArray::cast(elements())->length(); 6393 Smi::cast(JSArray::cast(this)->length())->value() :
6200 for (int i = 0; i < length; i++) { 6394 FixedArray::cast(elements())->length();
6201 if (!FixedArray::cast(elements())->get(i)->IsTheHole()) { 6395 for (int i = 0; i < length; i++) {
6202 if (storage) { 6396 if (!FixedArray::cast(elements())->get(i)->IsTheHole()) {
6203 storage->set(counter, Smi::FromInt(i), SKIP_WRITE_BARRIER); 6397 if (storage != NULL) {
6398 storage->set(counter, Smi::FromInt(i), SKIP_WRITE_BARRIER);
6399 }
6400 counter++;
6401 }
6402 }
6403 ASSERT(!storage || storage->length() >= counter);
6404 break;
6405 }
6406 case PIXEL_ELEMENTS: {
6407 int length = PixelArray::cast(elements())->length();
6408 while (counter < length) {
6409 if (storage != NULL) {
6410 storage->set(counter, Smi::FromInt(counter), SKIP_WRITE_BARRIER);
6204 } 6411 }
6205 counter++; 6412 counter++;
6206 } 6413 }
6414 ASSERT(!storage || storage->length() >= counter);
6415 break;
6207 } 6416 }
6208 ASSERT(!storage || storage->length() >= counter); 6417 case DICTIONARY_ELEMENTS: {
6209 } else { 6418 if (storage != NULL) {
6210 if (storage) { 6419 element_dictionary()->CopyKeysTo(storage, filter);
6211 element_dictionary()->CopyKeysTo(storage, filter); 6420 }
6421 counter = element_dictionary()->NumberOfElementsFilterAttributes(filter);
6422 break;
6212 } 6423 }
6213 counter = element_dictionary()->NumberOfElementsFilterAttributes(filter); 6424 default:
6425 UNREACHABLE();
6426 break;
6214 } 6427 }
6215 6428
6216 if (this->IsJSValue()) { 6429 if (this->IsJSValue()) {
6217 Object* val = JSValue::cast(this)->value(); 6430 Object* val = JSValue::cast(this)->value();
6218 if (val->IsString()) { 6431 if (val->IsString()) {
6219 String* str = String::cast(val); 6432 String* str = String::cast(val);
6220 if (storage) { 6433 if (storage) {
6221 for (int i = 0; i < str->length(); i++) { 6434 for (int i = 0; i < str->length(); i++) {
6222 storage->set(counter + i, Smi::FromInt(i), SKIP_WRITE_BARRIER); 6435 storage->set(counter + i, Smi::FromInt(i), SKIP_WRITE_BARRIER);
6223 } 6436 }
(...skipping 438 matching lines...) Expand 10 before | Expand all | Expand 10 after
6662 6875
6663 template 6876 template
6664 int Dictionary<NumberDictionaryShape, uint32_t>::NumberOfEnumElements(); 6877 int Dictionary<NumberDictionaryShape, uint32_t>::NumberOfEnumElements();
6665 6878
6666 template 6879 template
6667 int Dictionary<StringDictionaryShape, String*>::NumberOfEnumElements(); 6880 int Dictionary<StringDictionaryShape, String*>::NumberOfEnumElements();
6668 6881
6669 // Collates undefined and unexisting elements below limit from position 6882 // Collates undefined and unexisting elements below limit from position
6670 // zero of the elements. The object stays in Dictionary mode. 6883 // zero of the elements. The object stays in Dictionary mode.
6671 Object* JSObject::PrepareSlowElementsForSort(uint32_t limit) { 6884 Object* JSObject::PrepareSlowElementsForSort(uint32_t limit) {
6672 ASSERT(!HasFastElements()); 6885 ASSERT(HasDictionaryElements());
6673 // Must stay in dictionary mode, either because of requires_slow_elements, 6886 // Must stay in dictionary mode, either because of requires_slow_elements,
6674 // or because we are not going to sort (and therefore compact) all of the 6887 // or because we are not going to sort (and therefore compact) all of the
6675 // elements. 6888 // elements.
6676 NumberDictionary* dict = element_dictionary(); 6889 NumberDictionary* dict = element_dictionary();
6677 HeapNumber* result_double = NULL; 6890 HeapNumber* result_double = NULL;
6678 if (limit > static_cast<uint32_t>(Smi::kMaxValue)) { 6891 if (limit > static_cast<uint32_t>(Smi::kMaxValue)) {
6679 // Allocate space for result before we start mutating the object. 6892 // Allocate space for result before we start mutating the object.
6680 Object* new_double = Heap::AllocateHeapNumber(0.0); 6893 Object* new_double = Heap::AllocateHeapNumber(0.0);
6681 if (new_double->IsFailure()) return new_double; 6894 if (new_double->IsFailure()) return new_double;
6682 result_double = HeapNumber::cast(new_double); 6895 result_double = HeapNumber::cast(new_double);
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
6736 result_double->set_value(static_cast<double>(result)); 6949 result_double->set_value(static_cast<double>(result));
6737 return result_double; 6950 return result_double;
6738 } 6951 }
6739 6952
6740 6953
6741 // Collects all defined (non-hole) and non-undefined (array) elements at 6954 // Collects all defined (non-hole) and non-undefined (array) elements at
6742 // the start of the elements array. 6955 // the start of the elements array.
6743 // If the object is in dictionary mode, it is converted to fast elements 6956 // If the object is in dictionary mode, it is converted to fast elements
6744 // mode. 6957 // mode.
6745 Object* JSObject::PrepareElementsForSort(uint32_t limit) { 6958 Object* JSObject::PrepareElementsForSort(uint32_t limit) {
6746 if (!HasFastElements()) { 6959 ASSERT(!HasPixelElements());
6960
6961 if (HasDictionaryElements()) {
6747 // Convert to fast elements containing only the existing properties. 6962 // Convert to fast elements containing only the existing properties.
6748 // Ordering is irrelevant, since we are going to sort anyway. 6963 // Ordering is irrelevant, since we are going to sort anyway.
6749 NumberDictionary* dict = element_dictionary(); 6964 NumberDictionary* dict = element_dictionary();
6750 if (IsJSArray() || dict->requires_slow_elements() || 6965 if (IsJSArray() || dict->requires_slow_elements() ||
6751 dict->max_number_key() >= limit) { 6966 dict->max_number_key() >= limit) {
6752 return PrepareSlowElementsForSort(limit); 6967 return PrepareSlowElementsForSort(limit);
6753 } 6968 }
6754 // Convert to fast elements. 6969 // Convert to fast elements.
6755 6970
6756 PretenureFlag tenure = Heap::InNewSpace(this) ? NOT_TENURED: TENURED; 6971 PretenureFlag tenure = Heap::InNewSpace(this) ? NOT_TENURED: TENURED;
6757 Object* new_array = 6972 Object* new_array =
6758 Heap::AllocateFixedArray(dict->NumberOfElements(), tenure); 6973 Heap::AllocateFixedArray(dict->NumberOfElements(), tenure);
6759 if (new_array->IsFailure()) { 6974 if (new_array->IsFailure()) {
6760 return new_array; 6975 return new_array;
6761 } 6976 }
6762 FixedArray* fast_elements = FixedArray::cast(new_array); 6977 FixedArray* fast_elements = FixedArray::cast(new_array);
6763 dict->CopyValuesTo(fast_elements); 6978 dict->CopyValuesTo(fast_elements);
6764 set_elements(fast_elements); 6979 set_elements(fast_elements);
6765 } 6980 }
6766 ASSERT(HasFastElements()); 6981 ASSERT(HasFastElements());
6767 6982
6768 // Collect holes at the end, undefined before that and the rest at the 6983 // Collect holes at the end, undefined before that and the rest at the
6769 // start, and return the number of non-hole, non-undefined values. 6984 // start, and return the number of non-hole, non-undefined values.
6770 6985
6771 FixedArray* elements = this->elements(); 6986 FixedArray* elements = FixedArray::cast(this->elements());
6772 uint32_t elements_length = static_cast<uint32_t>(elements->length()); 6987 uint32_t elements_length = static_cast<uint32_t>(elements->length());
6773 if (limit > elements_length) { 6988 if (limit > elements_length) {
6774 limit = elements_length ; 6989 limit = elements_length ;
6775 } 6990 }
6776 if (limit == 0) { 6991 if (limit == 0) {
6777 return Smi::FromInt(0); 6992 return Smi::FromInt(0);
6778 } 6993 }
6779 6994
6780 HeapNumber* result_double = NULL; 6995 HeapNumber* result_double = NULL;
6781 if (limit > static_cast<uint32_t>(Smi::kMaxValue)) { 6996 if (limit > static_cast<uint32_t>(Smi::kMaxValue)) {
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
6831 7046
6832 if (result <= static_cast<uint32_t>(Smi::kMaxValue)) { 7047 if (result <= static_cast<uint32_t>(Smi::kMaxValue)) {
6833 return Smi::FromInt(static_cast<int>(result)); 7048 return Smi::FromInt(static_cast<int>(result));
6834 } 7049 }
6835 ASSERT_NE(NULL, result_double); 7050 ASSERT_NE(NULL, result_double);
6836 result_double->set_value(static_cast<double>(result)); 7051 result_double->set_value(static_cast<double>(result));
6837 return result_double; 7052 return result_double;
6838 } 7053 }
6839 7054
6840 7055
7056 Object* PixelArray::SetValue(uint32_t index, Object* value) {
7057 uint8_t clamped_value = 0;
7058 if (index < static_cast<uint32_t>(length())) {
7059 int int_value = 0;
7060 if (value->IsSmi()) {
7061 int_value = Smi::cast(value)->value();
7062 } else if (value->IsHeapNumber()) {
7063 static const DoubleRepresentation nan(OS::nan_value());
7064 DoubleRepresentation double_value = HeapNumber::cast(value)->value();
7065 if (nan.bits != double_value.bits) {
7066 int_value = static_cast<int>(double_value.value + 0.5);
7067 } else {
7068 // NaN clamps to zero.
7069 int_value = 0;
7070 }
7071 } else if (value->IsUndefined()) {
7072 int_value = 0;
7073 } else {
7074 // All other types have been converted to a number type further up in the
7075 // call chain.
7076 UNREACHABLE();
7077 }
7078 if (int_value < 0) {
7079 clamped_value = 0;
7080 } else if (int_value > 255) {
7081 clamped_value = 255;
7082 } else {
7083 clamped_value = static_cast<uint8_t>(int_value);
7084 }
7085 set(index, clamped_value);
7086 }
7087 return Smi::FromInt(clamped_value);
7088 }
7089
7090
6841 Object* GlobalObject::GetPropertyCell(LookupResult* result) { 7091 Object* GlobalObject::GetPropertyCell(LookupResult* result) {
6842 ASSERT(!HasFastProperties()); 7092 ASSERT(!HasFastProperties());
6843 Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry()); 7093 Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry());
6844 ASSERT(value->IsJSGlobalPropertyCell()); 7094 ASSERT(value->IsJSGlobalPropertyCell());
6845 return value; 7095 return value;
6846 } 7096 }
6847 7097
6848 7098
6849 Object* GlobalObject::EnsurePropertyCell(String* name) { 7099 Object* GlobalObject::EnsurePropertyCell(String* name) {
6850 ASSERT(!HasFastProperties()); 7100 ASSERT(!HasFastProperties());
(...skipping 896 matching lines...) Expand 10 before | Expand all | Expand 10 after
7747 if (break_point_objects()->IsUndefined()) return 0; 7997 if (break_point_objects()->IsUndefined()) return 0;
7748 // Single beak point. 7998 // Single beak point.
7749 if (!break_point_objects()->IsFixedArray()) return 1; 7999 if (!break_point_objects()->IsFixedArray()) return 1;
7750 // Multiple break points. 8000 // Multiple break points.
7751 return FixedArray::cast(break_point_objects())->length(); 8001 return FixedArray::cast(break_point_objects())->length();
7752 } 8002 }
7753 #endif 8003 #endif
7754 8004
7755 8005
7756 } } // namespace v8::internal 8006 } } // 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