OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/api.h" | 7 #include "src/api.h" |
8 #include "src/api-natives.h" | 8 #include "src/api-natives.h" |
9 #include "src/arguments.h" | 9 #include "src/arguments.h" |
10 #include "src/base/once.h" | 10 #include "src/base/once.h" |
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
177 | 177 |
178 | 178 |
179 static void MoveDoubleElements(FixedDoubleArray* dst, int dst_index, | 179 static void MoveDoubleElements(FixedDoubleArray* dst, int dst_index, |
180 FixedDoubleArray* src, int src_index, int len) { | 180 FixedDoubleArray* src, int src_index, int len) { |
181 if (len == 0) return; | 181 if (len == 0) return; |
182 MemMove(dst->data_start() + dst_index, src->data_start() + src_index, | 182 MemMove(dst->data_start() + dst_index, src->data_start() + src_index, |
183 len * kDoubleSize); | 183 len * kDoubleSize); |
184 } | 184 } |
185 | 185 |
186 | 186 |
187 static bool ArrayPrototypeHasNoElements(Heap* heap, PrototypeIterator* iter) { | 187 static bool ArrayPrototypeHasNoElements(PrototypeIterator* iter) { |
188 DisallowHeapAllocation no_gc; | 188 DisallowHeapAllocation no_gc; |
189 for (; !iter->IsAtEnd(); iter->Advance()) { | 189 for (; !iter->IsAtEnd(); iter->Advance()) { |
190 if (iter->GetCurrent()->IsJSProxy()) return false; | 190 if (iter->GetCurrent()->IsJSProxy()) return false; |
191 if (JSObject::cast(iter->GetCurrent())->elements() != | 191 JSObject* current = JSObject::cast(iter->GetCurrent()); |
192 heap->empty_fixed_array()) { | 192 if (current->IsAccessCheckNeeded()) return false; |
193 return false; | 193 if (current->HasIndexedInterceptor()) return false; |
194 } | 194 if (current->elements()->length() != 0) return false; |
195 } | 195 } |
196 return true; | 196 return true; |
197 } | 197 } |
198 | 198 |
199 | 199 |
200 static inline bool IsJSArrayFastElementMovingAllowed(Heap* heap, | 200 static inline bool IsJSArrayFastElementMovingAllowed(Isolate* isolate, |
201 JSArray* receiver) { | 201 JSArray* receiver) { |
202 DisallowHeapAllocation no_gc; | 202 DisallowHeapAllocation no_gc; |
203 Isolate* isolate = heap->isolate(); | |
204 if (!isolate->IsFastArrayConstructorPrototypeChainIntact()) { | |
205 return false; | |
206 } | |
207 | |
208 // If the array prototype chain is intact (and free of elements), and if the | 203 // If the array prototype chain is intact (and free of elements), and if the |
209 // receiver's prototype is the array prototype, then we are done. | 204 // receiver's prototype is the array prototype, then we are done. |
210 Object* prototype = receiver->map()->prototype(); | 205 Object* prototype = receiver->map()->prototype(); |
211 if (prototype->IsJSArray() && | 206 if (prototype->IsJSArray() && |
212 isolate->is_initial_array_prototype(JSArray::cast(prototype))) { | 207 isolate->is_initial_array_prototype(JSArray::cast(prototype)) && |
| 208 isolate->IsFastArrayConstructorPrototypeChainIntact()) { |
213 return true; | 209 return true; |
214 } | 210 } |
215 | 211 |
216 // Slow case. | 212 // Slow case. |
217 PrototypeIterator iter(isolate, receiver); | 213 PrototypeIterator iter(isolate, receiver); |
218 return ArrayPrototypeHasNoElements(heap, &iter); | 214 return ArrayPrototypeHasNoElements(&iter); |
219 } | 215 } |
220 | 216 |
221 | 217 |
222 // Returns empty handle if not applicable. | 218 // Returns empty handle if not applicable. |
223 MUST_USE_RESULT | 219 MUST_USE_RESULT |
224 static inline MaybeHandle<FixedArrayBase> EnsureJSArrayWithWritableFastElements( | 220 static inline MaybeHandle<FixedArrayBase> EnsureJSArrayWithWritableFastElements( |
225 Isolate* isolate, | 221 Isolate* isolate, |
226 Handle<Object> receiver, | 222 Handle<Object> receiver, |
227 Arguments* args, | 223 Arguments* args, |
228 int first_added_arg) { | 224 int first_added_arg) { |
229 if (!receiver->IsJSArray()) return MaybeHandle<FixedArrayBase>(); | 225 if (!receiver->IsJSArray()) return MaybeHandle<FixedArrayBase>(); |
230 Handle<JSArray> array = Handle<JSArray>::cast(receiver); | 226 Handle<JSArray> array = Handle<JSArray>::cast(receiver); |
231 // If there may be elements accessors in the prototype chain, the fast path | 227 // If there may be elements accessors in the prototype chain, the fast path |
232 // cannot be used if there arguments to add to the array. | 228 // cannot be used if there arguments to add to the array. |
233 Heap* heap = isolate->heap(); | 229 Heap* heap = isolate->heap(); |
234 if (args != NULL && !IsJSArrayFastElementMovingAllowed(heap, *array)) { | 230 if (args != NULL && !IsJSArrayFastElementMovingAllowed(isolate, *array)) { |
235 return MaybeHandle<FixedArrayBase>(); | 231 return MaybeHandle<FixedArrayBase>(); |
236 } | 232 } |
237 if (array->map()->is_observed()) return MaybeHandle<FixedArrayBase>(); | 233 if (array->map()->is_observed()) return MaybeHandle<FixedArrayBase>(); |
238 if (!array->map()->is_extensible()) return MaybeHandle<FixedArrayBase>(); | 234 if (!array->map()->is_extensible()) return MaybeHandle<FixedArrayBase>(); |
239 Handle<FixedArrayBase> elms(array->elements(), isolate); | 235 Handle<FixedArrayBase> elms(array->elements(), isolate); |
240 Map* map = elms->map(); | 236 Map* map = elms->map(); |
241 if (map == heap->fixed_array_map()) { | 237 if (map == heap->fixed_array_map()) { |
242 if (args == NULL || array->HasFastObjectElements()) return elms; | 238 if (args == NULL || array->HasFastObjectElements()) return elms; |
243 } else if (map == heap->fixed_cow_array_map()) { | 239 } else if (map == heap->fixed_cow_array_map()) { |
244 elms = JSObject::EnsureWritableFastElements(array); | 240 elms = JSObject::EnsureWritableFastElements(array); |
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
456 | 452 |
457 | 453 |
458 BUILTIN(ArrayShift) { | 454 BUILTIN(ArrayShift) { |
459 HandleScope scope(isolate); | 455 HandleScope scope(isolate); |
460 Heap* heap = isolate->heap(); | 456 Heap* heap = isolate->heap(); |
461 Handle<Object> receiver = args.receiver(); | 457 Handle<Object> receiver = args.receiver(); |
462 MaybeHandle<FixedArrayBase> maybe_elms_obj = | 458 MaybeHandle<FixedArrayBase> maybe_elms_obj = |
463 EnsureJSArrayWithWritableFastElements(isolate, receiver, NULL, 0); | 459 EnsureJSArrayWithWritableFastElements(isolate, receiver, NULL, 0); |
464 Handle<FixedArrayBase> elms_obj; | 460 Handle<FixedArrayBase> elms_obj; |
465 if (!maybe_elms_obj.ToHandle(&elms_obj) || | 461 if (!maybe_elms_obj.ToHandle(&elms_obj) || |
466 !IsJSArrayFastElementMovingAllowed(heap, JSArray::cast(*receiver))) { | 462 !IsJSArrayFastElementMovingAllowed(isolate, JSArray::cast(*receiver))) { |
467 return CallJsBuiltin(isolate, "$arrayShift", args); | 463 return CallJsBuiltin(isolate, "$arrayShift", args); |
468 } | 464 } |
469 Handle<JSArray> array = Handle<JSArray>::cast(receiver); | 465 Handle<JSArray> array = Handle<JSArray>::cast(receiver); |
470 DCHECK(!array->map()->is_observed()); | 466 DCHECK(!array->map()->is_observed()); |
471 | 467 |
472 int len = Smi::cast(array->length())->value(); | 468 int len = Smi::cast(array->length())->value(); |
473 if (len == 0) return heap->undefined_value(); | 469 if (len == 0) return heap->undefined_value(); |
474 | 470 |
475 if (JSArray::HasReadOnlyLength(array)) { | 471 if (JSArray::HasReadOnlyLength(array)) { |
476 return CallJsBuiltin(isolate, "$arrayShift", args); | 472 return CallJsBuiltin(isolate, "$arrayShift", args); |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
559 } | 555 } |
560 | 556 |
561 // Set the length. | 557 // Set the length. |
562 array->set_length(Smi::FromInt(new_length)); | 558 array->set_length(Smi::FromInt(new_length)); |
563 return Smi::FromInt(new_length); | 559 return Smi::FromInt(new_length); |
564 } | 560 } |
565 | 561 |
566 | 562 |
567 BUILTIN(ArraySlice) { | 563 BUILTIN(ArraySlice) { |
568 HandleScope scope(isolate); | 564 HandleScope scope(isolate); |
569 Heap* heap = isolate->heap(); | |
570 Handle<Object> receiver = args.receiver(); | 565 Handle<Object> receiver = args.receiver(); |
571 int len = -1; | 566 int len = -1; |
572 int relative_start = 0; | 567 int relative_start = 0; |
573 int relative_end = 0; | 568 int relative_end = 0; |
574 { | 569 { |
575 DisallowHeapAllocation no_gc; | 570 DisallowHeapAllocation no_gc; |
576 if (receiver->IsJSArray()) { | 571 if (receiver->IsJSArray()) { |
577 JSArray* array = JSArray::cast(*receiver); | 572 JSArray* array = JSArray::cast(*receiver); |
578 if (!IsJSArrayFastElementMovingAllowed(heap, array)) { | 573 if (!IsJSArrayFastElementMovingAllowed(isolate, array)) { |
579 AllowHeapAllocation allow_allocation; | 574 AllowHeapAllocation allow_allocation; |
580 return CallJsBuiltin(isolate, "$arraySlice", args); | 575 return CallJsBuiltin(isolate, "$arraySlice", args); |
581 } | 576 } |
582 | 577 |
583 if (!array->HasFastElements()) { | 578 if (!array->HasFastElements()) { |
584 AllowHeapAllocation allow_allocation; | 579 AllowHeapAllocation allow_allocation; |
585 return CallJsBuiltin(isolate, "$arraySlice", args); | 580 return CallJsBuiltin(isolate, "$arraySlice", args); |
586 } | 581 } |
587 | 582 |
588 len = Smi::cast(array->length())->value(); | 583 len = Smi::cast(array->length())->value(); |
(...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
927 | 922 |
928 BUILTIN(ArrayConcat) { | 923 BUILTIN(ArrayConcat) { |
929 HandleScope scope(isolate); | 924 HandleScope scope(isolate); |
930 | 925 |
931 int n_arguments = args.length(); | 926 int n_arguments = args.length(); |
932 int result_len = 0; | 927 int result_len = 0; |
933 ElementsKind elements_kind = GetInitialFastElementsKind(); | 928 ElementsKind elements_kind = GetInitialFastElementsKind(); |
934 bool has_double = false; | 929 bool has_double = false; |
935 { | 930 { |
936 DisallowHeapAllocation no_gc; | 931 DisallowHeapAllocation no_gc; |
937 Heap* heap = isolate->heap(); | |
938 Context* native_context = isolate->context()->native_context(); | 932 Context* native_context = isolate->context()->native_context(); |
939 Object* array_proto = native_context->array_function()->prototype(); | 933 Object* array_proto = native_context->array_function()->prototype(); |
940 PrototypeIterator iter(isolate, array_proto, | 934 PrototypeIterator iter(isolate, array_proto, |
941 PrototypeIterator::START_AT_RECEIVER); | 935 PrototypeIterator::START_AT_RECEIVER); |
942 if (!ArrayPrototypeHasNoElements(heap, &iter)) { | 936 if (!ArrayPrototypeHasNoElements(&iter)) { |
943 AllowHeapAllocation allow_allocation; | 937 AllowHeapAllocation allow_allocation; |
944 return CallJsBuiltin(isolate, "$arrayConcat", args); | 938 return CallJsBuiltin(isolate, "$arrayConcat", args); |
945 } | 939 } |
946 | 940 |
947 // Iterate through all the arguments performing checks | 941 // Iterate through all the arguments performing checks |
948 // and calculating total length. | 942 // and calculating total length. |
949 bool is_holey = false; | 943 bool is_holey = false; |
950 for (int i = 0; i < n_arguments; i++) { | 944 for (int i = 0; i < n_arguments; i++) { |
951 Object* arg = args[i]; | 945 Object* arg = args[i]; |
952 PrototypeIterator iter(isolate, arg); | 946 PrototypeIterator iter(isolate, arg); |
(...skipping 698 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1651 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C) | 1645 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C) |
1652 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A) | 1646 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A) |
1653 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H) | 1647 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H) |
1654 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) | 1648 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) |
1655 #undef DEFINE_BUILTIN_ACCESSOR_C | 1649 #undef DEFINE_BUILTIN_ACCESSOR_C |
1656 #undef DEFINE_BUILTIN_ACCESSOR_A | 1650 #undef DEFINE_BUILTIN_ACCESSOR_A |
1657 | 1651 |
1658 | 1652 |
1659 } // namespace internal | 1653 } // namespace internal |
1660 } // namespace v8 | 1654 } // namespace v8 |
OLD | NEW |