Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 15 matching lines...) Expand all Loading... | |
| 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 | 27 |
| 28 #include "v8.h" | 28 #include "v8.h" |
| 29 | 29 |
| 30 #include "api.h" | 30 #include "api.h" |
| 31 #include "arguments.h" | 31 #include "arguments.h" |
| 32 #include "bootstrapper.h" | 32 #include "bootstrapper.h" |
| 33 #include "codegen.h" | 33 #include "codegen.h" |
| 34 #include "debug.h" | 34 #include "debug.h" |
| 35 #include "deoptimizer.h" | 35 #include "deoptimizer.h" |
| 36 #include "elements.h" | |
| 36 #include "execution.h" | 37 #include "execution.h" |
| 37 #include "full-codegen.h" | 38 #include "full-codegen.h" |
| 38 #include "hydrogen.h" | 39 #include "hydrogen.h" |
| 39 #include "objects-inl.h" | 40 #include "objects-inl.h" |
| 40 #include "objects-visiting.h" | 41 #include "objects-visiting.h" |
| 41 #include "macro-assembler.h" | 42 #include "macro-assembler.h" |
| 42 #include "safepoint-table.h" | 43 #include "safepoint-table.h" |
| 43 #include "scanner-base.h" | 44 #include "scanner-base.h" |
| 44 #include "string-stream.h" | 45 #include "string-stream.h" |
| 45 #include "utils.h" | 46 #include "utils.h" |
| (...skipping 2870 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2916 if (has_double_elements) { | 2917 if (has_double_elements) { |
| 2917 FixedDoubleArray* double_array = FixedDoubleArray::cast(array); | 2918 FixedDoubleArray* double_array = FixedDoubleArray::cast(array); |
| 2918 if (double_array->is_the_hole(i)) { | 2919 if (double_array->is_the_hole(i)) { |
| 2919 value = GetIsolate()->heap()->the_hole_value(); | 2920 value = GetIsolate()->heap()->the_hole_value(); |
| 2920 } else { | 2921 } else { |
| 2921 // Objects must be allocated in the old object space, since the | 2922 // Objects must be allocated in the old object space, since the |
| 2922 // overall number of HeapNumbers needed for the conversion might | 2923 // overall number of HeapNumbers needed for the conversion might |
| 2923 // exceed the capacity of new space, and we would fail repeatedly | 2924 // exceed the capacity of new space, and we would fail repeatedly |
| 2924 // trying to convert the FixedDoubleArray. | 2925 // trying to convert the FixedDoubleArray. |
| 2925 MaybeObject* maybe_value_object = | 2926 MaybeObject* maybe_value_object = |
| 2926 GetHeap()->AllocateHeapNumber(double_array->get(i), TENURED); | 2927 GetHeap()->AllocateHeapNumber(double_array->get_scalar(i), TENURED); |
| 2927 if (!maybe_value_object->ToObject(&value)) return maybe_value_object; | 2928 if (!maybe_value_object->ToObject(&value)) return maybe_value_object; |
| 2928 } | 2929 } |
| 2929 } else { | 2930 } else { |
| 2930 ASSERT(old_map->has_fast_elements()); | 2931 ASSERT(old_map->has_fast_elements()); |
| 2931 value = FixedArray::cast(array)->get(i); | 2932 value = FixedArray::cast(array)->get(i); |
| 2932 } | 2933 } |
| 2933 PropertyDetails details = PropertyDetails(NONE, NORMAL); | 2934 PropertyDetails details = PropertyDetails(NONE, NORMAL); |
| 2934 if (!value->IsTheHole()) { | 2935 if (!value->IsTheHole()) { |
| 2935 Object* result; | 2936 Object* result; |
| 2936 MaybeObject* maybe_result = | 2937 MaybeObject* maybe_result = |
| (...skipping 1954 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4891 // We cannot optimize if 'this' is empty, as other may have holes | 4892 // We cannot optimize if 'this' is empty, as other may have holes |
| 4892 // or non keys. | 4893 // or non keys. |
| 4893 if (len1 == 0) return this; | 4894 if (len1 == 0) return this; |
| 4894 | 4895 |
| 4895 // Compute how many elements are not in this. | 4896 // Compute how many elements are not in this. |
| 4896 int extra = 0; | 4897 int extra = 0; |
| 4897 Heap* heap = GetHeap(); | 4898 Heap* heap = GetHeap(); |
| 4898 Object* obj; | 4899 Object* obj; |
| 4899 for (int y = 0; y < len1; y++) { | 4900 for (int y = 0; y < len1; y++) { |
| 4900 if (!other->is_the_hole(y)) { | 4901 if (!other->is_the_hole(y)) { |
| 4901 MaybeObject* maybe_obj = heap->NumberFromDouble(other->get(y)); | 4902 MaybeObject* maybe_obj = heap->NumberFromDouble(other->get_scalar(y)); |
| 4902 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 4903 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 4903 if (!HasKey(this, obj)) extra++; | 4904 if (!HasKey(this, obj)) extra++; |
| 4904 } | 4905 } |
| 4905 } | 4906 } |
| 4906 | 4907 |
| 4907 if (extra == 0) return this; | 4908 if (extra == 0) return this; |
| 4908 | 4909 |
| 4909 // Allocate the result | 4910 // Allocate the result |
| 4910 { MaybeObject* maybe_obj = GetHeap()->AllocateFixedArray(len0 + extra); | 4911 { MaybeObject* maybe_obj = GetHeap()->AllocateFixedArray(len0 + extra); |
| 4911 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 4912 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 4912 } | 4913 } |
| 4913 // Fill in the content | 4914 // Fill in the content |
| 4914 FixedArray* result = FixedArray::cast(obj); | 4915 FixedArray* result = FixedArray::cast(obj); |
| 4915 { | 4916 { |
| 4916 // Limit the scope of the AssertNoAllocation | 4917 // Limit the scope of the AssertNoAllocation |
| 4917 AssertNoAllocation no_gc; | 4918 AssertNoAllocation no_gc; |
| 4918 WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc); | 4919 WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc); |
| 4919 for (int i = 0; i < len0; i++) { | 4920 for (int i = 0; i < len0; i++) { |
| 4920 Object* e = get(i); | 4921 Object* e = get(i); |
| 4921 ASSERT(e->IsString() || e->IsNumber()); | 4922 ASSERT(e->IsString() || e->IsNumber()); |
| 4922 result->set(i, e, mode); | 4923 result->set(i, e, mode); |
| 4923 } | 4924 } |
| 4924 } | 4925 } |
| 4925 | 4926 |
| 4926 // Fill in the extra keys. | 4927 // Fill in the extra keys. |
| 4927 int index = 0; | 4928 int index = 0; |
| 4928 for (int y = 0; y < len1; y++) { | 4929 for (int y = 0; y < len1; y++) { |
| 4929 if (!other->is_the_hole(y)) { | 4930 if (!other->is_the_hole(y)) { |
| 4930 MaybeObject* maybe_obj = heap->NumberFromDouble(other->get(y)); | 4931 MaybeObject* maybe_obj = heap->NumberFromDouble(other->get_scalar(y)); |
| 4931 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 4932 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 4932 if (!HasKey(this, obj)) { | 4933 if (!HasKey(this, obj)) { |
| 4933 result->set(len0 + index, obj); | 4934 result->set(len0 + index, obj); |
| 4934 index++; | 4935 index++; |
| 4935 } | 4936 } |
| 4936 } | 4937 } |
| 4937 } | 4938 } |
| 4938 ASSERT(extra == index); | 4939 ASSERT(extra == index); |
| 4939 return result; | 4940 return result; |
| 4940 } | 4941 } |
| (...skipping 2654 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7595 uint32_t old_length = static_cast<uint32_t>(old_elements->length()); | 7596 uint32_t old_length = static_cast<uint32_t>(old_elements->length()); |
| 7596 // Fill out the new array with this content and array holes. | 7597 // Fill out the new array with this content and array holes. |
| 7597 for (uint32_t i = 0; i < old_length; i++) { | 7598 for (uint32_t i = 0; i < old_length; i++) { |
| 7598 if (!old_elements->is_the_hole(i)) { | 7599 if (!old_elements->is_the_hole(i)) { |
| 7599 Object* obj; | 7600 Object* obj; |
| 7600 // Objects must be allocated in the old object space, since the | 7601 // Objects must be allocated in the old object space, since the |
| 7601 // overall number of HeapNumbers needed for the conversion might | 7602 // overall number of HeapNumbers needed for the conversion might |
| 7602 // exceed the capacity of new space, and we would fail repeatedly | 7603 // exceed the capacity of new space, and we would fail repeatedly |
| 7603 // trying to convert the FixedDoubleArray. | 7604 // trying to convert the FixedDoubleArray. |
| 7604 MaybeObject* maybe_value_object = | 7605 MaybeObject* maybe_value_object = |
| 7605 GetHeap()->AllocateHeapNumber(old_elements->get(i), TENURED); | 7606 GetHeap()->AllocateHeapNumber(old_elements->get_scalar(i), |
| 7607 TENURED); | |
| 7606 if (!maybe_value_object->ToObject(&obj)) return maybe_value_object; | 7608 if (!maybe_value_object->ToObject(&obj)) return maybe_value_object; |
| 7607 // Force write barrier. It's not worth trying to exploit | 7609 // Force write barrier. It's not worth trying to exploit |
| 7608 // elems->GetWriteBarrierMode(), since it requires an | 7610 // elems->GetWriteBarrierMode(), since it requires an |
| 7609 // AssertNoAllocation stack object that would have to be positioned | 7611 // AssertNoAllocation stack object that would have to be positioned |
| 7610 // after the HeapNumber allocation anyway. | 7612 // after the HeapNumber allocation anyway. |
| 7611 new_elements->set(i, obj, UPDATE_WRITE_BARRIER); | 7613 new_elements->set(i, obj, UPDATE_WRITE_BARRIER); |
| 7612 } | 7614 } |
| 7613 } | 7615 } |
| 7614 set_map(new_map); | 7616 set_map(new_map); |
| 7615 set_elements(new_elements); | 7617 set_elements(new_elements); |
| (...skipping 1322 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8938 { MaybeObject* maybe_len = | 8940 { MaybeObject* maybe_len = |
| 8939 GetHeap()->NumberFromDouble(static_cast<double>(index) + 1); | 8941 GetHeap()->NumberFromDouble(static_cast<double>(index) + 1); |
| 8940 if (!maybe_len->ToObject(&len)) return maybe_len; | 8942 if (!maybe_len->ToObject(&len)) return maybe_len; |
| 8941 } | 8943 } |
| 8942 set_length(len); | 8944 set_length(len); |
| 8943 } | 8945 } |
| 8944 return value; | 8946 return value; |
| 8945 } | 8947 } |
| 8946 | 8948 |
| 8947 | 8949 |
| 8948 MaybeObject* JSObject::GetElementPostInterceptor(Object* receiver, | |
| 8949 uint32_t index) { | |
| 8950 // Get element works for both JSObject and JSArray since | |
| 8951 // JSArray::length cannot change. | |
| 8952 switch (GetElementsKind()) { | |
| 8953 case FAST_ELEMENTS: { | |
| 8954 FixedArray* elms = FixedArray::cast(elements()); | |
| 8955 if (index < static_cast<uint32_t>(elms->length())) { | |
| 8956 Object* value = elms->get(index); | |
| 8957 if (!value->IsTheHole()) return value; | |
| 8958 } | |
| 8959 break; | |
| 8960 } | |
| 8961 case FAST_DOUBLE_ELEMENTS: { | |
| 8962 FixedDoubleArray* elms = FixedDoubleArray::cast(elements()); | |
| 8963 if (index < static_cast<uint32_t>(elms->length())) { | |
| 8964 if (!elms->is_the_hole(index)) { | |
| 8965 return GetHeap()->NumberFromDouble(elms->get(index)); | |
| 8966 } | |
| 8967 } | |
| 8968 break; | |
| 8969 } | |
| 8970 case EXTERNAL_PIXEL_ELEMENTS: | |
| 8971 case EXTERNAL_BYTE_ELEMENTS: | |
| 8972 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | |
| 8973 case EXTERNAL_SHORT_ELEMENTS: | |
| 8974 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | |
| 8975 case EXTERNAL_INT_ELEMENTS: | |
| 8976 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | |
| 8977 case EXTERNAL_FLOAT_ELEMENTS: | |
| 8978 case EXTERNAL_DOUBLE_ELEMENTS: { | |
| 8979 MaybeObject* maybe_value = GetExternalElement(index); | |
| 8980 Object* value; | |
| 8981 if (!maybe_value->ToObject(&value)) return maybe_value; | |
| 8982 if (!value->IsUndefined()) return value; | |
| 8983 break; | |
| 8984 } | |
| 8985 case DICTIONARY_ELEMENTS: { | |
| 8986 NumberDictionary* dictionary = element_dictionary(); | |
| 8987 int entry = dictionary->FindEntry(index); | |
| 8988 if (entry != NumberDictionary::kNotFound) { | |
| 8989 Object* element = dictionary->ValueAt(entry); | |
| 8990 PropertyDetails details = dictionary->DetailsAt(entry); | |
| 8991 if (details.type() == CALLBACKS) { | |
| 8992 return GetElementWithCallback(receiver, | |
| 8993 element, | |
| 8994 index, | |
| 8995 this); | |
| 8996 } | |
| 8997 return element; | |
| 8998 } | |
| 8999 break; | |
| 9000 } | |
| 9001 case NON_STRICT_ARGUMENTS_ELEMENTS: | |
| 9002 UNIMPLEMENTED(); | |
| 9003 break; | |
| 9004 } | |
| 9005 | |
| 9006 // Continue searching via the prototype chain. | |
| 9007 Object* pt = GetPrototype(); | |
| 9008 if (pt->IsNull()) return GetHeap()->undefined_value(); | |
| 9009 return pt->GetElementWithReceiver(receiver, index); | |
| 9010 } | |
| 9011 | |
| 9012 | |
| 9013 MaybeObject* JSObject::GetElementWithInterceptor(Object* receiver, | 8950 MaybeObject* JSObject::GetElementWithInterceptor(Object* receiver, |
| 9014 uint32_t index) { | 8951 uint32_t index) { |
| 9015 Isolate* isolate = GetIsolate(); | 8952 Isolate* isolate = GetIsolate(); |
| 9016 // Make sure that the top context does not change when doing | 8953 // Make sure that the top context does not change when doing |
| 9017 // callbacks or interceptor calls. | 8954 // callbacks or interceptor calls. |
| 9018 AssertNoContextChange ncc; | 8955 AssertNoContextChange ncc; |
| 9019 HandleScope scope(isolate); | 8956 HandleScope scope(isolate); |
| 9020 Handle<InterceptorInfo> interceptor(GetIndexedInterceptor(), isolate); | 8957 Handle<InterceptorInfo> interceptor(GetIndexedInterceptor(), isolate); |
| 9021 Handle<Object> this_handle(receiver, isolate); | 8958 Handle<Object> this_handle(receiver, isolate); |
| 9022 Handle<JSObject> holder_handle(this, isolate); | 8959 Handle<JSObject> holder_handle(this, isolate); |
| 9023 if (!interceptor->getter()->IsUndefined()) { | 8960 if (!interceptor->getter()->IsUndefined()) { |
| 9024 v8::IndexedPropertyGetter getter = | 8961 v8::IndexedPropertyGetter getter = |
| 9025 v8::ToCData<v8::IndexedPropertyGetter>(interceptor->getter()); | 8962 v8::ToCData<v8::IndexedPropertyGetter>(interceptor->getter()); |
| 9026 LOG(isolate, | 8963 LOG(isolate, |
| 9027 ApiIndexedPropertyAccess("interceptor-indexed-get", this, index)); | 8964 ApiIndexedPropertyAccess("interceptor-indexed-get", this, index)); |
| 9028 CustomArguments args(isolate, interceptor->data(), receiver, this); | 8965 CustomArguments args(isolate, interceptor->data(), receiver, this); |
| 9029 v8::AccessorInfo info(args.end()); | 8966 v8::AccessorInfo info(args.end()); |
| 9030 v8::Handle<v8::Value> result; | 8967 v8::Handle<v8::Value> result; |
| 9031 { | 8968 { |
| 9032 // Leaving JavaScript. | 8969 // Leaving JavaScript. |
| 9033 VMState state(isolate, EXTERNAL); | 8970 VMState state(isolate, EXTERNAL); |
| 9034 result = getter(index, info); | 8971 result = getter(index, info); |
| 9035 } | 8972 } |
| 9036 RETURN_IF_SCHEDULED_EXCEPTION(isolate); | 8973 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
| 9037 if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result); | 8974 if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result); |
| 9038 } | 8975 } |
| 9039 | 8976 |
| 9040 MaybeObject* raw_result = | 8977 Heap* heap = holder_handle->GetHeap(); |
| 9041 holder_handle->GetElementPostInterceptor(*this_handle, index); | 8978 ElementsAccessor* handler = holder_handle->GetElementsAccessor(); |
| 8979 MaybeObject* raw_result = handler->GetWithReceiver(*holder_handle, | |
| 8980 *this_handle, | |
| 8981 index); | |
| 8982 if (raw_result != heap->the_hole_value()) return raw_result; | |
| 8983 | |
| 9042 RETURN_IF_SCHEDULED_EXCEPTION(isolate); | 8984 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
| 9043 return raw_result; | 8985 |
| 8986 Object* pt = holder_handle->GetPrototype(); | |
| 8987 if (pt == heap->null_value()) return heap->undefined_value(); | |
| 8988 return pt->GetElementWithReceiver(*this_handle, index); | |
| 9044 } | 8989 } |
| 9045 | 8990 |
| 9046 | 8991 |
| 9047 MaybeObject* JSObject::GetElementWithReceiver(Object* receiver, | 8992 MaybeObject* JSObject::GetElementWithReceiver(Object* receiver, |
| 9048 uint32_t index) { | 8993 uint32_t index) { |
| 9049 // Check access rights if needed. | 8994 // Check access rights if needed. |
| 9050 if (IsAccessCheckNeeded()) { | 8995 if (IsAccessCheckNeeded()) { |
| 9051 Heap* heap = GetHeap(); | 8996 Heap* heap = GetHeap(); |
| 9052 if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_GET)) { | 8997 if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_GET)) { |
| 9053 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_GET); | 8998 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_GET); |
| 9054 return heap->undefined_value(); | 8999 return heap->undefined_value(); |
| 9055 } | 9000 } |
| 9056 } | 9001 } |
| 9057 | 9002 |
| 9058 if (HasIndexedInterceptor()) { | 9003 if (HasIndexedInterceptor()) { |
| 9059 return GetElementWithInterceptor(receiver, index); | 9004 return GetElementWithInterceptor(receiver, index); |
| 9060 } | 9005 } |
| 9061 | 9006 |
| 9062 // Get element works for both JSObject and JSArray since | 9007 Heap* heap = GetHeap(); |
| 9063 // JSArray::length cannot change. | 9008 if (elements() != heap->empty_fixed_array()) { |
| 9064 switch (GetElementsKind()) { | 9009 MaybeObject* result = GetElementsAccessor()->GetWithReceiver(this, |
| 9065 case FAST_ELEMENTS: { | 9010 receiver, |
| 9066 FixedArray* elms = FixedArray::cast(elements()); | 9011 index); |
| 9067 if (index < static_cast<uint32_t>(elms->length())) { | 9012 if (result != heap->the_hole_value()) return result; |
| 9068 Object* value = elms->get(index); | |
| 9069 if (!value->IsTheHole()) return value; | |
| 9070 } | |
| 9071 break; | |
| 9072 } | |
| 9073 case FAST_DOUBLE_ELEMENTS: { | |
| 9074 FixedDoubleArray* elms = FixedDoubleArray::cast(elements()); | |
| 9075 if (index < static_cast<uint32_t>(elms->length())) { | |
| 9076 if (!elms->is_the_hole(index)) { | |
| 9077 double double_value = elms->get(index); | |
| 9078 return GetHeap()->NumberFromDouble(double_value); | |
| 9079 } | |
| 9080 } | |
| 9081 break; | |
| 9082 } | |
| 9083 case EXTERNAL_PIXEL_ELEMENTS: | |
| 9084 case EXTERNAL_BYTE_ELEMENTS: | |
| 9085 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | |
| 9086 case EXTERNAL_SHORT_ELEMENTS: | |
| 9087 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | |
| 9088 case EXTERNAL_INT_ELEMENTS: | |
| 9089 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | |
| 9090 case EXTERNAL_FLOAT_ELEMENTS: | |
| 9091 case EXTERNAL_DOUBLE_ELEMENTS: { | |
| 9092 MaybeObject* maybe_value = GetExternalElement(index); | |
| 9093 Object* value; | |
| 9094 if (!maybe_value->ToObject(&value)) return maybe_value; | |
| 9095 if (!value->IsUndefined()) return value; | |
| 9096 break; | |
| 9097 } | |
| 9098 case DICTIONARY_ELEMENTS: { | |
| 9099 NumberDictionary* dictionary = element_dictionary(); | |
| 9100 int entry = dictionary->FindEntry(index); | |
| 9101 if (entry != NumberDictionary::kNotFound) { | |
| 9102 Object* element = dictionary->ValueAt(entry); | |
| 9103 PropertyDetails details = dictionary->DetailsAt(entry); | |
| 9104 if (details.type() == CALLBACKS) { | |
| 9105 return GetElementWithCallback(receiver, | |
| 9106 element, | |
| 9107 index, | |
| 9108 this); | |
| 9109 } | |
| 9110 return element; | |
| 9111 } | |
| 9112 break; | |
| 9113 } | |
| 9114 case NON_STRICT_ARGUMENTS_ELEMENTS: { | |
| 9115 FixedArray* parameter_map = FixedArray::cast(elements()); | |
| 9116 uint32_t length = parameter_map->length(); | |
| 9117 Object* probe = | |
| 9118 (index < length - 2) ? parameter_map->get(index + 2) : NULL; | |
| 9119 if (probe != NULL && !probe->IsTheHole()) { | |
| 9120 Context* context = Context::cast(parameter_map->get(0)); | |
| 9121 int context_index = Smi::cast(probe)->value(); | |
| 9122 ASSERT(!context->get(context_index)->IsTheHole()); | |
| 9123 return context->get(context_index); | |
| 9124 } else { | |
| 9125 // Object is not mapped, defer to the arguments. | |
| 9126 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | |
| 9127 if (arguments->IsDictionary()) { | |
| 9128 NumberDictionary* dictionary = NumberDictionary::cast(arguments); | |
| 9129 int entry = dictionary->FindEntry(index); | |
| 9130 if (entry != NumberDictionary::kNotFound) { | |
| 9131 Object* element = dictionary->ValueAt(entry); | |
| 9132 PropertyDetails details = dictionary->DetailsAt(entry); | |
| 9133 if (details.type() == CALLBACKS) { | |
| 9134 return GetElementWithCallback(receiver, | |
| 9135 element, | |
| 9136 index, | |
| 9137 this); | |
| 9138 } | |
| 9139 return element; | |
| 9140 } | |
| 9141 } else if (index < static_cast<uint32_t>(arguments->length())) { | |
| 9142 Object* value = arguments->get(index); | |
| 9143 if (!value->IsTheHole()) return value; | |
| 9144 } | |
| 9145 } | |
| 9146 break; | |
| 9147 } | |
| 9148 } | 9013 } |
| 9149 | 9014 |
| 9150 Object* pt = GetPrototype(); | 9015 Object* pt = GetPrototype(); |
| 9151 Heap* heap = GetHeap(); | |
| 9152 if (pt == heap->null_value()) return heap->undefined_value(); | 9016 if (pt == heap->null_value()) return heap->undefined_value(); |
| 9153 return pt->GetElementWithReceiver(receiver, index); | 9017 return pt->GetElementWithReceiver(receiver, index); |
| 9154 } | 9018 } |
| 9155 | 9019 |
| 9156 | 9020 |
| 9157 MaybeObject* JSObject::GetExternalElement(uint32_t index) { | |
| 9158 // Get element works for both JSObject and JSArray since | |
| 9159 // JSArray::length cannot change. | |
| 9160 switch (GetElementsKind()) { | |
| 9161 case EXTERNAL_PIXEL_ELEMENTS: { | |
| 9162 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements()); | |
| 9163 if (index < static_cast<uint32_t>(pixels->length())) { | |
| 9164 uint8_t value = pixels->get(index); | |
| 9165 return Smi::FromInt(value); | |
| 9166 } | |
| 9167 break; | |
| 9168 } | |
| 9169 case EXTERNAL_BYTE_ELEMENTS: { | |
| 9170 ExternalByteArray* array = ExternalByteArray::cast(elements()); | |
| 9171 if (index < static_cast<uint32_t>(array->length())) { | |
| 9172 int8_t value = array->get(index); | |
| 9173 return Smi::FromInt(value); | |
| 9174 } | |
| 9175 break; | |
| 9176 } | |
| 9177 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: { | |
| 9178 ExternalUnsignedByteArray* array = | |
| 9179 ExternalUnsignedByteArray::cast(elements()); | |
| 9180 if (index < static_cast<uint32_t>(array->length())) { | |
| 9181 uint8_t value = array->get(index); | |
| 9182 return Smi::FromInt(value); | |
| 9183 } | |
| 9184 break; | |
| 9185 } | |
| 9186 case EXTERNAL_SHORT_ELEMENTS: { | |
| 9187 ExternalShortArray* array = ExternalShortArray::cast(elements()); | |
| 9188 if (index < static_cast<uint32_t>(array->length())) { | |
| 9189 int16_t value = array->get(index); | |
| 9190 return Smi::FromInt(value); | |
| 9191 } | |
| 9192 break; | |
| 9193 } | |
| 9194 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: { | |
| 9195 ExternalUnsignedShortArray* array = | |
| 9196 ExternalUnsignedShortArray::cast(elements()); | |
| 9197 if (index < static_cast<uint32_t>(array->length())) { | |
| 9198 uint16_t value = array->get(index); | |
| 9199 return Smi::FromInt(value); | |
| 9200 } | |
| 9201 break; | |
| 9202 } | |
| 9203 case EXTERNAL_INT_ELEMENTS: { | |
| 9204 ExternalIntArray* array = ExternalIntArray::cast(elements()); | |
| 9205 if (index < static_cast<uint32_t>(array->length())) { | |
| 9206 int32_t value = array->get(index); | |
| 9207 return GetHeap()->NumberFromInt32(value); | |
| 9208 } | |
| 9209 break; | |
| 9210 } | |
| 9211 case EXTERNAL_UNSIGNED_INT_ELEMENTS: { | |
| 9212 ExternalUnsignedIntArray* array = | |
| 9213 ExternalUnsignedIntArray::cast(elements()); | |
| 9214 if (index < static_cast<uint32_t>(array->length())) { | |
| 9215 uint32_t value = array->get(index); | |
| 9216 return GetHeap()->NumberFromUint32(value); | |
| 9217 } | |
| 9218 break; | |
| 9219 } | |
| 9220 case EXTERNAL_FLOAT_ELEMENTS: { | |
| 9221 ExternalFloatArray* array = ExternalFloatArray::cast(elements()); | |
| 9222 if (index < static_cast<uint32_t>(array->length())) { | |
| 9223 float value = array->get(index); | |
| 9224 return GetHeap()->AllocateHeapNumber(value); | |
| 9225 } | |
| 9226 break; | |
| 9227 } | |
| 9228 case EXTERNAL_DOUBLE_ELEMENTS: { | |
| 9229 ExternalDoubleArray* array = ExternalDoubleArray::cast(elements()); | |
| 9230 if (index < static_cast<uint32_t>(array->length())) { | |
| 9231 double value = array->get(index); | |
| 9232 return GetHeap()->AllocateHeapNumber(value); | |
| 9233 } | |
| 9234 break; | |
| 9235 } | |
| 9236 case FAST_DOUBLE_ELEMENTS: | |
| 9237 case FAST_ELEMENTS: | |
| 9238 case DICTIONARY_ELEMENTS: | |
| 9239 UNREACHABLE(); | |
| 9240 break; | |
| 9241 case NON_STRICT_ARGUMENTS_ELEMENTS: | |
| 9242 UNIMPLEMENTED(); | |
| 9243 break; | |
| 9244 } | |
| 9245 return GetHeap()->undefined_value(); | |
| 9246 } | |
| 9247 | |
| 9248 | |
| 9249 bool JSObject::HasDenseElements() { | 9021 bool JSObject::HasDenseElements() { |
| 9250 int capacity = 0; | 9022 int capacity = 0; |
| 9251 int used = 0; | 9023 int used = 0; |
| 9252 GetElementsCapacityAndUsage(&capacity, &used); | 9024 GetElementsCapacityAndUsage(&capacity, &used); |
| 9253 return (capacity == 0) || (used > (capacity / 2)); | 9025 return (capacity == 0) || (used > (capacity / 2)); |
| 9254 } | 9026 } |
| 9255 | 9027 |
| 9256 | 9028 |
| 9257 void JSObject::GetElementsCapacityAndUsage(int* capacity, int* used) { | 9029 void JSObject::GetElementsCapacityAndUsage(int* capacity, int* used) { |
| 9258 *capacity = 0; | 9030 *capacity = 0; |
| (...skipping 1462 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 10721 if (elements->is_the_hole(i)) { | 10493 if (elements->is_the_hole(i)) { |
| 10722 holes--; | 10494 holes--; |
| 10723 } else { | 10495 } else { |
| 10724 continue; | 10496 continue; |
| 10725 } | 10497 } |
| 10726 // Position i needs to be filled. | 10498 // Position i needs to be filled. |
| 10727 while (holes > i) { | 10499 while (holes > i) { |
| 10728 if (elements->is_the_hole(holes)) { | 10500 if (elements->is_the_hole(holes)) { |
| 10729 holes--; | 10501 holes--; |
| 10730 } else { | 10502 } else { |
| 10731 elements->set(i, elements->get(holes)); | 10503 elements->set(i, elements->get_scalar(holes)); |
| 10732 break; | 10504 break; |
| 10733 } | 10505 } |
| 10734 } | 10506 } |
| 10735 } | 10507 } |
| 10736 result = holes; | 10508 result = holes; |
| 10737 while (holes < limit) { | 10509 while (holes < limit) { |
| 10738 elements->set_the_hole(holes); | 10510 elements->set_the_hole(holes); |
| 10739 holes++; | 10511 holes++; |
| 10740 } | 10512 } |
| 10741 } else { | 10513 } else { |
| (...skipping 1344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 12086 new_array->set(old_array->length(), *break_point_object); | 11858 new_array->set(old_array->length(), *break_point_object); |
| 12087 break_point_info->set_break_point_objects(*new_array); | 11859 break_point_info->set_break_point_objects(*new_array); |
| 12088 } | 11860 } |
| 12089 | 11861 |
| 12090 | 11862 |
| 12091 bool BreakPointInfo::HasBreakPointObject( | 11863 bool BreakPointInfo::HasBreakPointObject( |
| 12092 Handle<BreakPointInfo> break_point_info, | 11864 Handle<BreakPointInfo> break_point_info, |
| 12093 Handle<Object> break_point_object) { | 11865 Handle<Object> break_point_object) { |
| 12094 // No break point. | 11866 // No break point. |
| 12095 if (break_point_info->break_point_objects()->IsUndefined()) return false; | 11867 if (break_point_info->break_point_objects()->IsUndefined()) return false; |
| 12096 // Single beak point. | 11868 // Single beak point. |
|
Lasse Reichstein
2011/08/03 10:35:39
Spotted a missing "r" in "break" here :)
| |
| 12097 if (!break_point_info->break_point_objects()->IsFixedArray()) { | 11869 if (!break_point_info->break_point_objects()->IsFixedArray()) { |
| 12098 return break_point_info->break_point_objects() == *break_point_object; | 11870 return break_point_info->break_point_objects() == *break_point_object; |
| 12099 } | 11871 } |
| 12100 // Multiple break points. | 11872 // Multiple break points. |
| 12101 FixedArray* array = FixedArray::cast(break_point_info->break_point_objects()); | 11873 FixedArray* array = FixedArray::cast(break_point_info->break_point_objects()); |
| 12102 for (int i = 0; i < array->length(); i++) { | 11874 for (int i = 0; i < array->length(); i++) { |
| 12103 if (array->get(i) == *break_point_object) { | 11875 if (array->get(i) == *break_point_object) { |
| 12104 return true; | 11876 return true; |
| 12105 } | 11877 } |
| 12106 } | 11878 } |
| 12107 return false; | 11879 return false; |
| 12108 } | 11880 } |
| 12109 | 11881 |
| 12110 | 11882 |
| 12111 // Get the number of break points. | 11883 // Get the number of break points. |
| 12112 int BreakPointInfo::GetBreakPointCount() { | 11884 int BreakPointInfo::GetBreakPointCount() { |
| 12113 // No break point. | 11885 // No break point. |
| 12114 if (break_point_objects()->IsUndefined()) return 0; | 11886 if (break_point_objects()->IsUndefined()) return 0; |
| 12115 // Single beak point. | 11887 // Single beak point. |
| 12116 if (!break_point_objects()->IsFixedArray()) return 1; | 11888 if (!break_point_objects()->IsFixedArray()) return 1; |
| 12117 // Multiple break points. | 11889 // Multiple break points. |
| 12118 return FixedArray::cast(break_point_objects())->length(); | 11890 return FixedArray::cast(break_point_objects())->length(); |
| 12119 } | 11891 } |
| 12120 #endif | 11892 #endif |
| 12121 | 11893 |
| 12122 | 11894 |
| 12123 } } // namespace v8::internal | 11895 } } // namespace v8::internal |
| OLD | NEW |