[arm64] Ensure pools are emitted before emitting large branch tables
Change-Id: Iedb78a62886177f5c603b2f3ce9b586ac1320d31 Bug: chromium:968078 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1664067 Reviewed-by: Andreas Haas <ahaas@chromium.org> Commit-Queue: Sigurd Schneider <sigurds@chromium.org> Cr-Commit-Position: refs/heads/master@{#62244}
This commit is contained in:
parent
fd074f9a80
commit
19eb7234ba
src
codegen
compiler/backend/arm64
test/mjsunit/regress/wasm
@ -4418,7 +4418,7 @@ bool Assembler::ShouldEmitVeneer(int max_reachable_pc, size_t margin) {
|
||||
}
|
||||
|
||||
void Assembler::RecordVeneerPool(int location_offset, int size) {
|
||||
Assembler::BlockPoolsScope block_pools(this);
|
||||
Assembler::BlockPoolsScope block_pools(this, PoolEmissionCheck::kSkip);
|
||||
RelocInfo rinfo(reinterpret_cast<Address>(buffer_start_) + location_offset,
|
||||
RelocInfo::VENEER_POOL, static_cast<intptr_t>(size), Code());
|
||||
reloc_info_writer.Write(&rinfo);
|
||||
@ -4426,7 +4426,7 @@ void Assembler::RecordVeneerPool(int location_offset, int size) {
|
||||
|
||||
void Assembler::EmitVeneers(bool force_emit, bool need_protection,
|
||||
size_t margin) {
|
||||
BlockPoolsScope scope(this, ConstantPool::PoolEmissionCheck::kSkip);
|
||||
BlockPoolsScope scope(this, PoolEmissionCheck::kSkip);
|
||||
RecordComment("[ Veneers");
|
||||
|
||||
// The exact size of the veneer pool must be recorded (see the comment at the
|
||||
|
@ -2371,12 +2371,15 @@ class V8_EXPORT_PRIVATE Assembler : public AssemblerBase {
|
||||
|
||||
class BlockPoolsScope {
|
||||
public:
|
||||
explicit BlockPoolsScope(Assembler* assem)
|
||||
: assem_(assem), block_const_pool_(assem) {
|
||||
// Block veneer and constant pool. Emits pools if necessary to ensure that
|
||||
// {margin} more bytes can be emitted without triggering pool emission.
|
||||
explicit BlockPoolsScope(Assembler* assem, size_t margin = 0)
|
||||
: assem_(assem), block_const_pool_(assem, margin) {
|
||||
assem_->CheckVeneerPool(false, true, margin);
|
||||
assem_->StartBlockVeneerPool();
|
||||
}
|
||||
|
||||
BlockPoolsScope(Assembler* assem, ConstantPool::PoolEmissionCheck check)
|
||||
BlockPoolsScope(Assembler* assem, PoolEmissionCheck check)
|
||||
: assem_(assem), block_const_pool_(assem, check) {
|
||||
assem_->StartBlockVeneerPool();
|
||||
}
|
||||
|
@ -235,6 +235,7 @@ enum class Jump { kOmitted, kRequired };
|
||||
enum class Emission { kIfNeeded, kForced };
|
||||
enum class Alignment { kOmitted, kRequired };
|
||||
enum class RelocInfoStatus { kMustRecord, kMustOmitForDuplicate };
|
||||
enum class PoolEmissionCheck { kSkip };
|
||||
|
||||
// Pools are emitted in the instruction stream, preferably after unconditional
|
||||
// jumps or after returns from functions (in dead code locations).
|
||||
@ -279,7 +280,6 @@ class ConstantPool {
|
||||
void SetNextCheckIn(size_t instructions);
|
||||
|
||||
// Class for scoping postponing the constant pool generation.
|
||||
enum class PoolEmissionCheck { kSkip };
|
||||
class V8_EXPORT_PRIVATE BlockScope {
|
||||
public:
|
||||
// BlockScope immediatelly emits the pool if necessary to ensure that
|
||||
|
@ -2401,7 +2401,8 @@ void CodeGenerator::AssembleArchTableSwitch(Instruction* instr) {
|
||||
__ Add(temp, temp, Operand(input, UXTW, 2));
|
||||
__ Br(temp);
|
||||
{
|
||||
TurboAssembler::BlockPoolsScope block_pools(tasm());
|
||||
TurboAssembler::BlockPoolsScope block_pools(tasm(),
|
||||
case_count * kInstrSize);
|
||||
__ Bind(&table);
|
||||
for (size_t index = 0; index < case_count; ++index) {
|
||||
__ B(GetLabel(i.InputRpo(index + 2)));
|
||||
|
47
test/mjsunit/regress/wasm/regress-968078.js
Normal file
47
test/mjsunit/regress/wasm/regress-968078.js
Normal file
@ -0,0 +1,47 @@
|
||||
// Copyright 2019 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-wasm
|
||||
|
||||
load("test/mjsunit/wasm/wasm-module-builder.js");
|
||||
|
||||
(function() {
|
||||
function repeat(value, length) {
|
||||
var arr = new Array(length);
|
||||
for (let i = 0; i < length; i++) {
|
||||
arr[i] = value;
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
function br_table(block_index, length, def_block) {
|
||||
const bytes = new Binary();
|
||||
bytes.emit_bytes([kExprBrTable]);
|
||||
// Functions count (different than the count in the functions section.
|
||||
bytes.emit_u32v(length);
|
||||
bytes.emit_bytes(repeat(block_index, length));
|
||||
bytes.emit_bytes([def_block]);
|
||||
return Array.from(bytes.trunc_buffer());
|
||||
}
|
||||
var builder = new WasmModuleBuilder();
|
||||
builder.addMemory(12, 12, false);
|
||||
builder.addFunction("foo", kSig_v_iii)
|
||||
.addBody([].concat([
|
||||
kExprBlock, kWasmStmt,
|
||||
kExprGetLocal, 0x2,
|
||||
kExprI32Const, 0x01,
|
||||
kExprI32And,
|
||||
// Generate a test branch (which has 32k limited reach).
|
||||
kExprIf, kWasmStmt,
|
||||
kExprGetLocal, 0x0,
|
||||
kExprI32Const, 0x01,
|
||||
kExprI32And,
|
||||
kExprBrIf, 0x1,
|
||||
kExprGetLocal, 0x0,
|
||||
// Emit a br_table that is long enough to make the test branch go out of range.
|
||||
], br_table(0x1, 9000, 0x00), [
|
||||
kExprEnd,
|
||||
kExprEnd,
|
||||
])).exportFunc();
|
||||
builder.instantiate();
|
||||
})();
|
Loading…
Reference in New Issue
Block a user