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 556 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 567 | 567 |
| 568 if (!array->HasFastElements()) { | 568 if (!array->HasFastElements()) { |
| 569 AllowHeapAllocation allow_allocation; | 569 AllowHeapAllocation allow_allocation; |
| 570 return CallJsBuiltin(isolate, "ArraySlice", args); | 570 return CallJsBuiltin(isolate, "ArraySlice", args); |
| 571 } | 571 } |
| 572 | 572 |
| 573 len = Smi::cast(array->length())->value(); | 573 len = Smi::cast(array->length())->value(); |
| 574 } else { | 574 } else { |
| 575 // Array.slice(arguments, ...) is quite a common idiom (notably more | 575 // Array.slice(arguments, ...) is quite a common idiom (notably more |
| 576 // than 50% of invocations in Web apps). Treat it in C++ as well. | 576 // than 50% of invocations in Web apps). Treat it in C++ as well. |
| 577 Map* arguments_map = | 577 Map* sloppy_arguments_map = |
| 578 isolate->context()->native_context()->sloppy_arguments_map(); | 578 isolate->context()->native_context()->sloppy_arguments_map(); |
| 579 Map* strict_arguments_map = | |
| 580 isolate->context()->native_context()->strict_arguments_map(); | |
| 581 Map* aliased_arguments_map = | |
| 582 isolate->context()->native_context()->aliased_arguments_map(); | |
| 579 | 583 |
| 580 bool is_arguments_object_with_fast_elements = | 584 bool is_arguments_object_with_fast_elements = |
| 581 receiver->IsJSObject() && | 585 receiver->IsJSObject() && |
| 582 JSObject::cast(*receiver)->map() == arguments_map; | 586 (JSObject::cast(*receiver)->map() == sloppy_arguments_map || |
| 587 JSObject::cast(*receiver)->map() == strict_arguments_map || | |
| 588 JSObject::cast(*receiver)->map() == aliased_arguments_map); | |
| 583 if (!is_arguments_object_with_fast_elements) { | 589 if (!is_arguments_object_with_fast_elements) { |
| 584 AllowHeapAllocation allow_allocation; | 590 AllowHeapAllocation allow_allocation; |
| 585 return CallJsBuiltin(isolate, "ArraySlice", args); | 591 return CallJsBuiltin(isolate, "ArraySlice", args); |
| 586 } | 592 } |
| 587 JSObject* object = JSObject::cast(*receiver); | 593 JSObject* object = JSObject::cast(*receiver); |
| 588 | 594 |
| 589 if (!object->HasFastElements()) { | 595 if (!object->HasFastElements() && !object->HasSloppyArgumentsElements()) { |
| 590 AllowHeapAllocation allow_allocation; | 596 AllowHeapAllocation allow_allocation; |
| 591 return CallJsBuiltin(isolate, "ArraySlice", args); | 597 return CallJsBuiltin(isolate, "ArraySlice", args); |
| 592 } | 598 } |
| 593 | 599 |
| 594 Object* len_obj = object->InObjectPropertyAt(Heap::kArgumentsLengthIndex); | 600 Object* len_obj = object->InObjectPropertyAt(Heap::kArgumentsLengthIndex); |
| 595 if (!len_obj->IsSmi()) { | 601 if (!len_obj->IsSmi()) { |
| 596 AllowHeapAllocation allow_allocation; | 602 AllowHeapAllocation allow_allocation; |
| 597 return CallJsBuiltin(isolate, "ArraySlice", args); | 603 return CallJsBuiltin(isolate, "ArraySlice", args); |
| 598 } | 604 } |
| 599 len = Smi::cast(len_obj)->value(); | 605 len = Smi::cast(len_obj)->value(); |
| 600 if (len > object->elements()->length()) { | 606 if (object->map() == sloppy_arguments_map && |
|
Igor Sheludko
2015/01/30 14:13:29
Ok, elements of the |aliased_arguments_map| is a s
| |
| 607 len > object->elements()->length()) { | |
| 601 AllowHeapAllocation allow_allocation; | 608 AllowHeapAllocation allow_allocation; |
| 602 return CallJsBuiltin(isolate, "ArraySlice", args); | 609 return CallJsBuiltin(isolate, "ArraySlice", args); |
| 603 } | 610 } |
| 604 } | 611 } |
| 605 | 612 |
| 606 DCHECK(len >= 0); | 613 DCHECK(len >= 0); |
| 607 int n_arguments = args.length() - 1; | 614 int n_arguments = args.length() - 1; |
| 608 | 615 |
| 609 // Note carefully choosen defaults---if argument is missing, | 616 // Note carefully choosen defaults---if argument is missing, |
| 610 // it's undefined which gets converted to 0 for relative_start | 617 // it's undefined which gets converted to 0 for relative_start |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 653 int final = (relative_end < 0) ? Max(len + relative_end, 0) | 660 int final = (relative_end < 0) ? Max(len + relative_end, 0) |
| 654 : Min(relative_end, len); | 661 : Min(relative_end, len); |
| 655 | 662 |
| 656 // Calculate the length of result array. | 663 // Calculate the length of result array. |
| 657 int result_len = Max(final - k, 0); | 664 int result_len = Max(final - k, 0); |
| 658 | 665 |
| 659 Handle<JSObject> object = Handle<JSObject>::cast(receiver); | 666 Handle<JSObject> object = Handle<JSObject>::cast(receiver); |
| 660 Handle<FixedArrayBase> elms(object->elements(), isolate); | 667 Handle<FixedArrayBase> elms(object->elements(), isolate); |
| 661 | 668 |
| 662 ElementsKind kind = object->GetElementsKind(); | 669 ElementsKind kind = object->GetElementsKind(); |
| 670 if (kind == SLOPPY_ARGUMENTS_ELEMENTS) { | |
| 671 Handle<FixedArray> arguments( | |
| 672 FixedArray::cast(FixedArray::cast(*elms)->get(1))); | |
| 673 if (arguments->IsDictionary()) { | |
| 674 AllowHeapAllocation allow_allocation; | |
| 675 return CallJsBuiltin(isolate, "ArraySlice", args); | |
| 676 } | |
| 677 kind = FAST_HOLEY_ELEMENTS; | |
| 678 } | |
| 679 | |
| 663 if (IsHoleyElementsKind(kind)) { | 680 if (IsHoleyElementsKind(kind)) { |
| 664 DisallowHeapAllocation no_gc; | 681 DisallowHeapAllocation no_gc; |
| 665 bool packed = true; | 682 bool packed = true; |
| 666 ElementsAccessor* accessor = ElementsAccessor::ForKind(kind); | 683 ElementsAccessor* accessor = ElementsAccessor::ForKind(kind); |
| 667 for (int i = k; i < final; i++) { | 684 for (int i = k; i < final; i++) { |
| 668 if (!accessor->HasElement(object, object, i, elms)) { | 685 if (!accessor->HasElement(object, object, i, elms)) { |
| 669 packed = false; | 686 packed = false; |
| 670 break; | 687 break; |
| 671 } | 688 } |
| 672 } | 689 } |
| (...skipping 971 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1644 } | 1661 } |
| 1645 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C) | 1662 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C) |
| 1646 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A) | 1663 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A) |
| 1647 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H) | 1664 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H) |
| 1648 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) | 1665 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) |
| 1649 #undef DEFINE_BUILTIN_ACCESSOR_C | 1666 #undef DEFINE_BUILTIN_ACCESSOR_C |
| 1650 #undef DEFINE_BUILTIN_ACCESSOR_A | 1667 #undef DEFINE_BUILTIN_ACCESSOR_A |
| 1651 | 1668 |
| 1652 | 1669 |
| 1653 } } // namespace v8::internal | 1670 } } // namespace v8::internal |
| OLD | NEW |