[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:
Sigurd Schneider 2019-06-18 15:04:43 +02:00 committed by Commit Bot
parent fd074f9a80
commit 19eb7234ba
5 changed files with 58 additions and 7 deletions
src
test/mjsunit/regress/wasm

View File

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

View File

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

View File

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

View File

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

View 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();
})();