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 |