Commit 3bd1efd5 authored by Andreas Haas's avatar Andreas Haas Committed by Commit Bot

Reland "[wasm][liftoff] Support for most externref globals" on ia32

Global.set requires a write barrier. This write barrier was missing in
the original CL. The reland only adds the write barrier for ia32, and
bails out on the other platforms.

Original message:

With this CL we add support for all externref globals except for
imported mutable globals.

R=thibaudm@chromium.org, ulan@chromium.org

Bug: v8:7581
Change-Id: I86328a17200d1edc505f4c4357bdf795d95cf0c8
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2404777Reviewed-by: 's avatarUlan Degenbaev <ulan@chromium.org>
Reviewed-by: 's avatarThibaud Michaud <thibaudm@chromium.org>
Commit-Queue: Andreas Haas <ahaas@chromium.org>
Cr-Commit-Position: refs/heads/master@{#69912}
parent 4f12b45d
......@@ -659,6 +659,14 @@ void LiftoffAssembler::LoadTaggedPointer(Register dst, Register src_addr,
offset_imm, LoadType::kI32Load, pinned);
}
void LiftoffAssembler::StoreTaggedPointer(Register dst_addr,
Register offset_reg,
int32_t offset_imm,
LiftoffRegister src,
LiftoffRegList pinned) {
bailout(kRefTypes, "GlobalSet");
}
void LiftoffAssembler::Load(LiftoffRegister dst, Register src_addr,
Register offset_reg, uint32_t offset_imm,
LoadType type, LiftoffRegList pinned,
......
......@@ -338,6 +338,14 @@ void LiftoffAssembler::LoadTaggedPointer(Register dst, Register src_addr,
LoadTaggedPointerField(dst, src_op);
}
void LiftoffAssembler::StoreTaggedPointer(Register dst_addr,
Register offset_reg,
int32_t offset_imm,
LiftoffRegister src,
LiftoffRegList pinned) {
bailout(kRefTypes, "GlobalSet");
}
void LiftoffAssembler::Load(LiftoffRegister dst, Register src_addr,
Register offset_reg, uint32_t offset_imm,
LoadType type, LiftoffRegList pinned,
......
......@@ -6,6 +6,7 @@
#define V8_WASM_BASELINE_IA32_LIFTOFF_ASSEMBLER_IA32_H_
#include "src/codegen/assembler.h"
#include "src/heap/memory-chunk.h"
#include "src/wasm/baseline/liftoff-assembler.h"
#include "src/wasm/simd-shuffle.h"
#include "src/wasm/value-type.h"
......@@ -291,6 +292,37 @@ void LiftoffAssembler::LoadTaggedPointer(Register dst, Register src_addr,
static_cast<uint32_t>(offset_imm), LoadType::kI32Load, pinned);
}
void LiftoffAssembler::StoreTaggedPointer(Register dst_addr,
Register offset_reg,
int32_t offset_imm,
LiftoffRegister src,
LiftoffRegList pinned) {
DCHECK_GE(offset_imm, 0);
DCHECK_LE(offset_imm, std::numeric_limits<int32_t>::max());
STATIC_ASSERT(kTaggedSize == kInt32Size);
Register scratch = pinned.set(GetUnusedRegister(kGpReg, pinned)).gp();
Operand dst_op = offset_reg == no_reg
? Operand(dst_addr, offset_imm)
: Operand(dst_addr, offset_reg, times_1, offset_imm);
mov(dst_op, src.gp());
Label write_barrier;
Label exit;
CheckPageFlag(dst_addr, scratch,
MemoryChunk::kPointersFromHereAreInterestingMask, not_zero,
&write_barrier, Label::kNear);
jmp(&exit, Label::kNear);
bind(&write_barrier);
JumpIfSmi(src.gp(), &exit, Label::kNear);
CheckPageFlag(src.gp(), scratch,
MemoryChunk::kPointersToHereAreInterestingMask, zero, &exit,
Label::kNear);
lea(scratch, dst_op);
CallRecordWriteStub(dst_addr, scratch, EMIT_REMEMBERED_SET, kSaveFPRegs,
wasm::WasmCode::kRecordWrite);
bind(&exit);
}
void LiftoffAssembler::Load(LiftoffRegister dst, Register src_addr,
Register offset_reg, uint32_t offset_imm,
LoadType type, LiftoffRegList pinned,
......
......@@ -485,6 +485,9 @@ class LiftoffAssembler : public TurboAssembler {
inline void LoadTaggedPointer(Register dst, Register src_addr,
Register offset_reg, int32_t offset_imm,
LiftoffRegList pinned);
inline void StoreTaggedPointer(Register dst_addr, Register offset_reg,
int32_t offset_imm, LiftoffRegister src,
LiftoffRegList pinned);
inline void Load(LiftoffRegister dst, Register src_addr, Register offset_reg,
uint32_t offset_imm, LoadType type, LiftoffRegList pinned,
uint32_t* protected_load_pc = nullptr,
......
......@@ -1813,8 +1813,30 @@ class LiftoffCompiler {
void GlobalGet(FullDecoder* decoder, Value* result,
const GlobalIndexImmediate<validate>& imm) {
const auto* global = &env_->module->globals[imm.index];
if (!CheckSupportedType(decoder, kSupportedTypesWithoutRefs, global->type,
"global")) {
if (!CheckSupportedType(decoder,
FLAG_liftoff_extern_ref
? kSupportedTypes
: kSupportedTypesWithoutRefs,
global->type, "global")) {
return;
}
if (global->type.is_reference_type()) {
if (global->mutability && global->imported) {
unsupported(decoder, kRefTypes, "imported mutable globals");
return;
}
LiftoffRegList pinned;
Register globals_buffer =
pinned.set(__ GetUnusedRegister(kGpReg, pinned)).gp();
LOAD_TAGGED_PTR_INSTANCE_FIELD(globals_buffer, TaggedGlobalsBuffer);
Register value = pinned.set(__ GetUnusedRegister(kGpReg, pinned)).gp();
__ LoadTaggedPointer(value, globals_buffer, no_reg,
wasm::ObjectAccess::ElementOffsetInTaggedFixedArray(
imm.global->offset),
pinned);
__ PushRegister(global->type, LiftoffRegister(value));
return;
}
LiftoffRegList pinned;
......@@ -1830,9 +1852,31 @@ class LiftoffCompiler {
void GlobalSet(FullDecoder* decoder, const Value& value,
const GlobalIndexImmediate<validate>& imm) {
auto* global = &env_->module->globals[imm.index];
if (!CheckSupportedType(decoder, kSupportedTypesWithoutRefs, global->type,
"global"))
if (!CheckSupportedType(decoder,
FLAG_liftoff_extern_ref
? kSupportedTypes
: kSupportedTypesWithoutRefs,
global->type, "global")) {
return;
}
if (global->type.is_reference_type()) {
if (global->mutability && global->imported) {
unsupported(decoder, kRefTypes, "imported mutable globals");
return;
}
LiftoffRegList pinned;
Register globals_buffer =
pinned.set(__ GetUnusedRegister(kGpReg, pinned)).gp();
LOAD_TAGGED_PTR_INSTANCE_FIELD(globals_buffer, TaggedGlobalsBuffer);
LiftoffRegister value = pinned.set(__ PopToRegister(pinned));
__ StoreTaggedPointer(globals_buffer, no_reg,
wasm::ObjectAccess::ElementOffsetInTaggedFixedArray(
imm.global->offset),
value, pinned);
return;
}
LiftoffRegList pinned;
uint32_t offset = 0;
Register addr = GetGlobalBaseAndOffset(global, &pinned, &offset);
......
......@@ -391,6 +391,14 @@ void LiftoffAssembler::LoadTaggedPointer(Register dst, Register src_addr,
static_cast<uint32_t>(offset_imm), LoadType::kI32Load, pinned);
}
void LiftoffAssembler::StoreTaggedPointer(Register dst_addr,
Register offset_reg,
int32_t offset_imm,
LiftoffRegister src,
LiftoffRegList pinned) {
bailout(kRefTypes, "GlobalSet");
}
void LiftoffAssembler::Load(LiftoffRegister dst, Register src_addr,
Register offset_reg, uint32_t offset_imm,
LoadType type, LiftoffRegList pinned,
......
......@@ -358,6 +358,14 @@ void LiftoffAssembler::LoadTaggedPointer(Register dst, Register src_addr,
static_cast<uint32_t>(offset_imm), LoadType::kI64Load, pinned);
}
void LiftoffAssembler::StoreTaggedPointer(Register dst_addr,
Register offset_reg,
int32_t offset_imm,
LiftoffRegister src,
LiftoffRegList pinned) {
bailout(kRefTypes, "GlobalSet");
}
void LiftoffAssembler::Load(LiftoffRegister dst, Register src_addr,
Register offset_reg, uint32_t offset_imm,
LoadType type, LiftoffRegList pinned,
......
......@@ -113,6 +113,14 @@ void LiftoffAssembler::LoadTaggedPointer(Register dst, Register src_addr,
bailout(kUnsupportedArchitecture, "LoadTaggedPointer");
}
void LiftoffAssembler::StoreTaggedPointer(Register dst_addr,
Register offset_reg,
int32_t offset_imm,
LiftoffRegister src,
LiftoffRegList pinned) {
bailout(kRefTypes, "GlobalSet");
}
void LiftoffAssembler::Load(LiftoffRegister dst, Register src_addr,
Register offset_reg, uint32_t offset_imm,
LoadType type, LiftoffRegList pinned,
......
......@@ -112,6 +112,14 @@ void LiftoffAssembler::LoadTaggedPointer(Register dst, Register src_addr,
bailout(kUnsupportedArchitecture, "LoadTaggedPointer");
}
void LiftoffAssembler::StoreTaggedPointer(Register dst_addr,
Register offset_reg,
int32_t offset_imm,
LiftoffRegister src,
LiftoffRegList pinned) {
bailout(kRefTypes, "GlobalSet");
}
void LiftoffAssembler::Load(LiftoffRegister dst, Register src_addr,
Register offset_reg, uint32_t offset_imm,
LoadType type, LiftoffRegList pinned,
......
......@@ -275,6 +275,14 @@ void LiftoffAssembler::LoadTaggedPointer(Register dst, Register src_addr,
LoadTaggedPointerField(dst, src_op);
}
void LiftoffAssembler::StoreTaggedPointer(Register dst_addr,
Register offset_reg,
int32_t offset_imm,
LiftoffRegister src,
LiftoffRegList pinned) {
bailout(kRefTypes, "GlobalSet");
}
void LiftoffAssembler::AtomicLoad(LiftoffRegister dst, Register src_addr,
Register offset_reg, uint32_t offset_imm,
LoadType type, LiftoffRegList pinned) {
......
// Copyright 2020 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: --experimental-wasm-reftypes --expose-gc --liftoff
// Flags: --no-wasm-tier-up --liftoff-extern-ref
load("test/mjsunit/wasm/externref-globals.js");
......@@ -594,3 +594,25 @@ function dummy_func() {
assertSame(expected_wasm, instance.exports.get_global_wasm());
assertSame(expected_val, instance.exports.get_global_js()());
})();
(function TestSetGlobalWriteBarrier() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
const global = builder.addGlobal(kWasmExternRef, true).index;
builder.addFunction("set_global", kSig_v_r)
.addBody([kExprLocalGet, 0, kExprGlobalSet, global])
.exportFunc();
builder.addFunction("get_global", kSig_r_v)
.addBody([kExprGlobalGet, global])
.exportFunc();
const instance = builder.instantiate();
// Trigger GC twice to make sure the instance is moved to mature space.
gc();
gc();
const test_value = { hello: 'world' };
instance.exports.set_global(test_value);
// Run another GC to test if the writebarrier existed.
gc();
assertSame(test_value, instance.exports.get_global());
})();
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment