Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

wazevo(frontend): faster non-imported global access #1889

Merged
merged 5 commits into from
Dec 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions internal/engine/compiler/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -656,6 +656,14 @@ func (e *moduleEngine) ResolveImportedFunction(index, indexInImportedModule wasm
e.functions[index] = imported.functions[indexInImportedModule]
}

// GetGlobalValue implements the same method as documented on wasm.ModuleEngine.
func (e *moduleEngine) GetGlobalValue(wasm.Index) (lo, hi uint64) {
panic("BUG: GetGlobalValue should never be called on compiler mode")
}

// OwnsGlobals implements the same method as documented on wasm.ModuleEngine.
func (e *moduleEngine) OwnsGlobals() bool { return false }

// ResolveImportedMemory implements wasm.ModuleEngine.
func (e *moduleEngine) ResolveImportedMemory(wasm.ModuleEngine) {}

Expand Down
8 changes: 8 additions & 0 deletions internal/engine/interpreter/interpreter.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,14 @@ type moduleEngine struct {
parentEngine *engine
}

// GetGlobalValue implements the same method as documented on wasm.ModuleEngine.
func (e *moduleEngine) GetGlobalValue(wasm.Index) (lo, hi uint64) {
panic("BUG: GetGlobalValue should never be called on interpreter mode")
}

// OwnsGlobals implements the same method as documented on wasm.ModuleEngine.
func (e *moduleEngine) OwnsGlobals() bool { return false }

