Commit 2b985fb8 authored by Manos Koukoutos's avatar Manos Koukoutos Committed by V8 LUCI CQ

[wasm][turbofan] Refactor/improve global operations

Changes:
- Refactor all global base and offset computations into a single
  function and simplify GlobalGet and GlobalSet.
- Remove unneeded pointer arithmetic in the simd case. This enables the
  use of object operators, including LoadImmutableFromObject, which
  might enable more loads to be eliminated.

Bug: v8:11510

Change-Id: Ieab45fd9433863780bcfd6d4596786c08e3951a6
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3320457Reviewed-by: 's avatarAndreas Haas <ahaas@chromium.org>
Commit-Queue: Manos Koukoutos <manoskouk@chromium.org>
Cr-Commit-Position: refs/heads/main@{#78326}
parent 4113cf64
......@@ -3579,58 +3579,6 @@ void WasmGraphBuilder::SetEffectControl(Node* effect, Node* control) {
gasm_->InitializeEffectControl(effect, control);
}
Node* WasmGraphBuilder::GetImportedMutableGlobals() {
return LOAD_INSTANCE_FIELD(ImportedMutableGlobals, MachineType::UintPtr());
}
void WasmGraphBuilder::GetGlobalBaseAndOffset(MachineType mem_type,
const wasm::WasmGlobal& global,
Node** base_node,
Node** offset_node) {
if (global.mutability && global.imported) {
*base_node = gasm_->LoadFromObject(
MachineType::UintPtr(), GetImportedMutableGlobals(),
Int32Constant(global.index * sizeof(Address)));
*offset_node = Int32Constant(0);
} else {
Node* globals_start =
LOAD_INSTANCE_FIELD(GlobalsStart, MachineType::UintPtr());
*base_node = globals_start;
*offset_node = Int32Constant(global.offset);
if (mem_type == MachineType::Simd128() && global.offset != 0) {
// TODO(titzer,bbudge): code generation for SIMD memory offsets is broken.
*base_node = gasm_->IntAdd(*base_node, *offset_node);
*offset_node = Int32Constant(0);
}
}
}
void WasmGraphBuilder::GetBaseAndOffsetForImportedMutableExternRefGlobal(
const wasm::WasmGlobal& global, Node** base, Node** offset) {
// Load the base from the ImportedMutableGlobalsBuffer of the instance.
Node* buffers = LOAD_INSTANCE_FIELD(ImportedMutableGlobalsBuffers,
MachineType::TaggedPointer());
*base = gasm_->LoadFixedArrayElementAny(buffers, global.index);
// For the offset we need the index of the global in the buffer, and then
// calculate the actual offset from the index. Load the index from the
// ImportedMutableGlobals array of the instance.
Node* index =
gasm_->LoadFromObject(MachineType::UintPtr(), GetImportedMutableGlobals(),
Int32Constant(global.index * sizeof(Address)));
// From the index, calculate the actual offset in the FixedArray. This
// is kHeaderSize + (index * kTaggedSize). kHeaderSize can be acquired with
// wasm::ObjectAccess::ElementOffsetInTaggedFixedArray(0).
Node* index_times_tagged_size = gasm_->IntMul(
BuildChangeUint32ToUintPtr(index), Int32Constant(kTaggedSize));
*offset = gasm_->IntAdd(
index_times_tagged_size,
mcgraph()->IntPtrConstant(
wasm::ObjectAccess::ElementOffsetInTaggedFixedArray(0)));
}
Node* WasmGraphBuilder::MemBuffer(uintptr_t offset) {
DCHECK_NOT_NULL(instance_cache_);
Node* mem_start = instance_cache_->mem_start;
......@@ -3699,63 +3647,63 @@ Node* WasmGraphBuilder::BuildCallToRuntime(Runtime::FunctionId f,
parameter_count);
}
Node* WasmGraphBuilder::GlobalGet(uint32_t index) {
const wasm::WasmGlobal& global = env_->module->globals[index];
if (global.type.is_reference()) {
if (global.mutability && global.imported) {
Node* base = nullptr;
Node* offset = nullptr;
GetBaseAndOffsetForImportedMutableExternRefGlobal(global, &base, &offset);
return gasm_->LoadFromObject(MachineType::AnyTagged(), base, offset);
void WasmGraphBuilder::GetGlobalBaseAndOffset(const wasm::WasmGlobal& global,
Node** base, Node** offset) {
if (global.mutability && global.imported) {
Node* base_or_index = gasm_->LoadFromObject(
MachineType::UintPtr(),
LOAD_INSTANCE_FIELD(ImportedMutableGlobals, MachineType::UintPtr()),
Int32Constant(global.index * kSystemPointerSize));
if (global.type.is_reference()) {
// Load the base from the ImportedMutableGlobalsBuffer of the instance.
Node* buffers = LOAD_INSTANCE_FIELD(ImportedMutableGlobalsBuffers,
MachineType::TaggedPointer());
*base = gasm_->LoadFixedArrayElementAny(buffers, global.index);
// For this case, {base_or_index} gives the index of the global in the
// buffer. From the index, calculate the actual offset in the FixedArray.
// This is kHeaderSize + (index * kTaggedSize).
*offset = gasm_->IntAdd(
gasm_->IntMul(base_or_index, gasm_->IntPtrConstant(kTaggedSize)),
gasm_->IntPtrConstant(
wasm::ObjectAccess::ToTagged(FixedArray::kObjectsOffset)));
} else {
*base = base_or_index;
*offset = gasm_->IntPtrConstant(0);
}
Node* globals_buffer =
} else if (global.type.is_reference()) {
*base =
LOAD_INSTANCE_FIELD(TaggedGlobalsBuffer, MachineType::TaggedPointer());
return gasm_->LoadFixedArrayElementAny(globals_buffer, global.offset);
*offset = gasm_->IntPtrConstant(
wasm::ObjectAccess::ElementOffsetInTaggedFixedArray(global.offset));
} else {
*base = LOAD_INSTANCE_FIELD(GlobalsStart, MachineType::UintPtr());
*offset = gasm_->IntPtrConstant(global.offset);
}
}
MachineType mem_type = global.type.machine_type();
if (mem_type.representation() == MachineRepresentation::kSimd128) {
has_simd_ = true;
}
Node* WasmGraphBuilder::GlobalGet(uint32_t index) {
const wasm::WasmGlobal& global = env_->module->globals[index];
if (global.type == wasm::kWasmS128) has_simd_ = true;
Node* base = nullptr;
Node* offset = nullptr;
GetGlobalBaseAndOffset(mem_type, global, &base, &offset);
// TODO(manoskouk): Cannot use LoadFromObject here due to
// GetGlobalBaseAndOffset pointer arithmetic.
return gasm_->Load(mem_type, base, offset);
GetGlobalBaseAndOffset(global, &base, &offset);
MachineType mem_type = global.type.machine_type();
return global.mutability
? gasm_->LoadFromObject(mem_type, base, offset)
: gasm_->LoadImmutableFromObject(mem_type, base, offset);
}
void WasmGraphBuilder::GlobalSet(uint32_t index, Node* val) {
const wasm::WasmGlobal& global = env_->module->globals[index];
if (global.type.is_reference()) {
if (global.mutability && global.imported) {
Node* base = nullptr;
Node* offset = nullptr;
GetBaseAndOffsetForImportedMutableExternRefGlobal(global, &base, &offset);
gasm_->StoreToObject(
ObjectAccess(MachineType::AnyTagged(), kFullWriteBarrier), base,
offset, val);
return;
}
Node* globals_buffer =
LOAD_INSTANCE_FIELD(TaggedGlobalsBuffer, MachineType::TaggedPointer());
gasm_->StoreFixedArrayElementAny(globals_buffer, global.offset, val);
return;
}
MachineType mem_type = global.type.machine_type();
if (mem_type.representation() == MachineRepresentation::kSimd128) {
has_simd_ = true;
}
if (global.type == wasm::kWasmS128) has_simd_ = true;
Node* base = nullptr;
Node* offset = nullptr;
GetGlobalBaseAndOffset(mem_type, global, &base, &offset);
auto store_rep =
StoreRepresentation(mem_type.representation(), kNoWriteBarrier);
// TODO(manoskouk): Cannot use StoreToObject here due to
// GetGlobalBaseAndOffset pointer arithmetic.
gasm_->Store(store_rep, base, offset, val);
GetGlobalBaseAndOffset(global, &base, &offset);
ObjectAccess access(global.type.machine_type(), global.type.is_reference()
? kFullWriteBarrier
: kNoWriteBarrier);
gasm_->StoreToObject(access, base, offset, val);
}
Node* WasmGraphBuilder::TableGet(uint32_t table_index, Node* index,
......
......@@ -410,14 +410,6 @@ class WasmGraphBuilder {
return effect_and_control;
}
Node* GetImportedMutableGlobals();
void GetGlobalBaseAndOffset(MachineType mem_type, const wasm::WasmGlobal&,
Node** base_node, Node** offset_node);
void GetBaseAndOffsetForImportedMutableExternRefGlobal(
const wasm::WasmGlobal& global, Node** base, Node** offset);
// Utilities to manipulate sets of instance cache nodes.
void InitInstanceCache(WasmInstanceCacheNodes* instance_cache);
void PrepareInstanceCacheForLoop(WasmInstanceCacheNodes* instance_cache,
......@@ -693,6 +685,9 @@ class WasmGraphBuilder {
Node* IsNull(Node* object);
void GetGlobalBaseAndOffset(const wasm::WasmGlobal&, Node** base_node,
Node** offset_node);
using BranchBuilder = std::function<void(Node*, BranchHint)>;
struct Callbacks {
BranchBuilder succeed_if;
......
......@@ -78,8 +78,11 @@ struct WasmGlobal {
bool mutability; // {true} if mutable.
WireBytesRef init; // the initialization expression of the global.
union {
uint32_t index; // index of imported mutable global.
uint32_t offset; // offset into global memory (if not imported & mutable).
// Index of imported mutable global.
uint32_t index;
// Offset into global memory (if not imported & mutable). Expressed in bytes
// for value-typed globals, and in tagged words for reference-typed globals.
uint32_t offset;
};
bool imported; // true if imported.
bool exported; // true if exported.
......
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