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 check_prototype) { |
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, |
| 6824 *value_handle, |
| 6825 check_prototype); |
6823 RETURN_IF_SCHEDULED_EXCEPTION(); | 6826 RETURN_IF_SCHEDULED_EXCEPTION(); |
6824 return raw_result; | 6827 return raw_result; |
6825 } | 6828 } |
6826 | 6829 |
6827 | 6830 |
6828 MaybeObject* JSObject::GetElementWithCallback(Object* receiver, | 6831 MaybeObject* JSObject::GetElementWithCallback(Object* receiver, |
6829 Object* structure, | 6832 Object* structure, |
6830 uint32_t index, | 6833 uint32_t index, |
6831 Object* holder) { | 6834 Object* holder) { |
6832 ASSERT(!structure->IsProxy()); | 6835 ASSERT(!structure->IsProxy()); |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6923 } | 6926 } |
6924 | 6927 |
6925 UNREACHABLE(); | 6928 UNREACHABLE(); |
6926 return NULL; | 6929 return NULL; |
6927 } | 6930 } |
6928 | 6931 |
6929 | 6932 |
6930 // Adding n elements in fast case is O(n*n). | 6933 // Adding n elements in fast case is O(n*n). |
6931 // Note: revisit design to have dual undefined values to capture absent | 6934 // Note: revisit design to have dual undefined values to capture absent |
6932 // elements. | 6935 // elements. |
6933 MaybeObject* JSObject::SetFastElement(uint32_t index, Object* value) { | 6936 MaybeObject* JSObject::SetFastElement(uint32_t index, |
| 6937 Object* value, |
| 6938 bool check_prototype) { |
6934 ASSERT(HasFastElements()); | 6939 ASSERT(HasFastElements()); |
6935 | 6940 |
6936 Object* elms_obj; | 6941 Object* elms_obj; |
6937 { MaybeObject* maybe_elms_obj = EnsureWritableFastElements(); | 6942 { MaybeObject* maybe_elms_obj = EnsureWritableFastElements(); |
6938 if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj; | 6943 if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj; |
6939 } | 6944 } |
6940 FixedArray* elms = FixedArray::cast(elms_obj); | 6945 FixedArray* elms = FixedArray::cast(elms_obj); |
6941 uint32_t elms_length = static_cast<uint32_t>(elms->length()); | 6946 uint32_t elms_length = static_cast<uint32_t>(elms->length()); |
6942 | 6947 |
6943 if (!IsJSArray() && (index >= elms_length || elms->get(index)->IsTheHole())) { | 6948 if (check_prototype && !IsJSArray() && |
| 6949 (index >= elms_length || elms->get(index)->IsTheHole())) { |
6944 if (SetElementWithCallbackSetterInPrototypes(index, value)) { | 6950 if (SetElementWithCallbackSetterInPrototypes(index, value)) { |
6945 return value; | 6951 return value; |
6946 } | 6952 } |
6947 } | 6953 } |
6948 | 6954 |
6949 // Check whether there is extra space in fixed array.. | 6955 // Check whether there is extra space in fixed array.. |
6950 if (index < elms_length) { | 6956 if (index < elms_length) { |
6951 elms->set(index, value); | 6957 elms->set(index, value); |
6952 if (IsJSArray()) { | 6958 if (IsJSArray()) { |
6953 // Update the length of the array if needed. | 6959 // Update the length of the array if needed. |
(...skipping 22 matching lines...) Expand all Loading... |
6976 return value; | 6982 return value; |
6977 } | 6983 } |
6978 } | 6984 } |
6979 | 6985 |
6980 // Otherwise default to slow case. | 6986 // Otherwise default to slow case. |
6981 Object* obj; | 6987 Object* obj; |
6982 { MaybeObject* maybe_obj = NormalizeElements(); | 6988 { MaybeObject* maybe_obj = NormalizeElements(); |
6983 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 6989 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
6984 } | 6990 } |
6985 ASSERT(HasDictionaryElements()); | 6991 ASSERT(HasDictionaryElements()); |
6986 return SetElement(index, value); | 6992 return SetElement(index, value, check_prototype); |
6987 } | 6993 } |
6988 | 6994 |
6989 | 6995 |
6990 MaybeObject* JSObject::SetElement(uint32_t index, Object* value) { | 6996 MaybeObject* JSObject::SetElement(uint32_t index, |
| 6997 Object* value, |
| 6998 bool check_prototype) { |
6991 // Check access rights if needed. | 6999 // Check access rights if needed. |
6992 if (IsAccessCheckNeeded() && | 7000 if (IsAccessCheckNeeded() && |
6993 !Top::MayIndexedAccess(this, index, v8::ACCESS_SET)) { | 7001 !Top::MayIndexedAccess(this, index, v8::ACCESS_SET)) { |
6994 HandleScope scope; | 7002 HandleScope scope; |
6995 Handle<Object> value_handle(value); | 7003 Handle<Object> value_handle(value); |
6996 Top::ReportFailedAccessCheck(this, v8::ACCESS_SET); | 7004 Top::ReportFailedAccessCheck(this, v8::ACCESS_SET); |
6997 return *value_handle; | 7005 return *value_handle; |
6998 } | 7006 } |
6999 | 7007 |
7000 if (IsJSGlobalProxy()) { | 7008 if (IsJSGlobalProxy()) { |
7001 Object* proto = GetPrototype(); | 7009 Object* proto = GetPrototype(); |
7002 if (proto->IsNull()) return value; | 7010 if (proto->IsNull()) return value; |
7003 ASSERT(proto->IsJSGlobalObject()); | 7011 ASSERT(proto->IsJSGlobalObject()); |
7004 return JSObject::cast(proto)->SetElement(index, value); | 7012 return JSObject::cast(proto)->SetElement(index, value, check_prototype); |
7005 } | 7013 } |
7006 | 7014 |
7007 // Check for lookup interceptor | 7015 // Check for lookup interceptor |
7008 if (HasIndexedInterceptor()) { | 7016 if (HasIndexedInterceptor()) { |
7009 return SetElementWithInterceptor(index, value); | 7017 return SetElementWithInterceptor(index, value, check_prototype); |
7010 } | 7018 } |
7011 | 7019 |
7012 return SetElementWithoutInterceptor(index, value); | 7020 return SetElementWithoutInterceptor(index, value, check_prototype); |
7013 } | 7021 } |
7014 | 7022 |
7015 | 7023 |
7016 MaybeObject* JSObject::SetElementWithoutInterceptor(uint32_t index, | 7024 MaybeObject* JSObject::SetElementWithoutInterceptor(uint32_t index, |
7017 Object* value) { | 7025 Object* value, |
| 7026 bool check_prototype) { |
7018 switch (GetElementsKind()) { | 7027 switch (GetElementsKind()) { |
7019 case FAST_ELEMENTS: | 7028 case FAST_ELEMENTS: |
7020 // Fast case. | 7029 // Fast case. |
7021 return SetFastElement(index, value); | 7030 return SetFastElement(index, value, check_prototype); |
7022 case PIXEL_ELEMENTS: { | 7031 case PIXEL_ELEMENTS: { |
7023 PixelArray* pixels = PixelArray::cast(elements()); | 7032 PixelArray* pixels = PixelArray::cast(elements()); |
7024 return pixels->SetValue(index, value); | 7033 return pixels->SetValue(index, value); |
7025 } | 7034 } |
7026 case EXTERNAL_BYTE_ELEMENTS: { | 7035 case EXTERNAL_BYTE_ELEMENTS: { |
7027 ExternalByteArray* array = ExternalByteArray::cast(elements()); | 7036 ExternalByteArray* array = ExternalByteArray::cast(elements()); |
7028 return array->SetValue(index, value); | 7037 return array->SetValue(index, value); |
7029 } | 7038 } |
7030 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: { | 7039 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: { |
7031 ExternalUnsignedByteArray* array = | 7040 ExternalUnsignedByteArray* array = |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7064 Object* element = dictionary->ValueAt(entry); | 7073 Object* element = dictionary->ValueAt(entry); |
7065 PropertyDetails details = dictionary->DetailsAt(entry); | 7074 PropertyDetails details = dictionary->DetailsAt(entry); |
7066 if (details.type() == CALLBACKS) { | 7075 if (details.type() == CALLBACKS) { |
7067 return SetElementWithCallback(element, index, value, this); | 7076 return SetElementWithCallback(element, index, value, this); |
7068 } else { | 7077 } else { |
7069 dictionary->UpdateMaxNumberKey(index); | 7078 dictionary->UpdateMaxNumberKey(index); |
7070 dictionary->ValueAtPut(entry, value); | 7079 dictionary->ValueAtPut(entry, value); |
7071 } | 7080 } |
7072 } else { | 7081 } else { |
7073 // Index not already used. Look for an accessor in the prototype chain. | 7082 // Index not already used. Look for an accessor in the prototype chain. |
7074 if (!IsJSArray()) { | 7083 if (check_prototype && !IsJSArray() && |
7075 if (SetElementWithCallbackSetterInPrototypes(index, value)) { | 7084 SetElementWithCallbackSetterInPrototypes(index, value)) { |
7076 return value; | 7085 return value; |
7077 } | |
7078 } | 7086 } |
7079 // When we set the is_extensible flag to false we always force | 7087 // When we set the is_extensible flag to false we always force |
7080 // the element into dictionary mode (and force them to stay there). | 7088 // the element into dictionary mode (and force them to stay there). |
7081 if (!map()->is_extensible()) { | 7089 if (!map()->is_extensible()) { |
7082 Handle<Object> number(Factory::NewNumberFromUint(index)); | 7090 Handle<Object> number(Factory::NewNumberFromUint(index)); |
7083 Handle<String> index_string(Factory::NumberToString(number)); | 7091 Handle<String> index_string(Factory::NumberToString(number)); |
7084 Handle<Object> args[1] = { index_string }; | 7092 Handle<Object> args[1] = { index_string }; |
7085 return Top::Throw(*Factory::NewTypeError("object_not_extensible", | 7093 return Top::Throw(*Factory::NewTypeError("object_not_extensible", |
7086 HandleVector(args, 1))); | 7094 HandleVector(args, 1))); |
7087 } | 7095 } |
(...skipping 2771 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9859 if (break_point_objects()->IsUndefined()) return 0; | 9867 if (break_point_objects()->IsUndefined()) return 0; |
9860 // Single beak point. | 9868 // Single beak point. |
9861 if (!break_point_objects()->IsFixedArray()) return 1; | 9869 if (!break_point_objects()->IsFixedArray()) return 1; |
9862 // Multiple break points. | 9870 // Multiple break points. |
9863 return FixedArray::cast(break_point_objects())->length(); | 9871 return FixedArray::cast(break_point_objects())->length(); |
9864 } | 9872 } |
9865 #endif | 9873 #endif |
9866 | 9874 |
9867 | 9875 |
9868 } } // namespace v8::internal | 9876 } } // namespace v8::internal |
OLD | NEW |