Skip to content
Open
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
21 changes: 14 additions & 7 deletions bbq/compiler/compiler.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,9 @@ type Compiler[E, T any] struct {
// this table maps a global from its address qualified name to its original un-aliased typename
// used mainly for exporting imports for linking
globalRemoveAddressTable map[string]string

// Passed to the vm to avoid repeated conversions from static-types to sema-types.
semaTypeCache map[sema.TypeID]sema.Type
}

var _ ast.DeclarationVisitor[struct{}] = &Compiler[any, any]{}
Expand Down Expand Up @@ -194,6 +197,7 @@ func newCompiler[E, T any](
importedGlobals: importedGlobals,
typesInPool: make(map[sema.TypeID]uint16),
constantsInPool: make(map[constantUniqueKey]*DecodedConstant),
semaTypeCache: make(map[sema.TypeID]sema.Type),
compositeTypeStack: &Stack[sema.CompositeKindedType]{
elements: make([]sema.CompositeKindedType, 0),
},
Expand Down Expand Up @@ -722,13 +726,14 @@ func (c *Compiler[E, T]) Compile() *bbq.Program[E, T] {
}

return &bbq.Program[E, T]{
Functions: functions,
Constants: constants,
Types: types,
Imports: imports,
Contracts: contracts,
Variables: variables,
Globals: globals,
Functions: functions,
Constants: constants,
Types: types,
Imports: imports,
Contracts: contracts,
Variables: variables,
Globals: globals,
SemaTypeCache: c.semaTypeCache,
}
}

Expand Down Expand Up @@ -4099,6 +4104,8 @@ func (c *Compiler[_, _]) getOrAddType(ty sema.Type) uint16 {
data := c.typeGen.CompileType(staticType)
index = c.addCompiledType(ty, data)
c.typesInPool[typeID] = index

c.semaTypeCache[typeID] = ty
}

return index
Expand Down
16 changes: 9 additions & 7 deletions bbq/program.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,18 @@ package bbq
import (
"github.com/onflow/cadence/bbq/constant"
"github.com/onflow/cadence/bbq/opcode"
"github.com/onflow/cadence/sema"
)

type Program[E, T any] struct {
Contracts []*Contract
Imports []Import
Functions []Function[E]
Constants []constant.DecodedConstant
Variables []Variable[E]
Types []T
Globals []Global
Contracts []*Contract
Imports []Import
Functions []Function[E]
Constants []constant.DecodedConstant
Variables []Variable[E]
Types []T
Globals []Global
SemaTypeCache map[sema.TypeID]sema.Type
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bbq.Program is currently serializable (and deserializable), even though we don't make use of it at the moment. But, we would lose this capability if we include sema.Type information in bbq.Program.

Could we instead pass this mapping externally? i.e: maybe as part of the vm.Config?

}

type InstructionProgram = Program[opcode.Instruction, StaticType]
3 changes: 2 additions & 1 deletion bbq/vm/vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ func NewVM(
vm.configureContext()

context.recoverErrors = vm.RecoverErrors
context.semaTypeCache = program.SemaTypeCache

// Link global variables and functions.
linkedGlobals := context.linkGlobals(
Expand Down Expand Up @@ -1069,7 +1070,7 @@ func checkMemberAccessTargetType(

context := vm.context

// TODO: Avoid sema type conversion.
// TODO: Avoid sema type conversion
accessedSemaType := context.SemaTypeFromStaticType(accessedType)

interpreter.CheckMemberAccessTargetType(
Expand Down
15 changes: 7 additions & 8 deletions interpreter/memory_metering_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9234,14 +9234,13 @@ func TestInterpretStaticTypeConversionMetering(t *testing.T) {
_, err = inter.Invoke("main")
require.NoError(t, err)

assert.Equal(t, uint64(2), meter.getMemory(common.MemoryKindDictionarySemaType))
assert.Equal(t, uint64(4), meter.getMemory(common.MemoryKindVariableSizedSemaType))
assert.Equal(t, uint64(2), meter.getMemory(common.MemoryKindConstantSizedSemaType))
assert.Equal(t, uint64(3), meter.getMemory(common.MemoryKindIntersectionSemaType))
assert.Equal(t, uint64(4), meter.getMemory(common.MemoryKindReferenceSemaType))
assert.Equal(t, uint64(2), meter.getMemory(common.MemoryKindCapabilitySemaType))
// TODO: investigate why this is different for the compiler/VM
assert.Equal(t, ifCompile[uint64](3, 2), meter.getMemory(common.MemoryKindOptionalSemaType))
assert.Equal(t, ifCompile[uint64](1, 2), meter.getMemory(common.MemoryKindDictionarySemaType))
assert.Equal(t, ifCompile[uint64](2, 4), meter.getMemory(common.MemoryKindVariableSizedSemaType))
assert.Equal(t, ifCompile[uint64](1, 2), meter.getMemory(common.MemoryKindConstantSizedSemaType))
assert.Equal(t, ifCompile[uint64](2, 3), meter.getMemory(common.MemoryKindIntersectionSemaType))
assert.Equal(t, ifCompile[uint64](2, 4), meter.getMemory(common.MemoryKindReferenceSemaType))
assert.Equal(t, ifCompile[uint64](1, 2), meter.getMemory(common.MemoryKindCapabilitySemaType))
assert.Equal(t, ifCompile[uint64](1, 2), meter.getMemory(common.MemoryKindOptionalSemaType))
})
}

Expand Down
Loading