diff --git a/src/compiler/graph-assembler.cc b/src/compiler/graph-assembler.cc index 367c7a7d97..a98899cb14 100644 --- a/src/compiler/graph-assembler.cc +++ b/src/compiler/graph-assembler.cc @@ -470,9 +470,14 @@ Node* JSGraphAssembler::StringCharCodeAt(TNode string, class ArrayBufferViewAccessBuilder { public: explicit ArrayBufferViewAccessBuilder(JSGraphAssembler* assembler, + InstanceType instance_type, std::set candidates) - : assembler_(assembler), candidates_(std::move(candidates)) { + : assembler_(assembler), + instance_type_(instance_type), + candidates_(std::move(candidates)) { DCHECK_NOT_NULL(assembler_); + DCHECK(instance_type_ == JS_DATA_VIEW_TYPE || + instance_type_ == JS_TYPED_ARRAY_TYPE); } bool maybe_rab_gsab() const { @@ -483,6 +488,7 @@ class ArrayBufferViewAccessBuilder { } base::Optional TryComputeStaticElementShift() { + if (instance_type_ == JS_DATA_VIEW_TYPE) return 0; if (candidates_.empty()) return base::nullopt; int shift = ElementsKindToShiftSize(*candidates_.begin()); if (!base::all_of(candidates_, [shift](auto e) { @@ -494,6 +500,7 @@ class ArrayBufferViewAccessBuilder { } base::Optional TryComputeStaticElementSize() { + if (instance_type_ == JS_DATA_VIEW_TYPE) return 1; if (candidates_.empty()) return base::nullopt; int size = ElementsKindToByteSize(*candidates_.begin()); if (!base::all_of(candidates_, [size](auto e) { @@ -540,6 +547,7 @@ class ArrayBufferViewAccessBuilder { if (auto size_opt = TryComputeStaticElementSize()) { element_size = a.Uint32Constant(*size_opt); } else { + DCHECK_EQ(instance_type_, JS_TYPED_ARRAY_TYPE); TNode typed_array_map = a.LoadField( AccessBuilder::ForMap(WriteBarrierKind::kNoWriteBarrier), view); TNode elements_kind = a.LoadElementsKind(typed_array_map); @@ -682,6 +690,7 @@ class ArrayBufferViewAccessBuilder { return TNode::UncheckedCast( a.WordAnd(byte_size, a.UintPtrConstant(all_bits << (*shift_opt)))); } + DCHECK_EQ(instance_type_, JS_TYPED_ARRAY_TYPE); TNode typed_array_map = a.LoadField( AccessBuilder::ForMap(WriteBarrierKind::kNoWriteBarrier), view); TNode elements_kind = a.LoadElementsKind(typed_array_map); @@ -751,13 +760,14 @@ class ArrayBufferViewAccessBuilder { } JSGraphAssembler* assembler_; + InstanceType instance_type_; std::set candidates_; }; TNode JSGraphAssembler::ArrayBufferViewByteLength( - TNode array_buffer_view, + TNode array_buffer_view, InstanceType instance_type, std::set elements_kinds_candidates, TNode context) { - ArrayBufferViewAccessBuilder builder(this, + ArrayBufferViewAccessBuilder builder(this, instance_type, std::move(elements_kinds_candidates)); return ExitMachineGraph( builder.BuildByteLength(array_buffer_view, context), @@ -768,7 +778,8 @@ TNode JSGraphAssembler::ArrayBufferViewByteLength( TNode JSGraphAssembler::TypedArrayLength( TNode typed_array, std::set elements_kinds_candidates, TNode context) { - ArrayBufferViewAccessBuilder builder(this, elements_kinds_candidates); + ArrayBufferViewAccessBuilder builder(this, JS_TYPED_ARRAY_TYPE, + elements_kinds_candidates); return ExitMachineGraph(builder.BuildLength(typed_array, context), MachineType::PointerRepresentation(), TypeCache::Get()->kJSTypedArrayLengthType); diff --git a/src/compiler/graph-assembler.h b/src/compiler/graph-assembler.h index c3b56f94e2..7246861c16 100644 --- a/src/compiler/graph-assembler.h +++ b/src/compiler/graph-assembler.h @@ -1034,7 +1034,7 @@ class V8_EXPORT_PRIVATE JSGraphAssembler : public GraphAssembler { // efficient code. Pass an empty {elements_kinds_candidates} to generate code // that is generic enough to handle all ElementsKinds. TNode ArrayBufferViewByteLength( - TNode array_buffer_view, + TNode array_buffer_view, InstanceType instance_type, std::set elements_kinds_candidates, TNode context); // Computes the length for a given {typed_array}. If the set of possible // ElementsKinds is known statically pass as {elements_kinds_candidates} to diff --git a/src/compiler/js-call-reducer.cc b/src/compiler/js-call-reducer.cc index 42b9f79209..69f272e453 100644 --- a/src/compiler/js-call-reducer.cc +++ b/src/compiler/js-call-reducer.cc @@ -7287,7 +7287,7 @@ Reduction JSCallReducer::ReduceArrayBufferViewByteLengthAccessor( TNode typed_array = TNode::UncheckedCast(receiver); TNode length = a.ArrayBufferViewByteLength( - typed_array, std::move(elements_kinds), a.ContextInput()); + typed_array, instance_type, std::move(elements_kinds), a.ContextInput()); return ReplaceWithSubgraph(&a, length); } @@ -7976,8 +7976,8 @@ Reduction JSCallReducer::ReduceDataViewAccess(Node* node, DataViewAccess access, } else { JSCallReducerAssembler a(this, node); byte_length = a.ArrayBufferViewByteLength( - TNode::UncheckedCast(receiver), {}, - a.ContextInput()); + TNode::UncheckedCast(receiver), JS_DATA_VIEW_TYPE, + {}, a.ContextInput()); std::tie(effect, control) = ReleaseEffectAndControlFromAssembler(&a); } diff --git a/test/mjsunit/regress/regress-1380398.js b/test/mjsunit/regress/regress-1380398.js new file mode 100644 index 0000000000..a6f07ba098 --- /dev/null +++ b/test/mjsunit/regress/regress-1380398.js @@ -0,0 +1,19 @@ +// Copyright 2022 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: --allow-natives-syntax --turbofan --harmony-rab-gsab + +function test() { + const ab = new ArrayBuffer(2996, { maxByteLength: 8588995 }); + const dv = new DataView(ab); + const len = dv.byteLength; + return len >= 255; +} + +%PrepareFunctionForOptimization(test); +assertTrue(test()); +assertTrue(test()); +%OptimizeFunctionOnNextCall(test); +assertTrue(test()); +assertOptimized(test);