| 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 |