OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 6777 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6788 // Handle [] on String objects. | 6788 // Handle [] on String objects. |
6789 if (this->IsStringObjectWithCharacterAt(index)) return true; | 6789 if (this->IsStringObjectWithCharacterAt(index)) return true; |
6790 | 6790 |
6791 Object* pt = GetPrototype(); | 6791 Object* pt = GetPrototype(); |
6792 if (pt == Heap::null_value()) return false; | 6792 if (pt == Heap::null_value()) return false; |
6793 return JSObject::cast(pt)->HasElementWithReceiver(receiver, index); | 6793 return JSObject::cast(pt)->HasElementWithReceiver(receiver, index); |
6794 } | 6794 } |
6795 | 6795 |
6796 | 6796 |
6797 MaybeObject* JSObject::SetElementWithInterceptor(uint32_t index, | 6797 MaybeObject* JSObject::SetElementWithInterceptor(uint32_t index, |
6798 Object* value) { | 6798 Object* value, |
| 6799 bool own) { |
6799 // Make sure that the top context does not change when doing | 6800 // Make sure that the top context does not change when doing |
6800 // callbacks or interceptor calls. | 6801 // callbacks or interceptor calls. |
6801 AssertNoContextChange ncc; | 6802 AssertNoContextChange ncc; |
6802 HandleScope scope; | 6803 HandleScope scope; |
6803 Handle<InterceptorInfo> interceptor(GetIndexedInterceptor()); | 6804 Handle<InterceptorInfo> interceptor(GetIndexedInterceptor()); |
6804 Handle<JSObject> this_handle(this); | 6805 Handle<JSObject> this_handle(this); |
6805 Handle<Object> value_handle(value); | 6806 Handle<Object> value_handle(value); |
6806 if (!interceptor->setter()->IsUndefined()) { | 6807 if (!interceptor->setter()->IsUndefined()) { |
6807 v8::IndexedPropertySetter setter = | 6808 v8::IndexedPropertySetter setter = |
6808 v8::ToCData<v8::IndexedPropertySetter>(interceptor->setter()); | 6809 v8::ToCData<v8::IndexedPropertySetter>(interceptor->setter()); |
6809 LOG(ApiIndexedPropertyAccess("interceptor-indexed-set", this, index)); | 6810 LOG(ApiIndexedPropertyAccess("interceptor-indexed-set", this, index)); |
6810 CustomArguments args(interceptor->data(), this, this); | 6811 CustomArguments args(interceptor->data(), this, this); |
6811 v8::AccessorInfo info(args.end()); | 6812 v8::AccessorInfo info(args.end()); |
6812 v8::Handle<v8::Value> result; | 6813 v8::Handle<v8::Value> result; |
6813 { | 6814 { |
6814 // Leaving JavaScript. | 6815 // Leaving JavaScript. |
6815 VMState state(EXTERNAL); | 6816 VMState state(EXTERNAL); |
6816 result = setter(index, v8::Utils::ToLocal(value_handle), info); | 6817 result = setter(index, v8::Utils::ToLocal(value_handle), info); |
6817 } | 6818 } |
6818 RETURN_IF_SCHEDULED_EXCEPTION(); | 6819 RETURN_IF_SCHEDULED_EXCEPTION(); |
6819 if (!result.IsEmpty()) return *value_handle; | 6820 if (!result.IsEmpty()) return *value_handle; |
6820 } | 6821 } |
6821 MaybeObject* raw_result = | 6822 MaybeObject* raw_result = |
6822 this_handle->SetElementWithoutInterceptor(index, *value_handle); | 6823 this_handle->SetElementWithoutInterceptor(index, *value_handle, own); |
6823 RETURN_IF_SCHEDULED_EXCEPTION(); | 6824 RETURN_IF_SCHEDULED_EXCEPTION(); |
6824 return raw_result; | 6825 return raw_result; |
6825 } | 6826 } |
6826 | 6827 |
6827 | 6828 |
6828 MaybeObject* JSObject::GetElementWithCallback(Object* receiver, | 6829 MaybeObject* JSObject::GetElementWithCallback(Object* receiver, |
6829 Object* structure, | 6830 Object* structure, |
6830 uint32_t index, | 6831 uint32_t index, |
6831 Object* holder) { | 6832 Object* holder) { |
6832 ASSERT(!structure->IsProxy()); | 6833 ASSERT(!structure->IsProxy()); |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6923 } | 6924 } |
6924 | 6925 |
6925 UNREACHABLE(); | 6926 UNREACHABLE(); |
6926 return NULL; | 6927 return NULL; |
6927 } | 6928 } |
6928 | 6929 |
6929 | 6930 |
6930 // Adding n elements in fast case is O(n*n). | 6931 // Adding n elements in fast case is O(n*n). |
6931 // Note: revisit design to have dual undefined values to capture absent | 6932 // Note: revisit design to have dual undefined values to capture absent |
6932 // elements. | 6933 // elements. |
6933 MaybeObject* JSObject::SetFastElement(uint32_t index, Object* value) { | 6934 MaybeObject* JSObject::SetFastElement(uint32_t index, Object* value, bool own) { |
6934 ASSERT(HasFastElements()); | 6935 ASSERT(HasFastElements()); |
6935 | 6936 |
6936 Object* elms_obj; | 6937 Object* elms_obj; |
6937 { MaybeObject* maybe_elms_obj = EnsureWritableFastElements(); | 6938 { MaybeObject* maybe_elms_obj = EnsureWritableFastElements(); |
6938 if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj; | 6939 if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj; |
6939 } | 6940 } |
6940 FixedArray* elms = FixedArray::cast(elms_obj); | 6941 FixedArray* elms = FixedArray::cast(elms_obj); |
6941 uint32_t elms_length = static_cast<uint32_t>(elms->length()); | 6942 uint32_t elms_length = static_cast<uint32_t>(elms->length()); |
6942 | 6943 |
6943 if (!IsJSArray() && (index >= elms_length || elms->get(index)->IsTheHole())) { | 6944 if (!own && !IsJSArray() && |
| 6945 (index >= elms_length || elms->get(index)->IsTheHole())) { |
6944 if (SetElementWithCallbackSetterInPrototypes(index, value)) { | 6946 if (SetElementWithCallbackSetterInPrototypes(index, value)) { |
6945 return value; | 6947 return value; |
6946 } | 6948 } |
6947 } | 6949 } |
6948 | 6950 |
6949 // Check whether there is extra space in fixed array.. | 6951 // Check whether there is extra space in fixed array.. |
6950 if (index < elms_length) { | 6952 if (index < elms_length) { |
6951 elms->set(index, value); | 6953 elms->set(index, value); |
6952 if (IsJSArray()) { | 6954 if (IsJSArray()) { |
6953 // Update the length of the array if needed. | 6955 // Update the length of the array if needed. |
(...skipping 22 matching lines...) Expand all Loading... |
6976 return value; | 6978 return value; |
6977 } | 6979 } |
6978 } | 6980 } |
6979 | 6981 |
6980 // Otherwise default to slow case. | 6982 // Otherwise default to slow case. |
6981 Object* obj; | 6983 Object* obj; |
6982 { MaybeObject* maybe_obj = NormalizeElements(); | 6984 { MaybeObject* maybe_obj = NormalizeElements(); |
6983 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 6985 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
6984 } | 6986 } |
6985 ASSERT(HasDictionaryElements()); | 6987 ASSERT(HasDictionaryElements()); |
6986 return SetElement(index, value); | 6988 return SetElement(index, value, own); |
6987 } | 6989 } |
6988 | 6990 |
6989 | 6991 |
6990 MaybeObject* JSObject::SetElement(uint32_t index, Object* value) { | 6992 MaybeObject* JSObject::SetElement(uint32_t index, Object* value, bool own) { |
6991 // Check access rights if needed. | 6993 // Check access rights if needed. |
6992 if (IsAccessCheckNeeded() && | 6994 if (IsAccessCheckNeeded() && |
6993 !Top::MayIndexedAccess(this, index, v8::ACCESS_SET)) { | 6995 !Top::MayIndexedAccess(this, index, v8::ACCESS_SET)) { |
6994 HandleScope scope; | 6996 HandleScope scope; |
6995 Handle<Object> value_handle(value); | 6997 Handle<Object> value_handle(value); |
6996 Top::ReportFailedAccessCheck(this, v8::ACCESS_SET); | 6998 Top::ReportFailedAccessCheck(this, v8::ACCESS_SET); |
6997 return *value_handle; | 6999 return *value_handle; |
6998 } | 7000 } |
6999 | 7001 |
7000 if (IsJSGlobalProxy()) { | 7002 if (IsJSGlobalProxy()) { |
7001 Object* proto = GetPrototype(); | 7003 Object* proto = GetPrototype(); |
7002 if (proto->IsNull()) return value; | 7004 if (proto->IsNull()) return value; |
7003 ASSERT(proto->IsJSGlobalObject()); | 7005 ASSERT(proto->IsJSGlobalObject()); |
7004 return JSObject::cast(proto)->SetElement(index, value); | 7006 return JSObject::cast(proto)->SetElement(index, value, own); |
7005 } | 7007 } |
7006 | 7008 |
7007 // Check for lookup interceptor | 7009 // Check for lookup interceptor |
7008 if (HasIndexedInterceptor()) { | 7010 if (HasIndexedInterceptor()) { |
7009 return SetElementWithInterceptor(index, value); | 7011 return SetElementWithInterceptor(index, value, own); |
7010 } | 7012 } |
7011 | 7013 |
7012 return SetElementWithoutInterceptor(index, value); | 7014 return SetElementWithoutInterceptor(index, value, own); |
7013 } | 7015 } |
7014 | 7016 |
7015 | 7017 |
7016 MaybeObject* JSObject::SetElementWithoutInterceptor(uint32_t index, | 7018 MaybeObject* JSObject::SetElementWithoutInterceptor(uint32_t index, |
7017 Object* value) { | 7019 Object* value, |
| 7020 bool own) { |
7018 switch (GetElementsKind()) { | 7021 switch (GetElementsKind()) { |
7019 case FAST_ELEMENTS: | 7022 case FAST_ELEMENTS: |
7020 // Fast case. | 7023 // Fast case. |
7021 return SetFastElement(index, value); | 7024 return SetFastElement(index, value, own); |
7022 case PIXEL_ELEMENTS: { | 7025 case PIXEL_ELEMENTS: { |
7023 PixelArray* pixels = PixelArray::cast(elements()); | 7026 PixelArray* pixels = PixelArray::cast(elements()); |
7024 return pixels->SetValue(index, value); | 7027 return pixels->SetValue(index, value); |
7025 } | 7028 } |
7026 case EXTERNAL_BYTE_ELEMENTS: { | 7029 case EXTERNAL_BYTE_ELEMENTS: { |
7027 ExternalByteArray* array = ExternalByteArray::cast(elements()); | 7030 ExternalByteArray* array = ExternalByteArray::cast(elements()); |
7028 return array->SetValue(index, value); | 7031 return array->SetValue(index, value); |
7029 } | 7032 } |
7030 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: { | 7033 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: { |
7031 ExternalUnsignedByteArray* array = | 7034 ExternalUnsignedByteArray* array = |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7064 Object* element = dictionary->ValueAt(entry); | 7067 Object* element = dictionary->ValueAt(entry); |
7065 PropertyDetails details = dictionary->DetailsAt(entry); | 7068 PropertyDetails details = dictionary->DetailsAt(entry); |
7066 if (details.type() == CALLBACKS) { | 7069 if (details.type() == CALLBACKS) { |
7067 return SetElementWithCallback(element, index, value, this); | 7070 return SetElementWithCallback(element, index, value, this); |
7068 } else { | 7071 } else { |
7069 dictionary->UpdateMaxNumberKey(index); | 7072 dictionary->UpdateMaxNumberKey(index); |
7070 dictionary->ValueAtPut(entry, value); | 7073 dictionary->ValueAtPut(entry, value); |
7071 } | 7074 } |
7072 } else { | 7075 } else { |
7073 // Index not already used. Look for an accessor in the prototype chain. | 7076 // Index not already used. Look for an accessor in the prototype chain. |
7074 if (!IsJSArray()) { | 7077 if (!own && !IsJSArray() && |
7075 if (SetElementWithCallbackSetterInPrototypes(index, value)) { | 7078 SetElementWithCallbackSetterInPrototypes(index, value)) { |
7076 return value; | 7079 return value; |
7077 } | |
7078 } | 7080 } |
7079 // When we set the is_extensible flag to false we always force | 7081 // When we set the is_extensible flag to false we always force |
7080 // the element into dictionary mode (and force them to stay there). | 7082 // the element into dictionary mode (and force them to stay there). |
7081 if (!map()->is_extensible()) { | 7083 if (!map()->is_extensible()) { |
7082 Handle<Object> number(Factory::NewNumberFromUint(index)); | 7084 Handle<Object> number(Factory::NewNumberFromUint(index)); |
7083 Handle<String> index_string(Factory::NumberToString(number)); | 7085 Handle<String> index_string(Factory::NumberToString(number)); |
7084 Handle<Object> args[1] = { index_string }; | 7086 Handle<Object> args[1] = { index_string }; |
7085 return Top::Throw(*Factory::NewTypeError("object_not_extensible", | 7087 return Top::Throw(*Factory::NewTypeError("object_not_extensible", |
7086 HandleVector(args, 1))); | 7088 HandleVector(args, 1))); |
7087 } | 7089 } |
(...skipping 2771 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9859 if (break_point_objects()->IsUndefined()) return 0; | 9861 if (break_point_objects()->IsUndefined()) return 0; |
9860 // Single beak point. | 9862 // Single beak point. |
9861 if (!break_point_objects()->IsFixedArray()) return 1; | 9863 if (!break_point_objects()->IsFixedArray()) return 1; |
9862 // Multiple break points. | 9864 // Multiple break points. |
9863 return FixedArray::cast(break_point_objects())->length(); | 9865 return FixedArray::cast(break_point_objects())->length(); |
9864 } | 9866 } |
9865 #endif | 9867 #endif |
9866 | 9868 |
9867 | 9869 |
9868 } } // namespace v8::internal | 9870 } } // namespace v8::internal |
OLD | NEW |