aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Merger (Role) <noreply-android-build-merger@google.com>2018-05-03 21:23:08 +0000
committerAndroid Build Merger (Role) <noreply-android-build-merger@google.com>2018-05-03 21:23:08 +0000
commit05a61246f14ffde0d9554049a526294df6c1458e (patch)
treeaa94c8a3288b210a7058b40fe7279a2ede057dc9
parent36e9ff165057671a77b8167b225792f1f8ceef33 (diff)
parentd8c6189dcb76343d80f76907a1d728f8635bc20b (diff)
downloadv8-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.cc25
-rw-r--r--test/mjsunit/regress/regress-crbug-682194.js35
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]);
+}