[maglev] Consider DataView/TypedArray backed by RAB and GSAB
- For TypedArrays, we bail out trying to reduce the access. - For DataView, we check dynamically the DataView object bitfield and call a builtin on a slow path. Drive by: fix presubmit lint to allow assertOptimized when passing --maglev flag. Bug: v8:7700, v8:13645 Change-Id: I3ce4773466f045ff10c86c41734e00fbb94eb331 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4146435 Commit-Queue: Victor Gomes <victorgomes@chromium.org> Reviewed-by: Marja Hölttä <marja@chromium.org> Reviewed-by: Darius Mercadier <dmercadier@chromium.org> Auto-Submit: Victor Gomes <victorgomes@chromium.org> Cr-Commit-Position: refs/heads/main@{#85171}
This commit is contained in:
parent
82c7f93aeb
commit
eb00054f61
@ -1454,24 +1454,51 @@ void CheckJSTypedArrayBounds::GenerateCode(MaglevAssembler* masm,
|
||||
__ EmitEagerDeoptIf(lo, DeoptimizeReason::kOutOfBounds, this);
|
||||
}
|
||||
|
||||
int CheckJSDataViewBounds::MaxCallStackArgs() const { return 1; }
|
||||
void CheckJSDataViewBounds::SetValueLocationConstraints() {
|
||||
UseRegister(receiver_input());
|
||||
UseRegister(index_input());
|
||||
set_temporaries_needed(1);
|
||||
}
|
||||
void CheckJSDataViewBounds::GenerateCode(MaglevAssembler* masm,
|
||||
const ProcessingState& state) {
|
||||
Register object = ToRegister(receiver_input());
|
||||
Register index = ToRegister(index_input());
|
||||
Register byte_length = kScratchRegister;
|
||||
Register scratch = general_temporaries().PopFirst();
|
||||
Register byte_length = scratch;
|
||||
if (v8_flags.debug_code) {
|
||||
__ AssertNotSmi(object);
|
||||
UseScratchRegisterScope temps(masm);
|
||||
Register scratch = temps.AcquireX();
|
||||
__ CompareObjectType(object, scratch, scratch, JS_DATA_VIEW_TYPE);
|
||||
__ Assert(eq, AbortReason::kUnexpectedValue);
|
||||
}
|
||||
|
||||
ZoneLabelRef done_byte_length(masm);
|
||||
DeferredCodeInfo* deferred_get_byte_length = __ PushDeferredCode(
|
||||
[](MaglevAssembler* masm, CheckJSDataViewBounds* node, ZoneLabelRef done,
|
||||
Register object, Register index, Register byte_length) {
|
||||
RegisterSnapshot snapshot = node->register_snapshot();
|
||||
snapshot.live_registers.set(index); // Make sure index is saved.
|
||||
{
|
||||
// TODO(v8:7700): Inline DataViewPrototypeGetByteLength or create a
|
||||
// different builtin that does not re-check the DataView object.
|
||||
SaveRegisterStateForCall save_register_state(masm, snapshot);
|
||||
__ Mov(kContextRegister, masm->native_context().object());
|
||||
__ Mov(kJavaScriptCallArgCountRegister, 1);
|
||||
__ Push(object);
|
||||
__ CallBuiltin(Builtin::kDataViewPrototypeGetByteLength);
|
||||
}
|
||||
__ SmiUntag(byte_length, kReturnRegister0);
|
||||
__ B(*done);
|
||||
},
|
||||
this, done_byte_length, object, index, byte_length);
|
||||
__ Ldr(scratch.W(), FieldMemOperand(object, JSDataView::kBitFieldOffset));
|
||||
__ Cbnz(scratch.W(), &deferred_get_byte_length->deferred_code_label);
|
||||
|
||||
// Normal DataView (backed by AB / SAB) or non-length tracking backed by GSAB.
|
||||
__ LoadBoundedSizeFromObject(byte_length, object,
|
||||
JSDataView::kRawByteLengthOffset);
|
||||
__ bind(*done_byte_length);
|
||||
|
||||
int element_size = ExternalArrayElementSize(element_type_);
|
||||
if (element_size > 1) {
|
||||
__ Cmp(byte_length, Immediate(element_size - 1));
|
||||
|
@ -2212,6 +2212,10 @@ bool MaglevGraphBuilder::TryBuildElementAccess(
|
||||
|
||||
// TODO(victorgomes): Support more elements kind.
|
||||
ElementsKind elements_kind = access_info.elements_kind();
|
||||
if (IsRabGsabTypedArrayElementsKind(elements_kind)) {
|
||||
// TODO(victorgomes): Support RAB/GSAB backed typed arrays.
|
||||
return false;
|
||||
}
|
||||
if (IsTypedArrayElementsKind(elements_kind)) {
|
||||
if (JSTypedArray::kMaxSizeInHeap != 0) {
|
||||
// TODO(dmercadier): re-enable support for in-heap Typed Arrays.
|
||||
|
@ -3782,7 +3782,8 @@ class CheckJSDataViewBounds : public FixedInputNodeT<2, CheckJSDataViewBounds> {
|
||||
ExternalArrayType element_type)
|
||||
: Base(bitfield), element_type_(element_type) {}
|
||||
|
||||
static constexpr OpProperties kProperties = OpProperties::EagerDeopt();
|
||||
static constexpr OpProperties kProperties =
|
||||
OpProperties::EagerDeopt() | OpProperties::DeferredCall();
|
||||
static constexpr typename Base::InputTypes kInputTypes{
|
||||
ValueRepresentation::kTagged, ValueRepresentation::kInt32};
|
||||
|
||||
@ -3791,6 +3792,7 @@ class CheckJSDataViewBounds : public FixedInputNodeT<2, CheckJSDataViewBounds> {
|
||||
Input& receiver_input() { return input(kReceiverIndex); }
|
||||
Input& index_input() { return input(kIndexIndex); }
|
||||
|
||||
int MaxCallStackArgs() const;
|
||||
void SetValueLocationConstraints();
|
||||
void GenerateCode(MaglevAssembler*, const ProcessingState&);
|
||||
void PrintParams(std::ostream&, MaglevGraphLabeller*) const {}
|
||||
|
@ -507,6 +507,7 @@ void CheckJSTypedArrayBounds::GenerateCode(MaglevAssembler* masm,
|
||||
__ EmitEagerDeoptIf(above_equal, DeoptimizeReason::kOutOfBounds, this);
|
||||
}
|
||||
|
||||
int CheckJSDataViewBounds::MaxCallStackArgs() const { return 1; }
|
||||
void CheckJSDataViewBounds::SetValueLocationConstraints() {
|
||||
UseRegister(receiver_input());
|
||||
UseRegister(index_input());
|
||||
@ -521,8 +522,35 @@ void CheckJSDataViewBounds::GenerateCode(MaglevAssembler* masm,
|
||||
__ CmpObjectType(object, JS_DATA_VIEW_TYPE, kScratchRegister);
|
||||
__ Assert(equal, AbortReason::kUnexpectedValue);
|
||||
}
|
||||
|
||||
ZoneLabelRef done_byte_length(masm);
|
||||
__ movl(kScratchRegister, FieldOperand(object, JSDataView::kBitFieldOffset));
|
||||
__ testb(kScratchRegister, kScratchRegister);
|
||||
__ JumpToDeferredIf(
|
||||
not_zero,
|
||||
[](MaglevAssembler* masm, CheckJSDataViewBounds* node, ZoneLabelRef done,
|
||||
Register object, Register index, Register byte_length) {
|
||||
RegisterSnapshot snapshot = node->register_snapshot();
|
||||
snapshot.live_registers.set(index); // Make sure index is saved.
|
||||
{
|
||||
// TODO(v8:7700): Inline DataViewPrototypeGetByteLength or create a
|
||||
// different builtin that does not re-check the DataView object.
|
||||
SaveRegisterStateForCall save_register_state(masm, snapshot);
|
||||
__ Move(kContextRegister, masm->native_context().object());
|
||||
__ Move(kJavaScriptCallArgCountRegister, 1);
|
||||
__ Push(object);
|
||||
__ CallBuiltin(Builtin::kDataViewPrototypeGetByteLength);
|
||||
}
|
||||
__ SmiUntag(byte_length, kReturnRegister0);
|
||||
__ jmp(*done);
|
||||
},
|
||||
this, done_byte_length, object, index, byte_length);
|
||||
|
||||
// Normal DataView (backed by AB / SAB) or non-length tracking backed by GSAB.
|
||||
__ LoadBoundedSizeFromObject(byte_length, object,
|
||||
JSDataView::kRawByteLengthOffset);
|
||||
__ bind(*done_byte_length);
|
||||
|
||||
int element_size = ExternalArrayElementSize(element_type_);
|
||||
if (element_size > 1) {
|
||||
__ subq(byte_length, Immediate(element_size - 1));
|
||||
|
815
test/mjsunit/maglev/typedarray-resizablearraybuffer.js
Normal file
815
test/mjsunit/maglev/typedarray-resizablearraybuffer.js
Normal file
@ -0,0 +1,815 @@
|
||||
// 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: --harmony-rab-gsab --allow-natives-syntax --maglev
|
||||
// Flags: --no-always-turbofan --turbo-rab-gsab
|
||||
|
||||
"use strict";
|
||||
|
||||
d8.file.execute('test/mjsunit/typedarray-helpers.js');
|
||||
|
||||
const is_little_endian = (() => {
|
||||
var buffer = new ArrayBuffer(4);
|
||||
const HEAP32 = new Int32Array(buffer);
|
||||
const HEAPU8 = new Uint8Array(buffer);
|
||||
HEAP32[0] = 255;
|
||||
return (HEAPU8[0] === 255 && HEAPU8[3] === 0);
|
||||
})();
|
||||
|
||||
function FillBuffer(buffer) {
|
||||
const view = new Uint8Array(buffer);
|
||||
for (let i = 0; i < view.length; ++i) {
|
||||
view[i] = i;
|
||||
}
|
||||
}
|
||||
%NeverOptimizeFunction(FillBuffer);
|
||||
|
||||
function asU16(index) {
|
||||
const start = index * 2;
|
||||
if (is_little_endian) {
|
||||
return (start + 1) * 256 + start;
|
||||
} else {
|
||||
return start * 256 + start + 1;
|
||||
}
|
||||
}
|
||||
%NeverOptimizeFunction(asU16);
|
||||
|
||||
function asU32(index) {
|
||||
const start = index * 4;
|
||||
if (is_little_endian) {
|
||||
return (((start + 3) * 256 + start + 2) * 256 + start + 1) * 256 + start;
|
||||
} else {
|
||||
return ((((start * 256) + start + 1) * 256) + start + 2) * 256 + start + 3;
|
||||
}
|
||||
}
|
||||
%NeverOptimizeFunction(asU32);
|
||||
|
||||
function asF32(index) {
|
||||
const start = index * 4;
|
||||
const ab = new ArrayBuffer(4);
|
||||
const ta = new Uint8Array(ab);
|
||||
for (let i = 0; i < 4; ++i) ta[i] = start + i;
|
||||
return new Float32Array(ab)[0];
|
||||
}
|
||||
%NeverOptimizeFunction(asF32);
|
||||
|
||||
function asF64(index) {
|
||||
const start = index * 8;
|
||||
const ab = new ArrayBuffer(8);
|
||||
const ta = new Uint8Array(ab);
|
||||
for (let i = 0; i < 8; ++i) ta[i] = start + i;
|
||||
return new Float64Array(ab)[0];
|
||||
}
|
||||
%NeverOptimizeFunction(asF64);
|
||||
|
||||
function asB64(index) {
|
||||
const start = index * 8;
|
||||
let result = 0n;
|
||||
if (is_little_endian) {
|
||||
for (let i = 0; i < 8; ++i) {
|
||||
result = result << 8n;
|
||||
result += BigInt(start + 7 - i);
|
||||
}
|
||||
} else {
|
||||
for (let i = 0; i < 8; ++i) {
|
||||
result = result << 8n;
|
||||
result += BigInt(start + i);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
%NeverOptimizeFunction(asB64);
|
||||
|
||||
function CreateBuffer(shared, len, max_len) {
|
||||
return shared ? new SharedArrayBuffer(len, {maxByteLength: max_len}) :
|
||||
new ArrayBuffer(len, {maxByteLength: max_len});
|
||||
}
|
||||
%NeverOptimizeFunction(CreateBuffer);
|
||||
|
||||
function MakeResize(target, shared, offset, fixed_len) {
|
||||
const bpe = target.name === 'DataView' ? 1 : target.BYTES_PER_ELEMENT;
|
||||
function RoundDownToElementSize(blen) {
|
||||
return Math.floor(blen / bpe) * bpe;
|
||||
}
|
||||
if (!shared) {
|
||||
if (fixed_len === undefined) {
|
||||
return (b, len) => {
|
||||
b.resize(len);
|
||||
const blen = Math.max(0, len - offset);
|
||||
return RoundDownToElementSize(blen);
|
||||
};
|
||||
} else {
|
||||
const fixed_blen = fixed_len * bpe;
|
||||
return (b, len) => {
|
||||
b.resize(len);
|
||||
const blen = fixed_blen <= (len - offset) ? fixed_blen : 0;
|
||||
return RoundDownToElementSize(blen);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (fixed_len === undefined) {
|
||||
return (b, len) => {
|
||||
let blen = 0;
|
||||
if (len > b.byteLength) {
|
||||
b.grow(len);
|
||||
blen = Math.max(0, len - offset);
|
||||
} else {
|
||||
blen = b.byteLength - offset;
|
||||
}
|
||||
return RoundDownToElementSize(blen);
|
||||
};
|
||||
} else {
|
||||
return (b, len) => {
|
||||
if (len > b.byteLength) {
|
||||
b.grow(len);
|
||||
}
|
||||
return fixed_len * bpe;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
%NeverOptimizeFunction(MakeResize);
|
||||
|
||||
function MakeElement(target, offset) {
|
||||
const o = offset / target.BYTES_PER_ELEMENT;
|
||||
if (target.name === 'Int8Array') {
|
||||
return (index) => {
|
||||
return o + index;
|
||||
};
|
||||
} else if (target.name === 'Uint32Array') {
|
||||
return (index) => {
|
||||
return asU32(o + index);
|
||||
};
|
||||
} else if (target.name === 'Float64Array') {
|
||||
return (index) => {
|
||||
return asF64(o + index);
|
||||
};
|
||||
} else if (target.name === 'BigInt64Array') {
|
||||
return (index) => {
|
||||
return asB64(o + index);
|
||||
};
|
||||
} else {
|
||||
console.log(`unimplemented: MakeElement(${target.name})`);
|
||||
return () => undefined;
|
||||
}
|
||||
}
|
||||
%NeverOptimizeFunction(MakeElement);
|
||||
|
||||
function MakeCheckBuffer(target, offset) {
|
||||
return (ab, up_to) => {
|
||||
const view = new Uint8Array(ab);
|
||||
for (let i = 0; i < offset; ++i) {
|
||||
assertEquals(0, view[i]);
|
||||
}
|
||||
for (let i = 0; i < (up_to * target.BYTES_PER_ELEMENT) + 1; ++i) {
|
||||
// Use PrintBuffer(ab) for debugging.
|
||||
assertEquals(offset + i, view[offset + i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
%NeverOptimizeFunction(MakeCheckBuffer);
|
||||
|
||||
function ClearBuffer(ab) {
|
||||
for (let i = 0; i < ab.byteLength; ++i) ab[i] = 0;
|
||||
}
|
||||
%NeverOptimizeFunction(ClearBuffer);
|
||||
|
||||
// Use this for debugging these tests.
|
||||
function PrintBuffer(buffer) {
|
||||
const view = new Uint8Array(buffer);
|
||||
for (let i = 0; i < 32; ++i) {
|
||||
console.log(`[${i}]: ${view[i]}`)
|
||||
}
|
||||
}
|
||||
%NeverOptimizeFunction(PrintBuffer);
|
||||
|
||||
(function() {
|
||||
for (let shared of [false, true]) {
|
||||
for (let length_tracking of [false, true]) {
|
||||
for (let with_offset of [false, true]) {
|
||||
for (let target
|
||||
of [Int8Array, Uint32Array, Float64Array, BigInt64Array]) {
|
||||
const test_case = `Testing: Length_${shared ? 'GSAB' : 'RAB'}_${
|
||||
length_tracking ? 'LengthTracking' : 'FixedLength'}${
|
||||
with_offset ? 'WithOffset' : ''}_${target.name}`;
|
||||
// console.log(test_case);
|
||||
|
||||
const byte_length_code = 'return ta.byteLength; // ' + test_case;
|
||||
const ByteLength = new Function('ta', byte_length_code);
|
||||
const length_code = 'return ta.length; // ' + test_case;
|
||||
const Length = new Function('ta', length_code);
|
||||
const offset = with_offset ? 8 : 0;
|
||||
|
||||
let blen = 16 - offset;
|
||||
const fixed_len =
|
||||
length_tracking ? undefined : (blen / target.BYTES_PER_ELEMENT);
|
||||
const ab = CreateBuffer(shared, 16, 40);
|
||||
const ta = new target(ab, offset, fixed_len);
|
||||
const Resize = MakeResize(target, shared, offset, fixed_len);
|
||||
|
||||
assertUnoptimized(ByteLength);
|
||||
assertUnoptimized(Length);
|
||||
%PrepareFunctionForOptimization(ByteLength);
|
||||
%PrepareFunctionForOptimization(Length);
|
||||
assertEquals(blen, ByteLength(ta));
|
||||
assertEquals(blen, ByteLength(ta));
|
||||
assertEquals(Math.floor(blen / target.BYTES_PER_ELEMENT), Length(ta));
|
||||
assertEquals(Math.floor(blen / target.BYTES_PER_ELEMENT), Length(ta));
|
||||
%OptimizeMaglevOnNextCall(ByteLength);
|
||||
%OptimizeMaglevOnNextCall(Length);
|
||||
assertEquals(blen, ByteLength(ta));
|
||||
assertEquals(Math.floor(blen / target.BYTES_PER_ELEMENT), Length(ta));
|
||||
blen = Resize(ab, 32);
|
||||
assertEquals(blen, ByteLength(ta));
|
||||
assertEquals(Math.floor(blen / target.BYTES_PER_ELEMENT), Length(ta));
|
||||
blen = Resize(ab, 9);
|
||||
assertEquals(blen, ByteLength(ta));
|
||||
assertEquals(Math.floor(blen / target.BYTES_PER_ELEMENT), Length(ta));
|
||||
assertOptimized(ByteLength);
|
||||
assertOptimized(Length);
|
||||
blen = Resize(ab, 24);
|
||||
assertEquals(blen, ByteLength(ta));
|
||||
assertEquals(Math.floor(blen / target.BYTES_PER_ELEMENT), Length(ta));
|
||||
assertOptimized(ByteLength);
|
||||
assertOptimized(Length);
|
||||
|
||||
if (!shared) {
|
||||
%ArrayBufferDetach(ab);
|
||||
assertEquals(0, ByteLength(ta));
|
||||
assertEquals(0, Length(ta));
|
||||
assertOptimized(Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
||||
(function() {
|
||||
for (let shared of [false, true]) {
|
||||
for (let length_tracking of [false, true]) {
|
||||
for (let with_offset of [false, true]) {
|
||||
for (let target
|
||||
of [Int8Array, Uint32Array, Float64Array, BigInt64Array]) {
|
||||
const test_case = `Testing: Read_${shared ? 'GSAB' : 'RAB'}_${
|
||||
length_tracking ? 'LengthTracking' : 'FixedLength'}${
|
||||
with_offset ? 'WithOffset' : ''}_${target.name}`;
|
||||
// console.log(test_case);
|
||||
|
||||
const read_code = 'return ta[index]; // ' + test_case;
|
||||
const Read = new Function('ta', 'index', read_code);
|
||||
const offset = with_offset ? 8 : 0;
|
||||
|
||||
let blen = 16 - offset;
|
||||
let len = Math.floor(blen / target.BYTES_PER_ELEMENT);
|
||||
const fixed_len = length_tracking ? undefined : len;
|
||||
const ab = CreateBuffer(shared, 16, 40);
|
||||
const ta = new target(ab, offset, fixed_len);
|
||||
const Resize = MakeResize(target, shared, offset, fixed_len);
|
||||
const Element = MakeElement(target, offset);
|
||||
FillBuffer(ab);
|
||||
|
||||
assertUnoptimized(Read);
|
||||
%PrepareFunctionForOptimization(Read);
|
||||
for (let i = 0; i < len * 2; ++i)
|
||||
assertEquals(i < len ? Element(i) : undefined, Read(ta, i));
|
||||
%OptimizeMaglevOnNextCall(Read);
|
||||
for (let i = 0; i < len * 2; ++i)
|
||||
assertEquals(i < len ? Element(i) : undefined, Read(ta, i));
|
||||
assertOptimized(Read);
|
||||
blen = Resize(ab, 32);
|
||||
FillBuffer(ab);
|
||||
len = Math.floor(blen / target.BYTES_PER_ELEMENT);
|
||||
for (let i = 0; i < len * 2; ++i)
|
||||
assertEquals(i < len ? Element(i) : undefined, Read(ta, i));
|
||||
assertOptimized(Read);
|
||||
blen = Resize(ab, 9);
|
||||
FillBuffer(ab);
|
||||
len = Math.floor(blen / target.BYTES_PER_ELEMENT);
|
||||
for (let i = 0; i < len * 2; ++i)
|
||||
assertEquals(i < len ? Element(i) : undefined, Read(ta, i));
|
||||
assertOptimized(Read);
|
||||
blen = Resize(ab, 0);
|
||||
len = Math.floor(blen / target.BYTES_PER_ELEMENT);
|
||||
for (let i = 0; i < len * 2; ++i)
|
||||
assertEquals(i < len ? Element(i) : undefined, Read(ta, i));
|
||||
assertOptimized(Read);
|
||||
blen = Resize(ab, 24);
|
||||
FillBuffer(ab);
|
||||
len = Math.floor(blen / target.BYTES_PER_ELEMENT);
|
||||
for (let i = 0; i < len * 2; ++i)
|
||||
assertEquals(i < len ? Element(i) : undefined, Read(ta, i));
|
||||
assertOptimized(Read);
|
||||
|
||||
if (!shared) {
|
||||
%ArrayBufferDetach(ab);
|
||||
assertEquals(undefined, Read(ta, 0));
|
||||
// assertOptimized(Read);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
||||
(function() {
|
||||
for (let shared of [false, true]) {
|
||||
for (let length_tracking of [false, true]) {
|
||||
for (let with_offset of [false, true]) {
|
||||
for (let target
|
||||
of [Int8Array, Uint32Array, Float64Array, BigInt64Array]) {
|
||||
const test_case = `Testing: Write_${shared ? 'GSAB' : 'RAB'}_${
|
||||
length_tracking ? 'LengthTracking' : 'FixedLength'}${
|
||||
with_offset ? 'WithOffset' : ''}_${target.name}`;
|
||||
// console.log(test_case);
|
||||
|
||||
const write_code = 'ta[index] = value; // ' + test_case;
|
||||
const Write = new Function('ta', 'index', 'value', write_code);
|
||||
const offset = with_offset ? 8 : 0;
|
||||
|
||||
let blen = 16 - offset;
|
||||
let len = Math.floor(blen / target.BYTES_PER_ELEMENT);
|
||||
const fixed_len = length_tracking ? undefined : len;
|
||||
const ab = CreateBuffer(shared, 16, 40);
|
||||
const ta = new target(ab, offset, fixed_len);
|
||||
const Resize = MakeResize(target, shared, offset, fixed_len);
|
||||
const Element = MakeElement(target, offset);
|
||||
const CheckBuffer = MakeCheckBuffer(target, offset);
|
||||
ClearBuffer(ab);
|
||||
|
||||
assertUnoptimized(Write);
|
||||
%PrepareFunctionForOptimization(Write);
|
||||
for (let i = 0; i < len; ++i) {
|
||||
Write(ta, i, Element(i));
|
||||
CheckBuffer(ab, i);
|
||||
}
|
||||
ClearBuffer(ab);
|
||||
%OptimizeMaglevOnNextCall(Write);
|
||||
for (let i = 0; i < len; ++i) {
|
||||
Write(ta, i, Element(i));
|
||||
CheckBuffer(ab, i);
|
||||
}
|
||||
assertOptimized(Write);
|
||||
blen = Resize(ab, 32);
|
||||
ClearBuffer(ab);
|
||||
len = Math.floor(blen / target.BYTES_PER_ELEMENT);
|
||||
for (let i = 0; i < len; ++i) {
|
||||
Write(ta, i, Element(i));
|
||||
CheckBuffer(ab, i);
|
||||
}
|
||||
assertOptimized(Write);
|
||||
blen = Resize(ab, 9);
|
||||
ClearBuffer(ab);
|
||||
len = Math.floor(blen / target.BYTES_PER_ELEMENT);
|
||||
for (let i = 0; i < len; ++i) {
|
||||
Write(ta, i, Element(i));
|
||||
CheckBuffer(ab, i);
|
||||
}
|
||||
assertOptimized(Write);
|
||||
blen = Resize(ab, 24);
|
||||
ClearBuffer(ab);
|
||||
len = Math.floor(blen / target.BYTES_PER_ELEMENT);
|
||||
for (let i = 0; i < len; ++i) {
|
||||
Write(ta, i, Element(i));
|
||||
CheckBuffer(ab, i);
|
||||
}
|
||||
assertOptimized(Write);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
||||
(function() {
|
||||
for (let shared of [false, true]) {
|
||||
for (let length_tracking of [false, true]) {
|
||||
for (let with_offset of [false, true]) {
|
||||
const test_case = `Testing: ByteLength_${shared ? 'GSAB' : 'RAB'}_${
|
||||
length_tracking ?
|
||||
'LengthTracking' :
|
||||
'FixedLength'}${with_offset ? 'WithOffset' : ''}_DataView`;
|
||||
// console.log(test_case);
|
||||
|
||||
const byte_length_code = 'return dv.byteLength; // ' + test_case;
|
||||
const ByteLength = new Function('dv', byte_length_code);
|
||||
const offset = with_offset ? 8 : 0;
|
||||
|
||||
let blen = 16 - offset;
|
||||
const fixed_blen = length_tracking ? undefined : blen;
|
||||
const ab = CreateBuffer(shared, 16, 40);
|
||||
const dv = new DataView(ab, offset, fixed_blen);
|
||||
const Resize = MakeResize(DataView, shared, offset, fixed_blen);
|
||||
|
||||
assertUnoptimized(ByteLength);
|
||||
%PrepareFunctionForOptimization(ByteLength);
|
||||
assertEquals(blen, ByteLength(dv));
|
||||
assertEquals(blen, ByteLength(dv));
|
||||
%OptimizeMaglevOnNextCall(ByteLength);
|
||||
assertEquals(blen, ByteLength(dv));
|
||||
assertOptimized(ByteLength);
|
||||
blen = Resize(ab, 32);
|
||||
assertEquals(blen, ByteLength(dv));
|
||||
assertOptimized(ByteLength);
|
||||
blen = Resize(ab, 9);
|
||||
if (length_tracking || shared) {
|
||||
assertEquals(blen, ByteLength(dv));
|
||||
} else {
|
||||
// For fixed length rabs, Resize(ab, 9) will put the ArrayBuffer in
|
||||
// detached state, for which DataView.prototype.byteLength has to throw.
|
||||
assertThrows(() => { ByteLength(dv); }, TypeError);
|
||||
}
|
||||
assertOptimized(ByteLength);
|
||||
blen = Resize(ab, 24);
|
||||
assertEquals(blen, ByteLength(dv));
|
||||
assertOptimized(ByteLength);
|
||||
|
||||
if (!shared) {
|
||||
%ArrayBufferDetach(ab);
|
||||
assertThrows(() => { ByteLength(dv); }, TypeError);
|
||||
assertOptimized(ByteLength);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
||||
(function() {
|
||||
function ByteLength_RAB_LengthTrackingWithOffset_DataView(dv) {
|
||||
return dv.byteLength;
|
||||
}
|
||||
const ByteLength = ByteLength_RAB_LengthTrackingWithOffset_DataView;
|
||||
|
||||
const rab = CreateResizableArrayBuffer(16, 40);
|
||||
const dv = new DataView(rab, 7);
|
||||
|
||||
%PrepareFunctionForOptimization(ByteLength);
|
||||
assertEquals(9, ByteLength(dv));
|
||||
assertEquals(9, ByteLength(dv));
|
||||
%OptimizeMaglevOnNextCall(ByteLength);
|
||||
assertEquals(9, ByteLength(dv));
|
||||
assertOptimized(ByteLength);
|
||||
})();
|
||||
|
||||
(function() {
|
||||
function Read_TA_RAB_LengthTracking_Mixed(ta, index) {
|
||||
return ta[index];
|
||||
}
|
||||
const Get = Read_TA_RAB_LengthTracking_Mixed;
|
||||
|
||||
const ab = new ArrayBuffer(16);
|
||||
FillBuffer(ab);
|
||||
const rab = CreateResizableArrayBuffer(16, 40);
|
||||
FillBuffer(rab);
|
||||
let ta_int8 = new Int8Array(ab);
|
||||
let ta_uint16 = new Uint16Array(rab);
|
||||
let ta_float32 = new Float32Array(ab);
|
||||
let ta_float64 = new Float64Array(rab);
|
||||
|
||||
// Train with feedback for all elements kinds.
|
||||
%PrepareFunctionForOptimization(Get);
|
||||
assertEquals(0, Get(ta_int8, 0));
|
||||
assertEquals(3, Get(ta_int8, 3));
|
||||
assertEquals(15, Get(ta_int8, 15));
|
||||
assertEquals(undefined, Get(ta_int8, 16));
|
||||
assertEquals(undefined, Get(ta_int8, 32));
|
||||
assertEquals(asU16(0), Get(ta_uint16, 0));
|
||||
assertEquals(asU16(3), Get(ta_uint16, 3));
|
||||
assertEquals(asU16(7), Get(ta_uint16, 7));
|
||||
assertEquals(undefined, Get(ta_uint16, 8));
|
||||
assertEquals(undefined, Get(ta_uint16, 12));
|
||||
assertEquals(asF32(0), Get(ta_float32, 0));
|
||||
assertEquals(asF32(3), Get(ta_float32, 3));
|
||||
assertEquals(undefined, Get(ta_float32, 4));
|
||||
assertEquals(undefined, Get(ta_float32, 12));
|
||||
assertEquals(asF64(0), Get(ta_float64, 0));
|
||||
assertEquals(asF64(1), Get(ta_float64, 1));
|
||||
assertEquals(undefined, Get(ta_float64, 2));
|
||||
assertEquals(undefined, Get(ta_float64, 12));
|
||||
%OptimizeMaglevOnNextCall(Get);
|
||||
assertEquals(0, Get(ta_int8, 0));
|
||||
assertEquals(3, Get(ta_int8, 3));
|
||||
assertEquals(15, Get(ta_int8, 15));
|
||||
assertEquals(undefined, Get(ta_int8, 16));
|
||||
assertEquals(undefined, Get(ta_int8, 32));
|
||||
assertEquals(asU16(0), Get(ta_uint16, 0));
|
||||
assertEquals(asU16(3), Get(ta_uint16, 3));
|
||||
assertEquals(asU16(7), Get(ta_uint16, 7));
|
||||
assertEquals(undefined, Get(ta_uint16, 8));
|
||||
assertEquals(undefined, Get(ta_uint16, 12));
|
||||
assertEquals(asF32(0), Get(ta_float32, 0));
|
||||
assertEquals(asF32(3), Get(ta_float32, 3));
|
||||
assertEquals(undefined, Get(ta_float32, 4));
|
||||
assertEquals(undefined, Get(ta_float32, 12));
|
||||
assertEquals(asF64(0), Get(ta_float64, 0));
|
||||
assertEquals(asF64(1), Get(ta_float64, 1));
|
||||
assertEquals(undefined, Get(ta_float64, 2));
|
||||
assertEquals(undefined, Get(ta_float64, 12));
|
||||
assertOptimized(Get);
|
||||
rab.resize(32);
|
||||
FillBuffer(rab);
|
||||
assertEquals(0, Get(ta_int8, 0));
|
||||
assertEquals(3, Get(ta_int8, 3));
|
||||
assertEquals(15, Get(ta_int8, 15));
|
||||
assertEquals(undefined, Get(ta_int8, 16));
|
||||
assertEquals(undefined, Get(ta_int8, 32));
|
||||
assertEquals(asU16(0), Get(ta_uint16, 0));
|
||||
assertEquals(asU16(3), Get(ta_uint16, 3));
|
||||
assertEquals(asU16(15), Get(ta_uint16, 15));
|
||||
assertEquals(undefined, Get(ta_uint16, 16));
|
||||
assertEquals(undefined, Get(ta_uint16, 40));
|
||||
assertEquals(asF32(0), Get(ta_float32, 0));
|
||||
assertEquals(asF32(3), Get(ta_float32, 3));
|
||||
assertEquals(undefined, Get(ta_float32, 4));
|
||||
assertEquals(undefined, Get(ta_float32, 12));
|
||||
assertEquals(asF64(0), Get(ta_float64, 0));
|
||||
assertEquals(asF64(1), Get(ta_float64, 1));
|
||||
assertEquals(asF64(3), Get(ta_float64, 3));
|
||||
assertEquals(undefined, Get(ta_float64, 4));
|
||||
assertEquals(undefined, Get(ta_float64, 12));
|
||||
assertOptimized(Get);
|
||||
rab.resize(9);
|
||||
assertEquals(0, Get(ta_int8, 0));
|
||||
assertEquals(3, Get(ta_int8, 3));
|
||||
assertEquals(15, Get(ta_int8, 15));
|
||||
assertEquals(undefined, Get(ta_int8, 16));
|
||||
assertEquals(undefined, Get(ta_int8, 32));
|
||||
assertEquals(asU16(0), Get(ta_uint16, 0));
|
||||
assertEquals(asU16(3), Get(ta_uint16, 3));
|
||||
assertEquals(undefined, Get(ta_uint16, 4));
|
||||
assertEquals(undefined, Get(ta_uint16, 12));
|
||||
assertEquals(asF32(0), Get(ta_float32, 0));
|
||||
assertEquals(asF32(3), Get(ta_float32, 3));
|
||||
assertEquals(undefined, Get(ta_float32, 4));
|
||||
assertEquals(undefined, Get(ta_float32, 12));
|
||||
assertEquals(asF64(0), Get(ta_float64, 0));
|
||||
assertEquals(undefined, Get(ta_float64, 1));
|
||||
assertEquals(undefined, Get(ta_float64, 12));
|
||||
assertOptimized(Get);
|
||||
|
||||
}());
|
||||
|
||||
(function() {
|
||||
function Read_TA_RAB_LengthTracking_Mixed(ta, index) {
|
||||
return ta[index];
|
||||
}
|
||||
const Get = Read_TA_RAB_LengthTracking_Mixed;
|
||||
|
||||
const ab = new ArrayBuffer(16);
|
||||
FillBuffer(ab);
|
||||
const rab = CreateResizableArrayBuffer(16, 40);
|
||||
FillBuffer(rab);
|
||||
let ta_int8 = new Int8Array(ab);
|
||||
let ta_uint16 = new Uint16Array(rab);
|
||||
let ta_float32 = new Float32Array(ab);
|
||||
let ta_float64 = new Float64Array(rab);
|
||||
|
||||
// Train with feedback for all elements kinds.
|
||||
%PrepareFunctionForOptimization(Get);
|
||||
assertEquals(0, Get(ta_int8, 0));
|
||||
assertEquals(3, Get(ta_int8, 3));
|
||||
assertEquals(15, Get(ta_int8, 15));
|
||||
assertEquals(undefined, Get(ta_int8, 16));
|
||||
assertEquals(undefined, Get(ta_int8, 32));
|
||||
assertEquals(asU16(0), Get(ta_uint16, 0));
|
||||
assertEquals(asU16(3), Get(ta_uint16, 3));
|
||||
assertEquals(asU16(7), Get(ta_uint16, 7));
|
||||
assertEquals(undefined, Get(ta_uint16, 8));
|
||||
assertEquals(undefined, Get(ta_uint16, 12));
|
||||
assertEquals(asF32(0), Get(ta_float32, 0));
|
||||
assertEquals(asF32(3), Get(ta_float32, 3));
|
||||
assertEquals(undefined, Get(ta_float32, 4));
|
||||
assertEquals(undefined, Get(ta_float32, 12));
|
||||
assertEquals(asF64(0), Get(ta_float64, 0));
|
||||
assertEquals(asF64(1), Get(ta_float64, 1));
|
||||
assertEquals(undefined, Get(ta_float64, 2));
|
||||
assertEquals(undefined, Get(ta_float64, 12));
|
||||
%OptimizeMaglevOnNextCall(Get);
|
||||
assertEquals(0, Get(ta_int8, 0));
|
||||
assertEquals(3, Get(ta_int8, 3));
|
||||
assertEquals(15, Get(ta_int8, 15));
|
||||
assertEquals(undefined, Get(ta_int8, 16));
|
||||
assertEquals(undefined, Get(ta_int8, 32));
|
||||
assertEquals(asU16(0), Get(ta_uint16, 0));
|
||||
assertEquals(asU16(3), Get(ta_uint16, 3));
|
||||
assertEquals(asU16(7), Get(ta_uint16, 7));
|
||||
assertEquals(undefined, Get(ta_uint16, 8));
|
||||
assertEquals(undefined, Get(ta_uint16, 12));
|
||||
assertEquals(asF32(0), Get(ta_float32, 0));
|
||||
assertEquals(asF32(3), Get(ta_float32, 3));
|
||||
assertEquals(undefined, Get(ta_float32, 4));
|
||||
assertEquals(undefined, Get(ta_float32, 12));
|
||||
assertEquals(asF64(0), Get(ta_float64, 0));
|
||||
assertEquals(asF64(1), Get(ta_float64, 1));
|
||||
assertEquals(undefined, Get(ta_float64, 2));
|
||||
assertEquals(undefined, Get(ta_float64, 12));
|
||||
assertOptimized(Get);
|
||||
rab.resize(32);
|
||||
FillBuffer(rab);
|
||||
assertEquals(0, Get(ta_int8, 0));
|
||||
assertEquals(3, Get(ta_int8, 3));
|
||||
assertEquals(15, Get(ta_int8, 15));
|
||||
assertEquals(undefined, Get(ta_int8, 16));
|
||||
assertEquals(undefined, Get(ta_int8, 32));
|
||||
assertEquals(asU16(0), Get(ta_uint16, 0));
|
||||
assertEquals(asU16(3), Get(ta_uint16, 3));
|
||||
assertEquals(asU16(15), Get(ta_uint16, 15));
|
||||
assertEquals(undefined, Get(ta_uint16, 16));
|
||||
assertEquals(undefined, Get(ta_uint16, 40));
|
||||
assertEquals(asF32(0), Get(ta_float32, 0));
|
||||
assertEquals(asF32(3), Get(ta_float32, 3));
|
||||
assertEquals(undefined, Get(ta_float32, 4));
|
||||
assertEquals(undefined, Get(ta_float32, 12));
|
||||
assertEquals(asF64(0), Get(ta_float64, 0));
|
||||
assertEquals(asF64(1), Get(ta_float64, 1));
|
||||
assertEquals(asF64(3), Get(ta_float64, 3));
|
||||
assertEquals(undefined, Get(ta_float64, 4));
|
||||
assertEquals(undefined, Get(ta_float64, 12));
|
||||
assertOptimized(Get);
|
||||
rab.resize(9);
|
||||
assertEquals(0, Get(ta_int8, 0));
|
||||
assertEquals(3, Get(ta_int8, 3));
|
||||
assertEquals(15, Get(ta_int8, 15));
|
||||
assertEquals(undefined, Get(ta_int8, 16));
|
||||
assertEquals(undefined, Get(ta_int8, 32));
|
||||
assertEquals(asU16(0), Get(ta_uint16, 0));
|
||||
assertEquals(asU16(3), Get(ta_uint16, 3));
|
||||
assertEquals(undefined, Get(ta_uint16, 4));
|
||||
assertEquals(undefined, Get(ta_uint16, 12));
|
||||
assertEquals(asF32(0), Get(ta_float32, 0));
|
||||
assertEquals(asF32(3), Get(ta_float32, 3));
|
||||
assertEquals(undefined, Get(ta_float32, 4));
|
||||
assertEquals(undefined, Get(ta_float32, 12));
|
||||
assertEquals(asF64(0), Get(ta_float64, 0));
|
||||
assertEquals(undefined, Get(ta_float64, 1));
|
||||
assertEquals(undefined, Get(ta_float64, 12));
|
||||
assertOptimized(Get);
|
||||
|
||||
}());
|
||||
|
||||
(function() {
|
||||
function Length_TA_RAB_LengthTracking_Mixed(ta) {
|
||||
return ta.length;
|
||||
}
|
||||
let Length = Length_TA_RAB_LengthTracking_Mixed;
|
||||
|
||||
const ab = new ArrayBuffer(32);
|
||||
const rab = CreateResizableArrayBuffer(16, 40);
|
||||
let ta_int8 = new Int8Array(ab);
|
||||
let ta_uint16 = new Uint16Array(rab);
|
||||
let ta_float32 = new Float32Array(ab);
|
||||
let ta_bigint64 = new BigInt64Array(rab);
|
||||
|
||||
// Train with feedback for all elements kinds.
|
||||
%PrepareFunctionForOptimization(Length);
|
||||
assertEquals(32, Length(ta_int8));
|
||||
assertEquals(8, Length(ta_uint16));
|
||||
assertEquals(8, Length(ta_float32));
|
||||
assertEquals(2, Length(ta_bigint64));
|
||||
%OptimizeMaglevOnNextCall(Length);
|
||||
assertEquals(32, Length(ta_int8));
|
||||
assertEquals(8, Length(ta_uint16));
|
||||
assertEquals(8, Length(ta_float32));
|
||||
assertEquals(2, Length(ta_bigint64));
|
||||
assertOptimized(Length);
|
||||
}());
|
||||
|
||||
(function() {
|
||||
function Length_RAB_GSAB_LengthTrackingWithOffset_Mixed(ta) {
|
||||
return ta.length;
|
||||
}
|
||||
const Length = Length_RAB_GSAB_LengthTrackingWithOffset_Mixed;
|
||||
|
||||
const rab = CreateResizableArrayBuffer(16, 40);
|
||||
let ta_int8 = new Int8Array(rab);
|
||||
let ta_float64 = new Float64Array(rab);
|
||||
|
||||
// Train with feedback for Int8Array and Float64Array.
|
||||
%PrepareFunctionForOptimization(Length);
|
||||
assertEquals(16, Length(ta_int8));
|
||||
assertEquals(2, Length(ta_float64));
|
||||
%OptimizeMaglevOnNextCall(Length);
|
||||
assertEquals(16, Length(ta_int8));
|
||||
assertEquals(2, Length(ta_float64));
|
||||
assertOptimized(Length);
|
||||
|
||||
let ta_uint32 = new Uint32Array(rab);
|
||||
let ta_bigint64 = new BigInt64Array(rab);
|
||||
// Calling with Uint32Array will deopt because of the map check on length.
|
||||
assertEquals(4, Length(ta_uint32));
|
||||
assertUnoptimized(Length);
|
||||
%PrepareFunctionForOptimization(Length);
|
||||
assertEquals(2, Length(ta_bigint64));
|
||||
// Recompile with additional feedback for Uint32Array and BigInt64Array.
|
||||
%OptimizeMaglevOnNextCall(Length);
|
||||
assertEquals(2, Length(ta_bigint64));
|
||||
assertOptimized(Length);
|
||||
|
||||
// Length handles all four TypedArrays without deopting.
|
||||
assertEquals(16, Length(ta_int8));
|
||||
assertEquals(2, Length(ta_float64));
|
||||
assertEquals(4, Length(ta_uint32));
|
||||
assertEquals(2, Length(ta_bigint64));
|
||||
assertOptimized(Length);
|
||||
|
||||
// Length handles corresponding gsab-backed TypedArrays without deopting.
|
||||
const gsab = CreateGrowableSharedArrayBuffer(16, 40);
|
||||
let ta2_uint32 = new Uint32Array(gsab, 8);
|
||||
let ta2_float64 = new Float64Array(gsab, 8);
|
||||
let ta2_bigint64 = new BigInt64Array(gsab, 8);
|
||||
let ta2_int8 = new Int8Array(gsab, 8);
|
||||
assertEquals(8, Length(ta2_int8));
|
||||
assertEquals(1, Length(ta2_float64));
|
||||
assertEquals(2, Length(ta2_uint32));
|
||||
assertEquals(1, Length(ta2_bigint64));
|
||||
assertOptimized(Length);
|
||||
|
||||
// Test Length after rab has been resized to a smaller size.
|
||||
rab.resize(5);
|
||||
assertEquals(5, Length(ta_int8));
|
||||
assertEquals(0, Length(ta_float64));
|
||||
assertEquals(1, Length(ta_uint32));
|
||||
assertEquals(0, Length(ta_bigint64));
|
||||
assertOptimized(Length);
|
||||
|
||||
// Test Length after rab has been resized to a larger size.
|
||||
rab.resize(40);
|
||||
assertEquals(40, Length(ta_int8));
|
||||
assertEquals(5, Length(ta_float64));
|
||||
assertEquals(10, Length(ta_uint32));
|
||||
assertEquals(5, Length(ta_bigint64));
|
||||
assertOptimized(Length);
|
||||
|
||||
// Test Length after gsab has been grown to a larger size.
|
||||
gsab.grow(25);
|
||||
assertEquals(17, Length(ta2_int8));
|
||||
assertEquals(2, Length(ta2_float64));
|
||||
assertEquals(4, Length(ta2_uint32));
|
||||
assertEquals(2, Length(ta2_bigint64));
|
||||
assertOptimized(Length);
|
||||
})();
|
||||
|
||||
(function() {
|
||||
function Length_AB_RAB_GSAB_LengthTrackingWithOffset_Mixed(ta) {
|
||||
return ta.length;
|
||||
}
|
||||
const Length = Length_AB_RAB_GSAB_LengthTrackingWithOffset_Mixed;
|
||||
|
||||
let ab = new ArrayBuffer(32);
|
||||
let rab = CreateResizableArrayBuffer(16, 40);
|
||||
let gsab = CreateGrowableSharedArrayBuffer(16, 40);
|
||||
|
||||
let ta_ab_int32 = new Int32Array(ab, 8, 3);
|
||||
let ta_rab_int32 = new Int32Array(rab, 4);
|
||||
let ta_gsab_float64 = new Float64Array(gsab);
|
||||
let ta_gsab_bigint64 = new BigInt64Array(gsab, 0, 2);
|
||||
|
||||
// Optimize Length with polymorphic feedback.
|
||||
%PrepareFunctionForOptimization(Length);
|
||||
assertEquals(3, Length(ta_ab_int32));
|
||||
assertEquals(3, Length(ta_rab_int32));
|
||||
assertEquals(2, Length(ta_gsab_float64));
|
||||
assertEquals(2, Length(ta_gsab_bigint64));
|
||||
%OptimizeMaglevOnNextCall(Length);
|
||||
assertEquals(3, Length(ta_ab_int32));
|
||||
assertEquals(3, Length(ta_rab_int32));
|
||||
assertEquals(2, Length(ta_gsab_float64));
|
||||
assertEquals(2, Length(ta_gsab_bigint64));
|
||||
assertOptimized(Length);
|
||||
|
||||
// Test resizing and growing the underlying rab/gsab buffers.
|
||||
rab.resize(8);
|
||||
gsab.grow(36);
|
||||
assertEquals(3, Length(ta_ab_int32));
|
||||
assertEquals(1, Length(ta_rab_int32));
|
||||
assertEquals(4, Length(ta_gsab_float64));
|
||||
assertEquals(2, Length(ta_gsab_bigint64));
|
||||
assertOptimized(Length);
|
||||
|
||||
// Construct additional TypedArrays with the same ElementsKind.
|
||||
let ta2_ab_bigint64 = new BigInt64Array(ab, 0, 1);
|
||||
let ta2_gsab_int32 = new Int32Array(gsab, 16);
|
||||
let ta2_rab_float64 = new Float64Array(rab, 8);
|
||||
let ta2_rab_int32 = new Int32Array(rab, 0, 1);
|
||||
assertEquals(1, Length(ta2_ab_bigint64));
|
||||
assertEquals(5, Length(ta2_gsab_int32));
|
||||
assertEquals(0, Length(ta2_rab_float64));
|
||||
assertEquals(1, Length(ta2_rab_int32));
|
||||
assertOptimized(Length);
|
||||
})();
|
||||
|
||||
(function() {
|
||||
function ByteOffset(ta) {
|
||||
return ta.byteOffset;
|
||||
}
|
||||
|
||||
const rab = CreateResizableArrayBuffer(16, 40);
|
||||
const ta = new Int32Array(rab, 4);
|
||||
|
||||
%PrepareFunctionForOptimization(ByteOffset);
|
||||
assertEquals(4, ByteOffset(ta));
|
||||
assertEquals(4, ByteOffset(ta));
|
||||
%OptimizeMaglevOnNextCall(ByteOffset);
|
||||
assertEquals(4, ByteOffset(ta));
|
||||
assertOptimized(ByteOffset);
|
||||
})();
|
@ -73,6 +73,7 @@ LINT_RULES = """
|
||||
LINT_OUTPUT_PATTERN = re.compile(r'^.+[:(]\d+[:)]')
|
||||
FLAGS_LINE = re.compile("//\s*Flags:.*--([A-z0-9-])+_[A-z0-9].*\n")
|
||||
ASSERT_OPTIMIZED_PATTERN = re.compile("assertOptimized")
|
||||
FLAGS_ENABLE_MAGLEV = re.compile("//\s*Flags:.*--maglev[^-].*\n")
|
||||
FLAGS_ENABLE_TURBOFAN = re.compile("//\s*Flags:.*--turbofan[^-].*\n")
|
||||
ASSERT_UNOPTIMIZED_PATTERN = re.compile("assertUnoptimized")
|
||||
FLAGS_NO_ALWAYS_OPT = re.compile("//\s*Flags:.*--no-?always-turbofan.*\n")
|
||||
@ -596,8 +597,9 @@ class SourceProcessor(SourceFileProcessor):
|
||||
if (not "mjsunit/mjsunit.js" in name and
|
||||
not "mjsunit/mjsunit_numfuzz.js" in name):
|
||||
if ASSERT_OPTIMIZED_PATTERN.search(contents) and \
|
||||
not FLAGS_ENABLE_MAGLEV.search(contents) and \
|
||||
not FLAGS_ENABLE_TURBOFAN.search(contents):
|
||||
print("%s Flag --turbofan should be set if " \
|
||||
print("%s Flag --maglev or --turbofan should be set if " \
|
||||
"assertOptimized() is used" % name)
|
||||
result = False
|
||||
if ASSERT_UNOPTIMIZED_PATTERN.search(contents) and \
|
||||
|
Loading…
Reference in New Issue
Block a user