// callEngine holds context per moduleEngine.Call, and shared across all the
// function calls originating from the same moduleEngine.Call execution.
//
Expand Down
100 changes: 38 additions & 62 deletions internal/engine/wazevo/backend/backend_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1937,34 +1937,26 @@ L2:
L1 (SSA Block: blk0):
mov x128?, x0
mov x129?, x1
ldr x130?, [x129?, #0x8]
ldr w131?, [x130?, #0x8]
ldr x132?, [x129?, #0x10]
ldr x133?, [x132?, #0x8]
ldr x134?, [x129?, #0x18]
ldr s135?, [x134?, #0x8]
ldr x136?, [x129?, #0x20]
ldr d137?, [x136?, #0x8]
ldr w130?, [x129?, #0x8]
ldr x131?, [x129?, #0x18]
ldr s132?, [x129?, #0x28]
ldr d133?, [x129?, #0x38]
str x129?, [x128?, #0x8]
mov x0, x128?
mov x1, x129?
bl f1
ldr x138?, [x129?, #0x8]
ldr w139?, [x138?, #0x8]
ldr x140?, [x129?, #0x10]
ldr x141?, [x140?, #0x8]
ldr x142?, [x129?, #0x18]
ldr s143?, [x142?, #0x8]
ldr x144?, [x129?, #0x20]
ldr d145?, [x144?, #0x8]
mov v3.8b, v145?.8b
mov v2.8b, v143?.8b
mov x3, x141?
mov x2, x139?
mov v1.8b, v137?.8b
mov v0.8b, v135?.8b
mov x1, x133?
mov x0, x131?
ldr w134?, [x129?, #0x8]
ldr x135?, [x129?, #0x18]
ldr s136?, [x129?, #0x28]
ldr d137?, [x129?, #0x38]
mov v3.8b, v137?.8b
mov v2.8b, v136?.8b
mov x3, x135?
mov x2, x134?
mov v1.8b, v133?.8b
mov v0.8b, v132?.8b
mov x1, x131?
mov x0, x130?
ret
`,
afterFinalizeARM64: `
Expand All @@ -1974,29 +1966,21 @@ L1 (SSA Block: blk0):
orr x27, xzr, #0x20
str x27, [sp, #-0x10]!
str x1, [sp, #0x10]
ldr x8, [x1, #0x8]
ldr w8, [x8, #0x8]
ldr w8, [x1, #0x8]
str w8, [sp, #0x2c]
ldr x9, [x1, #0x10]
ldr x9, [x9, #0x8]
ldr x9, [x1, #0x18]
str x9, [sp, #0x24]
ldr x10, [x1, #0x18]
ldr s8, [x10, #0x8]
ldr s8, [x1, #0x28]
str s8, [sp, #0x20]
ldr x10, [x1, #0x20]
ldr d9, [x10, #0x8]
ldr d9, [x1, #0x38]
str d9, [sp, #0x18]
str x1, [x0, #0x8]
bl f1
ldr x8, [sp, #0x10]
ldr x9, [x8, #0x8]
ldr w9, [x9, #0x8]
ldr x10, [x8, #0x10]
ldr x10, [x10, #0x8]
ldr x11, [x8, #0x18]
ldr s8, [x11, #0x8]
ldr x8, [x8, #0x20]
ldr d9, [x8, #0x8]
ldr w9, [x8, #0x8]
ldr x10, [x8, #0x18]
ldr s8, [x8, #0x28]
ldr d9, [x8, #0x38]
mov v3.8b, v9.8b
mov v2.8b, v8.8b
mov x3, x10
Expand All @@ -2022,36 +2006,28 @@ L1 (SSA Block: blk0):
afterLoweringARM64: `
L1 (SSA Block: blk0):
mov x129?, x1
ldr x131?, [x129?, #0x8]
orr w141?, wzr, #0x1
str w141?, [x131?, #0x8]
ldr x133?, [x129?, #0x10]
orr x140?, xzr, #0x2
str x140?, [x133?, #0x8]
ldr x135?, [x129?, #0x18]
ldr s139?, #8; b 8; data.f32 3.000000
str s139?, [x135?, #0x8]
ldr x137?, [x129?, #0x20]
ldr d138?, #8; b 16; data.f64 4.000000
str d138?, [x137?, #0x8]
orr w137?, wzr, #0x1
str w137?, [x129?, #0x8]
orr x136?, xzr, #0x2
str x136?, [x129?, #0x18]
ldr s135?, #8; b 8; data.f32 3.000000
str s135?, [x129?, #0x28]
ldr d134?, #8; b 16; data.f64 4.000000
str d134?, [x129?, #0x38]
ret
`,
afterFinalizeARM64: `
L1 (SSA Block: blk0):
stp x30, xzr, [sp, #-0x10]!
str xzr, [sp, #-0x10]!
ldr x8, [x1, #0x8]
orr w9, wzr, #0x1
str w9, [x8, #0x8]
ldr x8, [x1, #0x10]
orr x9, xzr, #0x2
str x9, [x8, #0x8]
ldr x8, [x1, #0x18]
orr w8, wzr, #0x1
str w8, [x1, #0x8]
orr x8, xzr, #0x2
str x8, [x1, #0x18]
ldr s8, #8; b 8; data.f32 3.000000
str s8, [x8, #0x8]
ldr x8, [x1, #0x20]
str s8, [x1, #0x28]
ldr d8, #8; b 16; data.f64 4.000000
str d8, [x8, #0x8]
str d8, [x1, #0x38]
add sp, sp, #0x10
ldr x30, [sp], #0x10
ret
Expand Down
86 changes: 31 additions & 55 deletions internal/engine/wazevo/frontend/frontend_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1181,15 +1181,11 @@ blk0: (exec_ctx:i64, module_ctx:i64, v2:i32)
m: testcases.GlobalsGet.Module,
exp: `
blk0: (exec_ctx:i64, module_ctx:i64)
v2:i64 = Load module_ctx, 0x8
v3:i32 = Load v2, 0x8
v4:i64 = Load module_ctx, 0x10
v5:i64 = Load v4, 0x8
v6:i64 = Load module_ctx, 0x18
v7:f32 = Load v6, 0x8
v8:i64 = Load module_ctx, 0x20
v9:f64 = Load v8, 0x8
Jump blk_ret, v3, v5, v7, v9
v2:i32 = Load module_ctx, 0x8
v3:i64 = Load module_ctx, 0x18
v4:f32 = Load module_ctx, 0x28
v5:f64 = Load module_ctx, 0x38
Jump blk_ret, v2, v3, v4, v5
`,
},
{
Expand All @@ -1198,18 +1194,14 @@ blk0: (exec_ctx:i64, module_ctx:i64)
exp: `
blk0: (exec_ctx:i64, module_ctx:i64)
v2:i32 = Iconst_32 0x1
v3:i64 = Load module_ctx, 0x8
Store v2, v3, 0x8
v4:i64 = Iconst_64 0x2
v5:i64 = Load module_ctx, 0x10
Store v4, v5, 0x8
v6:f32 = F32const 3.000000
v7:i64 = Load module_ctx, 0x18
Store v6, v7, 0x8
v8:f64 = F64const 4.000000
v9:i64 = Load module_ctx, 0x20
Store v8, v9, 0x8
Jump blk_ret, v2, v4, v6, v8
Store v2, module_ctx, 0x8
v3:i64 = Iconst_64 0x2
Store v3, module_ctx, 0x18
v4:f32 = F32const 3.000000
Store v4, module_ctx, 0x28
v5:f64 = F64const 4.000000
Store v5, module_ctx, 0x38
Jump blk_ret, v2, v3, v4, v5
`,
},
{
Expand All @@ -1220,50 +1212,34 @@ signatures:
sig1: i64i64_v

blk0: (exec_ctx:i64, module_ctx:i64)
v2:i64 = Load module_ctx, 0x8
v3:i32 = Load v2, 0x8
v4:i64 = Load module_ctx, 0x10
v5:i64 = Load v4, 0x8
v6:i64 = Load module_ctx, 0x18
v7:f32 = Load v6, 0x8
v8:i64 = Load module_ctx, 0x20
v9:f64 = Load v8, 0x8
v2:i32 = Load module_ctx, 0x8
v3:i64 = Load module_ctx, 0x18
v4:f32 = Load module_ctx, 0x28
v5:f64 = Load module_ctx, 0x38
Store module_ctx, exec_ctx, 0x8
Call f1:sig1, exec_ctx, module_ctx
v10:i64 = Load module_ctx, 0x8
v11:i32 = Load v10, 0x8
v12:i64 = Load module_ctx, 0x10
v13:i64 = Load v12, 0x8
v14:i64 = Load module_ctx, 0x18
v15:f32 = Load v14, 0x8
v16:i64 = Load module_ctx, 0x20
v17:f64 = Load v16, 0x8
Jump blk_ret, v3, v5, v7, v9, v11, v13, v15, v17
v6:i32 = Load module_ctx, 0x8
v7:i64 = Load module_ctx, 0x18
v8:f32 = Load module_ctx, 0x28
v9:f64 = Load module_ctx, 0x38
Jump blk_ret, v2, v3, v4, v5, v6, v7, v8, v9
`,
expAfterOpt: `
signatures:
sig1: i64i64_v

blk0: (exec_ctx:i64, module_ctx:i64)
v2:i64 = Load module_ctx, 0x8
v3:i32 = Load v2, 0x8
v4:i64 = Load module_ctx, 0x10
v5:i64 = Load v4, 0x8
v6:i64 = Load module_ctx, 0x18
v7:f32 = Load v6, 0x8
v8:i64 = Load module_ctx, 0x20
v9:f64 = Load v8, 0x8
v2:i32 = Load module_ctx, 0x8
v3:i64 = Load module_ctx, 0x18
v4:f32 = Load module_ctx, 0x28
v5:f64 = Load module_ctx, 0x38
Store module_ctx, exec_ctx, 0x8
Call f1:sig1, exec_ctx, module_ctx
v10:i64 = Load module_ctx, 0x8
v11:i32 = Load v10, 0x8
v12:i64 = Load module_ctx, 0x10
v13:i64 = Load v12, 0x8
v14:i64 = Load module_ctx, 0x18
v15:f32 = Load v14, 0x8
v16:i64 = Load module_ctx, 0x20
v17:f64 = Load v16, 0x8
Jump blk_ret, v3, v5, v7, v9, v11, v13, v15, v17
v6:i32 = Load module_ctx, 0x8
v7:i64 = Load module_ctx, 0x18
v8:f32 = Load module_ctx, 0x28
v9:f64 = Load module_ctx, 0x38
Jump blk_ret, v2, v3, v4, v5, v6, v7, v8, v9
`,
},
{
Expand Down
49 changes: 29 additions & 20 deletions internal/engine/wazevo/frontend/lower.go
Original file line number Diff line number Diff line change
Expand Up @@ -3459,21 +3459,25 @@ func (c *Compiler) reloadMemoryBaseLen() {
c.clearSafeBounds()
}

// globalInstanceValueOffset is the offsetOf .Value field of wasm.GlobalInstance.
const globalInstanceValueOffset = 8

func (c *Compiler) setWasmGlobalValue(index wasm.Index, v ssa.Value) {
variable := c.globalVariables[index]
instanceOffset := c.offset.GlobalInstanceOffset(index)
opaqueOffset := c.offset.GlobalInstanceOffset(index)

builder := c.ssaBuilder
loadGlobalInstPtr := builder.AllocateInstruction()
loadGlobalInstPtr.AsLoad(c.moduleCtxPtrValue, uint32(instanceOffset), ssa.TypeI64)
builder.InsertInstruction(loadGlobalInstPtr)
if index < c.m.ImportGlobalCount {
loadGlobalInstPtr := builder.AllocateInstruction()
loadGlobalInstPtr.AsLoad(c.moduleCtxPtrValue, uint32(opaqueOffset), ssa.TypeI64)
builder.InsertInstruction(loadGlobalInstPtr)

store := builder.AllocateInstruction()
store.AsStore(ssa.OpcodeStore, v, loadGlobalInstPtr.Return(), uint32(globalInstanceValueOffset))
builder.InsertInstruction(store)
store := builder.AllocateInstruction()
store.AsStore(ssa.OpcodeStore, v, loadGlobalInstPtr.Return(), uint32(0))
builder.InsertInstruction(store)

} else {
store := builder.AllocateInstruction()
store.AsStore(ssa.OpcodeStore, v, c.moduleCtxPtrValue, uint32(opaqueOffset))
builder.InsertInstruction(store)
}

// The value has changed to `v`, so we record it.
builder.DefineVariableInCurrentBB(variable, v)
Expand All @@ -3482,7 +3486,7 @@ func (c *Compiler) setWasmGlobalValue(index wasm.Index, v ssa.Value) {
func (c *Compiler) getWasmGlobalValue(index wasm.Index, forceLoad bool) ssa.Value {
variable := c.globalVariables[index]
typ := c.globalVariablesTypes[index]
instanceOffset := c.offset.GlobalInstanceOffset(index)
opaqueOffset := c.offset.GlobalInstanceOffset(index)

builder := c.ssaBuilder
if !forceLoad {
Expand All @@ -3491,16 +3495,21 @@ func (c *Compiler) getWasmGlobalValue(index wasm.Index, forceLoad bool) ssa.Valu
}
}

loadGlobalInstPtr := builder.AllocateInstruction()
loadGlobalInstPtr.AsLoad(c.moduleCtxPtrValue, uint32(instanceOffset), ssa.TypeI64)
builder.InsertInstruction(loadGlobalInstPtr)
var load *ssa.Instruction
if index < c.m.ImportGlobalCount {
loadGlobalInstPtr := builder.AllocateInstruction()
loadGlobalInstPtr.AsLoad(c.moduleCtxPtrValue, uint32(opaqueOffset), ssa.TypeI64)
builder.InsertInstruction(loadGlobalInstPtr)
load = builder.AllocateInstruction().
AsLoad(loadGlobalInstPtr.Return(), uint32(0), typ)
} else {
load = builder.AllocateInstruction().
AsLoad(c.moduleCtxPtrValue, uint32(opaqueOffset), typ)
}

load := builder.AllocateInstruction()
load.AsLoad(loadGlobalInstPtr.Return(), uint32(globalInstanceValueOffset), typ)
builder.InsertInstruction(load)
ret := load.Return()
builder.DefineVariableInCurrentBB(variable, ret)
return ret
v := load.Insert(builder).Return()
builder.DefineVariableInCurrentBB(variable, v)
return v
}

const (
Expand Down
2 changes: 0 additions & 2 deletions internal/engine/wazevo/frontend/lower_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ import (
)

func Test_Offsets(t *testing.T) {
var globalInstance wasm.GlobalInstance
require.Equal(t, int(unsafe.Offsetof(globalInstance.Val)), globalInstanceValueOffset)
var memInstance wasm.MemoryInstance
require.Equal(t, int(unsafe.Offsetof(memInstance.Buffer)), memoryInstanceBufOffset)
var tableInstance wasm.TableInstance
Expand Down
Loading
Loading