Repository: onflow/cadence

Issue:
Meter memory and computation for compiler
Add memory metering and computation metering to the compiler.

Hints from issue comments:
@SupunS: No need of computation metering for the compiler.

Solution patch:
diff --git a/bbq/compiler/compiler.go b/bbq/compiler/compiler.go
index 7b841a076..b049cff5f 100644
--- a/bbq/compiler/compiler.go
+++ b/bbq/compiler/compiler.go
@@ -377,6 +377,7 @@ func (c *Compiler[E, _]) newFunction(
 	functionTypeIndex := c.getOrAddType(functionType)
 
 	return newFunction[E](
+		c.Config.MemoryGauge,
 		c.currentFunction,
 		name,
 		qualifiedName,
@@ -732,6 +733,8 @@ func (c *Compiler[E, T]) Compile() *bbq.Program[E, T] {
 		}
 	}
 
+	common.UseMemory(c.Config.MemoryGauge, common.CompilerBBQProgramMemoryUsage)
+
 	return &bbq.Program[E, T]{
 		Functions: functions,
 		Constants: constants,
@@ -962,6 +965,15 @@ func (c *Compiler[_, _]) exportConstants() []constant.DecodedConstant {
 
 	count := len(c.constants)
 	if count > 0 {
+		common.UseMemory(c.Config.MemoryGauge, common.NewGoSliceMemoryUsages(count))
+		common.UseMemory(
+			c.Config.MemoryGauge,
+			common.NewMemoryUsage(
+				common.MemoryKindCompilerBBQConstant,
+				uint64(count),
+			),
+		)
+
 		constants = make([]constant.DecodedConstant, 0, count)
 		for _, c := range c.constants {
 			constants = append(
@@ -982,7 +994,10 @@ func (c *Compiler[_, T]) exportTypes() []T {
 }
 
 func (c *Compiler[E, _]) exportGlobals() []bbq.Global {
-	globals := make([]bbq.Global, len(c.Globals))
+	globalsCount := len(c.Globals)
+
+	common.UseMemory(c.Config.MemoryGauge, common.NewGoSliceMemoryUsages(globalsCount))
+	globals := make([]bbq.Global, globalsCount)
 
 	for _, global := range c.Globals { //nolint:maprange
 		index := int(global.GetGlobalInfo().Index)
@@ -1020,6 +1035,15 @@ func (c *Compiler[_, _]) exportImports() []bbq.Import {
 
 	count := len(c.usedImportedGlobals)
 	if count > 0 {
+		common.UseMemory(c.Config.MemoryGauge, common.NewGoSliceMemoryUsages(count))
+		common.UseMemory(
+			c.Config.MemoryGauge,
+			common.NewMemoryUsage(
+				common.MemoryKindCompilerBBQImport,
+				uint64(count),
+			),
+		)
+
 		exportedImports = make([]bbq.Import, 0, count)
 		for _, importedGlobal := range c.usedImportedGlobals {
 			name := c.removeAlias(importedGlobal.GetGlobalInfo().Name)
@@ -1039,7 +1063,9 @@ func (c *Compiler[E, _]) exportFunctions() []bbq.Function[E] {
 
 	count := len(c.functions)
 	if count > 0 {
+		common.UseMemory(c.Config.MemoryGauge, common.NewGoSliceMemoryUsages(count))
 		functions = make([]bbq.Function[E], 0, count)
+
 		for _, function := range c.functions {
 			newFunction := c.newBBQFunction(function)
 			functions = append(
@@ -1067,6 +1093,7 @@ func (c *Compiler[E, _]) exportFunctions() []bbq.Function[E] {
 }
 
 func (c *Compiler[E, _]) newBBQFunction(function *function[E]) bbq.Function[E] {
+	common.UseMemory(c.Config.MemoryGauge, common.CompilerBBQFunctionMemoryUsage)
 	return bbq.Function[E]{
 		Name:           function.name,
 		QualifiedName:  function.qualifiedName,
@@ -1083,6 +1110,15 @@ func (c *Compiler[E, _]) exportGlobalVariables() []bbq.Variable[E] {
 
 	count := len(c.globalVariables)
 	if count > 0 {
+		common.UseMemory(c.Config.MemoryGauge, common.NewGoSliceMemoryUsages(count))
+		common.UseMemory(
+			c.Config.MemoryGauge,
+			common.NewMemoryUsage(
+				common.MemoryKindCompilerBBQVariable,
+				uint64(count),
+			),
+		)
+
 		globalVariables = make([]bbq.Variable[E], 0, count)
 
 		for _, variable := range c.globalVariables {
@@ -1137,6 +1173,7 @@ func (c *Compiler[_, _]) exportContracts() []*bbq.Contract {
 		location := contractType.GetLocation()
 		name := contractType.GetIdentifier()
 
+		common.UseMemory(c.Config.MemoryGauge, common.CompilerBBQContractMemoryUsage)
 		contract := bbq.Contract{
 			Name:     name,
 			Location: location,
@@ -1530,7 +1567,10 @@ func (c *Compiler[_, _]) VisitForStatement(statement *ast.ForStatement) (_ struc
 		indexLocal = c.emitDeclareLocal(index.Identifier)
 	}
 
-	entryLocal := c.currentFunction.declareLocal(statement.Identifier.Identifier)
+	entryLocal := c.currentFunction.declareLocal(
+		c.Config.MemoryGauge,
+		statement.Identifier.Identifier,
+	)
 
 	testOffset := c.codeGen.Offset()
 	controlFlow := c.pushControlFlow(testOffset)
@@ -1723,7 +1763,7 @@ func (c *Compiler[_, _]) VisitVariableDeclaration(declaration *ast.VariableDecla
 
 		// Value can be nil only for synthetic-result variable.
 		if declaration.Value == nil {
-			c.currentFunction.declareLocal(name)
+			c.currentFunction.declareLocal(c.Config.MemoryGauge, name)
 			return
 		}
 
@@ -1907,7 +1947,7 @@ func (c *Compiler[_, _]) compileGlobalVariable(declaration *ast.VariableDeclarat
 }
 
 func (c *Compiler[_, _]) emitDeclareLocal(name string) *local {
-	local := c.currentFunction.declareLocal(name)
+	local := c.currentFunction.declareLocal(c.Config.MemoryGauge, name)
 	c.emitSetLocal(local.index)
 	return local
 }
@@ -2201,73 +2241,167 @@ func (c *Compiler[_, _]) emitIntegerConstant(
 	integerType sema.Type,
 ) {
 	constantKind := constant.FromSemaType(integerType)
+	memoryGauge := c.Config.MemoryGauge
 
 	var data constant.ConstantData
 
 	switch constantKind {
 	case constant.Int:
-		data = interpreter.NewUnmeteredIntValueFromBigInt(value)
+		memoryUsage := common.NewBigIntMemoryUsage(
+			common.BigIntByteLength(value),
+		)
+		data = interpreter.NewIntValueFromBigInt(
+			memoryGauge,
+			memoryUsage,
+			func() *big.Int {
+				return value
+			},
+		)
 
 	case constant.Int8:
-		data = interpreter.NewUnmeteredInt8Value(int8(value.Int64()))
+		data = interpreter.NewInt8Value(
+			memoryGauge,
+			func() int8 {
+				return int8(value.Int64())
+			},
+		)
 
 	case constant.Int16:
-		data = interpreter.NewUnmeteredInt16Value(int16(value.Int64()))
+		data = interpreter.NewInt16Value(
+			memoryGauge,
+			func() int16 {
+				return int16(value.Int64())
+			},
+		)
 
 	case constant.Int32:
-		data = interpreter.NewUnmeteredInt32Value(int32(value.Int64()))
+		data = interpreter.NewInt32Value(
+			memoryGauge,
+			func() int32 {
+				return int32(value.Int64())
+			},
+		)
 
 	case constant.Int64:
-		data = interpreter.NewUnmeteredInt64Value(value.Int64())
+		data = interpreter.NewInt64Value(memoryGauge, value.Int64)
 
 	case constant.Int128:
-		data = interpreter.NewUnmeteredInt128ValueFromBigInt(value)
+		data = interpreter.NewInt128ValueFromBigInt(
+			memoryGauge,
+			func() *big.Int {
+				return value
+			},
+		)
 
 	case constant.Int256:
-		data = interpreter.NewUnmeteredInt256ValueFromBigInt(value)
+		data = interpreter.NewInt256ValueFromBigInt(
+			memoryGauge,
+			func() *big.Int {
+				return value
+			},
+		)
 
 	case constant.UInt:
-		data = interpreter.NewUnmeteredUIntValueFromBigInt(value)
+		memoryUsage := common.NewBigIntMemoryUsage(
+			common.BigIntByteLength(value),
+		)
+		data = interpreter.NewUIntValueFromBigInt(
+			memoryGauge,
+			memoryUsage,
+			func() *big.Int {
+				return value
+			},
+		)
 
 	case constant.UInt8:
-		data = interpreter.NewUnmeteredUInt8Value(uint8(value.Uint64()))
+		data = interpreter.NewUInt8Value(
+			memoryGauge,
+			func() uint8 {
+				return uint8(value.Uint64())
+			},
+		)
 
 	case constant.UInt16:
-		data = interpreter.NewUnmeteredUInt16Value(uint16(value.Uint64()))
+		data = interpreter.NewUInt16Value(
+			memoryGauge,
+			func() uint16 {
+				return uint16(value.Uint64())
+			},
+		)
 
 	case constant.UInt32:
-		data = interpreter.NewUnmeteredUInt32Value(uint32(value.Uint64()))
+		data = interpreter.NewUInt32Value(
+			memoryGauge,
+			func() uint32 {
+				return uint32(value.Uint64())
+			},
+		)
 
 	case constant.UInt64:
-		data = interpreter.NewUnmeteredUInt64Value(value.Uint64())
+		data = interpreter.NewUInt64Value(memoryGauge, value.Uint64)
 
 	case constant.UInt128:
-		data = interpreter.NewUnmeteredUInt128ValueFromBigInt(value)
+		data = interpreter.NewUInt128ValueFromBigInt(
+			memoryGauge,
+			func() *big.Int {
+				return value
+			},
+		)
 
 	case constant.UInt256:
-		data = interpreter.NewUnmeteredUInt256ValueFromBigInt(value)
+		data = interpreter.NewUInt256ValueFromBigInt(
+			memoryGauge,
+			func() *big.Int {
+				return value
+			},
+		)
 
 	case constant.Word8:
-		data = interpreter.NewUnmeteredWord8Value(uint8(value.Uint64()))
+		data = interpreter.NewWord8Value(
+			memoryGauge,
+			func() uint8 {
+				return uint8(value.Uint64())
+			},
+		)
 
 	case constant.Word16:
-		data = interpreter.NewUnmeteredWord16Value(uint16(value.Uint64()))
+		data = interpreter.NewWord16Value(
+			memoryGauge,
+			func() uint16 {
+				return uint16(value.Uint64())
+			},
+		)
 
 	case constant.Word32:
-		data = interpreter.NewUnmeteredWord32Value(uint32(value.Uint64()))
+		data = interpreter.NewWord32Value(
+			memoryGauge,
+			func() uint32 {
+				return uint32(value.Uint64())
+			},
+		)
 
 	case constant.Word64:
-		data = interpreter.NewUnmeteredWord64Value(value.Uint64())
+		data = interpreter.NewWord64Value(memoryGauge, value.Uint64)
 
 	case constant.Word128:
-		data = interpreter.NewUnmeteredWord128ValueFromBigInt(value)
+		data = interpreter.NewWord128ValueFromBigInt(
+			memoryGauge,
+			func() *big.Int {
+				return value
+			},
+		)
 
 	case constant.Word256:
-		data = interpreter.NewUnmeteredWord256ValueFromBigInt(value)
+		data = interpreter.NewWord256ValueFromBigInt(
+			memoryGauge,
+			func() *big.Int {
+				return value
+			},
+		)
 
 	case constant.Address:
 		data = interpreter.NewAddressValueFromBytes(
-			c.Config.MemoryGauge,
+			memoryGauge,
 			func() []byte {
 				return value.Bytes()
 			},
@@ -2315,36 +2449,38 @@ func (c *Compiler[_, _]) VisitFixedPointExpression(expression *ast.FixedPointExp
 	var constantValue interpreter.Value
 	var constantKind constant.Kind
 
+	memoryGauge := c.Config.MemoryGauge
+
 	switch fixedPointSubType {
 	case sema.Fix64Type, sema.SignedFixedPointType:
 		constantKind = constant.Fix64
-		constantValue = interpreter.NewUnmeteredFix64Value(value.Int64())
+		constantValue = interpreter.NewFix64Value(memoryGauge, value.Int64)
 
 	case sema.UFix64Type:
 		constantKind = constant.UFix64
-		constantValue = interpreter.NewUnmeteredUFix64Value(value.Uint64())
+		constantValue = interpreter.NewUFix64Value(memoryGauge, value.Uint64)
 
 	case sema.Fix128Type:
 		constantKind = constant.Fix128
 		constantValue = interpreter.NewFix128ValueFromBigInt(
-			c.Config.MemoryGauge,
+			memoryGauge,
 			value,
 		)
 
 	case sema.UFix128Type:
 		constantKind = constant.UFix128
 		constantValue = interpreter.NewUFix128ValueFromBigInt(
-			c.Config.MemoryGauge,
+			memoryGauge,
 			value,
 		)
 
 	case sema.FixedPointType:
 		if expression.Negative {
 			constantKind = constant.Fix64
-			constantValue = interpreter.NewUnmeteredFix64Value(value.Int64())
+			constantValue = interpreter.NewFix64Value(memoryGauge, value.Int64)
 		} else {
 			constantKind = constant.UFix64
-			constantValue = interpreter.NewUnmeteredUFix64Value(value.Uint64())
+			constantValue = interpreter.NewUFix64Value(memoryGauge, value.Uint64)
 		}
 	default:
 		panic(errors.NewUnreachableError())
@@ -2382,13 +2518,11 @@ func (c *Compiler[_, _]) VisitArrayExpression(array *ast.ArrayExpression) (_ str
 		c.emitTransferIfNotResourceAndConvert(elementExpectedType)
 	}
 
-	c.emit(
-		opcode.InstructionNewArray{
-			Type:       typeIndex,
-			Size:       uint16(size),
-			IsResource: arrayTypes.ArrayType.IsResourceType(),
-		},
-	)
+	c.emit(opcode.InstructionNewArray{
+		Type:       typeIndex,
+		Size:       uint16(size),
+		IsResource: arrayTypes.ArrayType.IsResourceType(),
+	})
 
 	return
 }
@@ -2412,13 +2546,11 @@ func (c *Compiler[_, _]) VisitDictionaryExpression(dictionary *ast.DictionaryExp
 		c.emitTransferIfNotResourceAndConvert(dictionaryType.ValueType)
 	}
 
-	c.emit(
-		opcode.InstructionNewDictionary{
-			Type:       typeIndex,
-			Size:       uint16(size),
-			IsResource: dictionaryType.IsResourceType(),
-		},
-	)
+	c.emit(opcode.InstructionNewDictionary{
+		Type:       typeIndex,
+		Size:       uint16(size),
+		IsResource: dictionaryType.IsResourceType(),
+	})
 
 	return
 }
@@ -2807,9 +2939,8 @@ func isDynamicMethodInvocation(accessedType sema.Type) bool {
 		return isDynamicMethodInvocation(typ.Type)
 	case *sema.OptionalType:
 		return isDynamicMethodInvocation(typ.Type)
-	case *sema.IntersectionType:
-		return true
-	case *sema.InterfaceType:
+	case *sema.IntersectionType,
+		*sema.InterfaceType:
 		return true
 	default:
 		return false
@@ -2842,6 +2973,7 @@ func (c *Compiler[_, _]) loadTypeArguments(invocationTypes sema.InvocationExpres
 
 	var typeArgs []uint16
 	if typeArgsCount > 0 {
+		common.UseMemory(c.Config.MemoryGauge, common.NewGoSliceMemoryUsages(typeArgsCount))
 		typeArgs = make([]uint16, 0, typeArgsCount)
 
 		typeArguments.Foreach(func(key *sema.TypeParameter, typeParam sema.Type) {
@@ -3370,15 +3502,17 @@ func (c *Compiler[_, _]) compileInitializer(declaration *ast.SpecialFunctionDecl
 	// otherwise, base is declared as the second parameter after self.
 	c.declareParameters(parameterList, false, false)
 
+	memoryGauge := c.Config.MemoryGauge
+
 	var base *local
 	// must do this before declaring self
 	if kind == common.CompositeKindAttachment {
 		// base is provided as an argument at the end of the argument list implicitly
-		base = c.currentFunction.declareLocal(sema.BaseIdentifier)
+		base = c.currentFunction.declareLocal(memoryGauge, sema.BaseIdentifier)
 	}
 
 	// Declare `self`
-	self := c.currentFunction.declareLocal(sema.SelfIdentifier)
+	self := c.currentFunction.declareLocal(memoryGauge, sema.SelfIdentifier)
 
 	// Initialize an empty struct and assign to `self`.
 	// i.e: `self = New()`
@@ -3548,7 +3682,7 @@ func (c *Compiler[E, _]) VisitFunctionDeclaration(declaration *ast.FunctionDecla
 		// (i.e: doesn't rely on where this function is located in the AST; doesn't inherit from other functions, etc.).
 		declaration = c.desugar.DesugarInnerFunction(declaration)
 
-		innerFunctionLocal = c.currentFunction.declareLocal(identifier)
+		innerFunctionLocal = c.currentFunction.declareLocal(c.Config.MemoryGauge, identifier)
 	}
 
 	if parameterCount >= math.MaxUint16 {
@@ -3760,7 +3894,7 @@ func (c *Compiler[_, _]) createGlobalAlias(location common.Location, name string
 	// if alias exists or we want to force qualify (e.g. for aliased methods)
 	if ok || forceQualify {
 		// we want a table pointing from the alias -> address qualifier (Foo1 -> A.0001.Foo)
-		addressQualifiedName := string(location.TypeID(nil, name))
+		addressQualifiedName := string(location.TypeID(c.Config.MemoryGauge, name))
 		// check if alias exists in case of force qualification
 		if ok {
 			c.globalAliasTable[alias] = addressQualifiedName
@@ -3879,7 +4013,7 @@ func (c *Compiler[_, _]) VisitTransactionDeclaration(declaration *ast.Transactio
 			modifiedParamName := commons.TransactionGeneratedParamPrefix +
 				parameter.Identifier.Identifier
 
-			local := c.currentFunction.declareLocal(modifiedParamName)
+			local := c.currentFunction.declareLocal(c.Config.MemoryGauge, modifiedParamName)
 			c.emitGetLocal(local.index)
 
 			global := c.findGlobal(parameter.Identifier.Identifier)
@@ -3997,16 +4131,20 @@ func (c *Compiler[_, _]) VisitAttachExpression(expression *ast.AttachExpression)
 	c.emitSetLocal(baseLocalIndex)
 	// get base back on stack
 	c.emitGetLocal(baseLocalIndex)
+
 	baseTyp, ok := baseType.(sema.EntitlementSupportingType)
 	if !ok {
 		// simulates defensive check in interpreter
 		panic(errors.NewUnreachableError())
 	}
+
 	baseAccess := baseTyp.SupportedEntitlements().Access()
-	refType := &sema.ReferenceType{
-		Type:          baseTyp,
-		Authorization: baseAccess,
-	}
+	refType := sema.NewReferenceType(
+		c.Config.MemoryGauge,
+		baseAccess,
+		baseTyp,
+	)
+
 	// create reference to base to pass as implicit arg
 	c.emit(opcode.InstructionNewRef{
 		Type:       c.getOrAddType(refType),
@@ -4152,22 +4290,24 @@ func (c *Compiler[_, T]) addCompiledType(ty sema.Type, data T) uint16 {
 }
 
 func (c *Compiler[_, _]) declareParameters(paramList *ast.ParameterList, declareReceiver bool, declareBase bool) {
+	memoryGauge := c.Config.MemoryGauge
+
 	if declareReceiver {
 		// Declare receiver as `self`.
 		// Receiver is always at the zero-th index of params.
-		c.currentFunction.declareLocal(sema.SelfIdentifier)
+		c.currentFunction.declareLocal(memoryGauge, sema.SelfIdentifier)
 	}
 
 	if declareBase {
 		// Declare base receiver as `base`
 		// Always at index one of params.
-		c.currentFunction.declareLocal(sema.BaseIdentifier)
+		c.currentFunction.declareLocal(memoryGauge, sema.BaseIdentifier)
 	}
 
 	if paramList != nil {
 		for _, parameter := range paramList.Parameters {
 			parameterName := parameter.Identifier.Identifier
-			c.currentFunction.declareLocal(parameterName)
+			c.currentFunction.declareLocal(memoryGauge, parameterName)
 		}
 	}
 }
@@ -4203,6 +4343,8 @@ func (c *Compiler[_, _]) emitCloseUpvalue(localIndex uint16) {
 }
 
 func (c *Compiler[E, _]) emit(instruction opcode.Instruction) {
+	common.UseMemory(c.Config.MemoryGauge, common.CompilerInstructionMemoryUsage)
+
 	// Get the index of the instruction to be emitted.
 	// This is the offset before emitting the current instruction.
 	instructionIndex := c.codeGen.Offset()
diff --git a/bbq/compiler/function.go b/bbq/compiler/function.go
index 85d3b553b..d3cf16ad5 100644
--- a/bbq/compiler/function.go
+++ b/bbq/compiler/function.go
@@ -24,6 +24,7 @@ import (
 	"github.com/onflow/cadence/activations"
 	"github.com/onflow/cadence/bbq"
 	"github.com/onflow/cadence/bbq/opcode"
+	"github.com/onflow/cadence/common"
 	"github.com/onflow/cadence/errors"
 )
 
@@ -43,17 +44,19 @@ type function[E any] struct {
 }
 
 func newFunction[E any](
+	memoryGauge common.MemoryGauge,
 	enclosing *function[E],
 	name string,
 	qualifiedName string,
 	parameterCount uint16,
 	functionTypeIndex uint16,
 ) *function[E] {
+	common.UseMemory(memoryGauge, common.CompilerFunctionMemoryUsage)
 	return &function[E]{
 		enclosing:      enclosing,
 		name:           name,
 		qualifiedName:  qualifiedName,
-		locals:         activations.NewActivations[*local](nil),
+		locals:         activations.NewActivations[*local](memoryGauge),
 		parameterCount: parameterCount,
 		typeIndex:      functionTypeIndex,
 	}
@@ -68,7 +71,8 @@ func (f *function[E]) generateLocalIndex() uint16 {
 	return localIndex
 }
 
-func (f *function[E]) declareLocal(name string) *local {
+func (f *function[E]) declareLocal(memoryGauge common.MemoryGauge, name string) *local {
+	common.UseMemory(memoryGauge, common.CompilerLocalMemoryUsage)
 	local := &local{
 		index: f.generateLocalIndex(),
 	}
diff --git a/common/memorykind.go b/common/memorykind.go
index 3e794a3a6..c27972d31 100644
--- a/common/memorykind.go
+++ b/common/memorykind.go
@@ -269,15 +269,27 @@ const (
 	MemoryKindGoSliceLength
 
 	// Compiler
+
 	MemoryKindCompiler
 	MemoryKindCompilerGlobal
+	MemoryKindCompilerLocal
 	MemoryKindCompilerConstant
+	MemoryKindCompilerFunction
+	MemoryKindCompilerInstruction
+
+	MemoryKindCompilerBBQProgram
+	MemoryKindCompilerBBQConstant
+	MemoryKindCompilerBBQFunction
+	MemoryKindCompilerBBQImport
+	MemoryKindCompilerBBQVariable
+	MemoryKindCompilerBBQContract
 
 	// VM
+
 	MemoryKindImplicitReferenceVMValue
 	MemoryKindBoundFunctionVMValue
 
-	// Placeholder kind to allow consistent indexing
-	// this should always be the last kind
+	// MemoryKindLast is a placeholder kind to allow consistent indexing.
+	// This should always be the last kind.
 	MemoryKindLast
 )
diff --git a/common/memorykind_string.go b/common/memorykind_string.go
index 82607f42d..4cb72808b 100644
--- a/common/memorykind_string.go
+++ b/common/memorykind_string.go
@@ -218,15 +218,24 @@ func _() {
 	_ = x[MemoryKindGoSliceLength-207]
 	_ = x[MemoryKindCompiler-208]
 	_ = x[MemoryKindCompilerGlobal-209]
-	_ = x[MemoryKindCompilerConstant-210]
-	_ = x[MemoryKindImplicitReferenceVMValue-211]
-	_ = x[MemoryKindBoundFunctionVMValue-212]
-	_ = x[MemoryKindLast-213]
+	_ = x[MemoryKindCompilerLocal-210]
+	_ = x[MemoryKindCompilerConstant-211]
+	_ = x[MemoryKindCompilerFunction-212]
+	_ = x[MemoryKindCompilerInstruction-213]
+	_ = x[MemoryKindCompilerBBQProgram-214]
+	_ = x[MemoryKindCompilerBBQConstant-215]
+	_ = x[MemoryKindCompilerBBQFunction-216]
+	_ = x[MemoryKindCompilerBBQImport-217]
+	_ = x[MemoryKindCompilerBBQVariable-218]
+	_ = x[MemoryKindCompilerBBQContract-219]
+	_ = x[MemoryKindImplicitReferenceVMValue-220]
+	_ = x[MemoryKindBoundFunctionVMValue-221]
+	_ = x[MemoryKindLast-222]
 }
 
-const _MemoryKind_name = "UnknownAddressValueStringValueCharacterValueNumberValueArrayValueBaseDictionaryValueBaseCompositeValueBaseSimpleCompositeValueBaseOptionalValueTypeValuePathValueCapabilityValueStorageReferenceValueEphemeralReferenceValueInterpretedFunctionValueHostFunctionValueBoundFunctionValueBigIntSimpleCompositeValuePublishedValueStorageCapabilityControllerValueAccountCapabilityControllerValueAtreeArrayDataSlabAtreeArrayMetaDataSlabAtreeArrayElementOverheadAtreeMapDataSlabAtreeMapMetaDataSlabAtreeMapElementOverheadAtreeMapPreAllocatedElementAtreeEncodedSlabPrimitiveStaticTypeCompositeStaticTypeInterfaceStaticTypeVariableSizedStaticTypeConstantSizedStaticTypeDictionaryStaticTypeInclusiveRangeStaticTypeOptionalStaticTypeIntersectionStaticTypeEntitlementSetStaticAccessEntitlementMapStaticAccessReferenceStaticTypeCapabilityStaticTypeFunctionStaticTypeCadenceVoidValueCadenceOptionalValueCadenceBoolValueCadenceStringValueCadenceCharacterValueCadenceAddressValueCadenceIntValueCadenceNumberValueCadenceArrayValueBaseCadenceArrayValueLengthCadenceDictionaryValueCadenceInclusiveRangeValueCadenceKeyValuePairCadenceStructValueBaseCadenceStructValueSizeCadenceResourceValueBaseCadenceAttachmentValueBaseCadenceResourceValueSizeCadenceAttachmentValueSizeCadenceEventValueBaseCadenceEventValueSizeCadenceContractValueBaseCadenceContractValueSizeCadenceEnumValueBaseCadenceEnumValueSizeCadencePathValueCadenceTypeValueCadenceCapabilityValueCadenceDeprecatedPathCapabilityTypeCadenceFunctionValueCadenceOptionalTypeCadenceDeprecatedRestrictedTypeCadenceVariableSizedArrayTypeCadenceConstantSizedArrayTypeCadenceDictionaryTypeCadenceInclusiveRangeTypeCadenceFieldCadenceParameterCadenceTypeParameterCadenceStructTypeCadenceResourceTypeCadenceAttachmentTypeCadenceEventTypeCadenceContractTypeCadenceStructInterfaceTypeCadenceResourceInterfaceTypeCadenceContractInterfaceTypeCadenceFunctionTypeCadenceEntitlementSetAccessCadenceEntitlementMapAccessCadenceReferenceTypeCadenceIntersectionTypeCadenceCapabilityTypeCadenceEnumTypeRawStringAddressLocationBytesVariableContractVariableCompositeTypeInfoCompositeFieldInvocationStorageMapStorageKeyTypeTokenErrorTokenSpaceTokenProgramIdentifierArgumentBlockFunctionBlockParameterParameterListTypeParameterTypeParameterListTransferMembersTypeAnnotationDictionaryEntrySwitchCaseFunctionDeclarationCompositeDeclarationAttachmentDeclarationInterfaceDeclarationEntitlementDeclarationEntitlementMappingElementEntitlementMappingDeclarationEnumCaseDeclarationFieldDeclarationTransactionDeclarationImportDeclarationVariableDeclarationSpecialFunctionDeclarationPragmaDeclarationAssignmentStatementBreakStatementContinueStatementEmitStatementExpressionStatementForStatementIfStatementReturnStatementSwapStatementSwitchStatementWhileStatementRemoveStatementBooleanExpressionVoidExpressionNilExpressionStringExpressionIntegerExpressionFixedPointExpressionArrayExpressionStringTemplateExpressionDictionaryExpressionIdentifierExpressionInvocationExpressionMemberExpressionIndexExpressionConditionalExpressionUnaryExpressionBinaryExpressionFunctionExpressionCastingExpressionCreateExpressionDestroyExpressionReferenceExpressionForceExpressionPathExpressionAttachExpressionConstantSizedTypeDictionaryTypeFunctionTypeInstantiationTypeNominalTypeOptionalTypeReferenceTypeIntersectionTypeVariableSizedTypePositionRangeElaborationActivationActivationEntriesVariableSizedSemaTypeConstantSizedSemaTypeDictionarySemaTypeOptionalSemaTypeIntersectionSemaTypeReferenceSemaTypeEntitlementSemaTypeEntitlementMapSemaTypeEntitlementRelationSemaTypeCapabilitySemaTypeInclusiveRangeSemaTypeOrderedMapOrderedMapEntryListOrderedMapEntryArrayIteratorDictionaryKeyIteratorStringIteratorGoSliceLengthCompilerCompilerGlobalCompilerConstantImplicitReferenceVMValueBoundFunctionVMValueLast"
+const _MemoryKind_name = "UnknownAddressValueStringValueCharacterValueNumberValueArrayValueBaseDictionaryValueBaseCompositeValueBaseSimpleCompositeValueBaseOptionalValueTypeValuePathValueCapabilityValueStorageReferenceValueEphemeralReferenceValueInterpretedFunctionValueHostFunctionValueBoundFunctionValueBigIntSimpleCompositeValuePublishedValueStorageCapabilityControllerValueAccountCapabilityControllerValueAtreeArrayDataSlabAtreeArrayMetaDataSlabAtreeArrayElementOverheadAtreeMapDataSlabAtreeMapMetaDataSlabAtreeMapElementOverheadAtreeMapPreAllocatedElementAtreeEncodedSlabPrimitiveStaticTypeCompositeStaticTypeInterfaceStaticTypeVariableSizedStaticTypeConstantSizedStaticTypeDictionaryStaticTypeInclusiveRangeStaticTypeOptionalStaticTypeIntersectionStaticTypeEntitlementSetStaticAccessEntitlementMapStaticAccessReferenceStaticTypeCapabilityStaticTypeFunctionStaticTypeCadenceVoidValueCadenceOptionalValueCadenceBoolValueCadenceStringValueCadenceCharacterValueCadenceAddressValueCadenceIntValueCadenceNumberValueCadenceArrayValueBaseCadenceArrayValueLengthCadenceDictionaryValueCadenceInclusiveRangeValueCadenceKeyValuePairCadenceStructValueBaseCadenceStructValueSizeCadenceResourceValueBaseCadenceAttachmentValueBaseCadenceResourceValueSizeCadenceAttachmentValueSizeCadenceEventValueBaseCadenceEventValueSizeCadenceContractValueBaseCadenceContractValueSizeCadenceEnumValueBaseCadenceEnumValueSizeCadencePathValueCadenceTypeValueCadenceCapabilityValueCadenceDeprecatedPathCapabilityTypeCadenceFunctionValueCadenceOptionalTypeCadenceDeprecatedRestrictedTypeCadenceVariableSizedArrayTypeCadenceConstantSizedArrayTypeCadenceDictionaryTypeCadenceInclusiveRangeTypeCadenceFieldCadenceParameterCadenceTypeParameterCadenceStructTypeCadenceResourceTypeCadenceAttachmentTypeCadenceEventTypeCadenceContractTypeCadenceStructInterfaceTypeCadenceResourceInterfaceTypeCadenceContractInterfaceTypeCadenceFunctionTypeCadenceEntitlementSetAccessCadenceEntitlementMapAccessCadenceReferenceTypeCadenceIntersectionTypeCadenceCapabilityTypeCadenceEnumTypeRawStringAddressLocationBytesVariableContractVariableCompositeTypeInfoCompositeFieldInvocationStorageMapStorageKeyTypeTokenErrorTokenSpaceTokenProgramIdentifierArgumentBlockFunctionBlockParameterParameterListTypeParameterTypeParameterListTransferMembersTypeAnnotationDictionaryEntrySwitchCaseFunctionDeclarationCompositeDeclarationAttachmentDeclarationInterfaceDeclarationEntitlementDeclarationEntitlementMappingElementEntitlementMappingDeclarationEnumCaseDeclarationFieldDeclarationTransactionDeclarationImportDeclarationVariableDeclarationSpecialFunctionDeclarationPragmaDeclarationAssignmentStatementBreakStatementContinueStatementEmitStatementExpressionStatementForStatementIfStatementReturnStatementSwapStatementSwitchStatementWhileStatementRemoveStatementBooleanExpressionVoidExpressionNilExpressionStringExpressionIntegerExpressionFixedPointExpressionArrayExpressionStringTemplateExpressionDictionaryExpressionIdentifierExpressionInvocationExpressionMemberExpressionIndexExpressionConditionalExpressionUnaryExpressionBinaryExpressionFunctionExpressionCastingExpressionCreateExpressionDestroyExpressionReferenceExpressionForceExpressionPathExpressionAttachExpressionConstantSizedTypeDictionaryTypeFunctionTypeInstantiationTypeNominalTypeOptionalTypeReferenceTypeIntersectionTypeVariableSizedTypePositionRangeElaborationActivationActivationEntriesVariableSizedSemaTypeConstantSizedSemaTypeDictionarySemaTypeOptionalSemaTypeIntersectionSemaTypeReferenceSemaTypeEntitlementSemaTypeEntitlementMapSemaTypeEntitlementRelationSemaTypeCapabilitySemaTypeInclusiveRangeSemaTypeOrderedMapOrderedMapEntryListOrderedMapEntryArrayIteratorDictionaryKeyIteratorStringIteratorGoSliceLengthCompilerCompilerGlobalCompilerLocalCompilerConstantCompilerFunctionCompilerInstructionCompilerBBQProgramCompilerBBQConstantCompilerBBQFunctionCompilerBBQImportCompilerBBQVariableCompilerBBQContractImplicitReferenceVMValueBoundFunctionVMValueLast"
 
-var _MemoryKind_index = [...]uint16{0, 7, 19, 30, 44, 55, 69, 88, 106, 130, 143, 152, 161, 176, 197, 220, 244, 261, 279, 285, 305, 319, 351, 383, 401, 423, 448, 464, 484, 507, 534, 550, 569, 588, 607, 630, 653, 673, 697, 715, 737, 763, 789, 808, 828, 846, 862, 882, 898, 916, 937, 956, 971, 989, 1010, 1033, 1055, 1081, 1100, 1122, 1144, 1168, 1194, 1218, 1244, 1265, 1286, 1310, 1334, 1354, 1374, 1390, 1406, 1428, 1463, 1483, 1502, 1533, 1562, 1591, 1612, 1637, 1649, 1665, 1685, 1702, 1721, 1742, 1758, 1777, 1803, 1831, 1859, 1878, 1905, 1932, 1952, 1975, 1996, 2011, 2020, 2035, 2040, 2048, 2064, 2081, 2095, 2105, 2115, 2125, 2134, 2144, 2154, 2161, 2171, 2179, 2184, 2197, 2206, 2219, 2232, 2249, 2257, 2264, 2278, 2293, 2303, 2322, 2342, 2363, 2383, 2405, 2430, 2459, 2478, 2494, 2516, 2533, 2552, 2578, 2595, 2614, 2628, 2645, 2658, 2677, 2689, 2700, 2715, 2728, 2743, 2757, 2772, 2789, 2803, 2816, 2832, 2849, 2869, 2884, 2908, 2928, 2948, 2968, 2984, 2999, 3020, 3035, 3051, 3069, 3086, 3102, 3119, 3138, 3153, 3167, 3183, 3200, 3214, 3226, 3243, 3254, 3266, 3279, 3295, 3312, 3320, 3325, 3336, 3346, 3363, 3384, 3405, 3423, 3439, 3459, 3476, 3495, 3517, 3544, 3562, 3584, 3594, 3613, 3628, 3641, 3662, 3676, 3689, 3697, 3711, 3727, 3751, 3771, 3775}
+var _MemoryKind_index = [...]uint16{0, 7, 19, 30, 44, 55, 69, 88, 106, 130, 143, 152, 161, 176, 197, 220, 244, 261, 279, 285, 305, 319, 351, 383, 401, 423, 448, 464, 484, 507, 534, 550, 569, 588, 607, 630, 653, 673, 697, 715, 737, 763, 789, 808, 828, 846, 862, 882, 898, 916, 937, 956, 971, 989, 1010, 1033, 1055, 1081, 1100, 1122, 1144, 1168, 1194, 1218, 1244, 1265, 1286, 1310, 1334, 1354, 1374, 1390, 1406, 1428, 1463, 1483, 1502, 1533, 1562, 1591, 1612, 1637, 1649, 1665, 1685, 1702, 1721, 1742, 1758, 1777, 1803, 1831, 1859, 1878, 1905, 1932, 1952, 1975, 1996, 2011, 2020, 2035, 2040, 2048, 2064, 2081, 2095, 2105, 2115, 2125, 2134, 2144, 2154, 2161, 2171, 2179, 2184, 2197, 2206, 2219, 2232, 2249, 2257, 2264, 2278, 2293, 2303, 2322, 2342, 2363, 2383, 2405, 2430, 2459, 2478, 2494, 2516, 2533, 2552, 2578, 2595, 2614, 2628, 2645, 2658, 2677, 2689, 2700, 2715, 2728, 2743, 2757, 2772, 2789, 2803, 2816, 2832, 2849, 2869, 2884, 2908, 2928, 2948, 2968, 2984, 2999, 3020, 3035, 3051, 3069, 3086, 3102, 3119, 3138, 3153, 3167, 3183, 3200, 3214, 3226, 3243, 3254, 3266, 3279, 3295, 3312, 3320, 3325, 3336, 3346, 3363, 3384, 3405, 3423, 3439, 3459, 3476, 3495, 3517, 3544, 3562, 3584, 3594, 3613, 3628, 3641, 3662, 3676, 3689, 3697, 3711, 3724, 3740, 3756, 3775, 3793, 3812, 3831, 3848, 3867, 3886, 3910, 3930, 3934}
 
 func (i MemoryKind) String() string {
 	if i >= MemoryKind(len(_MemoryKind_index)-1) {
diff --git a/common/metering.go b/common/metering.go
index 21c58d244..0d3a96d17 100644
--- a/common/metering.go
+++ b/common/metering.go
@@ -336,11 +336,25 @@ var (
 
 	// Compiler
 
-	CompilerMemoryUsage         = NewConstantMemoryUsage(MemoryKindCompiler)
-	CompilerGlobalMemoryUsage   = NewConstantMemoryUsage(MemoryKindCompilerGlobal)
-	CompilerConstantMemoryUsage = NewConstantMemoryUsage(MemoryKindCompilerConstant)
+	CompilerMemoryUsage            = NewConstantMemoryUsage(MemoryKindCompiler)
+	CompilerGlobalMemoryUsage      = NewConstantMemoryUsage(MemoryKindCompilerGlobal)
+	CompilerLocalMemoryUsage       = NewConstantMemoryUsage(MemoryKindCompilerLocal)
+	CompilerConstantMemoryUsage    = NewConstantMemoryUsage(MemoryKindCompilerConstant)
+	CompilerFunctionMemoryUsage    = NewConstantMemoryUsage(MemoryKindCompilerFunction)
+	CompilerInstructionMemoryUsage = NewConstantMemoryUsage(MemoryKindCompilerInstruction)
+
+	CompilerBBQProgramMemoryUsage  = NewConstantMemoryUsage(MemoryKindCompilerBBQProgram)
+	CompilerBBQFunctionMemoryUsage = NewConstantMemoryUsage(MemoryKindCompilerBBQFunction)
+	CompilerBBQContractMemoryUsage = NewConstantMemoryUsage(MemoryKindCompilerBBQContract)
 )
 
+func NewMemoryUsage(kind MemoryKind, amount uint64) MemoryUsage {
+	return MemoryUsage{
+		Kind:   kind,
+		Amount: amount,
+	}
+}
+
 func NewConstantMemoryUsage(kind MemoryKind) MemoryUsage {
 	return MemoryUsage{
 		Kind:   kind,



Test patch:
diff --git a/bbq/compiler/compiler_metering_test.go b/bbq/compiler/compiler_metering_test.go
new file mode 100644
index 000000000..b9d368017
--- /dev/null
+++ b/bbq/compiler/compiler_metering_test.go
@@ -0,0 +1,280 @@
+/*
+ * Cadence - The resource-oriented smart contract programming language
+ *
+ * Copyright Flow Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package compiler
+
+import (
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
+
+	"github.com/onflow/cadence/bbq"
+	"github.com/onflow/cadence/common"
+	"github.com/onflow/cadence/interpreter"
+	. "github.com/onflow/cadence/test_utils/sema_utils"
+)
+
+type testMemoryGauge struct {
+	meter map[common.MemoryKind]uint64
+}
+
+var _ common.MemoryGauge = &testMemoryGauge{}
+
+func newTestMemoryGauge() *testMemoryGauge {
+	return &testMemoryGauge{
+		meter: make(map[common.MemoryKind]uint64),
+	}
+}
+
+func (g *testMemoryGauge) MeterMemory(usage common.MemoryUsage) error {
+	if g.meter == nil {
+		g.meter = make(map[common.MemoryKind]uint64)
+	}
+	g.meter[usage.Kind] += usage.Amount
+
+	return nil
+}
+
+func assertMemoryIntensitiesContains(t *testing.T, actual, contains map[common.MemoryKind]uint64) {
+	for containKind, containAmount := range contains {
+		// If the memory kind doesn't exist, it is same as zero-intensity.
+		actualAmount := actual[containKind]
+
+		assert.Equal(
+			t,
+			containAmount,
+			actualAmount,
+			"memory metering mismatch for %s. expected %d, found %d",
+			containKind,
+			int(containAmount),
+			int(actualAmount),
+		)
+	}
+}
+
+func parseCheckAndCompile(t *testing.T, code string, meter common.MemoryGauge) *bbq.InstructionProgram {
+	checker, err := ParseAndCheck(t, code)
+	require.NoError(t, err)
+
+	comp := NewInstructionCompilerWithConfig(
+		interpreter.ProgramFromChecker(checker),
+		checker.Location,
+		&Config{
+			MemoryGauge: meter,
+		},
+	)
+
+	return comp.Compile()
+}
+
+func TestCompilerMemoryMetering(t *testing.T) {
+
+	t.Parallel()
+
+	t.Run("variables", func(t *testing.T) {
+		t.Parallel()
+
+		script := `
+          var a = 5
+          var b = 6
+          var c = a + b
+        `
+
+		meter := newTestMemoryGauge()
+		_ = parseCheckAndCompile(t, script, meter)
+
+		expected := map[common.MemoryKind]uint64{
+			common.MemoryKindCompiler:            1,
+			common.MemoryKindCompilerGlobal:      3,
+			common.MemoryKindCompilerLocal:       0,
+			common.MemoryKindCompilerConstant:    2,
+			common.MemoryKindCompilerFunction:    3,
+			common.MemoryKindCompilerInstruction: 11,
+
+			common.MemoryKindCompilerBBQProgram:  1,
+			common.MemoryKindCompilerBBQConstant: 2,
+			common.MemoryKindCompilerBBQFunction: 3,
+			common.MemoryKindCompilerBBQImport:   0,
+			common.MemoryKindCompilerBBQVariable: 3,
+			common.MemoryKindCompilerBBQContract: 0,
+
+			common.MemoryKindNumberValue: 0,
+			common.MemoryKindBigInt:      16,
+
+			common.MemoryKindGoSliceLength: 8,
+		}
+
+		assertMemoryIntensitiesContains(t, meter.meter, expected)
+	})
+
+	t.Run("empty functions", func(t *testing.T) {
+		t.Parallel()
+
+		script := `
+          fun foo() {}
+
+          fun bar() {}
+        `
+
+		meter := newTestMemoryGauge()
+		_ = parseCheckAndCompile(t, script, meter)
+
+		expected := map[common.MemoryKind]uint64{
+			common.MemoryKindCompiler:            1,
+			common.MemoryKindCompilerGlobal:      2,
+			common.MemoryKindCompilerLocal:       0,
+			common.MemoryKindCompilerConstant:    0,
+			common.MemoryKindCompilerFunction:    2,
+			common.MemoryKindCompilerInstruction: 2,
+
+			common.MemoryKindCompilerBBQProgram:  1,
+			common.MemoryKindCompilerBBQConstant: 0,
+			common.MemoryKindCompilerBBQFunction: 2,
+			common.MemoryKindCompilerBBQImport:   0,
+			common.MemoryKindCompilerBBQVariable: 0,
+			common.MemoryKindCompilerBBQContract: 0,
+
+			common.MemoryKindNumberValue: 0,
+			common.MemoryKindBigInt:      0,
+
+			common.MemoryKindGoSliceLength: 4,
+		}
+
+		assertMemoryIntensitiesContains(t, meter.meter, expected)
+	})
+
+	t.Run("non-empty functions", func(t *testing.T) {
+		t.Parallel()
+
+		script := `
+          fun foo(s: String) {
+              let a = 1
+              let b: UInt8 = 2
+          }
+        `
+
+		meter := newTestMemoryGauge()
+		_ = parseCheckAndCompile(t, script, meter)
+
+		expected := map[common.MemoryKind]uint64{
+			common.MemoryKindCompiler:            1,
+			common.MemoryKindCompilerGlobal:      1,
+			common.MemoryKindCompilerLocal:       3,
+			common.MemoryKindCompilerConstant:    2,
+			common.MemoryKindCompilerFunction:    1,
+			common.MemoryKindCompilerInstruction: 9,
+
+			common.MemoryKindCompilerBBQProgram:  1,
+			common.MemoryKindCompilerBBQConstant: 2,
+			common.MemoryKindCompilerBBQFunction: 1,
+			common.MemoryKindCompilerBBQImport:   0,
+			common.MemoryKindCompilerBBQVariable: 0,
+			common.MemoryKindCompilerBBQContract: 0,
+
+			common.MemoryKindNumberValue: 1,
+			common.MemoryKindBigInt:      8,
+
+			common.MemoryKindGoSliceLength: 4,
+		}
+
+		assertMemoryIntensitiesContains(t, meter.meter, expected)
+	})
+
+	t.Run("contract", func(t *testing.T) {
+		t.Parallel()
+
+		script := `
+          contract Foo{}
+        `
+
+		meter := newTestMemoryGauge()
+		_ = parseCheckAndCompile(t, script, meter)
+
+		expected := map[common.MemoryKind]uint64{
+			common.MemoryKindCompiler:            1,
+			common.MemoryKindCompilerGlobal:      4,
+			common.MemoryKindCompilerLocal:       1,
+			common.MemoryKindCompilerConstant:    0,
+			common.MemoryKindCompilerFunction:    3,
+			common.MemoryKindCompilerInstruction: 6,
+
+			common.MemoryKindCompilerBBQProgram:  1,
+			common.MemoryKindCompilerBBQConstant: 0,
+			common.MemoryKindCompilerBBQFunction: 3,
+			common.MemoryKindCompilerBBQImport:   0,
+			common.MemoryKindCompilerBBQVariable: 0,
+			common.MemoryKindCompilerBBQContract: 1,
+
+			common.MemoryKindNumberValue: 0,
+			common.MemoryKindBigInt:      0,
+
+			common.MemoryKindGoSliceLength: 7,
+		}
+
+		assertMemoryIntensitiesContains(t, meter.meter, expected)
+	})
+
+	t.Run("transaction", func(t *testing.T) {
+		t.Parallel()
+
+		script := `
+          transaction {
+
+              prepare(signer: &Account) {}
+
+              pre {
+                  true
+              }
+
+              post {
+                  false
+              }
+
+              execute {}
+          }
+        `
+
+		meter := newTestMemoryGauge()
+		_ = parseCheckAndCompile(t, script, meter)
+
+		expected := map[common.MemoryKind]uint64{
+			common.MemoryKindCompiler:            1,
+			common.MemoryKindCompilerGlobal:      8,
+			common.MemoryKindCompilerLocal:       4,
+			common.MemoryKindCompilerConstant:    1,
+			common.MemoryKindCompilerFunction:    6,
+			common.MemoryKindCompilerInstruction: 26,
+
+			common.MemoryKindCompilerBBQProgram:  1,
+			common.MemoryKindCompilerBBQConstant: 1,
+			common.MemoryKindCompilerBBQFunction: 6,
+			common.MemoryKindCompilerBBQImport:   2,
+			common.MemoryKindCompilerBBQVariable: 0,
+			common.MemoryKindCompilerBBQContract: 0,
+
+			common.MemoryKindNumberValue: 0,
+			common.MemoryKindBigInt:      0,
+
+			common.MemoryKindGoSliceLength: 17,
+		}
+
+		assertMemoryIntensitiesContains(t, meter.meter, expected)
+	})
+
+}