[turbofan] Fix incorrect size shift computation for DataViews

Bug: v8:11111, chromium:1380398, chromium:1380990
Change-Id: I99ee88341d1119d1372210741ddccb0e2cd33bf7
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4002688
Auto-Submit: Nico Hartmann <nicohartmann@chromium.org>
Commit-Queue: Nico Hartmann <nicohartmann@chromium.org>
Commit-Queue: Jakob Kummerow <jkummerow@chromium.org>
Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/main@{#84045}
This commit is contained in:
Nico Hartmann 2022-11-03 15:49:36 +01:00 committed by V8 LUCI CQ
parent 46a5e5a750
commit 2caf5d18db
4 changed files with 38 additions and 8 deletions

View File

@ -470,9 +470,14 @@ Node* JSGraphAssembler::StringCharCodeAt(TNode<String> string,
class ArrayBufferViewAccessBuilder {
public:
explicit ArrayBufferViewAccessBuilder(JSGraphAssembler* assembler,
InstanceType instance_type,
std::set<ElementsKind> 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<int> 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<int> 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<Map> typed_array_map = a.LoadField<Map>(
AccessBuilder::ForMap(WriteBarrierKind::kNoWriteBarrier), view);
TNode<Uint32T> elements_kind = a.LoadElementsKind(typed_array_map);
@ -682,6 +690,7 @@ class ArrayBufferViewAccessBuilder {
return TNode<UintPtrT>::UncheckedCast(
a.WordAnd(byte_size, a.UintPtrConstant(all_bits << (*shift_opt))));
}
DCHECK_EQ(instance_type_, JS_TYPED_ARRAY_TYPE);
TNode<Map> typed_array_map = a.LoadField<Map>(
AccessBuilder::ForMap(WriteBarrierKind::kNoWriteBarrier), view);
TNode<Uint32T> elements_kind = a.LoadElementsKind(typed_array_map);
@ -751,13 +760,14 @@ class ArrayBufferViewAccessBuilder {
}
JSGraphAssembler* assembler_;
InstanceType instance_type_;
std::set<ElementsKind> candidates_;
};
TNode<Number> JSGraphAssembler::ArrayBufferViewByteLength(
TNode<JSArrayBufferView> array_buffer_view,
TNode<JSArrayBufferView> array_buffer_view, InstanceType instance_type,
std::set<ElementsKind> elements_kinds_candidates, TNode<Context> context) {
ArrayBufferViewAccessBuilder builder(this,
ArrayBufferViewAccessBuilder builder(this, instance_type,
std::move(elements_kinds_candidates));
return ExitMachineGraph<Number>(
builder.BuildByteLength(array_buffer_view, context),
@ -768,7 +778,8 @@ TNode<Number> JSGraphAssembler::ArrayBufferViewByteLength(
TNode<Number> JSGraphAssembler::TypedArrayLength(
TNode<JSTypedArray> typed_array,
std::set<ElementsKind> elements_kinds_candidates, TNode<Context> context) {
ArrayBufferViewAccessBuilder builder(this, elements_kinds_candidates);
ArrayBufferViewAccessBuilder builder(this, JS_TYPED_ARRAY_TYPE,
elements_kinds_candidates);
return ExitMachineGraph<Number>(builder.BuildLength(typed_array, context),
MachineType::PointerRepresentation(),
TypeCache::Get()->kJSTypedArrayLengthType);

View File

@ -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<Number> ArrayBufferViewByteLength(
TNode<JSArrayBufferView> array_buffer_view,
TNode<JSArrayBufferView> array_buffer_view, InstanceType instance_type,
std::set<ElementsKind> elements_kinds_candidates, TNode<Context> context);
// Computes the length for a given {typed_array}. If the set of possible
// ElementsKinds is known statically pass as {elements_kinds_candidates} to

View File

@ -7287,7 +7287,7 @@ Reduction JSCallReducer::ReduceArrayBufferViewByteLengthAccessor(
TNode<JSTypedArray> typed_array =
TNode<JSTypedArray>::UncheckedCast(receiver);
TNode<Number> 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<JSArrayBufferView>::UncheckedCast(receiver), {},
a.ContextInput());
TNode<JSArrayBufferView>::UncheckedCast(receiver), JS_DATA_VIEW_TYPE,
{}, a.ContextInput());
std::tie(effect, control) = ReleaseEffectAndControlFromAssembler(&a);
}

View File

@ -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);