Skip to content

cache: includes cpu features in cache keys #2220

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

Merged
merged 3 commits into from
May 28, 2024
Merged
Show file tree
Hide file tree
Changes from 2 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
9 changes: 6 additions & 3 deletions internal/engine/wazevo/backend/isa/amd64/machine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -443,18 +443,21 @@ L2:
}
}

// mockCpuFlags implements platform.CpuFeatureFlags
// mockCpuFlags implements platform.CpuFeatureFlags.
type mockCpuFlags struct {
flags platform.CpuFeature
extraFlags platform.CpuFeature
}

// Has implements the method of the same name in platform.CpuFeatureFlags
// Has implements the method of the same name in platform.CpuFeatureFlags.
func (f *mockCpuFlags) Has(flag platform.CpuFeature) bool {
return (f.flags & flag) != 0
}

// HasExtra implements the method of the same name in platform.CpuFeatureFlags
// HasExtra implements the method of the same name in platform.CpuFeatureFlags.
func (f *mockCpuFlags) HasExtra(flag platform.CpuFeature) bool {
return (f.extraFlags & flag) != 0
}

// Raw implements the method of the same name in platform.CpuFeatureFlags.
func (f *mockCpuFlags) Raw() [2]uint64 { return [2]uint64{uint64(f.flags), uint64(f.extraFlags)} }
8 changes: 8 additions & 0 deletions internal/engine/wazevo/engine_cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,14 @@ func fileCacheKey(m *wasm.Module) (ret filecache.Key) {
s := sha256.New()
s.Write(m.ID[:])
s.Write(magic)
// Write the CPU features so that we can cache the compiled module for the same CPU.
// This prevents the incompatible CPU features from being used.
cpu := platform.CpuFeatures.Raw()
// Reuse the `ret` buffer to write the first 16 bytes of the CPU features so that we can avoid the allocation.
binary.LittleEndian.PutUint64(ret[:8], cpu[0])
binary.LittleEndian.PutUint64(ret[8:16], cpu[1])
s.Write(ret[:16])
// Finally, write the hash to the ret buffer.
s.Sum(ret[:0])
return
}
Expand Down
2 changes: 2 additions & 0 deletions internal/platform/cpuid.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ type CpuFeatureFlags interface {
Has(cpuFeature CpuFeature) bool
// HasExtra returns true when the specified extraFlag (represented as uint64) is supported
HasExtra(cpuFeature CpuFeature) bool
// Raw returns the raw flags as a pair of uint64 values. This can be used for cache keying.
Raw() [2]uint64
}

type CpuFeature uint64
Expand Down
19 changes: 11 additions & 8 deletions internal/platform/cpuid_amd64.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

package platform

// CpuFeatures exposes the capabilities for this CPU, queried via the Has, HasExtra methods
var CpuFeatures CpuFeatureFlags = loadCpuFeatureFlags()
// CpuFeatures exposes the capabilities for this CPU, queried via the Has, HasExtra methods.
var CpuFeatures = loadCpuFeatureFlags()

// cpuFeatureFlags implements CpuFeatureFlags interface
// cpuFeatureFlags implements CpuFeatureFlags interface.
type cpuFeatureFlags struct {
flags uint64
extraFlags uint64
Expand All @@ -15,13 +15,13 @@ type cpuFeatureFlags struct {
// implemented in impl_amd64.s
func cpuid(arg1, arg2 uint32) (eax, ebx, ecx, edx uint32)

// cpuidAsBitmap combines the result of invoking cpuid to uint64 bitmap
// cpuidAsBitmap combines the result of invoking cpuid to uint64 bitmap.
func cpuidAsBitmap(arg1, arg2 uint32) uint64 {
_ /* eax */, _ /* ebx */, ecx, edx := cpuid(arg1, arg2)
return (uint64(edx) << 32) | uint64(ecx)
}

// loadStandardRange load flags from the standard range, panics otherwise
// loadStandardRange load flags from the standard range, panics otherwise.
func loadStandardRange(id uint32) uint64 {
// ensure that the id is in the valid range, returned by cpuid(0,0)
maxRange, _, _, _ := cpuid(0, 0)
Expand All @@ -31,7 +31,7 @@ func loadStandardRange(id uint32) uint64 {
return cpuidAsBitmap(id, 0)
}

// loadStandardRange load flags from the extended range, panics otherwise
// loadStandardRange load flags from the extended range, panics otherwise.
func loadExtendedRange(id uint32) uint64 {
// ensure that the id is in the valid range, returned by cpuid(0x80000000,0)
maxRange, _, _, _ := cpuid(0x80000000, 0)
Expand All @@ -48,12 +48,15 @@ func loadCpuFeatureFlags() CpuFeatureFlags {
}
}

// Has implements the same method on the CpuFeatureFlags interface
// Has implements the same method on the CpuFeatureFlags interface.
func (f *cpuFeatureFlags) Has(cpuFeature CpuFeature) bool {
return (f.flags & uint64(cpuFeature)) != 0
}

// HasExtra implements the same method on the CpuFeatureFlags interface
// HasExtra implements the same method on the CpuFeatureFlags interface.
func (f *cpuFeatureFlags) HasExtra(cpuFeature CpuFeature) bool {
return (f.extraFlags & uint64(cpuFeature)) != 0
}

// Raw implements the same method on the CpuFeatureFlags interface.
func (f *cpuFeatureFlags) Raw() [2]uint64 { return [2]uint64{f.flags, f.extraFlags} }
9 changes: 6 additions & 3 deletions internal/platform/cpuid_unsupported.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,14 @@ package platform

var CpuFeatures CpuFeatureFlags = &cpuFeatureFlags{}

// cpuFeatureFlags implements CpuFeatureFlags for unsupported platforms
// cpuFeatureFlags implements CpuFeatureFlags for unsupported platforms.
type cpuFeatureFlags struct{}

// Has implements the same method on the CpuFeatureFlags interface
// Has implements the same method on the CpuFeatureFlags interface.
func (c *cpuFeatureFlags) Has(cpuFeature CpuFeature) bool { return false }

// HasExtra implements the same method on the CpuFeatureFlags interface
// HasExtra implements the same method on the CpuFeatureFlags interface.
func (c *cpuFeatureFlags) HasExtra(cpuFeature CpuFeature) bool { return false }

// Raw implements the same method on the CpuFeatureFlags interface.
func (c *cpuFeatureFlags) Raw() [2]uint64 { return [2]uint64{0, 0} }
Loading