diff options
author | Android Build Merger (Role) <noreply-android-build-merger@google.com> | 2018-05-03 21:23:08 +0000 |
---|---|---|
committer | Android Build Merger (Role) <noreply-android-build-merger@google.com> | 2018-05-03 21:23:08 +0000 |
commit | 05a61246f14ffde0d9554049a526294df6c1458e (patch) | |
tree | aa94c8a3288b210a7058b40fe7279a2ede057dc9 | |
parent | 36e9ff165057671a77b8167b225792f1f8ceef33 (diff) | |
parent | d8c6189dcb76343d80f76907a1d728f8635bc20b (diff) | |
download | v8-05a61246f14ffde0d9554049a526294df6c1458e.tar.gz |
[automerger] [DO NOT MERGE] [runtime] Fix Array.prototype.concat with complex @@species am: d8c6189dcb
Change-Id: If9b9de9c4e9498be59a38fb586483b6aec644fb2
-rw-r--r-- | src/builtins.cc | 25 | ||||
-rw-r--r-- | test/mjsunit/regress/regress-crbug-682194.js | 35 |
2 files changed, 53 insertions, 7 deletions
diff --git a/src/builtins.cc b/src/builtins.cc index 24abb722..6b7dbd11 100644 --- a/src/builtins.cc +++ b/src/builtins.cc @@ -651,14 +651,18 @@ namespace { */ class ArrayConcatVisitor { public: - ArrayConcatVisitor(Isolate* isolate, Handle<Object> storage, + ArrayConcatVisitor(Isolate* isolate, Handle<HeapObject> storage, bool fast_elements) : isolate_(isolate), storage_(isolate->global_handles()->Create(*storage)), index_offset_(0u), - bit_field_(FastElementsField::encode(fast_elements) | - ExceedsLimitField::encode(false) | - IsFixedArrayField::encode(storage->IsFixedArray())) { + bit_field_( + FastElementsField::encode(fast_elements) | + ExceedsLimitField::encode(false) | + IsFixedArrayField::encode(storage->IsFixedArray()) | + HasSimpleElementsField::encode(storage->IsFixedArray() || + storage->map()->instance_type() > + LAST_CUSTOM_ELEMENTS_RECEIVER)) { DCHECK(!(this->fast_elements() && !is_fixed_array())); } @@ -747,12 +751,16 @@ class ArrayConcatVisitor { // (otherwise) Handle<FixedArray> storage_fixed_array() { DCHECK(is_fixed_array()); + DCHECK(has_simple_elements()); return Handle<FixedArray>::cast(storage_); } Handle<JSReceiver> storage_jsreceiver() { DCHECK(!is_fixed_array()); return Handle<JSReceiver>::cast(storage_); } + bool has_simple_elements() const { + return HasSimpleElementsField::decode(bit_field_); + } private: // Convert storage to dictionary mode. @@ -785,12 +793,14 @@ class ArrayConcatVisitor { inline void set_storage(FixedArray* storage) { DCHECK(is_fixed_array()); + DCHECK(has_simple_elements()); storage_ = isolate_->global_handles()->Create(storage); } class FastElementsField : public BitField<bool, 0, 1> {}; class ExceedsLimitField : public BitField<bool, 1, 1> {}; class IsFixedArrayField : public BitField<bool, 2, 1> {}; + class HasSimpleElementsField : public BitField<bool, 3, 1> {}; bool fast_elements() const { return FastElementsField::decode(bit_field_); } void set_fast_elements(bool fast) { @@ -1051,7 +1061,8 @@ bool IterateElements(Isolate* isolate, Handle<JSReceiver> receiver, return IterateElementsSlow(isolate, receiver, length, visitor); } - if (!HasOnlySimpleElements(isolate, *receiver)) { + if (!HasOnlySimpleElements(isolate, *receiver) || + !visitor->has_simple_elements()) { return IterateElementsSlow(isolate, receiver, length, visitor); } Handle<JSObject> array = Handle<JSObject>::cast(receiver); @@ -1320,7 +1331,7 @@ Object* Slow_ArrayConcat(BuiltinArguments* args, Handle<Object> species, // In case of failure, fall through. } - Handle<Object> storage; + Handle<HeapObject> storage; if (fast_case) { // The backing storage array must have non-existing elements to preserve // holes across concat operations. @@ -1338,7 +1349,7 @@ Object* Slow_ArrayConcat(BuiltinArguments* args, Handle<Object> species, ASSIGN_RETURN_FAILURE_ON_EXCEPTION( isolate, storage_object, Execution::New(isolate, species, species, 1, &length)); - storage = storage_object; + storage = Handle<HeapObject>::cast(storage_object); } ArrayConcatVisitor visitor(isolate, storage, fast_case); diff --git a/test/mjsunit/regress/regress-crbug-682194.js b/test/mjsunit/regress/regress-crbug-682194.js new file mode 100644 index 00000000..62a4347e --- /dev/null +++ b/test/mjsunit/regress/regress-crbug-682194.js @@ -0,0 +1,35 @@ +// Copyright 2017 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --expose-gc + +var proxy = new Proxy([], { + defineProperty() { + w.length = 1; // shorten the array so the backstore pointer is relocated + gc(); // force gc to move the array's elements backstore + return Object.defineProperty.apply(this, arguments); + } +}); + +class MyArray extends Array { + // custom constructor which returns a proxy object + static get[Symbol.species](){ + return function() { + return proxy; + } + }; +} + +var w = new MyArray(100); +w[1] = 0.1; +w[2] = 0.1; + +var result = Array.prototype.concat.call(w); + +assertEquals(undefined, result[0]); +assertEquals(0.1, result[1]); + +for (var i = 2; i < 200; i++) { + assertEquals(undefined, result[i]); +} |