| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 1010 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1021 return context->symbol_function()->instance_prototype(); | 1021 return context->symbol_function()->instance_prototype(); |
| 1022 } | 1022 } |
| 1023 if (heap_object->IsBoolean()) { | 1023 if (heap_object->IsBoolean()) { |
| 1024 return context->boolean_function()->instance_prototype(); | 1024 return context->boolean_function()->instance_prototype(); |
| 1025 } else { | 1025 } else { |
| 1026 return isolate->heap()->null_value(); | 1026 return isolate->heap()->null_value(); |
| 1027 } | 1027 } |
| 1028 } | 1028 } |
| 1029 | 1029 |
| 1030 | 1030 |
| 1031 Map* Object::GetMarkerMap(Isolate* isolate) { |
| 1032 if (IsSmi()) return isolate->heap()->heap_number_map(); |
| 1033 return HeapObject::cast(this)->map(); |
| 1034 } |
| 1035 |
| 1036 |
| 1031 Object* Object::GetHash() { | 1037 Object* Object::GetHash() { |
| 1032 // The object is either a number, a name, an odd-ball, | 1038 // The object is either a number, a name, an odd-ball, |
| 1033 // a real JS object, or a Harmony proxy. | 1039 // a real JS object, or a Harmony proxy. |
| 1034 if (IsNumber()) { | 1040 if (IsNumber()) { |
| 1035 uint32_t hash = ComputeLongHash(double_to_uint64(Number())); | 1041 uint32_t hash = ComputeLongHash(double_to_uint64(Number())); |
| 1036 return Smi::FromInt(hash & Smi::kMaxValue); | 1042 return Smi::FromInt(hash & Smi::kMaxValue); |
| 1037 } | 1043 } |
| 1038 if (IsName()) { | 1044 if (IsName()) { |
| 1039 uint32_t hash = Name::cast(this)->Hash(); | 1045 uint32_t hash = Name::cast(this)->Hash(); |
| 1040 return Smi::FromInt(hash); | 1046 return Smi::FromInt(hash); |
| (...skipping 1918 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2959 bool has_pending_exception; | 2965 bool has_pending_exception; |
| 2960 Handle<Object> argv[] = { value }; | 2966 Handle<Object> argv[] = { value }; |
| 2961 Execution::Call( | 2967 Execution::Call( |
| 2962 isolate, setter, object, ARRAY_SIZE(argv), argv, &has_pending_exception); | 2968 isolate, setter, object, ARRAY_SIZE(argv), argv, &has_pending_exception); |
| 2963 // Check for pending exception and return the result. | 2969 // Check for pending exception and return the result. |
| 2964 if (has_pending_exception) return Handle<Object>(); | 2970 if (has_pending_exception) return Handle<Object>(); |
| 2965 return value; | 2971 return value; |
| 2966 } | 2972 } |
| 2967 | 2973 |
| 2968 | 2974 |
| 2969 MaybeObject* JSObject::SetElementWithCallbackSetterInPrototypes( | 2975 Handle<Object> JSObject::SetElementWithCallbackSetterInPrototypes( |
| 2976 Handle<JSObject> object, |
| 2970 uint32_t index, | 2977 uint32_t index, |
| 2971 Object* value, | 2978 Handle<Object> value, |
| 2972 bool* found, | 2979 bool* found, |
| 2973 StrictModeFlag strict_mode) { | 2980 StrictModeFlag strict_mode) { |
| 2974 Heap* heap = GetHeap(); | 2981 Isolate *isolate = object->GetIsolate(); |
| 2975 for (Object* pt = GetPrototype(); | 2982 for (Handle<Object> proto = handle(object->GetPrototype(), isolate); |
| 2976 pt != heap->null_value(); | 2983 !proto->IsNull(); |
| 2977 pt = pt->GetPrototype(GetIsolate())) { | 2984 proto = handle(proto->GetPrototype(isolate), isolate)) { |
| 2978 if (pt->IsJSProxy()) { | 2985 if (proto->IsJSProxy()) { |
| 2979 Isolate* isolate = GetIsolate(); | 2986 return JSProxy::SetPropertyViaPrototypesWithHandler( |
| 2980 HandleScope scope(isolate); | 2987 Handle<JSProxy>::cast(proto), |
| 2981 Handle<JSProxy> proxy(JSProxy::cast(pt)); | 2988 object, |
| 2982 Handle<JSObject> self(this, isolate); | 2989 isolate->factory()->Uint32ToString(index), // name |
| 2983 Handle<String> name = isolate->factory()->Uint32ToString(index); | 2990 value, |
| 2984 Handle<Object> value_handle(value, isolate); | 2991 NONE, |
| 2985 Handle<Object> result = JSProxy::SetPropertyViaPrototypesWithHandler( | 2992 strict_mode, |
| 2986 proxy, self, name, value_handle, NONE, strict_mode, found); | 2993 found); |
| 2987 RETURN_IF_EMPTY_HANDLE(isolate, result); | |
| 2988 return *result; | |
| 2989 } | 2994 } |
| 2990 if (!JSObject::cast(pt)->HasDictionaryElements()) { | 2995 Handle<JSObject> js_proto = Handle<JSObject>::cast(proto); |
| 2996 if (!js_proto->HasDictionaryElements()) { |
| 2991 continue; | 2997 continue; |
| 2992 } | 2998 } |
| 2993 SeededNumberDictionary* dictionary = | 2999 Handle<SeededNumberDictionary> dictionary(js_proto->element_dictionary()); |
| 2994 JSObject::cast(pt)->element_dictionary(); | |
| 2995 int entry = dictionary->FindEntry(index); | 3000 int entry = dictionary->FindEntry(index); |
| 2996 if (entry != SeededNumberDictionary::kNotFound) { | 3001 if (entry != SeededNumberDictionary::kNotFound) { |
| 2997 PropertyDetails details = dictionary->DetailsAt(entry); | 3002 PropertyDetails details = dictionary->DetailsAt(entry); |
| 2998 if (details.type() == CALLBACKS) { | 3003 if (details.type() == CALLBACKS) { |
| 2999 *found = true; | 3004 *found = true; |
| 3000 Isolate* isolate = GetIsolate(); | |
| 3001 HandleScope scope(isolate); | |
| 3002 Handle<JSObject> self(this, isolate); | |
| 3003 Handle<Object> structure(dictionary->ValueAt(entry), isolate); | 3005 Handle<Object> structure(dictionary->ValueAt(entry), isolate); |
| 3004 Handle<Object> value_handle(value, isolate); | 3006 return SetElementWithCallback(object, structure, index, value, js_proto, |
| 3005 Handle<JSObject> holder(JSObject::cast(pt)); | 3007 strict_mode); |
| 3006 Handle<Object> result = SetElementWithCallback( | |
| 3007 self, structure, index, value_handle, holder, strict_mode); | |
| 3008 RETURN_IF_EMPTY_HANDLE(isolate, result); | |
| 3009 return *result; | |
| 3010 } | 3008 } |
| 3011 } | 3009 } |
| 3012 } | 3010 } |
| 3013 *found = false; | 3011 *found = false; |
| 3014 return heap->the_hole_value(); | 3012 return isolate->factory()->the_hole_value(); |
| 3015 } | 3013 } |
| 3016 | 3014 |
| 3017 | 3015 |
| 3018 Handle<Object> JSObject::SetPropertyViaPrototypes(Handle<JSObject> object, | 3016 Handle<Object> JSObject::SetPropertyViaPrototypes(Handle<JSObject> object, |
| 3019 Handle<Name> name, | 3017 Handle<Name> name, |
| 3020 Handle<Object> value, | 3018 Handle<Object> value, |
| 3021 PropertyAttributes attributes, | 3019 PropertyAttributes attributes, |
| 3022 StrictModeFlag strict_mode, | 3020 StrictModeFlag strict_mode, |
| 3023 bool* done) { | 3021 bool* done) { |
| 3024 Isolate* isolate = object->GetIsolate(); | 3022 Isolate* isolate = object->GetIsolate(); |
| (...skipping 2582 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5607 return object; | 5605 return object; |
| 5608 } | 5606 } |
| 5609 | 5607 |
| 5610 | 5608 |
| 5611 void JSObject::SetObserved(Handle<JSObject> object) { | 5609 void JSObject::SetObserved(Handle<JSObject> object) { |
| 5612 Isolate* isolate = object->GetIsolate(); | 5610 Isolate* isolate = object->GetIsolate(); |
| 5613 | 5611 |
| 5614 if (object->map()->is_observed()) | 5612 if (object->map()->is_observed()) |
| 5615 return; | 5613 return; |
| 5616 | 5614 |
| 5617 if (!object->HasExternalArrayElements()) { | |
| 5618 // Go to dictionary mode, so that we don't skip map checks. | |
| 5619 NormalizeElements(object); | |
| 5620 ASSERT(!object->HasFastElements()); | |
| 5621 } | |
| 5622 | |
| 5623 LookupResult result(isolate); | 5615 LookupResult result(isolate); |
| 5624 object->map()->LookupTransition(*object, | 5616 object->map()->LookupTransition(*object, |
| 5625 isolate->heap()->observed_symbol(), | 5617 isolate->heap()->observed_symbol(), |
| 5626 &result); | 5618 &result); |
| 5627 | 5619 |
| 5628 Handle<Map> new_map; | 5620 Handle<Map> new_map; |
| 5629 if (result.IsTransition()) { | 5621 if (result.IsTransition()) { |
| 5630 new_map = handle(result.GetTransitionTarget()); | 5622 new_map = handle(result.GetTransitionTarget()); |
| 5631 ASSERT(new_map->is_observed()); | 5623 ASSERT(new_map->is_observed()); |
| 5632 } else if (object->map()->CanHaveMoreTransitions()) { | 5624 } else if (object->map()->CanHaveMoreTransitions()) { |
| 5633 new_map = Map::CopyForObserved(handle(object->map())); | 5625 new_map = Map::CopyForObserved(handle(object->map())); |
| 5634 } else { | 5626 } else { |
| 5635 new_map = Map::Copy(handle(object->map())); | 5627 new_map = Map::Copy(handle(object->map())); |
| 5636 new_map->set_is_observed(true); | 5628 new_map->set_is_observed(); |
| 5637 } | 5629 } |
| 5638 object->set_map(*new_map); | 5630 object->set_map(*new_map); |
| 5639 } | 5631 } |
| 5640 | 5632 |
| 5641 | 5633 |
| 5642 Handle<JSObject> JSObject::Copy(Handle<JSObject> object, | 5634 Handle<JSObject> JSObject::Copy(Handle<JSObject> object, |
| 5643 Handle<AllocationSite> site) { | 5635 Handle<AllocationSite> site) { |
| 5644 Isolate* isolate = object->GetIsolate(); | 5636 Isolate* isolate = object->GetIsolate(); |
| 5645 CALL_HEAP_FUNCTION(isolate, | 5637 CALL_HEAP_FUNCTION(isolate, |
| 5646 isolate->heap()->CopyJSObject(*object, *site), JSObject); | 5638 isolate->heap()->CopyJSObject(*object, *site), JSObject); |
| (...skipping 602 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6249 Handle<Object> structure, | 6241 Handle<Object> structure, |
| 6250 PropertyAttributes attributes) { | 6242 PropertyAttributes attributes) { |
| 6251 Heap* heap = object->GetHeap(); | 6243 Heap* heap = object->GetHeap(); |
| 6252 PropertyDetails details = PropertyDetails(attributes, CALLBACKS, 0); | 6244 PropertyDetails details = PropertyDetails(attributes, CALLBACKS, 0); |
| 6253 | 6245 |
| 6254 // Normalize elements to make this operation simple. | 6246 // Normalize elements to make this operation simple. |
| 6255 bool had_dictionary_elements = object->HasDictionaryElements(); | 6247 bool had_dictionary_elements = object->HasDictionaryElements(); |
| 6256 Handle<SeededNumberDictionary> dictionary = NormalizeElements(object); | 6248 Handle<SeededNumberDictionary> dictionary = NormalizeElements(object); |
| 6257 ASSERT(object->HasDictionaryElements() || | 6249 ASSERT(object->HasDictionaryElements() || |
| 6258 object->HasDictionaryArgumentsElements()); | 6250 object->HasDictionaryArgumentsElements()); |
| 6259 | |
| 6260 // Update the dictionary with the new CALLBACKS property. | 6251 // Update the dictionary with the new CALLBACKS property. |
| 6261 dictionary = SeededNumberDictionary::Set(dictionary, index, structure, | 6252 dictionary = SeededNumberDictionary::Set(dictionary, index, structure, |
| 6262 details); | 6253 details); |
| 6263 dictionary->set_requires_slow_elements(); | 6254 dictionary->set_requires_slow_elements(); |
| 6264 | 6255 |
| 6265 // Update the dictionary backing store on the object. | 6256 // Update the dictionary backing store on the object. |
| 6266 if (object->elements()->map() == heap->non_strict_arguments_elements_map()) { | 6257 if (object->elements()->map() == heap->non_strict_arguments_elements_map()) { |
| 6267 // Also delete any parameter alias. | 6258 // Also delete any parameter alias. |
| 6268 // | 6259 // |
| 6269 // TODO(kmillikin): when deleting the last parameter alias we could | 6260 // TODO(kmillikin): when deleting the last parameter alias we could |
| (...skipping 694 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6964 } else { | 6955 } else { |
| 6965 new_map = Map::Copy(map); | 6956 new_map = Map::Copy(map); |
| 6966 } | 6957 } |
| 6967 | 6958 |
| 6968 Handle<TransitionArray> transitions = | 6959 Handle<TransitionArray> transitions = |
| 6969 Map::AddTransition(map, isolate->factory()->observed_symbol(), new_map, | 6960 Map::AddTransition(map, isolate->factory()->observed_symbol(), new_map, |
| 6970 FULL_TRANSITION); | 6961 FULL_TRANSITION); |
| 6971 | 6962 |
| 6972 map->set_transitions(*transitions); | 6963 map->set_transitions(*transitions); |
| 6973 | 6964 |
| 6974 new_map->set_is_observed(true); | 6965 new_map->set_is_observed(); |
| 6975 | 6966 |
| 6976 if (map->owns_descriptors()) { | 6967 if (map->owns_descriptors()) { |
| 6977 new_map->InitializeDescriptors(map->instance_descriptors()); | 6968 new_map->InitializeDescriptors(map->instance_descriptors()); |
| 6978 map->set_owns_descriptors(false); | 6969 map->set_owns_descriptors(false); |
| 6979 } | 6970 } |
| 6980 | 6971 |
| 6981 new_map->SetBackPointer(*map); | 6972 new_map->SetBackPointer(*map); |
| 6982 return new_map; | 6973 return new_map; |
| 6983 } | 6974 } |
| 6984 | 6975 |
| (...skipping 2750 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9735 return CompileLazyHelper(&info, flag); | 9726 return CompileLazyHelper(&info, flag); |
| 9736 } | 9727 } |
| 9737 | 9728 |
| 9738 | 9729 |
| 9739 bool JSFunction::EnsureCompiled(Handle<JSFunction> function, | 9730 bool JSFunction::EnsureCompiled(Handle<JSFunction> function, |
| 9740 ClearExceptionFlag flag) { | 9731 ClearExceptionFlag flag) { |
| 9741 return function->is_compiled() || CompileLazy(function, flag); | 9732 return function->is_compiled() || CompileLazy(function, flag); |
| 9742 } | 9733 } |
| 9743 | 9734 |
| 9744 | 9735 |
| 9745 bool JSFunction::IsInlineable() { | |
| 9746 if (IsBuiltin()) return false; | |
| 9747 SharedFunctionInfo* shared_info = shared(); | |
| 9748 // Check that the function has a script associated with it. | |
| 9749 if (!shared_info->script()->IsScript()) return false; | |
| 9750 if (shared_info->optimization_disabled()) return false; | |
| 9751 Code* code = shared_info->code(); | |
| 9752 if (code->kind() == Code::OPTIMIZED_FUNCTION) return true; | |
| 9753 // If we never ran this (unlikely) then lets try to optimize it. | |
| 9754 if (code->kind() != Code::FUNCTION) return true; | |
| 9755 return code->optimizable(); | |
| 9756 } | |
| 9757 | |
| 9758 | |
| 9759 void JSObject::OptimizeAsPrototype(Handle<JSObject> object) { | 9736 void JSObject::OptimizeAsPrototype(Handle<JSObject> object) { |
| 9760 if (object->IsGlobalObject()) return; | 9737 if (object->IsGlobalObject()) return; |
| 9761 | 9738 |
| 9762 // Make sure prototypes are fast objects and their maps have the bit set | 9739 // Make sure prototypes are fast objects and their maps have the bit set |
| 9763 // so they remain fast. | 9740 // so they remain fast. |
| 9764 if (!object->HasFastProperties()) { | 9741 if (!object->HasFastProperties()) { |
| 9765 TransformToFastProperties(object, 0); | 9742 TransformToFastProperties(object, 0); |
| 9766 } | 9743 } |
| 9767 } | 9744 } |
| 9768 | 9745 |
| (...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10017 | 9994 |
| 10018 | 9995 |
| 10019 Handle<Object> SharedFunctionInfo::GetSourceCode() { | 9996 Handle<Object> SharedFunctionInfo::GetSourceCode() { |
| 10020 if (!HasSourceCode()) return GetIsolate()->factory()->undefined_value(); | 9997 if (!HasSourceCode()) return GetIsolate()->factory()->undefined_value(); |
| 10021 Handle<String> source(String::cast(Script::cast(script())->source())); | 9998 Handle<String> source(String::cast(Script::cast(script())->source())); |
| 10022 return GetIsolate()->factory()->NewSubString( | 9999 return GetIsolate()->factory()->NewSubString( |
| 10023 source, start_position(), end_position()); | 10000 source, start_position(), end_position()); |
| 10024 } | 10001 } |
| 10025 | 10002 |
| 10026 | 10003 |
| 10004 bool SharedFunctionInfo::IsInlineable() { |
| 10005 // Check that the function has a script associated with it. |
| 10006 if (!script()->IsScript()) return false; |
| 10007 if (optimization_disabled()) return false; |
| 10008 // If we never ran this (unlikely) then lets try to optimize it. |
| 10009 if (code()->kind() != Code::FUNCTION) return true; |
| 10010 return code()->optimizable(); |
| 10011 } |
| 10012 |
| 10013 |
| 10027 int SharedFunctionInfo::SourceSize() { | 10014 int SharedFunctionInfo::SourceSize() { |
| 10028 return end_position() - start_position(); | 10015 return end_position() - start_position(); |
| 10029 } | 10016 } |
| 10030 | 10017 |
| 10031 | 10018 |
| 10032 int SharedFunctionInfo::CalculateInstanceSize() { | 10019 int SharedFunctionInfo::CalculateInstanceSize() { |
| 10033 int instance_size = | 10020 int instance_size = |
| 10034 JSObject::kHeaderSize + | 10021 JSObject::kHeaderSize + |
| 10035 expected_nof_properties() * kPointerSize; | 10022 expected_nof_properties() * kPointerSize; |
| 10036 if (instance_size > JSObject::kMaxInstanceSize) { | 10023 if (instance_size > JSObject::kMaxInstanceSize) { |
| (...skipping 1170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11207 | 11194 |
| 11208 PrintF(out, "RelocInfo (size = %d)\n", relocation_size()); | 11195 PrintF(out, "RelocInfo (size = %d)\n", relocation_size()); |
| 11209 for (RelocIterator it(this); !it.done(); it.next()) { | 11196 for (RelocIterator it(this); !it.done(); it.next()) { |
| 11210 it.rinfo()->Print(GetIsolate(), out); | 11197 it.rinfo()->Print(GetIsolate(), out); |
| 11211 } | 11198 } |
| 11212 PrintF(out, "\n"); | 11199 PrintF(out, "\n"); |
| 11213 } | 11200 } |
| 11214 #endif // ENABLE_DISASSEMBLER | 11201 #endif // ENABLE_DISASSEMBLER |
| 11215 | 11202 |
| 11216 | 11203 |
| 11204 Handle<FixedArray> JSObject::SetFastElementsCapacityAndLength( |
| 11205 Handle<JSObject> object, |
| 11206 int capacity, |
| 11207 int length, |
| 11208 SetFastElementsCapacitySmiMode smi_mode) { |
| 11209 CALL_HEAP_FUNCTION( |
| 11210 object->GetIsolate(), |
| 11211 object->SetFastElementsCapacityAndLength(capacity, length, smi_mode), |
| 11212 FixedArray); |
| 11213 } |
| 11214 |
| 11215 |
| 11217 MaybeObject* JSObject::SetFastElementsCapacityAndLength( | 11216 MaybeObject* JSObject::SetFastElementsCapacityAndLength( |
| 11218 int capacity, | 11217 int capacity, |
| 11219 int length, | 11218 int length, |
| 11220 SetFastElementsCapacitySmiMode smi_mode) { | 11219 SetFastElementsCapacitySmiMode smi_mode) { |
| 11221 Heap* heap = GetHeap(); | 11220 Heap* heap = GetHeap(); |
| 11222 // We should never end in here with a pixel or external array. | 11221 // We should never end in here with a pixel or external array. |
| 11223 ASSERT(!HasExternalArrayElements()); | 11222 ASSERT(!HasExternalArrayElements()); |
| 11224 ASSERT(!map()->is_observed()); | |
| 11225 | 11223 |
| 11226 // Allocate a new fast elements backing store. | 11224 // Allocate a new fast elements backing store. |
| 11227 FixedArray* new_elements; | 11225 FixedArray* new_elements; |
| 11228 MaybeObject* maybe = heap->AllocateUninitializedFixedArray(capacity); | 11226 MaybeObject* maybe = heap->AllocateUninitializedFixedArray(capacity); |
| 11229 if (!maybe->To(&new_elements)) return maybe; | 11227 if (!maybe->To(&new_elements)) return maybe; |
| 11230 | 11228 |
| 11231 ElementsKind elements_kind = GetElementsKind(); | 11229 ElementsKind elements_kind = GetElementsKind(); |
| 11232 ElementsKind new_elements_kind; | 11230 ElementsKind new_elements_kind; |
| 11233 // The resized array has FAST_*_SMI_ELEMENTS if the capacity mode forces it, | 11231 // The resized array has FAST_*_SMI_ELEMENTS if the capacity mode forces it, |
| 11234 // or if it's allowed and the old elements array contained only SMIs. | 11232 // or if it's allowed and the old elements array contained only SMIs. |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11293 FLAG_weak_embedded_maps_in_optimized_code; | 11291 FLAG_weak_embedded_maps_in_optimized_code; |
| 11294 } | 11292 } |
| 11295 | 11293 |
| 11296 if (object->IsJSObject()) { | 11294 if (object->IsJSObject()) { |
| 11297 return FLAG_weak_embedded_objects_in_optimized_code; | 11295 return FLAG_weak_embedded_objects_in_optimized_code; |
| 11298 } | 11296 } |
| 11299 | 11297 |
| 11300 return false; | 11298 return false; |
| 11301 } | 11299 } |
| 11302 | 11300 |
| 11301 |
| 11302 void JSObject::SetFastDoubleElementsCapacityAndLength(Handle<JSObject> object, |
| 11303 int capacity, |
| 11304 int length) { |
| 11305 CALL_HEAP_FUNCTION_VOID( |
| 11306 object->GetIsolate(), |
| 11307 object->SetFastDoubleElementsCapacityAndLength(capacity, length)); |
| 11308 } |
| 11309 |
| 11310 |
| 11303 MaybeObject* JSObject::SetFastDoubleElementsCapacityAndLength( | 11311 MaybeObject* JSObject::SetFastDoubleElementsCapacityAndLength( |
| 11304 int capacity, | 11312 int capacity, |
| 11305 int length) { | 11313 int length) { |
| 11306 Heap* heap = GetHeap(); | 11314 Heap* heap = GetHeap(); |
| 11307 // We should never end in here with a pixel or external array. | 11315 // We should never end in here with a pixel or external array. |
| 11308 ASSERT(!HasExternalArrayElements()); | 11316 ASSERT(!HasExternalArrayElements()); |
| 11309 ASSERT(!map()->is_observed()); | |
| 11310 | 11317 |
| 11311 FixedArrayBase* elems; | 11318 FixedArrayBase* elems; |
| 11312 { MaybeObject* maybe_obj = | 11319 { MaybeObject* maybe_obj = |
| 11313 heap->AllocateUninitializedFixedDoubleArray(capacity); | 11320 heap->AllocateUninitializedFixedDoubleArray(capacity); |
| 11314 if (!maybe_obj->To(&elems)) return maybe_obj; | 11321 if (!maybe_obj->To(&elems)) return maybe_obj; |
| 11315 } | 11322 } |
| 11316 | 11323 |
| 11317 ElementsKind elements_kind = GetElementsKind(); | 11324 ElementsKind elements_kind = GetElementsKind(); |
| 11318 ElementsKind new_elements_kind = elements_kind; | 11325 ElementsKind new_elements_kind = elements_kind; |
| 11319 if (IsHoleyElementsKind(elements_kind)) { | 11326 if (IsHoleyElementsKind(elements_kind)) { |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11448 List<uint32_t> indices; | 11455 List<uint32_t> indices; |
| 11449 List<Handle<Object> > old_values; | 11456 List<Handle<Object> > old_values; |
| 11450 Handle<Object> old_length_handle(self->length(), isolate); | 11457 Handle<Object> old_length_handle(self->length(), isolate); |
| 11451 Handle<Object> new_length_handle(len, isolate); | 11458 Handle<Object> new_length_handle(len, isolate); |
| 11452 uint32_t old_length = 0; | 11459 uint32_t old_length = 0; |
| 11453 CHECK(old_length_handle->ToArrayIndex(&old_length)); | 11460 CHECK(old_length_handle->ToArrayIndex(&old_length)); |
| 11454 uint32_t new_length = 0; | 11461 uint32_t new_length = 0; |
| 11455 if (!new_length_handle->ToArrayIndex(&new_length)) | 11462 if (!new_length_handle->ToArrayIndex(&new_length)) |
| 11456 return Failure::InternalError(); | 11463 return Failure::InternalError(); |
| 11457 | 11464 |
| 11458 // Observed arrays should always be in dictionary mode; | |
| 11459 // if they were in fast mode, the below is slower than necessary | |
| 11460 // as it iterates over the array backing store multiple times. | |
| 11461 ASSERT(self->HasDictionaryElements()); | |
| 11462 static const PropertyAttributes kNoAttrFilter = NONE; | 11465 static const PropertyAttributes kNoAttrFilter = NONE; |
| 11463 int num_elements = self->NumberOfLocalElements(kNoAttrFilter); | 11466 int num_elements = self->NumberOfLocalElements(kNoAttrFilter); |
| 11464 if (num_elements > 0) { | 11467 if (num_elements > 0) { |
| 11465 if (old_length == static_cast<uint32_t>(num_elements)) { | 11468 if (old_length == static_cast<uint32_t>(num_elements)) { |
| 11466 // Simple case for arrays without holes. | 11469 // Simple case for arrays without holes. |
| 11467 for (uint32_t i = old_length - 1; i + 1 > new_length; --i) { | 11470 for (uint32_t i = old_length - 1; i + 1 > new_length; --i) { |
| 11468 if (!GetOldValue(isolate, self, i, &old_values, &indices)) break; | 11471 if (!GetOldValue(isolate, self, i, &old_values, &indices)) break; |
| 11469 } | 11472 } |
| 11470 } else { | 11473 } else { |
| 11471 // For sparse arrays, only iterate over existing elements. | 11474 // For sparse arrays, only iterate over existing elements. |
| 11475 // TODO(rafaelw): For fast, sparse arrays, we can avoid iterating over |
| 11476 // the to-be-removed indices twice. |
| 11472 Handle<FixedArray> keys = isolate->factory()->NewFixedArray(num_elements); | 11477 Handle<FixedArray> keys = isolate->factory()->NewFixedArray(num_elements); |
| 11473 self->GetLocalElementKeys(*keys, kNoAttrFilter); | 11478 self->GetLocalElementKeys(*keys, kNoAttrFilter); |
| 11474 while (num_elements-- > 0) { | 11479 while (num_elements-- > 0) { |
| 11475 uint32_t index = NumberToUint32(keys->get(num_elements)); | 11480 uint32_t index = NumberToUint32(keys->get(num_elements)); |
| 11476 if (index < new_length) break; | 11481 if (index < new_length) break; |
| 11477 if (!GetOldValue(isolate, self, index, &old_values, &indices)) break; | 11482 if (!GetOldValue(isolate, self, index, &old_values, &indices)) break; |
| 11478 } | 11483 } |
| 11479 } | 11484 } |
| 11480 } | 11485 } |
| 11481 | 11486 |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11630 start_indexes_[g] = start_indexes_[g - 1] + count; | 11635 start_indexes_[g] = start_indexes_[g - 1] + count; |
| 11631 } | 11636 } |
| 11632 } | 11637 } |
| 11633 | 11638 |
| 11634 | 11639 |
| 11635 DependentCode* DependentCode::ForObject(Handle<HeapObject> object, | 11640 DependentCode* DependentCode::ForObject(Handle<HeapObject> object, |
| 11636 DependencyGroup group) { | 11641 DependencyGroup group) { |
| 11637 AllowDeferredHandleDereference dependencies_are_safe; | 11642 AllowDeferredHandleDereference dependencies_are_safe; |
| 11638 if (group == DependentCode::kPropertyCellChangedGroup) { | 11643 if (group == DependentCode::kPropertyCellChangedGroup) { |
| 11639 return Handle<PropertyCell>::cast(object)->dependent_code(); | 11644 return Handle<PropertyCell>::cast(object)->dependent_code(); |
| 11645 } else if (group == DependentCode::kAllocationSiteTenuringChangedGroup || |
| 11646 group == DependentCode::kAllocationSiteTransitionChangedGroup) { |
| 11647 return Handle<AllocationSite>::cast(object)->dependent_code(); |
| 11640 } | 11648 } |
| 11641 return Handle<Map>::cast(object)->dependent_code(); | 11649 return Handle<Map>::cast(object)->dependent_code(); |
| 11642 } | 11650 } |
| 11643 | 11651 |
| 11644 | 11652 |
| 11645 Handle<DependentCode> DependentCode::Insert(Handle<DependentCode> entries, | 11653 Handle<DependentCode> DependentCode::Insert(Handle<DependentCode> entries, |
| 11646 DependencyGroup group, | 11654 DependencyGroup group, |
| 11647 Handle<Object> object) { | 11655 Handle<Object> object) { |
| 11648 GroupStartIndexes starts(*entries); | 11656 GroupStartIndexes starts(*entries); |
| 11649 int start = starts.at(group); | 11657 int start = starts.at(group); |
| 11650 int end = starts.at(group + 1); | 11658 int end = starts.at(group + 1); |
| 11651 int number_of_entries = starts.number_of_entries(); | 11659 int number_of_entries = starts.number_of_entries(); |
| 11652 if (start < end && entries->object_at(end - 1) == *object) { | 11660 // Check for existing entry to avoid duplicates. |
| 11653 // Do not append the compilation info if it is already in the array. | 11661 for (int i = start; i < end; i++) { |
| 11654 // It is sufficient to just check only the last element because | 11662 if (entries->object_at(i) == *object) return entries; |
| 11655 // we process embedded maps of an optimized code in one batch. | |
| 11656 return entries; | |
| 11657 } | 11663 } |
| 11658 if (entries->length() < kCodesStartIndex + number_of_entries + 1) { | 11664 if (entries->length() < kCodesStartIndex + number_of_entries + 1) { |
| 11659 Factory* factory = entries->GetIsolate()->factory(); | 11665 Factory* factory = entries->GetIsolate()->factory(); |
| 11660 int capacity = kCodesStartIndex + number_of_entries + 1; | 11666 int capacity = kCodesStartIndex + number_of_entries + 1; |
| 11661 if (capacity > 5) capacity = capacity * 5 / 4; | 11667 if (capacity > 5) capacity = capacity * 5 / 4; |
| 11662 Handle<DependentCode> new_entries = Handle<DependentCode>::cast( | 11668 Handle<DependentCode> new_entries = Handle<DependentCode>::cast( |
| 11663 factory->CopySizeFixedArray(entries, capacity, TENURED)); | 11669 factory->CopySizeFixedArray(entries, capacity, TENURED)); |
| 11664 // The number of codes can change after GC. | 11670 // The number of codes can change after GC. |
| 11665 starts.Recompute(*entries); | 11671 starts.Recompute(*entries); |
| 11666 start = starts.at(group); | 11672 start = starts.at(group); |
| (...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11929 return JSObject::cast(proto)->GetLocalElementAccessorPair(index); | 11935 return JSObject::cast(proto)->GetLocalElementAccessorPair(index); |
| 11930 } | 11936 } |
| 11931 | 11937 |
| 11932 // Check for lookup interceptor. | 11938 // Check for lookup interceptor. |
| 11933 if (HasIndexedInterceptor()) return NULL; | 11939 if (HasIndexedInterceptor()) return NULL; |
| 11934 | 11940 |
| 11935 return GetElementsAccessor()->GetAccessorPair(this, this, index); | 11941 return GetElementsAccessor()->GetAccessorPair(this, this, index); |
| 11936 } | 11942 } |
| 11937 | 11943 |
| 11938 | 11944 |
| 11939 MaybeObject* JSObject::SetElementWithInterceptor(uint32_t index, | 11945 Handle<Object> JSObject::SetElementWithInterceptor( |
| 11940 Object* value, | 11946 Handle<JSObject> object, |
| 11941 PropertyAttributes attributes, | 11947 uint32_t index, |
| 11942 StrictModeFlag strict_mode, | 11948 Handle<Object> value, |
| 11943 bool check_prototype, | 11949 PropertyAttributes attributes, |
| 11944 SetPropertyMode set_mode) { | 11950 StrictModeFlag strict_mode, |
| 11945 Isolate* isolate = GetIsolate(); | 11951 bool check_prototype, |
| 11946 HandleScope scope(isolate); | 11952 SetPropertyMode set_mode) { |
| 11953 Isolate* isolate = object->GetIsolate(); |
| 11947 | 11954 |
| 11948 // Make sure that the top context does not change when doing | 11955 // Make sure that the top context does not change when doing |
| 11949 // callbacks or interceptor calls. | 11956 // callbacks or interceptor calls. |
| 11950 AssertNoContextChange ncc(isolate); | 11957 AssertNoContextChange ncc(isolate); |
| 11951 | 11958 |
| 11952 Handle<InterceptorInfo> interceptor(GetIndexedInterceptor()); | 11959 Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor()); |
| 11953 Handle<JSObject> this_handle(this); | |
| 11954 Handle<Object> value_handle(value, isolate); | |
| 11955 if (!interceptor->setter()->IsUndefined()) { | 11960 if (!interceptor->setter()->IsUndefined()) { |
| 11956 v8::IndexedPropertySetterCallback setter = | 11961 v8::IndexedPropertySetterCallback setter = |
| 11957 v8::ToCData<v8::IndexedPropertySetterCallback>(interceptor->setter()); | 11962 v8::ToCData<v8::IndexedPropertySetterCallback>(interceptor->setter()); |
| 11958 LOG(isolate, | 11963 LOG(isolate, |
| 11959 ApiIndexedPropertyAccess("interceptor-indexed-set", this, index)); | 11964 ApiIndexedPropertyAccess("interceptor-indexed-set", *object, index)); |
| 11960 PropertyCallbackArguments args(isolate, interceptor->data(), this, this); | 11965 PropertyCallbackArguments args(isolate, interceptor->data(), *object, |
| 11966 *object); |
| 11961 v8::Handle<v8::Value> result = | 11967 v8::Handle<v8::Value> result = |
| 11962 args.Call(setter, index, v8::Utils::ToLocal(value_handle)); | 11968 args.Call(setter, index, v8::Utils::ToLocal(value)); |
| 11963 RETURN_IF_SCHEDULED_EXCEPTION(isolate); | 11969 RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); |
| 11964 if (!result.IsEmpty()) return *value_handle; | 11970 if (!result.IsEmpty()) return value; |
| 11965 } | 11971 } |
| 11966 MaybeObject* raw_result = | 11972 |
| 11967 this_handle->SetElementWithoutInterceptor(index, | 11973 return SetElementWithoutInterceptor(object, index, value, attributes, |
| 11968 *value_handle, | 11974 strict_mode, |
| 11969 attributes, | 11975 check_prototype, |
| 11970 strict_mode, | 11976 set_mode); |
| 11971 check_prototype, | |
| 11972 set_mode); | |
| 11973 RETURN_IF_SCHEDULED_EXCEPTION(isolate); | |
| 11974 return raw_result; | |
| 11975 } | 11977 } |
| 11976 | 11978 |
| 11977 | 11979 |
| 11978 MaybeObject* JSObject::GetElementWithCallback(Object* receiver, | 11980 MaybeObject* JSObject::GetElementWithCallback(Object* receiver, |
| 11979 Object* structure, | 11981 Object* structure, |
| 11980 uint32_t index, | 11982 uint32_t index, |
| 11981 Object* holder) { | 11983 Object* holder) { |
| 11982 Isolate* isolate = GetIsolate(); | 11984 Isolate* isolate = GetIsolate(); |
| 11983 ASSERT(!structure->IsForeign()); | 11985 ASSERT(!structure->IsForeign()); |
| 11984 | 11986 |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12112 return false; | 12114 return false; |
| 12113 } | 12115 } |
| 12114 FixedArray* arguments = FixedArray::cast(elements->get(1)); | 12116 FixedArray* arguments = FixedArray::cast(elements->get(1)); |
| 12115 return arguments->IsDictionary(); | 12117 return arguments->IsDictionary(); |
| 12116 } | 12118 } |
| 12117 | 12119 |
| 12118 | 12120 |
| 12119 // Adding n elements in fast case is O(n*n). | 12121 // Adding n elements in fast case is O(n*n). |
| 12120 // Note: revisit design to have dual undefined values to capture absent | 12122 // Note: revisit design to have dual undefined values to capture absent |
| 12121 // elements. | 12123 // elements. |
| 12122 MaybeObject* JSObject::SetFastElement(uint32_t index, | 12124 Handle<Object> JSObject::SetFastElement(Handle<JSObject> object, |
| 12123 Object* value, | 12125 uint32_t index, |
| 12124 StrictModeFlag strict_mode, | 12126 Handle<Object> value, |
| 12125 bool check_prototype) { | 12127 StrictModeFlag strict_mode, |
| 12126 ASSERT(HasFastSmiOrObjectElements() || | 12128 bool check_prototype) { |
| 12127 HasFastArgumentsElements()); | 12129 ASSERT(object->HasFastSmiOrObjectElements() || |
| 12130 object->HasFastArgumentsElements()); |
| 12131 |
| 12132 Isolate* isolate = object->GetIsolate(); |
| 12128 | 12133 |
| 12129 // Array optimizations rely on the prototype lookups of Array objects always | 12134 // Array optimizations rely on the prototype lookups of Array objects always |
| 12130 // returning undefined. If there is a store to the initial prototype object, | 12135 // returning undefined. If there is a store to the initial prototype object, |
| 12131 // make sure all of these optimizations are invalidated. | 12136 // make sure all of these optimizations are invalidated. |
| 12132 Isolate* isolate(GetIsolate()); | 12137 if (isolate->is_initial_object_prototype(*object) || |
| 12133 if (isolate->is_initial_object_prototype(this) || | 12138 isolate->is_initial_array_prototype(*object)) { |
| 12134 isolate->is_initial_array_prototype(this)) { | 12139 object->map()->dependent_code()->DeoptimizeDependentCodeGroup(isolate, |
| 12135 HandleScope scope(GetIsolate()); | |
| 12136 map()->dependent_code()->DeoptimizeDependentCodeGroup( | |
| 12137 GetIsolate(), | |
| 12138 DependentCode::kElementsCantBeAddedGroup); | 12140 DependentCode::kElementsCantBeAddedGroup); |
| 12139 } | 12141 } |
| 12140 | 12142 |
| 12141 FixedArray* backing_store = FixedArray::cast(elements()); | 12143 Handle<FixedArray> backing_store(FixedArray::cast(object->elements())); |
| 12142 if (backing_store->map() == GetHeap()->non_strict_arguments_elements_map()) { | 12144 if (backing_store->map() == |
| 12143 backing_store = FixedArray::cast(backing_store->get(1)); | 12145 isolate->heap()->non_strict_arguments_elements_map()) { |
| 12146 backing_store = handle(FixedArray::cast(backing_store->get(1))); |
| 12144 } else { | 12147 } else { |
| 12145 MaybeObject* maybe = EnsureWritableFastElements(); | 12148 backing_store = EnsureWritableFastElements(object); |
| 12146 if (!maybe->To(&backing_store)) return maybe; | |
| 12147 } | 12149 } |
| 12148 uint32_t capacity = static_cast<uint32_t>(backing_store->length()); | 12150 uint32_t capacity = static_cast<uint32_t>(backing_store->length()); |
| 12149 | 12151 |
| 12150 if (check_prototype && | 12152 if (check_prototype && |
| 12151 (index >= capacity || backing_store->get(index)->IsTheHole())) { | 12153 (index >= capacity || backing_store->get(index)->IsTheHole())) { |
| 12152 bool found; | 12154 bool found; |
| 12153 MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index, | 12155 Handle<Object> result = SetElementWithCallbackSetterInPrototypes( |
| 12154 value, | 12156 object, index, value, &found, strict_mode); |
| 12155 &found, | |
| 12156 strict_mode); | |
| 12157 if (found) return result; | 12157 if (found) return result; |
| 12158 } | 12158 } |
| 12159 | 12159 |
| 12160 uint32_t new_capacity = capacity; | 12160 uint32_t new_capacity = capacity; |
| 12161 // Check if the length property of this object needs to be updated. | 12161 // Check if the length property of this object needs to be updated. |
| 12162 uint32_t array_length = 0; | 12162 uint32_t array_length = 0; |
| 12163 bool must_update_array_length = false; | 12163 bool must_update_array_length = false; |
| 12164 bool introduces_holes = true; | 12164 bool introduces_holes = true; |
| 12165 if (IsJSArray()) { | 12165 if (object->IsJSArray()) { |
| 12166 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length)); | 12166 CHECK(Handle<JSArray>::cast(object)->length()->ToArrayIndex(&array_length)); |
| 12167 introduces_holes = index > array_length; | 12167 introduces_holes = index > array_length; |
| 12168 if (index >= array_length) { | 12168 if (index >= array_length) { |
| 12169 must_update_array_length = true; | 12169 must_update_array_length = true; |
| 12170 array_length = index + 1; | 12170 array_length = index + 1; |
| 12171 } | 12171 } |
| 12172 } else { | 12172 } else { |
| 12173 introduces_holes = index >= capacity; | 12173 introduces_holes = index >= capacity; |
| 12174 } | 12174 } |
| 12175 | 12175 |
| 12176 // If the array is growing, and it's not growth by a single element at the | 12176 // If the array is growing, and it's not growth by a single element at the |
| 12177 // end, make sure that the ElementsKind is HOLEY. | 12177 // end, make sure that the ElementsKind is HOLEY. |
| 12178 ElementsKind elements_kind = GetElementsKind(); | 12178 ElementsKind elements_kind = object->GetElementsKind(); |
| 12179 if (introduces_holes && | 12179 if (introduces_holes && |
| 12180 IsFastElementsKind(elements_kind) && | 12180 IsFastElementsKind(elements_kind) && |
| 12181 !IsFastHoleyElementsKind(elements_kind)) { | 12181 !IsFastHoleyElementsKind(elements_kind)) { |
| 12182 ElementsKind transitioned_kind = GetHoleyElementsKind(elements_kind); | 12182 ElementsKind transitioned_kind = GetHoleyElementsKind(elements_kind); |
| 12183 MaybeObject* maybe = TransitionElementsKind(transitioned_kind); | 12183 TransitionElementsKind(object, transitioned_kind); |
| 12184 if (maybe->IsFailure()) return maybe; | |
| 12185 } | 12184 } |
| 12186 | 12185 |
| 12187 // Check if the capacity of the backing store needs to be increased, or if | 12186 // Check if the capacity of the backing store needs to be increased, or if |
| 12188 // a transition to slow elements is necessary. | 12187 // a transition to slow elements is necessary. |
| 12189 if (index >= capacity) { | 12188 if (index >= capacity) { |
| 12190 bool convert_to_slow = true; | 12189 bool convert_to_slow = true; |
| 12191 if ((index - capacity) < kMaxGap) { | 12190 if ((index - capacity) < kMaxGap) { |
| 12192 new_capacity = NewElementsCapacity(index + 1); | 12191 new_capacity = NewElementsCapacity(index + 1); |
| 12193 ASSERT(new_capacity > index); | 12192 ASSERT(new_capacity > index); |
| 12194 if (!ShouldConvertToSlowElements(new_capacity)) { | 12193 if (!object->ShouldConvertToSlowElements(new_capacity)) { |
| 12195 convert_to_slow = false; | 12194 convert_to_slow = false; |
| 12196 } | 12195 } |
| 12197 } | 12196 } |
| 12198 if (convert_to_slow) { | 12197 if (convert_to_slow) { |
| 12199 MaybeObject* result = NormalizeElements(); | 12198 NormalizeElements(object); |
| 12200 if (result->IsFailure()) return result; | 12199 return SetDictionaryElement(object, index, value, NONE, strict_mode, |
| 12201 return SetDictionaryElement(index, value, NONE, strict_mode, | |
| 12202 check_prototype); | 12200 check_prototype); |
| 12203 } | 12201 } |
| 12204 } | 12202 } |
| 12205 // Convert to fast double elements if appropriate. | 12203 // Convert to fast double elements if appropriate. |
| 12206 if (HasFastSmiElements() && !value->IsSmi() && value->IsNumber()) { | 12204 if (object->HasFastSmiElements() && !value->IsSmi() && value->IsNumber()) { |
| 12207 // Consider fixing the boilerplate as well if we have one. | 12205 // Consider fixing the boilerplate as well if we have one. |
| 12208 ElementsKind to_kind = IsHoleyElementsKind(elements_kind) | 12206 ElementsKind to_kind = IsHoleyElementsKind(elements_kind) |
| 12209 ? FAST_HOLEY_DOUBLE_ELEMENTS | 12207 ? FAST_HOLEY_DOUBLE_ELEMENTS |
| 12210 : FAST_DOUBLE_ELEMENTS; | 12208 : FAST_DOUBLE_ELEMENTS; |
| 12211 | 12209 |
| 12212 MaybeObject* maybe_failure = UpdateAllocationSite(to_kind); | 12210 UpdateAllocationSite(object, to_kind); |
| 12213 if (maybe_failure->IsFailure()) return maybe_failure; | |
| 12214 | 12211 |
| 12215 MaybeObject* maybe = | 12212 SetFastDoubleElementsCapacityAndLength(object, new_capacity, array_length); |
| 12216 SetFastDoubleElementsCapacityAndLength(new_capacity, array_length); | 12213 FixedDoubleArray::cast(object->elements())->set(index, value->Number()); |
| 12217 if (maybe->IsFailure()) return maybe; | 12214 object->ValidateElements(); |
| 12218 FixedDoubleArray::cast(elements())->set(index, value->Number()); | |
| 12219 ValidateElements(); | |
| 12220 return value; | 12215 return value; |
| 12221 } | 12216 } |
| 12222 // Change elements kind from Smi-only to generic FAST if necessary. | 12217 // Change elements kind from Smi-only to generic FAST if necessary. |
| 12223 if (HasFastSmiElements() && !value->IsSmi()) { | 12218 if (object->HasFastSmiElements() && !value->IsSmi()) { |
| 12224 Map* new_map; | 12219 ElementsKind kind = object->HasFastHoleyElements() |
| 12225 ElementsKind kind = HasFastHoleyElements() | |
| 12226 ? FAST_HOLEY_ELEMENTS | 12220 ? FAST_HOLEY_ELEMENTS |
| 12227 : FAST_ELEMENTS; | 12221 : FAST_ELEMENTS; |
| 12228 | 12222 |
| 12229 MaybeObject* maybe_failure = UpdateAllocationSite(kind); | 12223 UpdateAllocationSite(object, kind); |
| 12230 if (maybe_failure->IsFailure()) return maybe_failure; | 12224 Handle<Map> new_map = GetElementsTransitionMap(object, kind); |
| 12231 | 12225 object->set_map(*new_map); |
| 12232 MaybeObject* maybe_new_map = GetElementsTransitionMap(GetIsolate(), | 12226 ASSERT(IsFastObjectElementsKind(object->GetElementsKind())); |
| 12233 kind); | |
| 12234 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | |
| 12235 | |
| 12236 set_map(new_map); | |
| 12237 } | 12227 } |
| 12238 // Increase backing store capacity if that's been decided previously. | 12228 // Increase backing store capacity if that's been decided previously. |
| 12239 if (new_capacity != capacity) { | 12229 if (new_capacity != capacity) { |
| 12240 FixedArray* new_elements; | |
| 12241 SetFastElementsCapacitySmiMode smi_mode = | 12230 SetFastElementsCapacitySmiMode smi_mode = |
| 12242 value->IsSmi() && HasFastSmiElements() | 12231 value->IsSmi() && object->HasFastSmiElements() |
| 12243 ? kAllowSmiElements | 12232 ? kAllowSmiElements |
| 12244 : kDontAllowSmiElements; | 12233 : kDontAllowSmiElements; |
| 12245 { MaybeObject* maybe = | 12234 Handle<FixedArray> new_elements = |
| 12246 SetFastElementsCapacityAndLength(new_capacity, | 12235 SetFastElementsCapacityAndLength(object, new_capacity, array_length, |
| 12247 array_length, | 12236 smi_mode); |
| 12248 smi_mode); | 12237 new_elements->set(index, *value); |
| 12249 if (!maybe->To(&new_elements)) return maybe; | 12238 object->ValidateElements(); |
| 12250 } | |
| 12251 new_elements->set(index, value); | |
| 12252 ValidateElements(); | |
| 12253 return value; | 12239 return value; |
| 12254 } | 12240 } |
| 12255 | 12241 |
| 12256 // Finally, set the new element and length. | 12242 // Finally, set the new element and length. |
| 12257 ASSERT(elements()->IsFixedArray()); | 12243 ASSERT(object->elements()->IsFixedArray()); |
| 12258 backing_store->set(index, value); | 12244 backing_store->set(index, *value); |
| 12259 if (must_update_array_length) { | 12245 if (must_update_array_length) { |
| 12260 JSArray::cast(this)->set_length(Smi::FromInt(array_length)); | 12246 Handle<JSArray>::cast(object)->set_length(Smi::FromInt(array_length)); |
| 12261 } | 12247 } |
| 12262 return value; | 12248 return value; |
| 12263 } | 12249 } |
| 12264 | 12250 |
| 12265 | 12251 |
| 12266 MaybeObject* JSObject::SetDictionaryElement(uint32_t index, | 12252 Handle<Object> JSObject::SetDictionaryElement(Handle<JSObject> object, |
| 12267 Object* value_raw, | 12253 uint32_t index, |
| 12268 PropertyAttributes attributes, | 12254 Handle<Object> value, |
| 12269 StrictModeFlag strict_mode, | 12255 PropertyAttributes attributes, |
| 12270 bool check_prototype, | 12256 StrictModeFlag strict_mode, |
| 12271 SetPropertyMode set_mode) { | 12257 bool check_prototype, |
| 12272 ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements()); | 12258 SetPropertyMode set_mode) { |
| 12273 Isolate* isolate = GetIsolate(); | 12259 ASSERT(object->HasDictionaryElements() || |
| 12274 Heap* heap = isolate->heap(); | 12260 object->HasDictionaryArgumentsElements()); |
| 12275 Handle<JSObject> self(this); | 12261 Isolate* isolate = object->GetIsolate(); |
| 12276 Handle<Object> value(value_raw, isolate); | |
| 12277 | 12262 |
| 12278 // Insert element in the dictionary. | 12263 // Insert element in the dictionary. |
| 12279 Handle<FixedArray> elements(FixedArray::cast(this->elements())); | 12264 Handle<FixedArray> elements(FixedArray::cast(object->elements())); |
| 12280 bool is_arguments = | 12265 bool is_arguments = |
| 12281 (elements->map() == heap->non_strict_arguments_elements_map()); | 12266 (elements->map() == isolate->heap()->non_strict_arguments_elements_map()); |
| 12282 Handle<SeededNumberDictionary> dictionary(is_arguments | 12267 Handle<SeededNumberDictionary> dictionary(is_arguments |
| 12283 ? SeededNumberDictionary::cast(elements->get(1)) | 12268 ? SeededNumberDictionary::cast(elements->get(1)) |
| 12284 : SeededNumberDictionary::cast(*elements)); | 12269 : SeededNumberDictionary::cast(*elements)); |
| 12285 | 12270 |
| 12286 int entry = dictionary->FindEntry(index); | 12271 int entry = dictionary->FindEntry(index); |
| 12287 if (entry != SeededNumberDictionary::kNotFound) { | 12272 if (entry != SeededNumberDictionary::kNotFound) { |
| 12288 Handle<Object> element(dictionary->ValueAt(entry), isolate); | 12273 Handle<Object> element(dictionary->ValueAt(entry), isolate); |
| 12289 PropertyDetails details = dictionary->DetailsAt(entry); | 12274 PropertyDetails details = dictionary->DetailsAt(entry); |
| 12290 if (details.type() == CALLBACKS && set_mode == SET_PROPERTY) { | 12275 if (details.type() == CALLBACKS && set_mode == SET_PROPERTY) { |
| 12291 Handle<Object> result = SetElementWithCallback(self, element, index, | 12276 return SetElementWithCallback(object, element, index, value, object, |
| 12292 value, self, strict_mode); | 12277 strict_mode); |
| 12293 RETURN_IF_EMPTY_HANDLE(isolate, result); | |
| 12294 return *result; | |
| 12295 } else { | 12278 } else { |
| 12296 dictionary->UpdateMaxNumberKey(index); | 12279 dictionary->UpdateMaxNumberKey(index); |
| 12297 // If a value has not been initialized we allow writing to it even if it | 12280 // If a value has not been initialized we allow writing to it even if it |
| 12298 // is read-only (a declared const that has not been initialized). If a | 12281 // is read-only (a declared const that has not been initialized). If a |
| 12299 // value is being defined we skip attribute checks completely. | 12282 // value is being defined we skip attribute checks completely. |
| 12300 if (set_mode == DEFINE_PROPERTY) { | 12283 if (set_mode == DEFINE_PROPERTY) { |
| 12301 details = PropertyDetails( | 12284 details = PropertyDetails( |
| 12302 attributes, NORMAL, details.dictionary_index()); | 12285 attributes, NORMAL, details.dictionary_index()); |
| 12303 dictionary->DetailsAtPut(entry, details); | 12286 dictionary->DetailsAtPut(entry, details); |
| 12304 } else if (details.IsReadOnly() && !element->IsTheHole()) { | 12287 } else if (details.IsReadOnly() && !element->IsTheHole()) { |
| 12305 if (strict_mode == kNonStrictMode) { | 12288 if (strict_mode == kNonStrictMode) { |
| 12306 return isolate->heap()->undefined_value(); | 12289 return isolate->factory()->undefined_value(); |
| 12307 } else { | 12290 } else { |
| 12308 Handle<Object> holder(this, isolate); | |
| 12309 Handle<Object> number = isolate->factory()->NewNumberFromUint(index); | 12291 Handle<Object> number = isolate->factory()->NewNumberFromUint(index); |
| 12310 Handle<Object> args[2] = { number, holder }; | 12292 Handle<Object> args[2] = { number, object }; |
| 12311 Handle<Object> error = | 12293 Handle<Object> error = |
| 12312 isolate->factory()->NewTypeError("strict_read_only_property", | 12294 isolate->factory()->NewTypeError("strict_read_only_property", |
| 12313 HandleVector(args, 2)); | 12295 HandleVector(args, 2)); |
| 12314 return isolate->Throw(*error); | 12296 isolate->Throw(*error); |
| 12297 return Handle<Object>(); |
| 12315 } | 12298 } |
| 12316 } | 12299 } |
| 12317 // Elements of the arguments object in slow mode might be slow aliases. | 12300 // Elements of the arguments object in slow mode might be slow aliases. |
| 12318 if (is_arguments && element->IsAliasedArgumentsEntry()) { | 12301 if (is_arguments && element->IsAliasedArgumentsEntry()) { |
| 12319 AliasedArgumentsEntry* entry = AliasedArgumentsEntry::cast(*element); | 12302 Handle<AliasedArgumentsEntry> entry = |
| 12320 Context* context = Context::cast(elements->get(0)); | 12303 Handle<AliasedArgumentsEntry>::cast(element); |
| 12304 Handle<Context> context(Context::cast(elements->get(0))); |
| 12321 int context_index = entry->aliased_context_slot(); | 12305 int context_index = entry->aliased_context_slot(); |
| 12322 ASSERT(!context->get(context_index)->IsTheHole()); | 12306 ASSERT(!context->get(context_index)->IsTheHole()); |
| 12323 context->set(context_index, *value); | 12307 context->set(context_index, *value); |
| 12324 // For elements that are still writable we keep slow aliasing. | 12308 // For elements that are still writable we keep slow aliasing. |
| 12325 if (!details.IsReadOnly()) value = element; | 12309 if (!details.IsReadOnly()) value = element; |
| 12326 } | 12310 } |
| 12327 dictionary->ValueAtPut(entry, *value); | 12311 dictionary->ValueAtPut(entry, *value); |
| 12328 } | 12312 } |
| 12329 } else { | 12313 } else { |
| 12330 // Index not already used. Look for an accessor in the prototype chain. | 12314 // Index not already used. Look for an accessor in the prototype chain. |
| 12331 // Can cause GC! | 12315 // Can cause GC! |
| 12332 if (check_prototype) { | 12316 if (check_prototype) { |
| 12333 bool found; | 12317 bool found; |
| 12334 MaybeObject* result = SetElementWithCallbackSetterInPrototypes( | 12318 Handle<Object> result = SetElementWithCallbackSetterInPrototypes(object, |
| 12335 index, *value, &found, strict_mode); | 12319 index, value, &found, strict_mode); |
| 12336 if (found) return result; | 12320 if (found) return result; |
| 12337 } | 12321 } |
| 12322 |
| 12338 // When we set the is_extensible flag to false we always force the | 12323 // When we set the is_extensible flag to false we always force the |
| 12339 // element into dictionary mode (and force them to stay there). | 12324 // element into dictionary mode (and force them to stay there). |
| 12340 if (!self->map()->is_extensible()) { | 12325 if (!object->map()->is_extensible()) { |
| 12341 if (strict_mode == kNonStrictMode) { | 12326 if (strict_mode == kNonStrictMode) { |
| 12342 return isolate->heap()->undefined_value(); | 12327 return isolate->factory()->undefined_value(); |
| 12343 } else { | 12328 } else { |
| 12344 Handle<Object> number = isolate->factory()->NewNumberFromUint(index); | 12329 Handle<Object> number = isolate->factory()->NewNumberFromUint(index); |
| 12345 Handle<String> name = isolate->factory()->NumberToString(number); | 12330 Handle<String> name = isolate->factory()->NumberToString(number); |
| 12346 Handle<Object> args[1] = { name }; | 12331 Handle<Object> args[1] = { name }; |
| 12347 Handle<Object> error = | 12332 Handle<Object> error = |
| 12348 isolate->factory()->NewTypeError("object_not_extensible", | 12333 isolate->factory()->NewTypeError("object_not_extensible", |
| 12349 HandleVector(args, 1)); | 12334 HandleVector(args, 1)); |
| 12350 return isolate->Throw(*error); | 12335 isolate->Throw(*error); |
| 12336 return Handle<Object>(); |
| 12351 } | 12337 } |
| 12352 } | 12338 } |
| 12353 FixedArrayBase* new_dictionary; | 12339 |
| 12354 PropertyDetails details = PropertyDetails(attributes, NORMAL, 0); | 12340 PropertyDetails details = PropertyDetails(attributes, NORMAL, 0); |
| 12355 MaybeObject* maybe = dictionary->AddNumberEntry(index, *value, details); | 12341 Handle<SeededNumberDictionary> new_dictionary = |
| 12356 if (!maybe->To(&new_dictionary)) return maybe; | 12342 SeededNumberDictionary::AddNumberEntry(dictionary, index, value, |
| 12357 if (*dictionary != SeededNumberDictionary::cast(new_dictionary)) { | 12343 details); |
| 12344 if (*dictionary != *new_dictionary) { |
| 12358 if (is_arguments) { | 12345 if (is_arguments) { |
| 12359 elements->set(1, new_dictionary); | 12346 elements->set(1, *new_dictionary); |
| 12360 } else { | 12347 } else { |
| 12361 self->set_elements(new_dictionary); | 12348 object->set_elements(*new_dictionary); |
| 12362 } | 12349 } |
| 12363 dictionary = | 12350 dictionary = new_dictionary; |
| 12364 handle(SeededNumberDictionary::cast(new_dictionary), isolate); | |
| 12365 } | 12351 } |
| 12366 } | 12352 } |
| 12367 | 12353 |
| 12368 // Update the array length if this JSObject is an array. | 12354 // Update the array length if this JSObject is an array. |
| 12369 if (self->IsJSArray()) { | 12355 if (object->IsJSArray()) { |
| 12370 MaybeObject* result = | 12356 JSArray::JSArrayUpdateLengthFromIndex(Handle<JSArray>::cast(object), index, |
| 12371 JSArray::cast(*self)->JSArrayUpdateLengthFromIndex(index, *value); | 12357 value); |
| 12372 if (result->IsFailure()) return result; | |
| 12373 } | 12358 } |
| 12374 | 12359 |
| 12375 // Attempt to put this object back in fast case. | 12360 // Attempt to put this object back in fast case. |
| 12376 if (self->ShouldConvertToFastElements()) { | 12361 if (object->ShouldConvertToFastElements()) { |
| 12377 uint32_t new_length = 0; | 12362 uint32_t new_length = 0; |
| 12378 if (self->IsJSArray()) { | 12363 if (object->IsJSArray()) { |
| 12379 CHECK(JSArray::cast(*self)->length()->ToArrayIndex(&new_length)); | 12364 CHECK(Handle<JSArray>::cast(object)->length()->ToArrayIndex(&new_length)); |
| 12380 } else { | 12365 } else { |
| 12381 new_length = dictionary->max_number_key() + 1; | 12366 new_length = dictionary->max_number_key() + 1; |
| 12382 } | 12367 } |
| 12383 SetFastElementsCapacitySmiMode smi_mode = FLAG_smi_only_arrays | 12368 SetFastElementsCapacitySmiMode smi_mode = FLAG_smi_only_arrays |
| 12384 ? kAllowSmiElements | 12369 ? kAllowSmiElements |
| 12385 : kDontAllowSmiElements; | 12370 : kDontAllowSmiElements; |
| 12386 bool has_smi_only_elements = false; | 12371 bool has_smi_only_elements = false; |
| 12387 bool should_convert_to_fast_double_elements = | 12372 bool should_convert_to_fast_double_elements = |
| 12388 self->ShouldConvertToFastDoubleElements(&has_smi_only_elements); | 12373 object->ShouldConvertToFastDoubleElements(&has_smi_only_elements); |
| 12389 if (has_smi_only_elements) { | 12374 if (has_smi_only_elements) { |
| 12390 smi_mode = kForceSmiElements; | 12375 smi_mode = kForceSmiElements; |
| 12391 } | 12376 } |
| 12392 MaybeObject* result = should_convert_to_fast_double_elements | 12377 |
| 12393 ? self->SetFastDoubleElementsCapacityAndLength(new_length, new_length) | 12378 if (should_convert_to_fast_double_elements) { |
| 12394 : self->SetFastElementsCapacityAndLength( | 12379 SetFastDoubleElementsCapacityAndLength(object, new_length, new_length); |
| 12395 new_length, new_length, smi_mode); | 12380 } else { |
| 12396 self->ValidateElements(); | 12381 SetFastElementsCapacityAndLength(object, new_length, new_length, |
| 12397 if (result->IsFailure()) return result; | 12382 smi_mode); |
| 12383 } |
| 12384 object->ValidateElements(); |
| 12398 #ifdef DEBUG | 12385 #ifdef DEBUG |
| 12399 if (FLAG_trace_normalization) { | 12386 if (FLAG_trace_normalization) { |
| 12400 PrintF("Object elements are fast case again:\n"); | 12387 PrintF("Object elements are fast case again:\n"); |
| 12401 Print(); | 12388 object->Print(); |
| 12402 } | 12389 } |
| 12403 #endif | 12390 #endif |
| 12404 } | 12391 } |
| 12405 return *value; | 12392 return value; |
| 12406 } | 12393 } |
| 12407 | 12394 |
| 12408 | 12395 Handle<Object> JSObject::SetFastDoubleElement( |
| 12409 MUST_USE_RESULT MaybeObject* JSObject::SetFastDoubleElement( | 12396 Handle<JSObject> object, |
| 12410 uint32_t index, | 12397 uint32_t index, |
| 12411 Object* value, | 12398 Handle<Object> value, |
| 12412 StrictModeFlag strict_mode, | 12399 StrictModeFlag strict_mode, |
| 12413 bool check_prototype) { | 12400 bool check_prototype) { |
| 12414 ASSERT(HasFastDoubleElements()); | 12401 ASSERT(object->HasFastDoubleElements()); |
| 12415 | 12402 |
| 12416 FixedArrayBase* base_elms = FixedArrayBase::cast(elements()); | 12403 Handle<FixedArrayBase> base_elms(FixedArrayBase::cast(object->elements())); |
| 12417 uint32_t elms_length = static_cast<uint32_t>(base_elms->length()); | 12404 uint32_t elms_length = static_cast<uint32_t>(base_elms->length()); |
| 12418 | 12405 |
| 12419 // If storing to an element that isn't in the array, pass the store request | 12406 // If storing to an element that isn't in the array, pass the store request |
| 12420 // up the prototype chain before storing in the receiver's elements. | 12407 // up the prototype chain before storing in the receiver's elements. |
| 12421 if (check_prototype && | 12408 if (check_prototype && |
| 12422 (index >= elms_length || | 12409 (index >= elms_length || |
| 12423 FixedDoubleArray::cast(base_elms)->is_the_hole(index))) { | 12410 Handle<FixedDoubleArray>::cast(base_elms)->is_the_hole(index))) { |
| 12424 bool found; | 12411 bool found; |
| 12425 MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index, | 12412 Handle<Object> result = SetElementWithCallbackSetterInPrototypes(object, |
| 12426 value, | 12413 index, value, &found, strict_mode); |
| 12427 &found, | |
| 12428 strict_mode); | |
| 12429 if (found) return result; | 12414 if (found) return result; |
| 12430 } | 12415 } |
| 12431 | 12416 |
| 12432 // If the value object is not a heap number, switch to fast elements and try | 12417 // If the value object is not a heap number, switch to fast elements and try |
| 12433 // again. | 12418 // again. |
| 12434 bool value_is_smi = value->IsSmi(); | 12419 bool value_is_smi = value->IsSmi(); |
| 12435 bool introduces_holes = true; | 12420 bool introduces_holes = true; |
| 12436 uint32_t length = elms_length; | 12421 uint32_t length = elms_length; |
| 12437 if (IsJSArray()) { | 12422 if (object->IsJSArray()) { |
| 12438 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length)); | 12423 CHECK(Handle<JSArray>::cast(object)->length()->ToArrayIndex(&length)); |
| 12439 introduces_holes = index > length; | 12424 introduces_holes = index > length; |
| 12440 } else { | 12425 } else { |
| 12441 introduces_holes = index >= elms_length; | 12426 introduces_holes = index >= elms_length; |
| 12442 } | 12427 } |
| 12443 | 12428 |
| 12444 if (!value->IsNumber()) { | 12429 if (!value->IsNumber()) { |
| 12445 MaybeObject* maybe_obj = SetFastElementsCapacityAndLength( | 12430 SetFastElementsCapacityAndLength(object, elms_length, length, |
| 12446 elms_length, | 12431 kDontAllowSmiElements); |
| 12447 length, | 12432 Handle<Object> result = SetFastElement(object, index, value, strict_mode, |
| 12448 kDontAllowSmiElements); | 12433 check_prototype); |
| 12449 if (maybe_obj->IsFailure()) return maybe_obj; | 12434 RETURN_IF_EMPTY_HANDLE_VALUE(object->GetIsolate(), result, |
| 12450 maybe_obj = SetFastElement(index, value, strict_mode, check_prototype); | 12435 Handle<Object>()); |
| 12451 if (maybe_obj->IsFailure()) return maybe_obj; | 12436 object->ValidateElements(); |
| 12452 ValidateElements(); | 12437 return result; |
| 12453 return maybe_obj; | |
| 12454 } | 12438 } |
| 12455 | 12439 |
| 12456 double double_value = value_is_smi | 12440 double double_value = value_is_smi |
| 12457 ? static_cast<double>(Smi::cast(value)->value()) | 12441 ? static_cast<double>(Handle<Smi>::cast(value)->value()) |
| 12458 : HeapNumber::cast(value)->value(); | 12442 : Handle<HeapNumber>::cast(value)->value(); |
| 12459 | 12443 |
| 12460 // If the array is growing, and it's not growth by a single element at the | 12444 // If the array is growing, and it's not growth by a single element at the |
| 12461 // end, make sure that the ElementsKind is HOLEY. | 12445 // end, make sure that the ElementsKind is HOLEY. |
| 12462 ElementsKind elements_kind = GetElementsKind(); | 12446 ElementsKind elements_kind = object->GetElementsKind(); |
| 12463 if (introduces_holes && !IsFastHoleyElementsKind(elements_kind)) { | 12447 if (introduces_holes && !IsFastHoleyElementsKind(elements_kind)) { |
| 12464 ElementsKind transitioned_kind = GetHoleyElementsKind(elements_kind); | 12448 ElementsKind transitioned_kind = GetHoleyElementsKind(elements_kind); |
| 12465 MaybeObject* maybe = TransitionElementsKind(transitioned_kind); | 12449 TransitionElementsKind(object, transitioned_kind); |
| 12466 if (maybe->IsFailure()) return maybe; | |
| 12467 } | 12450 } |
| 12468 | 12451 |
| 12469 // Check whether there is extra space in the fixed array. | 12452 // Check whether there is extra space in the fixed array. |
| 12470 if (index < elms_length) { | 12453 if (index < elms_length) { |
| 12471 FixedDoubleArray* elms = FixedDoubleArray::cast(elements()); | 12454 Handle<FixedDoubleArray> elms(FixedDoubleArray::cast(object->elements())); |
| 12472 elms->set(index, double_value); | 12455 elms->set(index, double_value); |
| 12473 if (IsJSArray()) { | 12456 if (object->IsJSArray()) { |
| 12474 // Update the length of the array if needed. | 12457 // Update the length of the array if needed. |
| 12475 uint32_t array_length = 0; | 12458 uint32_t array_length = 0; |
| 12476 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length)); | 12459 CHECK( |
| 12460 Handle<JSArray>::cast(object)->length()->ToArrayIndex(&array_length)); |
| 12477 if (index >= array_length) { | 12461 if (index >= array_length) { |
| 12478 JSArray::cast(this)->set_length(Smi::FromInt(index + 1)); | 12462 Handle<JSArray>::cast(object)->set_length(Smi::FromInt(index + 1)); |
| 12479 } | 12463 } |
| 12480 } | 12464 } |
| 12481 return value; | 12465 return value; |
| 12482 } | 12466 } |
| 12483 | 12467 |
| 12484 // Allow gap in fast case. | 12468 // Allow gap in fast case. |
| 12485 if ((index - elms_length) < kMaxGap) { | 12469 if ((index - elms_length) < kMaxGap) { |
| 12486 // Try allocating extra space. | 12470 // Try allocating extra space. |
| 12487 int new_capacity = NewElementsCapacity(index+1); | 12471 int new_capacity = NewElementsCapacity(index+1); |
| 12488 if (!ShouldConvertToSlowElements(new_capacity)) { | 12472 if (!object->ShouldConvertToSlowElements(new_capacity)) { |
| 12489 ASSERT(static_cast<uint32_t>(new_capacity) > index); | 12473 ASSERT(static_cast<uint32_t>(new_capacity) > index); |
| 12490 MaybeObject* maybe_obj = | 12474 SetFastDoubleElementsCapacityAndLength(object, new_capacity, index + 1); |
| 12491 SetFastDoubleElementsCapacityAndLength(new_capacity, index + 1); | 12475 FixedDoubleArray::cast(object->elements())->set(index, double_value); |
| 12492 if (maybe_obj->IsFailure()) return maybe_obj; | 12476 object->ValidateElements(); |
| 12493 FixedDoubleArray::cast(elements())->set(index, double_value); | |
| 12494 ValidateElements(); | |
| 12495 return value; | 12477 return value; |
| 12496 } | 12478 } |
| 12497 } | 12479 } |
| 12498 | 12480 |
| 12499 // Otherwise default to slow case. | 12481 // Otherwise default to slow case. |
| 12500 ASSERT(HasFastDoubleElements()); | 12482 ASSERT(object->HasFastDoubleElements()); |
| 12501 ASSERT(map()->has_fast_double_elements()); | 12483 ASSERT(object->map()->has_fast_double_elements()); |
| 12502 ASSERT(elements()->IsFixedDoubleArray()); | 12484 ASSERT(object->elements()->IsFixedDoubleArray()); |
| 12503 Object* obj; | 12485 |
| 12504 { MaybeObject* maybe_obj = NormalizeElements(); | 12486 NormalizeElements(object); |
| 12505 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 12487 ASSERT(object->HasDictionaryElements()); |
| 12506 } | 12488 return SetElement(object, index, value, NONE, strict_mode, check_prototype); |
| 12507 ASSERT(HasDictionaryElements()); | |
| 12508 return SetElement(index, value, NONE, strict_mode, check_prototype); | |
| 12509 } | 12489 } |
| 12510 | 12490 |
| 12511 | 12491 |
| 12512 Handle<Object> JSReceiver::SetElement(Handle<JSReceiver> object, | 12492 Handle<Object> JSReceiver::SetElement(Handle<JSReceiver> object, |
| 12513 uint32_t index, | 12493 uint32_t index, |
| 12514 Handle<Object> value, | 12494 Handle<Object> value, |
| 12515 PropertyAttributes attributes, | 12495 PropertyAttributes attributes, |
| 12516 StrictModeFlag strict_mode) { | 12496 StrictModeFlag strict_mode) { |
| 12517 if (object->IsJSProxy()) { | 12497 if (object->IsJSProxy()) { |
| 12518 return JSProxy::SetElementWithHandler( | 12498 return JSProxy::SetElementWithHandler( |
| 12519 Handle<JSProxy>::cast(object), object, index, value, strict_mode); | 12499 Handle<JSProxy>::cast(object), object, index, value, strict_mode); |
| 12520 } | 12500 } |
| 12521 return JSObject::SetElement( | 12501 return JSObject::SetElement( |
| 12522 Handle<JSObject>::cast(object), index, value, attributes, strict_mode); | 12502 Handle<JSObject>::cast(object), index, value, attributes, strict_mode); |
| 12523 } | 12503 } |
| 12524 | 12504 |
| 12525 | 12505 |
| 12526 Handle<Object> JSObject::SetOwnElement(Handle<JSObject> object, | 12506 Handle<Object> JSObject::SetOwnElement(Handle<JSObject> object, |
| 12527 uint32_t index, | 12507 uint32_t index, |
| 12528 Handle<Object> value, | 12508 Handle<Object> value, |
| 12529 StrictModeFlag strict_mode) { | 12509 StrictModeFlag strict_mode) { |
| 12530 ASSERT(!object->HasExternalArrayElements()); | 12510 ASSERT(!object->HasExternalArrayElements()); |
| 12531 CALL_HEAP_FUNCTION( | 12511 return JSObject::SetElement(object, index, value, NONE, strict_mode, false); |
| 12532 object->GetIsolate(), | |
| 12533 object->SetElement(index, *value, NONE, strict_mode, false), | |
| 12534 Object); | |
| 12535 } | 12512 } |
| 12536 | 12513 |
| 12537 | 12514 |
| 12538 Handle<Object> JSObject::SetElement(Handle<JSObject> object, | 12515 Handle<Object> JSObject::SetElement(Handle<JSObject> object, |
| 12539 uint32_t index, | 12516 uint32_t index, |
| 12540 Handle<Object> value, | 12517 Handle<Object> value, |
| 12541 PropertyAttributes attr, | 12518 PropertyAttributes attributes, |
| 12542 StrictModeFlag strict_mode, | 12519 StrictModeFlag strict_mode, |
| 12543 bool check_prototype, | 12520 bool check_prototype, |
| 12544 SetPropertyMode set_mode) { | 12521 SetPropertyMode set_mode) { |
| 12522 Isolate* isolate = object->GetIsolate(); |
| 12523 |
| 12545 if (object->HasExternalArrayElements()) { | 12524 if (object->HasExternalArrayElements()) { |
| 12546 if (!value->IsNumber() && !value->IsUndefined()) { | 12525 if (!value->IsNumber() && !value->IsUndefined()) { |
| 12547 bool has_exception; | 12526 bool has_exception; |
| 12548 Handle<Object> number = | 12527 Handle<Object> number = |
| 12549 Execution::ToNumber(object->GetIsolate(), value, &has_exception); | 12528 Execution::ToNumber(isolate, value, &has_exception); |
| 12550 if (has_exception) return Handle<Object>(); | 12529 if (has_exception) return Handle<Object>(); |
| 12551 value = number; | 12530 value = number; |
| 12552 } | 12531 } |
| 12553 } | 12532 } |
| 12554 CALL_HEAP_FUNCTION( | |
| 12555 object->GetIsolate(), | |
| 12556 object->SetElement(index, *value, attr, strict_mode, check_prototype, | |
| 12557 set_mode), | |
| 12558 Object); | |
| 12559 } | |
| 12560 | |
| 12561 | |
| 12562 MaybeObject* JSObject::SetElement(uint32_t index, | |
| 12563 Object* value_raw, | |
| 12564 PropertyAttributes attributes, | |
| 12565 StrictModeFlag strict_mode, | |
| 12566 bool check_prototype, | |
| 12567 SetPropertyMode set_mode) { | |
| 12568 Isolate* isolate = GetIsolate(); | |
| 12569 | 12533 |
| 12570 // Check access rights if needed. | 12534 // Check access rights if needed. |
| 12571 if (IsAccessCheckNeeded()) { | 12535 if (object->IsAccessCheckNeeded()) { |
| 12572 if (!isolate->MayIndexedAccess(this, index, v8::ACCESS_SET)) { | 12536 if (!isolate->MayIndexedAccess(*object, index, v8::ACCESS_SET)) { |
| 12573 isolate->ReportFailedAccessCheck(this, v8::ACCESS_SET); | 12537 isolate->ReportFailedAccessCheck(*object, v8::ACCESS_SET); |
| 12574 RETURN_IF_SCHEDULED_EXCEPTION(isolate); | 12538 RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); |
| 12575 return value_raw; | 12539 return value; |
| 12576 } | 12540 } |
| 12577 } | 12541 } |
| 12578 | 12542 |
| 12579 if (IsJSGlobalProxy()) { | 12543 if (object->IsJSGlobalProxy()) { |
| 12580 Object* proto = GetPrototype(); | 12544 Handle<Object> proto(object->GetPrototype(), isolate); |
| 12581 if (proto->IsNull()) return value_raw; | 12545 if (proto->IsNull()) return value; |
| 12582 ASSERT(proto->IsJSGlobalObject()); | 12546 ASSERT(proto->IsJSGlobalObject()); |
| 12583 return JSObject::cast(proto)->SetElement(index, | 12547 return SetElement(Handle<JSObject>::cast(proto), index, value, attributes, |
| 12584 value_raw, | 12548 strict_mode, |
| 12585 attributes, | 12549 check_prototype, |
| 12586 strict_mode, | 12550 set_mode); |
| 12587 check_prototype, | |
| 12588 set_mode); | |
| 12589 } | 12551 } |
| 12590 | 12552 |
| 12591 // Don't allow element properties to be redefined for external arrays. | 12553 // Don't allow element properties to be redefined for external arrays. |
| 12592 if (HasExternalArrayElements() && set_mode == DEFINE_PROPERTY) { | 12554 if (object->HasExternalArrayElements() && set_mode == DEFINE_PROPERTY) { |
| 12593 Handle<Object> number = isolate->factory()->NewNumberFromUint(index); | 12555 Handle<Object> number = isolate->factory()->NewNumberFromUint(index); |
| 12594 Handle<Object> args[] = { handle(this, isolate), number }; | 12556 Handle<Object> args[] = { object, number }; |
| 12595 Handle<Object> error = isolate->factory()->NewTypeError( | 12557 Handle<Object> error = isolate->factory()->NewTypeError( |
| 12596 "redef_external_array_element", HandleVector(args, ARRAY_SIZE(args))); | 12558 "redef_external_array_element", HandleVector(args, ARRAY_SIZE(args))); |
| 12597 return isolate->Throw(*error); | 12559 isolate->Throw(*error); |
| 12560 return Handle<Object>(); |
| 12598 } | 12561 } |
| 12599 | 12562 |
| 12600 // Normalize the elements to enable attributes on the property. | 12563 // Normalize the elements to enable attributes on the property. |
| 12601 if ((attributes & (DONT_DELETE | DONT_ENUM | READ_ONLY)) != 0) { | 12564 if ((attributes & (DONT_DELETE | DONT_ENUM | READ_ONLY)) != 0) { |
| 12602 SeededNumberDictionary* dictionary; | 12565 Handle<SeededNumberDictionary> dictionary = NormalizeElements(object); |
| 12603 MaybeObject* maybe_object = NormalizeElements(); | |
| 12604 if (!maybe_object->To(&dictionary)) return maybe_object; | |
| 12605 // Make sure that we never go back to fast case. | 12566 // Make sure that we never go back to fast case. |
| 12606 dictionary->set_requires_slow_elements(); | 12567 dictionary->set_requires_slow_elements(); |
| 12607 } | 12568 } |
| 12608 | 12569 |
| 12609 if (!(FLAG_harmony_observation && map()->is_observed())) { | 12570 if (!(FLAG_harmony_observation && object->map()->is_observed())) { |
| 12610 return HasIndexedInterceptor() | 12571 return object->HasIndexedInterceptor() |
| 12611 ? SetElementWithInterceptor( | 12572 ? SetElementWithInterceptor(object, index, value, attributes, strict_mode, |
| 12612 index, value_raw, attributes, strict_mode, check_prototype, set_mode) | 12573 check_prototype, |
| 12613 : SetElementWithoutInterceptor( | 12574 set_mode) |
| 12614 index, value_raw, attributes, strict_mode, check_prototype, set_mode); | 12575 : SetElementWithoutInterceptor(object, index, value, attributes, |
| 12615 } | 12576 strict_mode, |
| 12616 | 12577 check_prototype, |
| 12617 // From here on, everything has to be handlified. | 12578 set_mode); |
| 12618 Handle<JSObject> self(this); | 12579 } |
| 12619 Handle<Object> value(value_raw, isolate); | 12580 |
| 12620 PropertyAttributes old_attributes = self->GetLocalElementAttribute(index); | 12581 PropertyAttributes old_attributes = object->GetLocalElementAttribute(index); |
| 12621 Handle<Object> old_value = isolate->factory()->the_hole_value(); | 12582 Handle<Object> old_value = isolate->factory()->the_hole_value(); |
| 12622 Handle<Object> old_length_handle; | 12583 Handle<Object> old_length_handle; |
| 12623 Handle<Object> new_length_handle; | 12584 Handle<Object> new_length_handle; |
| 12624 | 12585 |
| 12625 if (old_attributes != ABSENT) { | 12586 if (old_attributes != ABSENT) { |
| 12626 if (self->GetLocalElementAccessorPair(index) == NULL) | 12587 if (object->GetLocalElementAccessorPair(index) == NULL) |
| 12627 old_value = Object::GetElement(isolate, self, index); | 12588 old_value = Object::GetElement(isolate, object, index); |
| 12628 } else if (self->IsJSArray()) { | 12589 } else if (object->IsJSArray()) { |
| 12629 // Store old array length in case adding an element grows the array. | 12590 // Store old array length in case adding an element grows the array. |
| 12630 old_length_handle = handle(Handle<JSArray>::cast(self)->length(), isolate); | 12591 old_length_handle = handle(Handle<JSArray>::cast(object)->length(), |
| 12592 isolate); |
| 12631 } | 12593 } |
| 12632 | 12594 |
| 12633 // Check for lookup interceptor | 12595 // Check for lookup interceptor |
| 12634 MaybeObject* result = self->HasIndexedInterceptor() | 12596 Handle<Object> result = object->HasIndexedInterceptor() |
| 12635 ? self->SetElementWithInterceptor( | 12597 ? SetElementWithInterceptor(object, index, value, attributes, strict_mode, |
| 12636 index, *value, attributes, strict_mode, check_prototype, set_mode) | 12598 check_prototype, |
| 12637 : self->SetElementWithoutInterceptor( | 12599 set_mode) |
| 12638 index, *value, attributes, strict_mode, check_prototype, set_mode); | 12600 : SetElementWithoutInterceptor(object, index, value, attributes, |
| 12639 | 12601 strict_mode, |
| 12640 Handle<Object> hresult; | 12602 check_prototype, |
| 12641 if (!result->ToHandle(&hresult, isolate)) return result; | 12603 set_mode); |
| 12604 RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<Object>()); |
| 12642 | 12605 |
| 12643 Handle<String> name = isolate->factory()->Uint32ToString(index); | 12606 Handle<String> name = isolate->factory()->Uint32ToString(index); |
| 12644 PropertyAttributes new_attributes = self->GetLocalElementAttribute(index); | 12607 PropertyAttributes new_attributes = object->GetLocalElementAttribute(index); |
| 12645 if (old_attributes == ABSENT) { | 12608 if (old_attributes == ABSENT) { |
| 12646 if (self->IsJSArray() && | 12609 if (object->IsJSArray() && |
| 12647 !old_length_handle->SameValue(Handle<JSArray>::cast(self)->length())) { | 12610 !old_length_handle->SameValue( |
| 12648 new_length_handle = handle(Handle<JSArray>::cast(self)->length(), | 12611 Handle<JSArray>::cast(object)->length())) { |
| 12612 new_length_handle = handle(Handle<JSArray>::cast(object)->length(), |
| 12649 isolate); | 12613 isolate); |
| 12650 uint32_t old_length = 0; | 12614 uint32_t old_length = 0; |
| 12651 uint32_t new_length = 0; | 12615 uint32_t new_length = 0; |
| 12652 CHECK(old_length_handle->ToArrayIndex(&old_length)); | 12616 CHECK(old_length_handle->ToArrayIndex(&old_length)); |
| 12653 CHECK(new_length_handle->ToArrayIndex(&new_length)); | 12617 CHECK(new_length_handle->ToArrayIndex(&new_length)); |
| 12654 | 12618 |
| 12655 BeginPerformSplice(Handle<JSArray>::cast(self)); | 12619 BeginPerformSplice(Handle<JSArray>::cast(object)); |
| 12656 EnqueueChangeRecord(self, "add", name, old_value); | 12620 EnqueueChangeRecord(object, "add", name, old_value); |
| 12657 EnqueueChangeRecord(self, "update", isolate->factory()->length_string(), | 12621 EnqueueChangeRecord(object, "update", isolate->factory()->length_string(), |
| 12658 old_length_handle); | 12622 old_length_handle); |
| 12659 EndPerformSplice(Handle<JSArray>::cast(self)); | 12623 EndPerformSplice(Handle<JSArray>::cast(object)); |
| 12660 Handle<JSArray> deleted = isolate->factory()->NewJSArray(0); | 12624 Handle<JSArray> deleted = isolate->factory()->NewJSArray(0); |
| 12661 EnqueueSpliceRecord(Handle<JSArray>::cast(self), old_length, deleted, | 12625 EnqueueSpliceRecord(Handle<JSArray>::cast(object), old_length, deleted, |
| 12662 new_length - old_length); | 12626 new_length - old_length); |
| 12663 } else { | 12627 } else { |
| 12664 EnqueueChangeRecord(self, "add", name, old_value); | 12628 EnqueueChangeRecord(object, "add", name, old_value); |
| 12665 } | 12629 } |
| 12666 } else if (old_value->IsTheHole()) { | 12630 } else if (old_value->IsTheHole()) { |
| 12667 EnqueueChangeRecord(self, "reconfigure", name, old_value); | 12631 EnqueueChangeRecord(object, "reconfigure", name, old_value); |
| 12668 } else { | 12632 } else { |
| 12669 Handle<Object> new_value = Object::GetElement(isolate, self, index); | 12633 Handle<Object> new_value = Object::GetElement(isolate, object, index); |
| 12670 bool value_changed = !old_value->SameValue(*new_value); | 12634 bool value_changed = !old_value->SameValue(*new_value); |
| 12671 if (old_attributes != new_attributes) { | 12635 if (old_attributes != new_attributes) { |
| 12672 if (!value_changed) old_value = isolate->factory()->the_hole_value(); | 12636 if (!value_changed) old_value = isolate->factory()->the_hole_value(); |
| 12673 EnqueueChangeRecord(self, "reconfigure", name, old_value); | 12637 EnqueueChangeRecord(object, "reconfigure", name, old_value); |
| 12674 } else if (value_changed) { | 12638 } else if (value_changed) { |
| 12675 EnqueueChangeRecord(self, "update", name, old_value); | 12639 EnqueueChangeRecord(object, "update", name, old_value); |
| 12676 } | 12640 } |
| 12677 } | 12641 } |
| 12678 | 12642 |
| 12679 return *hresult; | 12643 return result; |
| 12680 } | 12644 } |
| 12681 | 12645 |
| 12682 | 12646 |
| 12683 MaybeObject* JSObject::SetElementWithoutInterceptor(uint32_t index, | 12647 Handle<Object> JSObject::SetElementWithoutInterceptor( |
| 12684 Object* value, | 12648 Handle<JSObject> object, |
| 12685 PropertyAttributes attr, | 12649 uint32_t index, |
| 12686 StrictModeFlag strict_mode, | 12650 Handle<Object> value, |
| 12687 bool check_prototype, | 12651 PropertyAttributes attributes, |
| 12688 SetPropertyMode set_mode) { | 12652 StrictModeFlag strict_mode, |
| 12689 ASSERT(HasDictionaryElements() || | 12653 bool check_prototype, |
| 12690 HasDictionaryArgumentsElements() || | 12654 SetPropertyMode set_mode) { |
| 12691 (attr & (DONT_DELETE | DONT_ENUM | READ_ONLY)) == 0); | 12655 ASSERT(object->HasDictionaryElements() || |
| 12692 Isolate* isolate = GetIsolate(); | 12656 object->HasDictionaryArgumentsElements() || |
| 12657 (attributes & (DONT_DELETE | DONT_ENUM | READ_ONLY)) == 0); |
| 12658 Isolate* isolate = object->GetIsolate(); |
| 12693 if (FLAG_trace_external_array_abuse && | 12659 if (FLAG_trace_external_array_abuse && |
| 12694 IsExternalArrayElementsKind(GetElementsKind())) { | 12660 IsExternalArrayElementsKind(object->GetElementsKind())) { |
| 12695 CheckArrayAbuse(this, "external elements write", index); | 12661 CheckArrayAbuse(*object, "external elements write", index); |
| 12696 } | 12662 } |
| 12697 if (FLAG_trace_js_array_abuse && | 12663 if (FLAG_trace_js_array_abuse && |
| 12698 !IsExternalArrayElementsKind(GetElementsKind())) { | 12664 !IsExternalArrayElementsKind(object->GetElementsKind())) { |
| 12699 if (IsJSArray()) { | 12665 if (object->IsJSArray()) { |
| 12700 CheckArrayAbuse(this, "elements write", index, true); | 12666 CheckArrayAbuse(*object, "elements write", index, true); |
| 12701 } | 12667 } |
| 12702 } | 12668 } |
| 12703 switch (GetElementsKind()) { | 12669 switch (object->GetElementsKind()) { |
| 12704 case FAST_SMI_ELEMENTS: | 12670 case FAST_SMI_ELEMENTS: |
| 12705 case FAST_ELEMENTS: | 12671 case FAST_ELEMENTS: |
| 12706 case FAST_HOLEY_SMI_ELEMENTS: | 12672 case FAST_HOLEY_SMI_ELEMENTS: |
| 12707 case FAST_HOLEY_ELEMENTS: | 12673 case FAST_HOLEY_ELEMENTS: |
| 12708 return SetFastElement(index, value, strict_mode, check_prototype); | 12674 return SetFastElement(object, index, value, strict_mode, check_prototype); |
| 12709 case FAST_DOUBLE_ELEMENTS: | 12675 case FAST_DOUBLE_ELEMENTS: |
| 12710 case FAST_HOLEY_DOUBLE_ELEMENTS: | 12676 case FAST_HOLEY_DOUBLE_ELEMENTS: |
| 12711 return SetFastDoubleElement(index, value, strict_mode, check_prototype); | 12677 return SetFastDoubleElement(object, index, value, strict_mode, |
| 12678 check_prototype); |
| 12712 case EXTERNAL_PIXEL_ELEMENTS: { | 12679 case EXTERNAL_PIXEL_ELEMENTS: { |
| 12713 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements()); | 12680 ExternalPixelArray* pixels = ExternalPixelArray::cast(object->elements()); |
| 12714 return pixels->SetValue(index, value); | 12681 return handle(pixels->SetValue(index, *value), isolate); |
| 12715 } | 12682 } |
| 12716 case EXTERNAL_BYTE_ELEMENTS: { | 12683 case EXTERNAL_BYTE_ELEMENTS: { |
| 12717 ExternalByteArray* array = ExternalByteArray::cast(elements()); | 12684 Handle<ExternalByteArray> array( |
| 12718 return array->SetValue(index, value); | 12685 ExternalByteArray::cast(object->elements())); |
| 12686 return ExternalByteArray::SetValue(array, index, value); |
| 12719 } | 12687 } |
| 12720 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: { | 12688 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: { |
| 12721 ExternalUnsignedByteArray* array = | 12689 Handle<ExternalUnsignedByteArray> array( |
| 12722 ExternalUnsignedByteArray::cast(elements()); | 12690 ExternalUnsignedByteArray::cast(object->elements())); |
| 12723 return array->SetValue(index, value); | 12691 return ExternalUnsignedByteArray::SetValue(array, index, value); |
| 12724 } | 12692 } |
| 12725 case EXTERNAL_SHORT_ELEMENTS: { | 12693 case EXTERNAL_SHORT_ELEMENTS: { |
| 12726 ExternalShortArray* array = ExternalShortArray::cast(elements()); | 12694 Handle<ExternalShortArray> array(ExternalShortArray::cast( |
| 12727 return array->SetValue(index, value); | 12695 object->elements())); |
| 12696 return ExternalShortArray::SetValue(array, index, value); |
| 12728 } | 12697 } |
| 12729 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: { | 12698 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: { |
| 12730 ExternalUnsignedShortArray* array = | 12699 Handle<ExternalUnsignedShortArray> array( |
| 12731 ExternalUnsignedShortArray::cast(elements()); | 12700 ExternalUnsignedShortArray::cast(object->elements())); |
| 12732 return array->SetValue(index, value); | 12701 return ExternalUnsignedShortArray::SetValue(array, index, value); |
| 12733 } | 12702 } |
| 12734 case EXTERNAL_INT_ELEMENTS: { | 12703 case EXTERNAL_INT_ELEMENTS: { |
| 12735 ExternalIntArray* array = ExternalIntArray::cast(elements()); | 12704 Handle<ExternalIntArray> array( |
| 12736 return array->SetValue(index, value); | 12705 ExternalIntArray::cast(object->elements())); |
| 12706 return ExternalIntArray::SetValue(array, index, value); |
| 12737 } | 12707 } |
| 12738 case EXTERNAL_UNSIGNED_INT_ELEMENTS: { | 12708 case EXTERNAL_UNSIGNED_INT_ELEMENTS: { |
| 12739 ExternalUnsignedIntArray* array = | 12709 Handle<ExternalUnsignedIntArray> array( |
| 12740 ExternalUnsignedIntArray::cast(elements()); | 12710 ExternalUnsignedIntArray::cast(object->elements())); |
| 12741 return array->SetValue(index, value); | 12711 return ExternalUnsignedIntArray::SetValue(array, index, value); |
| 12742 } | 12712 } |
| 12743 case EXTERNAL_FLOAT_ELEMENTS: { | 12713 case EXTERNAL_FLOAT_ELEMENTS: { |
| 12744 ExternalFloatArray* array = ExternalFloatArray::cast(elements()); | 12714 Handle<ExternalFloatArray> array( |
| 12745 return array->SetValue(index, value); | 12715 ExternalFloatArray::cast(object->elements())); |
| 12716 return ExternalFloatArray::SetValue(array, index, value); |
| 12746 } | 12717 } |
| 12747 case EXTERNAL_DOUBLE_ELEMENTS: { | 12718 case EXTERNAL_DOUBLE_ELEMENTS: { |
| 12748 ExternalDoubleArray* array = ExternalDoubleArray::cast(elements()); | 12719 Handle<ExternalDoubleArray> array( |
| 12749 return array->SetValue(index, value); | 12720 ExternalDoubleArray::cast(object->elements())); |
| 12721 return ExternalDoubleArray::SetValue(array, index, value); |
| 12750 } | 12722 } |
| 12751 case DICTIONARY_ELEMENTS: | 12723 case DICTIONARY_ELEMENTS: |
| 12752 return SetDictionaryElement(index, value, attr, strict_mode, | 12724 return SetDictionaryElement(object, index, value, attributes, strict_mode, |
| 12753 check_prototype, set_mode); | 12725 check_prototype, |
| 12726 set_mode); |
| 12754 case NON_STRICT_ARGUMENTS_ELEMENTS: { | 12727 case NON_STRICT_ARGUMENTS_ELEMENTS: { |
| 12755 FixedArray* parameter_map = FixedArray::cast(elements()); | 12728 Handle<FixedArray> parameter_map(FixedArray::cast(object->elements())); |
| 12756 uint32_t length = parameter_map->length(); | 12729 uint32_t length = parameter_map->length(); |
| 12757 Object* probe = | 12730 Handle<Object> probe = index < length - 2 ? |
| 12758 (index < length - 2) ? parameter_map->get(index + 2) : NULL; | 12731 Handle<Object>(parameter_map->get(index + 2), isolate) : |
| 12759 if (probe != NULL && !probe->IsTheHole()) { | 12732 Handle<Object>(); |
| 12760 Context* context = Context::cast(parameter_map->get(0)); | 12733 if (!probe.is_null() && !probe->IsTheHole()) { |
| 12761 int context_index = Smi::cast(probe)->value(); | 12734 Handle<Context> context(Context::cast(parameter_map->get(0))); |
| 12735 int context_index = Handle<Smi>::cast(probe)->value(); |
| 12762 ASSERT(!context->get(context_index)->IsTheHole()); | 12736 ASSERT(!context->get(context_index)->IsTheHole()); |
| 12763 context->set(context_index, value); | 12737 context->set(context_index, *value); |
| 12764 // Redefining attributes of an aliased element destroys fast aliasing. | 12738 // Redefining attributes of an aliased element destroys fast aliasing. |
| 12765 if (set_mode == SET_PROPERTY || attr == NONE) return value; | 12739 if (set_mode == SET_PROPERTY || attributes == NONE) return value; |
| 12766 parameter_map->set_the_hole(index + 2); | 12740 parameter_map->set_the_hole(index + 2); |
| 12767 // For elements that are still writable we re-establish slow aliasing. | 12741 // For elements that are still writable we re-establish slow aliasing. |
| 12768 if ((attr & READ_ONLY) == 0) { | 12742 if ((attributes & READ_ONLY) == 0) { |
| 12769 MaybeObject* maybe_entry = | 12743 value = Handle<Object>::cast( |
| 12770 isolate->heap()->AllocateAliasedArgumentsEntry(context_index); | 12744 isolate->factory()->NewAliasedArgumentsEntry(context_index)); |
| 12771 if (!maybe_entry->ToObject(&value)) return maybe_entry; | |
| 12772 } | 12745 } |
| 12773 } | 12746 } |
| 12774 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | 12747 Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1))); |
| 12775 if (arguments->IsDictionary()) { | 12748 if (arguments->IsDictionary()) { |
| 12776 return SetDictionaryElement(index, value, attr, strict_mode, | 12749 return SetDictionaryElement(object, index, value, attributes, |
| 12777 check_prototype, set_mode); | 12750 strict_mode, |
| 12751 check_prototype, |
| 12752 set_mode); |
| 12778 } else { | 12753 } else { |
| 12779 return SetFastElement(index, value, strict_mode, check_prototype); | 12754 return SetFastElement(object, index, value, strict_mode, |
| 12755 check_prototype); |
| 12780 } | 12756 } |
| 12781 } | 12757 } |
| 12782 } | 12758 } |
| 12783 // All possible cases have been handled above. Add a return to avoid the | 12759 // All possible cases have been handled above. Add a return to avoid the |
| 12784 // complaints from the compiler. | 12760 // complaints from the compiler. |
| 12785 UNREACHABLE(); | 12761 UNREACHABLE(); |
| 12786 return isolate->heap()->null_value(); | 12762 return isolate->factory()->null_value(); |
| 12787 } | 12763 } |
| 12788 | 12764 |
| 12789 | 12765 |
| 12790 void JSObject::TransitionElementsKind(Handle<JSObject> object, | 12766 void JSObject::TransitionElementsKind(Handle<JSObject> object, |
| 12791 ElementsKind to_kind) { | 12767 ElementsKind to_kind) { |
| 12792 CALL_HEAP_FUNCTION_VOID(object->GetIsolate(), | 12768 CALL_HEAP_FUNCTION_VOID(object->GetIsolate(), |
| 12793 object->TransitionElementsKind(to_kind)); | 12769 object->TransitionElementsKind(to_kind)); |
| 12794 } | 12770 } |
| 12795 | 12771 |
| 12796 | 12772 |
| 12797 bool AllocationSite::IsNestedSite() { | 12773 bool AllocationSite::IsNestedSite() { |
| 12798 ASSERT(FLAG_trace_track_allocation_sites); | 12774 ASSERT(FLAG_trace_track_allocation_sites); |
| 12799 Object* current = GetHeap()->allocation_sites_list(); | 12775 Object* current = GetHeap()->allocation_sites_list(); |
| 12800 while (current != NULL && current->IsAllocationSite()) { | 12776 while (current != NULL && current->IsAllocationSite()) { |
| 12801 AllocationSite* current_site = AllocationSite::cast(current); | 12777 AllocationSite* current_site = AllocationSite::cast(current); |
| 12802 if (current_site->nested_site() == this) { | 12778 if (current_site->nested_site() == this) { |
| 12803 return true; | 12779 return true; |
| 12804 } | 12780 } |
| 12805 current = current_site->weak_next(); | 12781 current = current_site->weak_next(); |
| 12806 } | 12782 } |
| 12807 return false; | 12783 return false; |
| 12808 } | 12784 } |
| 12809 | 12785 |
| 12810 | 12786 |
| 12811 MaybeObject* JSObject::UpdateAllocationSite(ElementsKind to_kind) { | 12787 MaybeObject* AllocationSite::DigestTransitionFeedback(ElementsKind to_kind) { |
| 12812 if (!FLAG_track_allocation_sites || !IsJSArray()) { | 12788 Isolate* isolate = GetIsolate(); |
| 12813 return this; | |
| 12814 } | |
| 12815 | 12789 |
| 12816 AllocationMemento* memento = AllocationMemento::FindForJSObject(this); | 12790 if (SitePointsToLiteral() && transition_info()->IsJSArray()) { |
| 12817 if (memento == NULL || !memento->IsValid()) { | 12791 JSArray* transition_info = JSArray::cast(this->transition_info()); |
| 12818 return this; | |
| 12819 } | |
| 12820 | |
| 12821 // Walk through to the Allocation Site | |
| 12822 AllocationSite* site = memento->GetAllocationSite(); | |
| 12823 if (site->SitePointsToLiteral() && | |
| 12824 site->transition_info()->IsJSArray()) { | |
| 12825 JSArray* transition_info = JSArray::cast(site->transition_info()); | |
| 12826 ElementsKind kind = transition_info->GetElementsKind(); | 12792 ElementsKind kind = transition_info->GetElementsKind(); |
| 12827 // if kind is holey ensure that to_kind is as well. | 12793 // if kind is holey ensure that to_kind is as well. |
| 12828 if (IsHoleyElementsKind(kind)) { | 12794 if (IsHoleyElementsKind(kind)) { |
| 12829 to_kind = GetHoleyElementsKind(to_kind); | 12795 to_kind = GetHoleyElementsKind(to_kind); |
| 12830 } | 12796 } |
| 12831 if (IsMoreGeneralElementsKindTransition(kind, to_kind)) { | 12797 if (IsMoreGeneralElementsKindTransition(kind, to_kind)) { |
| 12832 // If the array is huge, it's not likely to be defined in a local | 12798 // If the array is huge, it's not likely to be defined in a local |
| 12833 // function, so we shouldn't make new instances of it very often. | 12799 // function, so we shouldn't make new instances of it very often. |
| 12834 uint32_t length = 0; | 12800 uint32_t length = 0; |
| 12835 CHECK(transition_info->length()->ToArrayIndex(&length)); | 12801 CHECK(transition_info->length()->ToArrayIndex(&length)); |
| 12836 if (length <= AllocationSite::kMaximumArrayBytesToPretransition) { | 12802 if (length <= kMaximumArrayBytesToPretransition) { |
| 12837 if (FLAG_trace_track_allocation_sites) { | 12803 if (FLAG_trace_track_allocation_sites) { |
| 12838 bool is_nested = site->IsNestedSite(); | 12804 bool is_nested = IsNestedSite(); |
| 12839 PrintF( | 12805 PrintF( |
| 12840 "AllocationSite: JSArray %p boilerplate %s updated %s->%s\n", | 12806 "AllocationSite: JSArray %p boilerplate %s updated %s->%s\n", |
| 12841 reinterpret_cast<void*>(this), | 12807 reinterpret_cast<void*>(this), |
| 12842 is_nested ? "(nested)" : "", | 12808 is_nested ? "(nested)" : "", |
| 12843 ElementsKindToString(kind), | 12809 ElementsKindToString(kind), |
| 12844 ElementsKindToString(to_kind)); | 12810 ElementsKindToString(to_kind)); |
| 12845 } | 12811 } |
| 12846 return transition_info->TransitionElementsKind(to_kind); | 12812 MaybeObject* result = transition_info->TransitionElementsKind(to_kind); |
| 12813 if (result->IsFailure()) return result; |
| 12814 dependent_code()->DeoptimizeDependentCodeGroup( |
| 12815 isolate, DependentCode::kAllocationSiteTransitionChangedGroup); |
| 12847 } | 12816 } |
| 12848 } | 12817 } |
| 12849 } else { | 12818 } else { |
| 12850 ElementsKind kind = site->GetElementsKind(); | 12819 ElementsKind kind = GetElementsKind(); |
| 12851 // if kind is holey ensure that to_kind is as well. | 12820 // if kind is holey ensure that to_kind is as well. |
| 12852 if (IsHoleyElementsKind(kind)) { | 12821 if (IsHoleyElementsKind(kind)) { |
| 12853 to_kind = GetHoleyElementsKind(to_kind); | 12822 to_kind = GetHoleyElementsKind(to_kind); |
| 12854 } | 12823 } |
| 12855 if (IsMoreGeneralElementsKindTransition(kind, to_kind)) { | 12824 if (IsMoreGeneralElementsKindTransition(kind, to_kind)) { |
| 12856 if (FLAG_trace_track_allocation_sites) { | 12825 if (FLAG_trace_track_allocation_sites) { |
| 12857 PrintF("AllocationSite: JSArray %p site updated %s->%s\n", | 12826 PrintF("AllocationSite: JSArray %p site updated %s->%s\n", |
| 12858 reinterpret_cast<void*>(this), | 12827 reinterpret_cast<void*>(this), |
| 12859 ElementsKindToString(kind), | 12828 ElementsKindToString(kind), |
| 12860 ElementsKindToString(to_kind)); | 12829 ElementsKindToString(to_kind)); |
| 12861 } | 12830 } |
| 12862 site->set_transition_info(Smi::FromInt(to_kind)); | 12831 SetElementsKind(to_kind); |
| 12832 dependent_code()->DeoptimizeDependentCodeGroup( |
| 12833 isolate, DependentCode::kAllocationSiteTransitionChangedGroup); |
| 12863 } | 12834 } |
| 12864 } | 12835 } |
| 12865 return this; | 12836 return this; |
| 12866 } | 12837 } |
| 12867 | 12838 |
| 12868 | 12839 |
| 12840 void AllocationSite::AddDependentCompilationInfo(Reason reason, |
| 12841 CompilationInfo* info) { |
| 12842 DependentCode::DependencyGroup group = ToDependencyGroup(reason); |
| 12843 Handle<DependentCode> dep(dependent_code()); |
| 12844 Handle<DependentCode> codes = |
| 12845 DependentCode::Insert(dep, group, info->object_wrapper()); |
| 12846 if (*codes != dependent_code()) set_dependent_code(*codes); |
| 12847 info->dependencies(group)->Add(Handle<HeapObject>(this), info->zone()); |
| 12848 } |
| 12849 |
| 12850 |
| 12851 void AllocationSite::AddDependentCode(Reason reason, Handle<Code> code) { |
| 12852 DependentCode::DependencyGroup group = ToDependencyGroup(reason); |
| 12853 Handle<DependentCode> codes = DependentCode::Insert( |
| 12854 Handle<DependentCode>(dependent_code()), group, code); |
| 12855 if (*codes != dependent_code()) set_dependent_code(*codes); |
| 12856 } |
| 12857 |
| 12858 |
| 12859 void JSObject::UpdateAllocationSite(Handle<JSObject> object, |
| 12860 ElementsKind to_kind) { |
| 12861 CALL_HEAP_FUNCTION_VOID(object->GetIsolate(), |
| 12862 object->UpdateAllocationSite(to_kind)); |
| 12863 } |
| 12864 |
| 12865 |
| 12866 MaybeObject* JSObject::UpdateAllocationSite(ElementsKind to_kind) { |
| 12867 if (!FLAG_track_allocation_sites || !IsJSArray()) { |
| 12868 return this; |
| 12869 } |
| 12870 |
| 12871 AllocationMemento* memento = AllocationMemento::FindForJSObject(this); |
| 12872 if (memento == NULL || !memento->IsValid()) { |
| 12873 return this; |
| 12874 } |
| 12875 |
| 12876 // Walk through to the Allocation Site |
| 12877 AllocationSite* site = memento->GetAllocationSite(); |
| 12878 return site->DigestTransitionFeedback(to_kind); |
| 12879 } |
| 12880 |
| 12881 |
| 12869 MaybeObject* JSObject::TransitionElementsKind(ElementsKind to_kind) { | 12882 MaybeObject* JSObject::TransitionElementsKind(ElementsKind to_kind) { |
| 12870 ASSERT(!map()->is_observed()); | |
| 12871 ElementsKind from_kind = map()->elements_kind(); | 12883 ElementsKind from_kind = map()->elements_kind(); |
| 12872 | 12884 |
| 12873 if (IsFastHoleyElementsKind(from_kind)) { | 12885 if (IsFastHoleyElementsKind(from_kind)) { |
| 12874 to_kind = GetHoleyElementsKind(to_kind); | 12886 to_kind = GetHoleyElementsKind(to_kind); |
| 12875 } | 12887 } |
| 12876 | 12888 |
| 12877 if (from_kind == to_kind) return this; | 12889 if (from_kind == to_kind) return this; |
| 12878 // Don't update the site if to_kind isn't fast | 12890 // Don't update the site if to_kind isn't fast |
| 12879 if (IsFastElementsKind(to_kind)) { | 12891 if (IsFastElementsKind(to_kind)) { |
| 12880 MaybeObject* maybe_failure = UpdateAllocationSite(to_kind); | 12892 MaybeObject* maybe_failure = UpdateAllocationSite(to_kind); |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12948 if (!IsMoreGeneralElementsKindTransition(from_kind, to_kind)) { | 12960 if (!IsMoreGeneralElementsKindTransition(from_kind, to_kind)) { |
| 12949 return false; | 12961 return false; |
| 12950 } | 12962 } |
| 12951 | 12963 |
| 12952 // Transitions from HOLEY -> PACKED are not allowed. | 12964 // Transitions from HOLEY -> PACKED are not allowed. |
| 12953 return !IsFastHoleyElementsKind(from_kind) || | 12965 return !IsFastHoleyElementsKind(from_kind) || |
| 12954 IsFastHoleyElementsKind(to_kind); | 12966 IsFastHoleyElementsKind(to_kind); |
| 12955 } | 12967 } |
| 12956 | 12968 |
| 12957 | 12969 |
| 12970 void JSArray::JSArrayUpdateLengthFromIndex(Handle<JSArray> array, |
| 12971 uint32_t index, |
| 12972 Handle<Object> value) { |
| 12973 CALL_HEAP_FUNCTION_VOID(array->GetIsolate(), |
| 12974 array->JSArrayUpdateLengthFromIndex(index, *value)); |
| 12975 } |
| 12976 |
| 12977 |
| 12958 MaybeObject* JSArray::JSArrayUpdateLengthFromIndex(uint32_t index, | 12978 MaybeObject* JSArray::JSArrayUpdateLengthFromIndex(uint32_t index, |
| 12959 Object* value) { | 12979 Object* value) { |
| 12960 uint32_t old_len = 0; | 12980 uint32_t old_len = 0; |
| 12961 CHECK(length()->ToArrayIndex(&old_len)); | 12981 CHECK(length()->ToArrayIndex(&old_len)); |
| 12962 // Check to see if we need to update the length. For now, we make | 12982 // Check to see if we need to update the length. For now, we make |
| 12963 // sure that the length stays within 32-bits (unsigned). | 12983 // sure that the length stays within 32-bits (unsigned). |
| 12964 if (index >= old_len && index != 0xffffffff) { | 12984 if (index >= old_len && index != 0xffffffff) { |
| 12965 Object* len; | 12985 Object* len; |
| 12966 { MaybeObject* maybe_len = | 12986 { MaybeObject* maybe_len = |
| 12967 GetHeap()->NumberFromDouble(static_cast<double>(index) + 1); | 12987 GetHeap()->NumberFromDouble(static_cast<double>(index) + 1); |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 13053 // Fall through if packing is not guaranteed. | 13073 // Fall through if packing is not guaranteed. |
| 13054 case FAST_HOLEY_SMI_ELEMENTS: | 13074 case FAST_HOLEY_SMI_ELEMENTS: |
| 13055 case FAST_HOLEY_ELEMENTS: | 13075 case FAST_HOLEY_ELEMENTS: |
| 13056 backing_store = FixedArray::cast(backing_store_base); | 13076 backing_store = FixedArray::cast(backing_store_base); |
| 13057 *capacity = backing_store->length(); | 13077 *capacity = backing_store->length(); |
| 13058 for (int i = 0; i < *capacity; ++i) { | 13078 for (int i = 0; i < *capacity; ++i) { |
| 13059 if (!backing_store->get(i)->IsTheHole()) ++(*used); | 13079 if (!backing_store->get(i)->IsTheHole()) ++(*used); |
| 13060 } | 13080 } |
| 13061 break; | 13081 break; |
| 13062 case DICTIONARY_ELEMENTS: { | 13082 case DICTIONARY_ELEMENTS: { |
| 13063 SeededNumberDictionary* dictionary = | 13083 SeededNumberDictionary* dictionary = element_dictionary(); |
| 13064 SeededNumberDictionary::cast(FixedArray::cast(elements())); | |
| 13065 *capacity = dictionary->Capacity(); | 13084 *capacity = dictionary->Capacity(); |
| 13066 *used = dictionary->NumberOfElements(); | 13085 *used = dictionary->NumberOfElements(); |
| 13067 break; | 13086 break; |
| 13068 } | 13087 } |
| 13069 case FAST_DOUBLE_ELEMENTS: | 13088 case FAST_DOUBLE_ELEMENTS: |
| 13070 if (IsJSArray()) { | 13089 if (IsJSArray()) { |
| 13071 *capacity = backing_store_base->length(); | 13090 *capacity = backing_store_base->length(); |
| 13072 *used = Smi::cast(JSArray::cast(this)->length())->value(); | 13091 *used = Smi::cast(JSArray::cast(this)->length())->value(); |
| 13073 break; | 13092 break; |
| 13074 } | 13093 } |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 13153 SeededNumberDictionary::kEntrySize; | 13172 SeededNumberDictionary::kEntrySize; |
| 13154 return 2 * dictionary_size >= array_size; | 13173 return 2 * dictionary_size >= array_size; |
| 13155 } | 13174 } |
| 13156 | 13175 |
| 13157 | 13176 |
| 13158 bool JSObject::ShouldConvertToFastDoubleElements( | 13177 bool JSObject::ShouldConvertToFastDoubleElements( |
| 13159 bool* has_smi_only_elements) { | 13178 bool* has_smi_only_elements) { |
| 13160 *has_smi_only_elements = false; | 13179 *has_smi_only_elements = false; |
| 13161 if (FLAG_unbox_double_arrays) { | 13180 if (FLAG_unbox_double_arrays) { |
| 13162 ASSERT(HasDictionaryElements()); | 13181 ASSERT(HasDictionaryElements()); |
| 13163 SeededNumberDictionary* dictionary = | 13182 SeededNumberDictionary* dictionary = element_dictionary(); |
| 13164 SeededNumberDictionary::cast(elements()); | |
| 13165 bool found_double = false; | 13183 bool found_double = false; |
| 13166 for (int i = 0; i < dictionary->Capacity(); i++) { | 13184 for (int i = 0; i < dictionary->Capacity(); i++) { |
| 13167 Object* key = dictionary->KeyAt(i); | 13185 Object* key = dictionary->KeyAt(i); |
| 13168 if (key->IsNumber()) { | 13186 if (key->IsNumber()) { |
| 13169 Object* value = dictionary->ValueAt(i); | 13187 Object* value = dictionary->ValueAt(i); |
| 13170 if (!value->IsNumber()) return false; | 13188 if (!value->IsNumber()) return false; |
| 13171 if (!value->IsSmi()) { | 13189 if (!value->IsSmi()) { |
| 13172 found_double = true; | 13190 found_double = true; |
| 13173 } | 13191 } |
| 13174 } | 13192 } |
| (...skipping 1357 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 14532 isolate->factory()->NewFixedArray(dict->NumberOfElements(), tenure); | 14550 isolate->factory()->NewFixedArray(dict->NumberOfElements(), tenure); |
| 14533 dict->CopyValuesTo(*fast_elements); | 14551 dict->CopyValuesTo(*fast_elements); |
| 14534 object->ValidateElements(); | 14552 object->ValidateElements(); |
| 14535 | 14553 |
| 14536 object->set_map_and_elements(*new_map, *fast_elements); | 14554 object->set_map_and_elements(*new_map, *fast_elements); |
| 14537 } else if (object->HasExternalArrayElements()) { | 14555 } else if (object->HasExternalArrayElements()) { |
| 14538 // External arrays cannot have holes or undefined elements. | 14556 // External arrays cannot have holes or undefined elements. |
| 14539 return handle(Smi::FromInt( | 14557 return handle(Smi::FromInt( |
| 14540 ExternalArray::cast(object->elements())->length()), isolate); | 14558 ExternalArray::cast(object->elements())->length()), isolate); |
| 14541 } else if (!object->HasFastDoubleElements()) { | 14559 } else if (!object->HasFastDoubleElements()) { |
| 14542 JSObject::EnsureWritableFastElements(object); | 14560 EnsureWritableFastElements(object); |
| 14543 } | 14561 } |
| 14544 ASSERT(object->HasFastSmiOrObjectElements() || | 14562 ASSERT(object->HasFastSmiOrObjectElements() || |
| 14545 object->HasFastDoubleElements()); | 14563 object->HasFastDoubleElements()); |
| 14546 | 14564 |
| 14547 // Collect holes at the end, undefined before that and the rest at the | 14565 // Collect holes at the end, undefined before that and the rest at the |
| 14548 // start, and return the number of non-hole, non-undefined values. | 14566 // start, and return the number of non-hole, non-undefined values. |
| 14549 | 14567 |
| 14550 Handle<FixedArrayBase> elements_base(object->elements()); | 14568 Handle<FixedArrayBase> elements_base(object->elements()); |
| 14551 uint32_t elements_length = static_cast<uint32_t>(elements_base->length()); | 14569 uint32_t elements_length = static_cast<uint32_t>(elements_base->length()); |
| 14552 if (limit > elements_length) { | 14570 if (limit > elements_length) { |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 14739 // Clamp undefined to zero (default). All other types have been | 14757 // Clamp undefined to zero (default). All other types have been |
| 14740 // converted to a number type further up in the call chain. | 14758 // converted to a number type further up in the call chain. |
| 14741 ASSERT(value->IsUndefined()); | 14759 ASSERT(value->IsUndefined()); |
| 14742 } | 14760 } |
| 14743 receiver->set(index, cast_value); | 14761 receiver->set(index, cast_value); |
| 14744 } | 14762 } |
| 14745 return heap->NumberFromInt32(cast_value); | 14763 return heap->NumberFromInt32(cast_value); |
| 14746 } | 14764 } |
| 14747 | 14765 |
| 14748 | 14766 |
| 14767 Handle<Object> ExternalByteArray::SetValue(Handle<ExternalByteArray> array, |
| 14768 uint32_t index, |
| 14769 Handle<Object> value) { |
| 14770 CALL_HEAP_FUNCTION(array->GetIsolate(), |
| 14771 array->SetValue(index, *value), |
| 14772 Object); |
| 14773 } |
| 14774 |
| 14775 |
| 14749 MaybeObject* ExternalByteArray::SetValue(uint32_t index, Object* value) { | 14776 MaybeObject* ExternalByteArray::SetValue(uint32_t index, Object* value) { |
| 14750 return ExternalArrayIntSetter<ExternalByteArray, int8_t> | 14777 return ExternalArrayIntSetter<ExternalByteArray, int8_t> |
| 14751 (GetHeap(), this, index, value); | 14778 (GetHeap(), this, index, value); |
| 14752 } | 14779 } |
| 14753 | 14780 |
| 14754 | 14781 |
| 14782 Handle<Object> ExternalUnsignedByteArray::SetValue( |
| 14783 Handle<ExternalUnsignedByteArray> array, |
| 14784 uint32_t index, |
| 14785 Handle<Object> value) { |
| 14786 CALL_HEAP_FUNCTION(array->GetIsolate(), |
| 14787 array->SetValue(index, *value), |
| 14788 Object); |
| 14789 } |
| 14790 |
| 14791 |
| 14755 MaybeObject* ExternalUnsignedByteArray::SetValue(uint32_t index, | 14792 MaybeObject* ExternalUnsignedByteArray::SetValue(uint32_t index, |
| 14756 Object* value) { | 14793 Object* value) { |
| 14757 return ExternalArrayIntSetter<ExternalUnsignedByteArray, uint8_t> | 14794 return ExternalArrayIntSetter<ExternalUnsignedByteArray, uint8_t> |
| 14758 (GetHeap(), this, index, value); | 14795 (GetHeap(), this, index, value); |
| 14759 } | 14796 } |
| 14760 | 14797 |
| 14761 | 14798 |
| 14799 Handle<Object> ExternalShortArray::SetValue( |
| 14800 Handle<ExternalShortArray> array, |
| 14801 uint32_t index, |
| 14802 Handle<Object> value) { |
| 14803 CALL_HEAP_FUNCTION(array->GetIsolate(), |
| 14804 array->SetValue(index, *value), |
| 14805 Object); |
| 14806 } |
| 14807 |
| 14808 |
| 14762 MaybeObject* ExternalShortArray::SetValue(uint32_t index, | 14809 MaybeObject* ExternalShortArray::SetValue(uint32_t index, |
| 14763 Object* value) { | 14810 Object* value) { |
| 14764 return ExternalArrayIntSetter<ExternalShortArray, int16_t> | 14811 return ExternalArrayIntSetter<ExternalShortArray, int16_t> |
| 14765 (GetHeap(), this, index, value); | 14812 (GetHeap(), this, index, value); |
| 14766 } | 14813 } |
| 14767 | 14814 |
| 14768 | 14815 |
| 14816 Handle<Object> ExternalUnsignedShortArray::SetValue( |
| 14817 Handle<ExternalUnsignedShortArray> array, |
| 14818 uint32_t index, |
| 14819 Handle<Object> value) { |
| 14820 CALL_HEAP_FUNCTION(array->GetIsolate(), |
| 14821 array->SetValue(index, *value), |
| 14822 Object); |
| 14823 } |
| 14824 |
| 14825 |
| 14769 MaybeObject* ExternalUnsignedShortArray::SetValue(uint32_t index, | 14826 MaybeObject* ExternalUnsignedShortArray::SetValue(uint32_t index, |
| 14770 Object* value) { | 14827 Object* value) { |
| 14771 return ExternalArrayIntSetter<ExternalUnsignedShortArray, uint16_t> | 14828 return ExternalArrayIntSetter<ExternalUnsignedShortArray, uint16_t> |
| 14772 (GetHeap(), this, index, value); | 14829 (GetHeap(), this, index, value); |
| 14773 } | 14830 } |
| 14774 | 14831 |
| 14775 | 14832 |
| 14833 Handle<Object> ExternalIntArray::SetValue(Handle<ExternalIntArray> array, |
| 14834 uint32_t index, |
| 14835 Handle<Object> value) { |
| 14836 CALL_HEAP_FUNCTION(array->GetIsolate(), |
| 14837 array->SetValue(index, *value), |
| 14838 Object); |
| 14839 } |
| 14840 |
| 14841 |
| 14776 MaybeObject* ExternalIntArray::SetValue(uint32_t index, Object* value) { | 14842 MaybeObject* ExternalIntArray::SetValue(uint32_t index, Object* value) { |
| 14777 return ExternalArrayIntSetter<ExternalIntArray, int32_t> | 14843 return ExternalArrayIntSetter<ExternalIntArray, int32_t> |
| 14778 (GetHeap(), this, index, value); | 14844 (GetHeap(), this, index, value); |
| 14779 } | 14845 } |
| 14780 | 14846 |
| 14781 | 14847 |
| 14848 Handle<Object> ExternalUnsignedIntArray::SetValue( |
| 14849 Handle<ExternalUnsignedIntArray> array, |
| 14850 uint32_t index, |
| 14851 Handle<Object> value) { |
| 14852 CALL_HEAP_FUNCTION(array->GetIsolate(), |
| 14853 array->SetValue(index, *value), |
| 14854 Object); |
| 14855 } |
| 14856 |
| 14857 |
| 14782 MaybeObject* ExternalUnsignedIntArray::SetValue(uint32_t index, Object* value) { | 14858 MaybeObject* ExternalUnsignedIntArray::SetValue(uint32_t index, Object* value) { |
| 14783 uint32_t cast_value = 0; | 14859 uint32_t cast_value = 0; |
| 14784 Heap* heap = GetHeap(); | 14860 Heap* heap = GetHeap(); |
| 14785 if (index < static_cast<uint32_t>(length())) { | 14861 if (index < static_cast<uint32_t>(length())) { |
| 14786 if (value->IsSmi()) { | 14862 if (value->IsSmi()) { |
| 14787 int int_value = Smi::cast(value)->value(); | 14863 int int_value = Smi::cast(value)->value(); |
| 14788 cast_value = static_cast<uint32_t>(int_value); | 14864 cast_value = static_cast<uint32_t>(int_value); |
| 14789 } else if (value->IsHeapNumber()) { | 14865 } else if (value->IsHeapNumber()) { |
| 14790 double double_value = HeapNumber::cast(value)->value(); | 14866 double double_value = HeapNumber::cast(value)->value(); |
| 14791 cast_value = static_cast<uint32_t>(DoubleToUint32(double_value)); | 14867 cast_value = static_cast<uint32_t>(DoubleToUint32(double_value)); |
| 14792 } else { | 14868 } else { |
| 14793 // Clamp undefined to zero (default). All other types have been | 14869 // Clamp undefined to zero (default). All other types have been |
| 14794 // converted to a number type further up in the call chain. | 14870 // converted to a number type further up in the call chain. |
| 14795 ASSERT(value->IsUndefined()); | 14871 ASSERT(value->IsUndefined()); |
| 14796 } | 14872 } |
| 14797 set(index, cast_value); | 14873 set(index, cast_value); |
| 14798 } | 14874 } |
| 14799 return heap->NumberFromUint32(cast_value); | 14875 return heap->NumberFromUint32(cast_value); |
| 14800 } | 14876 } |
| 14801 | 14877 |
| 14802 | 14878 |
| 14879 Handle<Object> ExternalFloatArray::SetValue(Handle<ExternalFloatArray> array, |
| 14880 uint32_t index, |
| 14881 Handle<Object> value) { |
| 14882 CALL_HEAP_FUNCTION(array->GetIsolate(), |
| 14883 array->SetValue(index, *value), |
| 14884 Object); |
| 14885 } |
| 14886 |
| 14887 |
| 14803 MaybeObject* ExternalFloatArray::SetValue(uint32_t index, Object* value) { | 14888 MaybeObject* ExternalFloatArray::SetValue(uint32_t index, Object* value) { |
| 14804 float cast_value = static_cast<float>(OS::nan_value()); | 14889 float cast_value = static_cast<float>(OS::nan_value()); |
| 14805 Heap* heap = GetHeap(); | 14890 Heap* heap = GetHeap(); |
| 14806 if (index < static_cast<uint32_t>(length())) { | 14891 if (index < static_cast<uint32_t>(length())) { |
| 14807 if (value->IsSmi()) { | 14892 if (value->IsSmi()) { |
| 14808 int int_value = Smi::cast(value)->value(); | 14893 int int_value = Smi::cast(value)->value(); |
| 14809 cast_value = static_cast<float>(int_value); | 14894 cast_value = static_cast<float>(int_value); |
| 14810 } else if (value->IsHeapNumber()) { | 14895 } else if (value->IsHeapNumber()) { |
| 14811 double double_value = HeapNumber::cast(value)->value(); | 14896 double double_value = HeapNumber::cast(value)->value(); |
| 14812 cast_value = static_cast<float>(double_value); | 14897 cast_value = static_cast<float>(double_value); |
| 14813 } else { | 14898 } else { |
| 14814 // Clamp undefined to NaN (default). All other types have been | 14899 // Clamp undefined to NaN (default). All other types have been |
| 14815 // converted to a number type further up in the call chain. | 14900 // converted to a number type further up in the call chain. |
| 14816 ASSERT(value->IsUndefined()); | 14901 ASSERT(value->IsUndefined()); |
| 14817 } | 14902 } |
| 14818 set(index, cast_value); | 14903 set(index, cast_value); |
| 14819 } | 14904 } |
| 14820 return heap->AllocateHeapNumber(cast_value); | 14905 return heap->AllocateHeapNumber(cast_value); |
| 14821 } | 14906 } |
| 14822 | 14907 |
| 14823 | 14908 |
| 14909 Handle<Object> ExternalDoubleArray::SetValue(Handle<ExternalDoubleArray> array, |
| 14910 uint32_t index, |
| 14911 Handle<Object> value) { |
| 14912 CALL_HEAP_FUNCTION(array->GetIsolate(), |
| 14913 array->SetValue(index, *value), |
| 14914 Object); |
| 14915 } |
| 14916 |
| 14917 |
| 14824 MaybeObject* ExternalDoubleArray::SetValue(uint32_t index, Object* value) { | 14918 MaybeObject* ExternalDoubleArray::SetValue(uint32_t index, Object* value) { |
| 14825 double double_value = OS::nan_value(); | 14919 double double_value = OS::nan_value(); |
| 14826 Heap* heap = GetHeap(); | 14920 Heap* heap = GetHeap(); |
| 14827 if (index < static_cast<uint32_t>(length())) { | 14921 if (index < static_cast<uint32_t>(length())) { |
| 14828 if (value->IsSmi()) { | 14922 if (value->IsSmi()) { |
| 14829 int int_value = Smi::cast(value)->value(); | 14923 int int_value = Smi::cast(value)->value(); |
| 14830 double_value = static_cast<double>(int_value); | 14924 double_value = static_cast<double>(int_value); |
| 14831 } else if (value->IsHeapNumber()) { | 14925 } else if (value->IsHeapNumber()) { |
| 14832 double_value = HeapNumber::cast(value)->value(); | 14926 double_value = HeapNumber::cast(value)->value(); |
| 14833 } else { | 14927 } else { |
| (...skipping 601 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 15435 return; | 15529 return; |
| 15436 } | 15530 } |
| 15437 // Update max key value. | 15531 // Update max key value. |
| 15438 Object* max_index_object = get(kMaxNumberKeyIndex); | 15532 Object* max_index_object = get(kMaxNumberKeyIndex); |
| 15439 if (!max_index_object->IsSmi() || max_number_key() < key) { | 15533 if (!max_index_object->IsSmi() || max_number_key() < key) { |
| 15440 FixedArray::set(kMaxNumberKeyIndex, | 15534 FixedArray::set(kMaxNumberKeyIndex, |
| 15441 Smi::FromInt(key << kRequiresSlowElementsTagSize)); | 15535 Smi::FromInt(key << kRequiresSlowElementsTagSize)); |
| 15442 } | 15536 } |
| 15443 } | 15537 } |
| 15444 | 15538 |
| 15539 Handle<SeededNumberDictionary> SeededNumberDictionary::AddNumberEntry( |
| 15540 Handle<SeededNumberDictionary> dictionary, |
| 15541 uint32_t key, |
| 15542 Handle<Object> value, |
| 15543 PropertyDetails details) { |
| 15544 CALL_HEAP_FUNCTION(dictionary->GetIsolate(), |
| 15545 dictionary->AddNumberEntry(key, *value, details), |
| 15546 SeededNumberDictionary); |
| 15547 } |
| 15445 | 15548 |
| 15446 MaybeObject* SeededNumberDictionary::AddNumberEntry(uint32_t key, | 15549 MaybeObject* SeededNumberDictionary::AddNumberEntry(uint32_t key, |
| 15447 Object* value, | 15550 Object* value, |
| 15448 PropertyDetails details) { | 15551 PropertyDetails details) { |
| 15449 UpdateMaxNumberKey(key); | 15552 UpdateMaxNumberKey(key); |
| 15450 SLOW_ASSERT(this->FindEntry(key) == kNotFound); | 15553 SLOW_ASSERT(this->FindEntry(key) == kNotFound); |
| 15451 return Add(key, value, details); | 15554 return Add(key, value, details); |
| 15452 } | 15555 } |
| 15453 | 15556 |
| 15454 | 15557 |
| (...skipping 1075 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 16530 #define ERROR_MESSAGES_TEXTS(C, T) T, | 16633 #define ERROR_MESSAGES_TEXTS(C, T) T, |
| 16531 static const char* error_messages_[] = { | 16634 static const char* error_messages_[] = { |
| 16532 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) | 16635 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) |
| 16533 }; | 16636 }; |
| 16534 #undef ERROR_MESSAGES_TEXTS | 16637 #undef ERROR_MESSAGES_TEXTS |
| 16535 return error_messages_[reason]; | 16638 return error_messages_[reason]; |
| 16536 } | 16639 } |
| 16537 | 16640 |
| 16538 | 16641 |
| 16539 } } // namespace v8::internal | 16642 } } // namespace v8::internal |
| OLD | NEW |