| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 8899 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8910 EnsureElementsMode mode) { | 8910 EnsureElementsMode mode) { |
| 8911 // Elements in |Arguments| are ordered backwards (because they're on the | 8911 // Elements in |Arguments| are ordered backwards (because they're on the |
| 8912 // stack), but the method that's called here iterates over them in forward | 8912 // stack), but the method that's called here iterates over them in forward |
| 8913 // direction. | 8913 // direction. |
| 8914 return EnsureCanContainElements( | 8914 return EnsureCanContainElements( |
| 8915 args->arguments() - first_arg - (arg_count - 1), | 8915 args->arguments() - first_arg - (arg_count - 1), |
| 8916 arg_count, mode); | 8916 arg_count, mode); |
| 8917 } | 8917 } |
| 8918 | 8918 |
| 8919 | 8919 |
| 8920 bool JSObject::HasElementPostInterceptor(JSReceiver* receiver, uint32_t index) { | |
| 8921 switch (GetElementsKind()) { | |
| 8922 case FAST_SMI_ONLY_ELEMENTS: | |
| 8923 case FAST_ELEMENTS: { | |
| 8924 uint32_t length = IsJSArray() ? | |
| 8925 static_cast<uint32_t> | |
| 8926 (Smi::cast(JSArray::cast(this)->length())->value()) : | |
| 8927 static_cast<uint32_t>(FixedArray::cast(elements())->length()); | |
| 8928 if ((index < length) && | |
| 8929 !FixedArray::cast(elements())->get(index)->IsTheHole()) { | |
| 8930 return true; | |
| 8931 } | |
| 8932 break; | |
| 8933 } | |
| 8934 case FAST_DOUBLE_ELEMENTS: { | |
| 8935 uint32_t length = IsJSArray() ? | |
| 8936 static_cast<uint32_t> | |
| 8937 (Smi::cast(JSArray::cast(this)->length())->value()) : | |
| 8938 static_cast<uint32_t>(FixedDoubleArray::cast(elements())->length()); | |
| 8939 if ((index < length) && | |
| 8940 !FixedDoubleArray::cast(elements())->is_the_hole(index)) { | |
| 8941 return true; | |
| 8942 } | |
| 8943 break; | |
| 8944 } | |
| 8945 case EXTERNAL_PIXEL_ELEMENTS: { | |
| 8946 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements()); | |
| 8947 if (index < static_cast<uint32_t>(pixels->length())) { | |
| 8948 return true; | |
| 8949 } | |
| 8950 break; | |
| 8951 } | |
| 8952 case EXTERNAL_BYTE_ELEMENTS: | |
| 8953 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | |
| 8954 case EXTERNAL_SHORT_ELEMENTS: | |
| 8955 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | |
| 8956 case EXTERNAL_INT_ELEMENTS: | |
| 8957 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | |
| 8958 case EXTERNAL_FLOAT_ELEMENTS: | |
| 8959 case EXTERNAL_DOUBLE_ELEMENTS: { | |
| 8960 ExternalArray* array = ExternalArray::cast(elements()); | |
| 8961 if (index < static_cast<uint32_t>(array->length())) { | |
| 8962 return true; | |
| 8963 } | |
| 8964 break; | |
| 8965 } | |
| 8966 case DICTIONARY_ELEMENTS: { | |
| 8967 if (element_dictionary()->FindEntry(index) | |
| 8968 != SeededNumberDictionary::kNotFound) { | |
| 8969 return true; | |
| 8970 } | |
| 8971 break; | |
| 8972 } | |
| 8973 case NON_STRICT_ARGUMENTS_ELEMENTS: | |
| 8974 UNREACHABLE(); | |
| 8975 break; | |
| 8976 } | |
| 8977 | |
| 8978 // Handle [] on String objects. | |
| 8979 if (this->IsStringObjectWithCharacterAt(index)) return true; | |
| 8980 | |
| 8981 Object* pt = GetPrototype(); | |
| 8982 if (pt->IsNull()) return false; | |
| 8983 if (pt->IsJSProxy()) { | |
| 8984 // We need to follow the spec and simulate a call to [[GetOwnProperty]]. | |
| 8985 return JSProxy::cast(pt)->GetElementAttributeWithHandler( | |
| 8986 receiver, index) != ABSENT; | |
| 8987 } | |
| 8988 return JSObject::cast(pt)->HasElementWithReceiver(receiver, index); | |
| 8989 } | |
| 8990 | |
| 8991 | |
| 8992 bool JSObject::HasElementWithInterceptor(JSReceiver* receiver, uint32_t index) { | 8920 bool JSObject::HasElementWithInterceptor(JSReceiver* receiver, uint32_t index) { |
| 8993 Isolate* isolate = GetIsolate(); | 8921 Isolate* isolate = GetIsolate(); |
| 8994 // Make sure that the top context does not change when doing | 8922 // Make sure that the top context does not change when doing |
| 8995 // callbacks or interceptor calls. | 8923 // callbacks or interceptor calls. |
| 8996 AssertNoContextChange ncc; | 8924 AssertNoContextChange ncc; |
| 8997 HandleScope scope(isolate); | 8925 HandleScope scope(isolate); |
| 8998 Handle<InterceptorInfo> interceptor(GetIndexedInterceptor()); | 8926 Handle<InterceptorInfo> interceptor(GetIndexedInterceptor()); |
| 8999 Handle<JSReceiver> receiver_handle(receiver); | 8927 Handle<JSReceiver> receiver_handle(receiver); |
| 9000 Handle<JSObject> holder_handle(this); | 8928 Handle<JSObject> holder_handle(this); |
| 9001 CustomArguments args(isolate, interceptor->data(), receiver, this); | 8929 CustomArguments args(isolate, interceptor->data(), receiver, this); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 9021 LOG(isolate, | 8949 LOG(isolate, |
| 9022 ApiIndexedPropertyAccess("interceptor-indexed-has-get", this, index)); | 8950 ApiIndexedPropertyAccess("interceptor-indexed-has-get", this, index)); |
| 9023 v8::Handle<v8::Value> result; | 8951 v8::Handle<v8::Value> result; |
| 9024 { | 8952 { |
| 9025 // Leaving JavaScript. | 8953 // Leaving JavaScript. |
| 9026 VMState state(isolate, EXTERNAL); | 8954 VMState state(isolate, EXTERNAL); |
| 9027 result = getter(index, info); | 8955 result = getter(index, info); |
| 9028 } | 8956 } |
| 9029 if (!result.IsEmpty()) return true; | 8957 if (!result.IsEmpty()) return true; |
| 9030 } | 8958 } |
| 9031 return holder_handle->HasElementPostInterceptor(*receiver_handle, index); | 8959 |
| 8960 if (holder_handle->GetElementsAccessor()->HasElement( |
| 8961 holder_handle->elements(), index, *holder_handle, *receiver_handle)) { |
| 8962 return true; |
| 8963 } |
| 8964 |
| 8965 if (holder_handle->IsStringObjectWithCharacterAt(index)) return true; |
| 8966 Object* pt = holder_handle->GetPrototype(); |
| 8967 if (pt->IsJSProxy()) { |
| 8968 // We need to follow the spec and simulate a call to [[GetOwnProperty]]. |
| 8969 return JSProxy::cast(pt)->GetElementAttributeWithHandler( |
| 8970 receiver, index) != ABSENT; |
| 8971 } |
| 8972 if (pt->IsNull()) return false; |
| 8973 return JSObject::cast(pt)->HasElementWithReceiver(*receiver_handle, index); |
| 9032 } | 8974 } |
| 9033 | 8975 |
| 9034 | 8976 |
| 9035 JSObject::LocalElementType JSObject::HasLocalElement(uint32_t index) { | 8977 JSObject::LocalElementType JSObject::HasLocalElement(uint32_t index) { |
| 9036 // Check access rights if needed. | 8978 // Check access rights if needed. |
| 9037 if (IsAccessCheckNeeded()) { | 8979 if (IsAccessCheckNeeded()) { |
| 9038 Heap* heap = GetHeap(); | 8980 Heap* heap = GetHeap(); |
| 9039 if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) { | 8981 if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) { |
| 9040 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS); | 8982 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS); |
| 9041 return UNDEFINED_ELEMENT; | 8983 return UNDEFINED_ELEMENT; |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9131 if (probe != NULL && !probe->IsTheHole()) return FAST_ELEMENT; | 9073 if (probe != NULL && !probe->IsTheHole()) return FAST_ELEMENT; |
| 9132 } | 9074 } |
| 9133 break; | 9075 break; |
| 9134 } | 9076 } |
| 9135 } | 9077 } |
| 9136 | 9078 |
| 9137 return UNDEFINED_ELEMENT; | 9079 return UNDEFINED_ELEMENT; |
| 9138 } | 9080 } |
| 9139 | 9081 |
| 9140 | 9082 |
| 9141 bool JSObject::HasElementInElements(FixedArray* elements, | |
| 9142 ElementsKind kind, | |
| 9143 uint32_t index) { | |
| 9144 ASSERT(kind == FAST_ELEMENTS || kind == DICTIONARY_ELEMENTS); | |
| 9145 if (kind == FAST_ELEMENTS) { | |
| 9146 int length = IsJSArray() | |
| 9147 ? Smi::cast(JSArray::cast(this)->length())->value() | |
| 9148 : elements->length(); | |
| 9149 if (index < static_cast<uint32_t>(length) && | |
| 9150 !elements->get(index)->IsTheHole()) { | |
| 9151 return true; | |
| 9152 } | |
| 9153 } else { | |
| 9154 if (SeededNumberDictionary::cast(elements)->FindEntry(index) != | |
| 9155 SeededNumberDictionary::kNotFound) { | |
| 9156 return true; | |
| 9157 } | |
| 9158 } | |
| 9159 return false; | |
| 9160 } | |
| 9161 | |
| 9162 | |
| 9163 bool JSObject::HasElementWithReceiver(JSReceiver* receiver, uint32_t index) { | 9083 bool JSObject::HasElementWithReceiver(JSReceiver* receiver, uint32_t index) { |
| 9164 // Check access rights if needed. | 9084 // Check access rights if needed. |
| 9165 if (IsAccessCheckNeeded()) { | 9085 if (IsAccessCheckNeeded()) { |
| 9166 Heap* heap = GetHeap(); | 9086 Heap* heap = GetHeap(); |
| 9167 if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) { | 9087 if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) { |
| 9168 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS); | 9088 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS); |
| 9169 return false; | 9089 return false; |
| 9170 } | 9090 } |
| 9171 } | 9091 } |
| 9172 | 9092 |
| 9173 // Check for lookup interceptor | 9093 // Check for lookup interceptor |
| 9174 if (HasIndexedInterceptor()) { | 9094 if (HasIndexedInterceptor()) { |
| 9175 return HasElementWithInterceptor(receiver, index); | 9095 return HasElementWithInterceptor(receiver, index); |
| 9176 } | 9096 } |
| 9177 | 9097 |
| 9178 ElementsKind kind = GetElementsKind(); | 9098 ElementsAccessor* accessor = GetElementsAccessor(); |
| 9179 switch (kind) { | 9099 if (accessor->HasElement(elements(), index, this, receiver)) { |
| 9180 case FAST_SMI_ONLY_ELEMENTS: | 9100 return true; |
| 9181 case FAST_ELEMENTS: { | |
| 9182 uint32_t length = IsJSArray() ? | |
| 9183 static_cast<uint32_t> | |
| 9184 (Smi::cast(JSArray::cast(this)->length())->value()) : | |
| 9185 static_cast<uint32_t>(FixedArray::cast(elements())->length()); | |
| 9186 if ((index < length) && | |
| 9187 !FixedArray::cast(elements())->get(index)->IsTheHole()) return true; | |
| 9188 break; | |
| 9189 } | |
| 9190 case FAST_DOUBLE_ELEMENTS: { | |
| 9191 uint32_t length = IsJSArray() ? | |
| 9192 static_cast<uint32_t> | |
| 9193 (Smi::cast(JSArray::cast(this)->length())->value()) : | |
| 9194 static_cast<uint32_t>(FixedDoubleArray::cast(elements())->length()); | |
| 9195 if ((index < length) && | |
| 9196 !FixedDoubleArray::cast(elements())->is_the_hole(index)) return true; | |
| 9197 break; | |
| 9198 } | |
| 9199 case EXTERNAL_PIXEL_ELEMENTS: { | |
| 9200 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements()); | |
| 9201 if (index < static_cast<uint32_t>(pixels->length())) { | |
| 9202 return true; | |
| 9203 } | |
| 9204 break; | |
| 9205 } | |
| 9206 case EXTERNAL_BYTE_ELEMENTS: | |
| 9207 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | |
| 9208 case EXTERNAL_SHORT_ELEMENTS: | |
| 9209 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | |
| 9210 case EXTERNAL_INT_ELEMENTS: | |
| 9211 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | |
| 9212 case EXTERNAL_FLOAT_ELEMENTS: | |
| 9213 case EXTERNAL_DOUBLE_ELEMENTS: { | |
| 9214 ExternalArray* array = ExternalArray::cast(elements()); | |
| 9215 if (index < static_cast<uint32_t>(array->length())) { | |
| 9216 return true; | |
| 9217 } | |
| 9218 break; | |
| 9219 } | |
| 9220 case DICTIONARY_ELEMENTS: { | |
| 9221 if (element_dictionary()->FindEntry(index) | |
| 9222 != SeededNumberDictionary::kNotFound) { | |
| 9223 return true; | |
| 9224 } | |
| 9225 break; | |
| 9226 } | |
| 9227 case NON_STRICT_ARGUMENTS_ELEMENTS: { | |
| 9228 FixedArray* parameter_map = FixedArray::cast(elements()); | |
| 9229 uint32_t length = parameter_map->length(); | |
| 9230 Object* probe = | |
| 9231 (index < length - 2) ? parameter_map->get(index + 2) : NULL; | |
| 9232 if (probe != NULL && !probe->IsTheHole()) return true; | |
| 9233 | |
| 9234 // Not a mapped parameter, check the arguments. | |
| 9235 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | |
| 9236 kind = arguments->IsDictionary() ? DICTIONARY_ELEMENTS : FAST_ELEMENTS; | |
| 9237 if (HasElementInElements(arguments, kind, index)) return true; | |
| 9238 break; | |
| 9239 } | |
| 9240 } | 9101 } |
| 9241 | 9102 |
| 9242 // Handle [] on String objects. | 9103 // Handle [] on String objects. |
| 9243 if (this->IsStringObjectWithCharacterAt(index)) return true; | 9104 if (this->IsStringObjectWithCharacterAt(index)) return true; |
| 9244 | 9105 |
| 9245 Object* pt = GetPrototype(); | 9106 Object* pt = GetPrototype(); |
| 9246 if (pt->IsNull()) return false; | 9107 if (pt->IsNull()) return false; |
| 9247 if (pt->IsJSProxy()) { | 9108 if (pt->IsJSProxy()) { |
| 9248 // We need to follow the spec and simulate a call to [[GetOwnProperty]]. | 9109 // We need to follow the spec and simulate a call to [[GetOwnProperty]]. |
| 9249 return JSProxy::cast(pt)->GetElementAttributeWithHandler( | 9110 return JSProxy::cast(pt)->GetElementAttributeWithHandler( |
| (...skipping 3913 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 13163 if (break_point_objects()->IsUndefined()) return 0; | 13024 if (break_point_objects()->IsUndefined()) return 0; |
| 13164 // Single break point. | 13025 // Single break point. |
| 13165 if (!break_point_objects()->IsFixedArray()) return 1; | 13026 if (!break_point_objects()->IsFixedArray()) return 1; |
| 13166 // Multiple break points. | 13027 // Multiple break points. |
| 13167 return FixedArray::cast(break_point_objects())->length(); | 13028 return FixedArray::cast(break_point_objects())->length(); |
| 13168 } | 13029 } |
| 13169 #endif // ENABLE_DEBUGGER_SUPPORT | 13030 #endif // ENABLE_DEBUGGER_SUPPORT |
| 13170 | 13031 |
| 13171 | 13032 |
| 13172 } } // namespace v8::internal | 13033 } } // namespace v8::internal |
| OLD | NEW |