Chromium Code Reviews| 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/arguments.h" | 8 #include "src/arguments.h" |
| 9 #include "src/base/once.h" | 9 #include "src/base/once.h" |
| 10 #include "src/bootstrapper.h" | 10 #include "src/bootstrapper.h" |
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 195 return false; | 195 return false; |
| 196 } | 196 } |
| 197 array_proto = JSObject::cast(iter.GetCurrent()); | 197 array_proto = JSObject::cast(iter.GetCurrent()); |
| 198 if (array_proto != native_context->initial_object_prototype()) return false; | 198 if (array_proto != native_context->initial_object_prototype()) return false; |
| 199 if (array_proto->elements() != heap->empty_fixed_array()) return false; | 199 if (array_proto->elements() != heap->empty_fixed_array()) return false; |
| 200 iter.Advance(); | 200 iter.Advance(); |
| 201 return iter.IsAtEnd(); | 201 return iter.IsAtEnd(); |
| 202 } | 202 } |
| 203 | 203 |
| 204 | 204 |
| 205 static inline bool IsJSArrayFastElementMovingAllowed(Heap* heap, | |
| 206 JSArray* receiver) { | |
| 207 if (!FLAG_clever_optimizations) return false; | |
| 208 DisallowHeapAllocation no_gc; | |
| 209 Context* native_context = heap->isolate()->context()->native_context(); | |
| 210 JSObject* array_proto = | |
| 211 JSObject::cast(native_context->array_function()->prototype()); | |
| 212 PrototypeIterator iter(heap->isolate(), receiver); | |
| 213 return iter.GetCurrent() == array_proto && | |
| 214 ArrayPrototypeHasNoElements(heap, native_context, array_proto); | |
| 215 } | |
| 216 | |
| 217 | |
| 205 // Returns empty handle if not applicable. | 218 // Returns empty handle if not applicable. |
| 206 MUST_USE_RESULT | 219 MUST_USE_RESULT |
| 207 static inline MaybeHandle<FixedArrayBase> EnsureJSArrayWithWritableFastElements( | 220 static inline MaybeHandle<FixedArrayBase> EnsureJSArrayWithWritableFastElements( |
| 208 Isolate* isolate, | 221 Isolate* isolate, |
| 209 Handle<Object> receiver, | 222 Handle<Object> receiver, |
| 210 Arguments* args, | 223 Arguments* args, |
| 211 int first_added_arg) { | 224 int first_added_arg) { |
| 212 if (!receiver->IsJSArray()) return MaybeHandle<FixedArrayBase>(); | 225 if (!receiver->IsJSArray()) return MaybeHandle<FixedArrayBase>(); |
| 213 Handle<JSArray> array = Handle<JSArray>::cast(receiver); | 226 Handle<JSArray> array = Handle<JSArray>::cast(receiver); |
| 214 // 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 |
| 215 // cannot be used if there arguments to add to the array. | 228 // cannot be used if there arguments to add to the array. |
| 216 if (args != NULL && array->map()->DictionaryElementsInPrototypeChainOnly()) { | 229 Heap* heap = isolate->heap(); |
| 230 if (args != NULL && !IsJSArrayFastElementMovingAllowed(heap, *array)) { | |
| 217 return MaybeHandle<FixedArrayBase>(); | 231 return MaybeHandle<FixedArrayBase>(); |
| 218 } | 232 } |
| 219 if (array->map()->is_observed()) return MaybeHandle<FixedArrayBase>(); | 233 if (array->map()->is_observed()) return MaybeHandle<FixedArrayBase>(); |
| 220 if (!array->map()->is_extensible()) return MaybeHandle<FixedArrayBase>(); | 234 if (!array->map()->is_extensible()) return MaybeHandle<FixedArrayBase>(); |
| 221 Handle<FixedArrayBase> elms(array->elements(), isolate); | 235 Handle<FixedArrayBase> elms(array->elements(), isolate); |
| 222 Heap* heap = isolate->heap(); | |
| 223 Map* map = elms->map(); | 236 Map* map = elms->map(); |
| 224 if (map == heap->fixed_array_map()) { | 237 if (map == heap->fixed_array_map()) { |
| 225 if (args == NULL || array->HasFastObjectElements()) return elms; | 238 if (args == NULL || array->HasFastObjectElements()) return elms; |
| 226 } else if (map == heap->fixed_cow_array_map()) { | 239 } else if (map == heap->fixed_cow_array_map()) { |
| 227 elms = JSObject::EnsureWritableFastElements(array); | 240 elms = JSObject::EnsureWritableFastElements(array); |
| 228 if (args == NULL || array->HasFastObjectElements()) return elms; | 241 if (args == NULL || array->HasFastObjectElements()) return elms; |
| 229 } else if (map == heap->fixed_double_array_map()) { | 242 } else if (map == heap->fixed_double_array_map()) { |
| 230 if (args == NULL) return elms; | 243 if (args == NULL) return elms; |
| 231 } else { | 244 } else { |
| 232 return MaybeHandle<FixedArrayBase>(); | 245 return MaybeHandle<FixedArrayBase>(); |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 257 } | 270 } |
| 258 } | 271 } |
| 259 if (target_kind != origin_kind) { | 272 if (target_kind != origin_kind) { |
| 260 JSObject::TransitionElementsKind(array, target_kind); | 273 JSObject::TransitionElementsKind(array, target_kind); |
| 261 return handle(array->elements(), isolate); | 274 return handle(array->elements(), isolate); |
| 262 } | 275 } |
| 263 return elms; | 276 return elms; |
| 264 } | 277 } |
| 265 | 278 |
| 266 | 279 |
| 267 static inline bool IsJSArrayFastElementMovingAllowed(Heap* heap, | |
| 268 JSArray* receiver) { | |
| 269 if (!FLAG_clever_optimizations) return false; | |
| 270 DisallowHeapAllocation no_gc; | |
| 271 Context* native_context = heap->isolate()->context()->native_context(); | |
| 272 JSObject* array_proto = | |
| 273 JSObject::cast(native_context->array_function()->prototype()); | |
| 274 PrototypeIterator iter(heap->isolate(), receiver); | |
| 275 return iter.GetCurrent() == array_proto && | |
| 276 ArrayPrototypeHasNoElements(heap, native_context, array_proto); | |
| 277 } | |
| 278 | |
| 279 | |
| 280 MUST_USE_RESULT static Object* CallJsBuiltin( | 280 MUST_USE_RESULT static Object* CallJsBuiltin( |
| 281 Isolate* isolate, | 281 Isolate* isolate, |
| 282 const char* name, | 282 const char* name, |
| 283 BuiltinArguments<NO_EXTRA_ARGUMENTS> args) { | 283 BuiltinArguments<NO_EXTRA_ARGUMENTS> args) { |
| 284 HandleScope handleScope(isolate); | 284 HandleScope handleScope(isolate); |
| 285 | 285 |
| 286 Handle<Object> js_builtin = Object::GetProperty( | 286 Handle<Object> js_builtin = Object::GetProperty( |
| 287 isolate, | 287 isolate, |
| 288 handle(isolate->native_context()->builtins(), isolate), | 288 handle(isolate->native_context()->builtins(), isolate), |
| 289 name).ToHandleChecked(); | 289 name).ToHandleChecked(); |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 446 | 446 |
| 447 | 447 |
| 448 BUILTIN(ArrayShift) { | 448 BUILTIN(ArrayShift) { |
| 449 HandleScope scope(isolate); | 449 HandleScope scope(isolate); |
| 450 Heap* heap = isolate->heap(); | 450 Heap* heap = isolate->heap(); |
| 451 Handle<Object> receiver = args.receiver(); | 451 Handle<Object> receiver = args.receiver(); |
| 452 MaybeHandle<FixedArrayBase> maybe_elms_obj = | 452 MaybeHandle<FixedArrayBase> maybe_elms_obj = |
| 453 EnsureJSArrayWithWritableFastElements(isolate, receiver, NULL, 0); | 453 EnsureJSArrayWithWritableFastElements(isolate, receiver, NULL, 0); |
| 454 Handle<FixedArrayBase> elms_obj; | 454 Handle<FixedArrayBase> elms_obj; |
| 455 if (!maybe_elms_obj.ToHandle(&elms_obj) || | 455 if (!maybe_elms_obj.ToHandle(&elms_obj) || |
| 456 !IsJSArrayFastElementMovingAllowed(heap, | 456 !IsJSArrayFastElementMovingAllowed(heap, JSArray::cast(*receiver))) { |
| 457 *Handle<JSArray>::cast(receiver))) { | |
| 458 return CallJsBuiltin(isolate, "ArrayShift", args); | 457 return CallJsBuiltin(isolate, "ArrayShift", args); |
| 459 } | 458 } |
| 460 Handle<JSArray> array = Handle<JSArray>::cast(receiver); | 459 Handle<JSArray> array = Handle<JSArray>::cast(receiver); |
| 461 DCHECK(!array->map()->is_observed()); | 460 DCHECK(!array->map()->is_observed()); |
| 462 | 461 |
| 463 int len = Smi::cast(array->length())->value(); | 462 int len = Smi::cast(array->length())->value(); |
| 464 if (len == 0) return heap->undefined_value(); | 463 if (len == 0) return heap->undefined_value(); |
| 465 | 464 |
| 466 // Get first element | 465 // Get first element |
| 467 ElementsAccessor* accessor = array->GetElementsAccessor(); | 466 ElementsAccessor* accessor = array->GetElementsAccessor(); |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 492 | 491 |
| 493 return *first; | 492 return *first; |
| 494 } | 493 } |
| 495 | 494 |
| 496 | 495 |
| 497 BUILTIN(ArrayUnshift) { | 496 BUILTIN(ArrayUnshift) { |
| 498 HandleScope scope(isolate); | 497 HandleScope scope(isolate); |
| 499 Heap* heap = isolate->heap(); | 498 Heap* heap = isolate->heap(); |
| 500 Handle<Object> receiver = args.receiver(); | 499 Handle<Object> receiver = args.receiver(); |
| 501 MaybeHandle<FixedArrayBase> maybe_elms_obj = | 500 MaybeHandle<FixedArrayBase> maybe_elms_obj = |
| 502 EnsureJSArrayWithWritableFastElements(isolate, receiver, NULL, 0); | 501 EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 1); |
| 503 Handle<FixedArrayBase> elms_obj; | 502 Handle<FixedArrayBase> elms_obj; |
| 504 if (!maybe_elms_obj.ToHandle(&elms_obj) || | 503 if (!maybe_elms_obj.ToHandle(&elms_obj)) { |
| 505 !IsJSArrayFastElementMovingAllowed(heap, | |
| 506 *Handle<JSArray>::cast(receiver))) { | |
| 507 return CallJsBuiltin(isolate, "ArrayUnshift", args); | 504 return CallJsBuiltin(isolate, "ArrayUnshift", args); |
| 508 } | 505 } |
| 509 Handle<JSArray> array = Handle<JSArray>::cast(receiver); | 506 Handle<JSArray> array = Handle<JSArray>::cast(receiver); |
| 510 DCHECK(!array->map()->is_observed()); | 507 DCHECK(!array->map()->is_observed()); |
| 511 if (!array->HasFastSmiOrObjectElements()) { | 508 if (!array->HasFastSmiOrObjectElements()) { |
| 512 return CallJsBuiltin(isolate, "ArrayUnshift", args); | 509 return CallJsBuiltin(isolate, "ArrayUnshift", args); |
| 513 } | 510 } |
| 514 int len = Smi::cast(array->length())->value(); | 511 int len = Smi::cast(array->length())->value(); |
| 515 int to_add = args.length() - 1; | 512 int to_add = args.length() - 1; |
| 516 int new_length = len + to_add; | 513 int new_length = len + to_add; |
| 517 // Currently fixed arrays cannot grow too big, so | 514 // Currently fixed arrays cannot grow too big, so |
| 518 // we should never hit this case. | 515 // we should never hit this case. |
| 519 DCHECK(to_add <= (Smi::kMaxValue - len)); | 516 DCHECK(to_add <= (Smi::kMaxValue - len)); |
| 520 | 517 |
| 521 if (to_add > 0 && JSArray::WouldChangeReadOnlyLength(array, len + to_add)) { | 518 if (to_add > 0 && JSArray::WouldChangeReadOnlyLength(array, len + to_add)) { |
| 522 return CallJsBuiltin(isolate, "ArrayUnshift", args); | 519 return CallJsBuiltin(isolate, "ArrayUnshift", args); |
| 523 } | 520 } |
| 524 | 521 |
| 525 Handle<FixedArray> elms = Handle<FixedArray>::cast(elms_obj); | 522 Handle<FixedArray> elms = Handle<FixedArray>::cast(elms_obj); |
| 526 | 523 |
| 527 JSObject::EnsureCanContainElements(array, &args, 1, to_add, | |
| 528 DONT_ALLOW_DOUBLE_ELEMENTS); | |
|
mvstanton
2014/11/03 12:59:13
nit: should prolly be in another CL but up to you.
| |
| 529 | |
| 530 if (new_length > elms->length()) { | 524 if (new_length > elms->length()) { |
| 531 // New backing storage is needed. | 525 // New backing storage is needed. |
| 532 int capacity = new_length + (new_length >> 1) + 16; | 526 int capacity = new_length + (new_length >> 1) + 16; |
| 533 Handle<FixedArray> new_elms = | 527 Handle<FixedArray> new_elms = |
| 534 isolate->factory()->NewUninitializedFixedArray(capacity); | 528 isolate->factory()->NewUninitializedFixedArray(capacity); |
| 535 | 529 |
| 536 ElementsKind kind = array->GetElementsKind(); | 530 ElementsKind kind = array->GetElementsKind(); |
| 537 ElementsAccessor* accessor = array->GetElementsAccessor(); | 531 ElementsAccessor* accessor = array->GetElementsAccessor(); |
| 538 accessor->CopyElements( | 532 accessor->CopyElements( |
| 539 elms, 0, kind, new_elms, to_add, | 533 elms, 0, kind, new_elms, to_add, |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 701 } | 695 } |
| 702 | 696 |
| 703 | 697 |
| 704 BUILTIN(ArraySplice) { | 698 BUILTIN(ArraySplice) { |
| 705 HandleScope scope(isolate); | 699 HandleScope scope(isolate); |
| 706 Heap* heap = isolate->heap(); | 700 Heap* heap = isolate->heap(); |
| 707 Handle<Object> receiver = args.receiver(); | 701 Handle<Object> receiver = args.receiver(); |
| 708 MaybeHandle<FixedArrayBase> maybe_elms_obj = | 702 MaybeHandle<FixedArrayBase> maybe_elms_obj = |
| 709 EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 3); | 703 EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 3); |
| 710 Handle<FixedArrayBase> elms_obj; | 704 Handle<FixedArrayBase> elms_obj; |
| 711 if (!maybe_elms_obj.ToHandle(&elms_obj) || | 705 if (!maybe_elms_obj.ToHandle(&elms_obj)) { |
| 712 !IsJSArrayFastElementMovingAllowed(heap, | |
| 713 *Handle<JSArray>::cast(receiver))) { | |
| 714 return CallJsBuiltin(isolate, "ArraySplice", args); | 706 return CallJsBuiltin(isolate, "ArraySplice", args); |
| 715 } | 707 } |
| 716 Handle<JSArray> array = Handle<JSArray>::cast(receiver); | 708 Handle<JSArray> array = Handle<JSArray>::cast(receiver); |
| 717 DCHECK(!array->map()->is_observed()); | 709 DCHECK(!array->map()->is_observed()); |
| 718 | 710 |
| 719 int len = Smi::cast(array->length())->value(); | 711 int len = Smi::cast(array->length())->value(); |
| 720 | 712 |
| 721 int n_arguments = args.length() - 1; | 713 int n_arguments = args.length() - 1; |
| 722 | 714 |
| 723 int relative_start = 0; | 715 int relative_start = 0; |
| (...skipping 926 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1650 } | 1642 } |
| 1651 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C) | 1643 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C) |
| 1652 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A) | 1644 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A) |
| 1653 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H) | 1645 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H) |
| 1654 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) | 1646 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) |
| 1655 #undef DEFINE_BUILTIN_ACCESSOR_C | 1647 #undef DEFINE_BUILTIN_ACCESSOR_C |
| 1656 #undef DEFINE_BUILTIN_ACCESSOR_A | 1648 #undef DEFINE_BUILTIN_ACCESSOR_A |
| 1657 | 1649 |
| 1658 | 1650 |
| 1659 } } // namespace v8::internal | 1651 } } // namespace v8::internal |
| OLD | NEW |