| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 9ec87dc commit 2d3e735
2 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -795,14 +795,18 @@ namespace { | |||
| 795 | 795 | */ | |
| 796 | 796 | class ArrayConcatVisitor { | |
| 797 | 797 | public: | |
| 798 | - ArrayConcatVisitor(Isolate* isolate, Handle<Object> storage, | ||
| 798 | + ArrayConcatVisitor(Isolate* isolate, Handle<HeapObject> storage, | ||
| 799 | 799 | bool fast_elements) | |
| 800 | 800 | : isolate_(isolate), | |
| 801 | 801 | storage_(isolate->global_handles()->Create(*storage)), | |
| 802 | 802 | index_offset_(0u), | |
| 803 | - bit_field_(FastElementsField::encode(fast_elements) | | ||
| 804 | - ExceedsLimitField::encode(false) | | ||
| 805 | - IsFixedArrayField::encode(storage->IsFixedArray())) { | ||
| 803 | + bit_field_( | ||
| 804 | + FastElementsField::encode(fast_elements) | | ||
| 805 | + ExceedsLimitField::encode(false) | | ||
| 806 | + IsFixedArrayField::encode(storage->IsFixedArray()) | | ||
| 807 | + HasSimpleElementsField::encode(storage->IsFixedArray() || | ||
| 808 | + storage->map()->instance_type() > | ||
| 809 | + LAST_CUSTOM_ELEMENTS_RECEIVER)) { | ||
| 806 | 810 | DCHECK(!(this->fast_elements() && !is_fixed_array())); | |
| 807 | 811 | } | |
| 808 | 812 | ||
@@ -891,12 +895,16 @@ class ArrayConcatVisitor { | |||
| 891 | 895 | // (otherwise) | |
| 892 | 896 | Handle<FixedArray> storage_fixed_array() { | |
| 893 | 897 | DCHECK(is_fixed_array()); | |
| 898 | + DCHECK(has_simple_elements()); | ||
| 894 | 899 | return Handle<FixedArray>::cast(storage_); | |
| 895 | 900 | } | |
| 896 | 901 | Handle<JSReceiver> storage_jsreceiver() { | |
| 897 | 902 | DCHECK(!is_fixed_array()); | |
| 898 | 903 | return Handle<JSReceiver>::cast(storage_); | |
| 899 | 904 | } | |
| 905 | + bool has_simple_elements() const { | ||
| 906 | + return HasSimpleElementsField::decode(bit_field_); | ||
| 907 | + } | ||
| 900 | 908 | ||
| 901 | 909 | private: | |
| 902 | 910 | // Convert storage to dictionary mode. | |
@@ -929,12 +937,14 @@ class ArrayConcatVisitor { | |||
| 929 | 937 | ||
| 930 | 938 | inline void set_storage(FixedArray* storage) { | |
| 931 | 939 | DCHECK(is_fixed_array()); | |
| 940 | + DCHECK(has_simple_elements()); | ||
| 932 | 941 | storage_ = isolate_->global_handles()->Create(storage); | |
| 933 | 942 | } | |
| 934 | 943 | ||
| 935 | 944 | class FastElementsField : public BitField<bool, 0, 1> {}; | |
| 936 | 945 | class ExceedsLimitField : public BitField<bool, 1, 1> {}; | |
| 937 | 946 | class IsFixedArrayField : public BitField<bool, 2, 1> {}; | |
| 947 | + class HasSimpleElementsField : public BitField<bool, 3, 1> {}; | ||
| 938 | 948 | ||
| 939 | 949 | bool fast_elements() const { return FastElementsField::decode(bit_field_); } | |
| 940 | 950 | void set_fast_elements(bool fast) { | |
@@ -1166,8 +1176,6 @@ bool IterateElementsSlow(Isolate* isolate, Handle<JSReceiver> receiver, | |||
| 1166 | 1176 | visitor->increase_index_offset(length); | |
| 1167 | 1177 | return true; | |
| 1168 | 1178 | } | |
| 1169 | - | ||
| 1170 | - | ||
| 1171 | 1179 | /** | |
| 1172 | 1180 | * A helper function that visits "array" elements of a JSReceiver in numerical | |
| 1173 | 1181 | * order. | |
@@ -1201,7 +1209,8 @@ bool IterateElements(Isolate* isolate, Handle<JSReceiver> receiver, | |||
| 1201 | 1209 | return IterateElementsSlow(isolate, receiver, length, visitor); | |
| 1202 | 1210 | } | |
| 1203 | 1211 | ||
| 1204 | - if (!HasOnlySimpleElements(isolate, *receiver)) { | ||
| 1212 | + if (!HasOnlySimpleElements(isolate, *receiver) || | ||
| 1213 | + !visitor->has_simple_elements()) { | ||
| 1205 | 1214 | return IterateElementsSlow(isolate, receiver, length, visitor); | |
| 1206 | 1215 | } | |
| 1207 | 1216 | Handle<JSObject> array = Handle<JSObject>::cast(receiver); | |
@@ -1476,7 +1485,7 @@ Object* Slow_ArrayConcat(Arguments* args, Handle<Object> species, | |||
| 1476 | 1485 | // In case of failure, fall through. | |
| 1477 | 1486 | } | |
| 1478 | 1487 | ||
| 1479 | - Handle<Object> storage; | ||
| 1488 | + Handle<HeapObject> storage; | ||
| 1480 | 1489 | if (fast_case) { | |
| 1481 | 1490 | // The backing storage array must have non-existing elements to preserve | |
| 1482 | 1491 | // holes across concat operations. | |
@@ -1494,7 +1503,7 @@ Object* Slow_ArrayConcat(Arguments* args, Handle<Object> species, | |||
| 1494 | 1503 | ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | |
| 1495 | 1504 | isolate, storage_object, | |
| 1496 | 1505 | Execution::New(isolate, species, species, 1, &length)); | |
| 1497 | - storage = storage_object; | ||
| 1506 | + storage = Handle<HeapObject>::cast(storage_object); | ||
| 1498 | 1507 | } | |
| 1499 | 1508 | ||
| 1500 | 1509 | ArrayConcatVisitor visitor(isolate, storage, fast_case); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,35 @@ | |||
| 1 | + // Copyright 2017 the V8 project authors. All rights reserved. | ||
| 2 | + // Use of this source code is governed by a BSD-style license that can be | ||
| 3 | + // found in the LICENSE file. | ||
| 4 | + | ||
| 5 | + // Flags: --expose-gc | ||
| 6 | + | ||
| 7 | + var proxy = new Proxy([], { | ||
| 8 | + defineProperty() { | ||
| 9 | + w.length = 1; // shorten the array so the backstore pointer is relocated | ||
| 10 | + gc(); // force gc to move the array's elements backstore | ||
| 11 | + return Object.defineProperty.apply(this, arguments); | ||
| 12 | + } | ||
| 13 | + }); | ||
| 14 | + | ||
| 15 | + class MyArray extends Array { | ||
| 16 | + // custom constructor which returns a proxy object | ||
| 17 | + static get[Symbol.species](){ | ||
| 18 | + return function() { | ||
| 19 | + return proxy; | ||
| 20 | + } | ||
| 21 | + }; | ||
| 22 | + } | ||
| 23 | + | ||
| 24 | + var w = new MyArray(100); | ||
| 25 | + w[1] = 0.1; | ||
| 26 | + w[2] = 0.1; | ||
| 27 | + | ||
| 28 | + var result = Array.prototype.concat.call(w); | ||
| 29 | + | ||
| 30 | + assertEquals(undefined, result[0]); | ||
| 31 | + assertEquals(0.1, result[1]); | ||
| 32 | + | ||
| 33 | + for (var i = 2; i < 200; i++) { | ||
| 34 | + assertEquals(undefined, result[i]); | ||
| 35 | + } | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments