diff --git a/runtime/common/memorykind.go b/runtime/common/memorykind.go index e372391554..f3482c10c2 100644 --- a/runtime/common/memorykind.go +++ b/runtime/common/memorykind.go @@ -35,9 +35,12 @@ const ( MemoryKindCharacter MemoryKindMetaType MemoryKindNumber - MemoryKindArray - MemoryKindDictionary - MemoryKindComposite + MemoryKindArrayBase + MemoryKindArrayLength + MemoryKindDictionaryBase + MemoryKindDictionarySize + MemoryKindCompositeBase + MemoryKindCompositeSize MemoryKindOptional MemoryKindNil MemoryKindVoid diff --git a/runtime/common/memorykind_string.go b/runtime/common/memorykind_string.go index 6f73aa8942..dc100704ec 100644 --- a/runtime/common/memorykind_string.go +++ b/runtime/common/memorykind_string.go @@ -15,97 +15,100 @@ func _() { _ = x[MemoryKindCharacter-4] _ = x[MemoryKindMetaType-5] _ = x[MemoryKindNumber-6] - _ = x[MemoryKindArray-7] - _ = x[MemoryKindDictionary-8] - _ = x[MemoryKindComposite-9] - _ = x[MemoryKindOptional-10] - _ = x[MemoryKindNil-11] - _ = x[MemoryKindVoid-12] - _ = x[MemoryKindTypeValue-13] - _ = x[MemoryKindPathValue-14] - _ = x[MemoryKindCapabilityValue-15] - _ = x[MemoryKindLinkValue-16] - _ = x[MemoryKindStorageReferenceValue-17] - _ = x[MemoryKindEphemeralReferenceValue-18] - _ = x[MemoryKindInterpretedFunction-19] - _ = x[MemoryKindHostFunction-20] - _ = x[MemoryKindBoundFunction-21] - _ = x[MemoryKindBigInt-22] - _ = x[MemoryKindRawString-23] - _ = x[MemoryKindAddressLocation-24] - _ = x[MemoryKindBytes-25] - _ = x[MemoryKindVariable-26] - _ = x[MemoryKindTokenIdentifier-27] - _ = x[MemoryKindTokenComment-28] - _ = x[MemoryKindTokenNumericLiteral-29] - _ = x[MemoryKindTokenSyntax-30] - _ = x[MemoryKindProgram-31] - _ = x[MemoryKindIdentifier-32] - _ = x[MemoryKindArgument-33] - _ = x[MemoryKindBlock-34] - _ = x[MemoryKindFunctionBlock-35] - _ = x[MemoryKindParameter-36] - _ = x[MemoryKindParameterList-37] - _ = x[MemoryKindTransfer-38] - _ = x[MemoryKindMembers-39] - _ = x[MemoryKindTypeAnnotation-40] - _ = x[MemoryKindFunctionDeclaration-41] - _ = x[MemoryKindCompositeDeclaration-42] - _ = x[MemoryKindInterfaceDeclaration-43] - _ = x[MemoryKindEnumCaseDeclaration-44] - _ = x[MemoryKindFieldDeclaration-45] - _ = x[MemoryKindTransactionDeclaration-46] - _ = x[MemoryKindImportDeclaration-47] - _ = x[MemoryKindVariableDeclaration-48] - _ = x[MemoryKindSpecialFunctionDeclaration-49] - _ = x[MemoryKindPragmaDeclaration-50] - _ = x[MemoryKindAssignmentStatement-51] - _ = x[MemoryKindBreakStatement-52] - _ = x[MemoryKindContinueStatement-53] - _ = x[MemoryKindEmitStatement-54] - _ = x[MemoryKindExpressionStatement-55] - _ = x[MemoryKindForStatement-56] - _ = x[MemoryKindIfStatement-57] - _ = x[MemoryKindReturnStatement-58] - _ = x[MemoryKindSwapStatement-59] - _ = x[MemoryKindSwitchStatement-60] - _ = x[MemoryKindWhileStatement-61] - _ = x[MemoryKindBooleanExpression-62] - _ = x[MemoryKindNilExpression-63] - _ = x[MemoryKindStringExpression-64] - _ = x[MemoryKindIntegerExpression-65] - _ = x[MemoryKindFixedPointExpression-66] - _ = x[MemoryKindArrayExpression-67] - _ = x[MemoryKindDictionaryExpression-68] - _ = x[MemoryKindIdentifierExpression-69] - _ = x[MemoryKindInvocationExpression-70] - _ = x[MemoryKindMemberExpression-71] - _ = x[MemoryKindIndexExpression-72] - _ = x[MemoryKindConditionalExpression-73] - _ = x[MemoryKindUnaryExpression-74] - _ = x[MemoryKindBinaryExpression-75] - _ = x[MemoryKindFunctionExpression-76] - _ = x[MemoryKindCastingExpression-77] - _ = x[MemoryKindCreateExpression-78] - _ = x[MemoryKindDestroyExpression-79] - _ = x[MemoryKindReferenceExpression-80] - _ = x[MemoryKindForceExpression-81] - _ = x[MemoryKindPathExpression-82] - _ = x[MemoryKindConstantSizedType-83] - _ = x[MemoryKindDictionaryType-84] - _ = x[MemoryKindFunctionType-85] - _ = x[MemoryKindInstantiationType-86] - _ = x[MemoryKindNominalType-87] - _ = x[MemoryKindOptionalType-88] - _ = x[MemoryKindReferenceType-89] - _ = x[MemoryKindRestrictedType-90] - _ = x[MemoryKindVariableSizedType-91] - _ = x[MemoryKindLast-92] + _ = x[MemoryKindArrayBase-7] + _ = x[MemoryKindArrayLength-8] + _ = x[MemoryKindDictionaryBase-9] + _ = x[MemoryKindDictionarySize-10] + _ = x[MemoryKindCompositeBase-11] + _ = x[MemoryKindCompositeSize-12] + _ = x[MemoryKindOptional-13] + _ = x[MemoryKindNil-14] + _ = x[MemoryKindVoid-15] + _ = x[MemoryKindTypeValue-16] + _ = x[MemoryKindPathValue-17] + _ = x[MemoryKindCapabilityValue-18] + _ = x[MemoryKindLinkValue-19] + _ = x[MemoryKindStorageReferenceValue-20] + _ = x[MemoryKindEphemeralReferenceValue-21] + _ = x[MemoryKindInterpretedFunction-22] + _ = x[MemoryKindHostFunction-23] + _ = x[MemoryKindBoundFunction-24] + _ = x[MemoryKindBigInt-25] + _ = x[MemoryKindRawString-26] + _ = x[MemoryKindAddressLocation-27] + _ = x[MemoryKindBytes-28] + _ = x[MemoryKindVariable-29] + _ = x[MemoryKindTokenIdentifier-30] + _ = x[MemoryKindTokenComment-31] + _ = x[MemoryKindTokenNumericLiteral-32] + _ = x[MemoryKindTokenSyntax-33] + _ = x[MemoryKindProgram-34] + _ = x[MemoryKindIdentifier-35] + _ = x[MemoryKindArgument-36] + _ = x[MemoryKindBlock-37] + _ = x[MemoryKindFunctionBlock-38] + _ = x[MemoryKindParameter-39] + _ = x[MemoryKindParameterList-40] + _ = x[MemoryKindTransfer-41] + _ = x[MemoryKindMembers-42] + _ = x[MemoryKindTypeAnnotation-43] + _ = x[MemoryKindFunctionDeclaration-44] + _ = x[MemoryKindCompositeDeclaration-45] + _ = x[MemoryKindInterfaceDeclaration-46] + _ = x[MemoryKindEnumCaseDeclaration-47] + _ = x[MemoryKindFieldDeclaration-48] + _ = x[MemoryKindTransactionDeclaration-49] + _ = x[MemoryKindImportDeclaration-50] + _ = x[MemoryKindVariableDeclaration-51] + _ = x[MemoryKindSpecialFunctionDeclaration-52] + _ = x[MemoryKindPragmaDeclaration-53] + _ = x[MemoryKindAssignmentStatement-54] + _ = x[MemoryKindBreakStatement-55] + _ = x[MemoryKindContinueStatement-56] + _ = x[MemoryKindEmitStatement-57] + _ = x[MemoryKindExpressionStatement-58] + _ = x[MemoryKindForStatement-59] + _ = x[MemoryKindIfStatement-60] + _ = x[MemoryKindReturnStatement-61] + _ = x[MemoryKindSwapStatement-62] + _ = x[MemoryKindSwitchStatement-63] + _ = x[MemoryKindWhileStatement-64] + _ = x[MemoryKindBooleanExpression-65] + _ = x[MemoryKindNilExpression-66] + _ = x[MemoryKindStringExpression-67] + _ = x[MemoryKindIntegerExpression-68] + _ = x[MemoryKindFixedPointExpression-69] + _ = x[MemoryKindArrayExpression-70] + _ = x[MemoryKindDictionaryExpression-71] + _ = x[MemoryKindIdentifierExpression-72] + _ = x[MemoryKindInvocationExpression-73] + _ = x[MemoryKindMemberExpression-74] + _ = x[MemoryKindIndexExpression-75] + _ = x[MemoryKindConditionalExpression-76] + _ = x[MemoryKindUnaryExpression-77] + _ = x[MemoryKindBinaryExpression-78] + _ = x[MemoryKindFunctionExpression-79] + _ = x[MemoryKindCastingExpression-80] + _ = x[MemoryKindCreateExpression-81] + _ = x[MemoryKindDestroyExpression-82] + _ = x[MemoryKindReferenceExpression-83] + _ = x[MemoryKindForceExpression-84] + _ = x[MemoryKindPathExpression-85] + _ = x[MemoryKindConstantSizedType-86] + _ = x[MemoryKindDictionaryType-87] + _ = x[MemoryKindFunctionType-88] + _ = x[MemoryKindInstantiationType-89] + _ = x[MemoryKindNominalType-90] + _ = x[MemoryKindOptionalType-91] + _ = x[MemoryKindReferenceType-92] + _ = x[MemoryKindRestrictedType-93] + _ = x[MemoryKindVariableSizedType-94] + _ = x[MemoryKindLast-95] } -const _MemoryKind_name = "UnknownBoolAddressStringCharacterMetaTypeNumberArrayDictionaryCompositeOptionalNilVoidTypeValuePathValueCapabilityValueLinkValueStorageReferenceValueEphemeralReferenceValueInterpretedFunctionHostFunctionBoundFunctionBigIntRawStringAddressLocationBytesVariableTokenIdentifierTokenCommentTokenNumericLiteralTokenSyntaxProgramIdentifierArgumentBlockFunctionBlockParameterParameterListTransferMembersTypeAnnotationFunctionDeclarationCompositeDeclarationInterfaceDeclarationEnumCaseDeclarationFieldDeclarationTransactionDeclarationImportDeclarationVariableDeclarationSpecialFunctionDeclarationPragmaDeclarationAssignmentStatementBreakStatementContinueStatementEmitStatementExpressionStatementForStatementIfStatementReturnStatementSwapStatementSwitchStatementWhileStatementBooleanExpressionNilExpressionStringExpressionIntegerExpressionFixedPointExpressionArrayExpressionDictionaryExpressionIdentifierExpressionInvocationExpressionMemberExpressionIndexExpressionConditionalExpressionUnaryExpressionBinaryExpressionFunctionExpressionCastingExpressionCreateExpressionDestroyExpressionReferenceExpressionForceExpressionPathExpressionConstantSizedTypeDictionaryTypeFunctionTypeInstantiationTypeNominalTypeOptionalTypeReferenceTypeRestrictedTypeVariableSizedTypeLast" +const _MemoryKind_name = "UnknownBoolAddressStringCharacterMetaTypeNumberArrayBaseArrayLengthDictionaryBaseDictionarySizeCompositeBaseCompositeSizeOptionalNilVoidTypeValuePathValueCapabilityValueLinkValueStorageReferenceValueEphemeralReferenceValueInterpretedFunctionHostFunctionBoundFunctionBigIntRawStringAddressLocationBytesVariableTokenIdentifierTokenCommentTokenNumericLiteralTokenSyntaxProgramIdentifierArgumentBlockFunctionBlockParameterParameterListTransferMembersTypeAnnotationFunctionDeclarationCompositeDeclarationInterfaceDeclarationEnumCaseDeclarationFieldDeclarationTransactionDeclarationImportDeclarationVariableDeclarationSpecialFunctionDeclarationPragmaDeclarationAssignmentStatementBreakStatementContinueStatementEmitStatementExpressionStatementForStatementIfStatementReturnStatementSwapStatementSwitchStatementWhileStatementBooleanExpressionNilExpressionStringExpressionIntegerExpressionFixedPointExpressionArrayExpressionDictionaryExpressionIdentifierExpressionInvocationExpressionMemberExpressionIndexExpressionConditionalExpressionUnaryExpressionBinaryExpressionFunctionExpressionCastingExpressionCreateExpressionDestroyExpressionReferenceExpressionForceExpressionPathExpressionConstantSizedTypeDictionaryTypeFunctionTypeInstantiationTypeNominalTypeOptionalTypeReferenceTypeRestrictedTypeVariableSizedTypeLast" -var _MemoryKind_index = [...]uint16{0, 7, 11, 18, 24, 33, 41, 47, 52, 62, 71, 79, 82, 86, 95, 104, 119, 128, 149, 172, 191, 203, 216, 222, 231, 246, 251, 259, 274, 286, 305, 316, 323, 333, 341, 346, 359, 368, 381, 389, 396, 410, 429, 449, 469, 488, 504, 526, 543, 562, 588, 605, 624, 638, 655, 668, 687, 699, 710, 725, 738, 753, 767, 784, 797, 813, 830, 850, 865, 885, 905, 925, 941, 956, 977, 992, 1008, 1026, 1043, 1059, 1076, 1095, 1110, 1124, 1141, 1155, 1167, 1184, 1195, 1207, 1220, 1234, 1251, 1255} +var _MemoryKind_index = [...]uint16{0, 7, 11, 18, 24, 33, 41, 47, 56, 67, 81, 95, 108, 121, 129, 132, 136, 145, 154, 169, 178, 199, 222, 241, 253, 266, 272, 281, 296, 301, 309, 324, 336, 355, 366, 373, 383, 391, 396, 409, 418, 431, 439, 446, 460, 479, 499, 519, 538, 554, 576, 593, 612, 638, 655, 674, 688, 705, 718, 737, 749, 760, 775, 788, 803, 817, 834, 847, 863, 880, 900, 915, 935, 955, 975, 991, 1006, 1027, 1042, 1058, 1076, 1093, 1109, 1126, 1145, 1160, 1174, 1191, 1205, 1217, 1234, 1245, 1257, 1270, 1284, 1301, 1305} func (i MemoryKind) String() string { if i >= MemoryKind(len(_MemoryKind_index)-1) { diff --git a/runtime/common/metering.go b/runtime/common/metering.go index 8722fab65d..4c178bd15b 100644 --- a/runtime/common/metering.go +++ b/runtime/common/metering.go @@ -115,6 +115,50 @@ func NewConstantMemoryUsage(kind MemoryKind) MemoryUsage { } } +func NewArrayMemoryUsages(length int) (MemoryUsage, MemoryUsage) { + return MemoryUsage{ + Kind: MemoryKindArrayBase, + Amount: 1, + }, MemoryUsage{ + Kind: MemoryKindArrayLength, + Amount: uint64(length), + } +} + +func NewArrayLengthUsage(length int) MemoryUsage { + return MemoryUsage{ + Kind: MemoryKindArrayLength, + Amount: uint64(length), + } +} + +func NewDictionaryMemoryUsages(length int) (MemoryUsage, MemoryUsage) { + return MemoryUsage{ + Kind: MemoryKindDictionaryBase, + Amount: 1, + }, MemoryUsage{ + Kind: MemoryKindDictionarySize, + Amount: uint64(length), + } +} + +func NewDictionarySizeUsage(length int) MemoryUsage { + return MemoryUsage{ + Kind: MemoryKindDictionarySize, + Amount: uint64(length), + } +} + +func NewCompositeMemoryUsages(length int) (MemoryUsage, MemoryUsage) { + return MemoryUsage{ + Kind: MemoryKindCompositeBase, + Amount: 1, + }, MemoryUsage{ + Kind: MemoryKindCompositeSize, + Amount: uint64(length), + } +} + func NewStringMemoryUsage(length int) MemoryUsage { return MemoryUsage{ Kind: MemoryKindString, diff --git a/runtime/imported_values_memory_metering_test.go b/runtime/imported_values_memory_metering_test.go index b8c351807b..94cf490012 100644 --- a/runtime/imported_values_memory_metering_test.go +++ b/runtime/imported_values_memory_metering_test.go @@ -372,7 +372,7 @@ func TestMemoryMeteringErrors(t *testing.T) { intf := &testRuntimeInterface{ meterMemory: func(usage common.MemoryUsage) error { if usage.Kind == common.MemoryKindString || - usage.Kind == common.MemoryKindArray { + usage.Kind == common.MemoryKindArrayBase { return testMemoryError{} } return nil diff --git a/runtime/interpreter/simplecompositevalue.go b/runtime/interpreter/simplecompositevalue.go index 6ed306749d..b37fcbcb29 100644 --- a/runtime/interpreter/simplecompositevalue.go +++ b/runtime/interpreter/simplecompositevalue.go @@ -57,7 +57,10 @@ func NewSimpleCompositeValue( fieldFormatters map[string]func(Value, SeenReferences) string, stringer func(SeenReferences) string, ) *SimpleCompositeValue { - common.UseConstantMemory(inter, common.MemoryKindComposite) + + baseUsage, lengthUsage := common.NewCompositeMemoryUsages(len(fields)) + common.UseMemory(inter, baseUsage) + common.UseMemory(inter, lengthUsage) return &SimpleCompositeValue{ TypeID: typeID, diff --git a/runtime/interpreter/value.go b/runtime/interpreter/value.go index 469d965e2e..0a03340342 100644 --- a/runtime/interpreter/value.go +++ b/runtime/interpreter/value.go @@ -1356,7 +1356,9 @@ func newArrayValueFromAtreeValue( staticType ArrayStaticType, ) *ArrayValue { - common.UseMemory(memoryGauge, common.NewConstantMemoryUsage(common.MemoryKindArray)) + baseUse, lengthUse := common.NewArrayMemoryUsages(int(array.Count())) + common.UseMemory(memoryGauge, baseUse) + common.UseMemory(memoryGauge, lengthUse) return &ArrayValue{ Type: staticType, @@ -1648,6 +1650,9 @@ func (v *ArrayValue) RecursiveString(seenReferences SeenReferences) string { func (v *ArrayValue) Append(interpreter *Interpreter, getLocationRange func() LocationRange, element Value) { + // length increases by 1 + common.UseMemory(interpreter, common.NewArrayLengthUsage(1)) + interpreter.checkContainerMutation(v.Type.ElementType(), element, getLocationRange) element = element.Transfer( @@ -1694,6 +1699,9 @@ func (v *ArrayValue) Insert(interpreter *Interpreter, getLocationRange func() Lo }) } + // length increases by 1 + common.UseMemory(interpreter, common.NewArrayLengthUsage(1)) + interpreter.checkContainerMutation(v.Type.ElementType(), element, getLocationRange) element = element.Transfer( @@ -13973,7 +13981,9 @@ func newCompositeValueFromOrderedMap( typeInfo compositeTypeInfo, ) *CompositeValue { - common.UseMemory(memoryGauge, common.NewConstantMemoryUsage(common.MemoryKindComposite)) + baseUse, lengthUse := common.NewCompositeMemoryUsages(int(dict.Count())) + common.UseMemory(memoryGauge, baseUse) + common.UseMemory(memoryGauge, lengthUse) return &CompositeValue{ dictionary: dict, @@ -15067,7 +15077,9 @@ func newDictionaryValueFromOrderedMap( staticType DictionaryStaticType, ) *DictionaryValue { - common.UseMemory(memoryGauge, common.NewConstantMemoryUsage(common.MemoryKindDictionary)) + baseUse, lengthUse := common.NewDictionaryMemoryUsages(int(dict.Count())) + common.UseMemory(memoryGauge, baseUse) + common.UseMemory(memoryGauge, lengthUse) return &DictionaryValue{ Type: staticType, @@ -15562,6 +15574,9 @@ func (v *DictionaryValue) Insert( keyValue, value Value, ) OptionalValue { + // length increases by 1 + common.UseMemory(interpreter, common.NewDictionarySizeUsage(1)) + interpreter.checkContainerMutation(v.Type.KeyType, keyValue, getLocationRange) interpreter.checkContainerMutation(v.Type.ValueType, value, getLocationRange) diff --git a/runtime/tests/interpreter/memory_metering_test.go b/runtime/tests/interpreter/memory_metering_test.go index 32c05351e5..243faf6350 100644 --- a/runtime/tests/interpreter/memory_metering_test.go +++ b/runtime/tests/interpreter/memory_metering_test.go @@ -60,12 +60,12 @@ func TestInterpretArrayMetering(t *testing.T) { t.Parallel() script := ` - pub fun main() { - let x: [Int8] = [] - let y: [[String]] = [[]] - let z: [[[Bool]]] = [[[]]] - } - ` + pub fun main() { + let x: [Int8] = [] + let y: [[String]] = [[]] + let z: [[[Bool]]] = [[[]]] + } + ` meter := newTestMemoryGauge() inter := parseCheckAndInterpretWithMemoryMetering(t, script, meter) @@ -73,15 +73,8 @@ func TestInterpretArrayMetering(t *testing.T) { _, err := inter.Invoke("main") require.NoError(t, err) - // 1 for creation of x - // 2 for creation of y - // 1 for transfer of y - // 1 dynamic type check of y - // 3 for creation of z - // 4 for transfer of z - // 3 for dynamic type check of z - // 14 from value transfer - assert.Equal(t, uint64(29), meter.getMemory(common.MemoryKindArray)) + assert.Equal(t, uint64(29), meter.getMemory(common.MemoryKindArrayBase)) + assert.Equal(t, uint64(10), meter.getMemory(common.MemoryKindArrayLength)) assert.Equal(t, uint64(4), meter.getMemory(common.MemoryKindVariable)) }) @@ -89,13 +82,13 @@ func TestInterpretArrayMetering(t *testing.T) { t.Parallel() script := ` - pub fun main() { - let values: [[Int8]] = [[], [], []] - for value in values { - let a = value + pub fun main() { + let values: [[Int8]] = [[], [], []] + for value in values { + let a = value + } } - } - ` + ` meter := newTestMemoryGauge() inter := parseCheckAndInterpretWithMemoryMetering(t, script, meter) @@ -103,17 +96,37 @@ func TestInterpretArrayMetering(t *testing.T) { _, err := inter.Invoke("main") require.NoError(t, err) - assert.Equal(t, uint64(33), meter.getMemory(common.MemoryKindArray)) + assert.Equal(t, uint64(33), meter.getMemory(common.MemoryKindArrayBase)) + assert.Equal(t, uint64(9), meter.getMemory(common.MemoryKindArrayLength)) assert.Equal(t, uint64(6), meter.getMemory(common.MemoryKindVariable)) }) t.Run("contains", func(t *testing.T) { t.Parallel() + script := ` + pub fun main() { + let x: [Int8] = [] + x.contains(5) + } + ` + + meter := newTestMemoryGauge() + inter := parseCheckAndInterpretWithMemoryMetering(t, script, meter) + + _, err := inter.Invoke("main") + require.NoError(t, err) + + assert.Equal(t, uint64(1), meter.getMemory(common.MemoryKindBool)) + }) + + t.Run("append", func(t *testing.T) { + t.Parallel() + script := ` pub fun main() { let x: [Int8] = [] - x.contains(5) + x.append(3) } ` @@ -123,7 +136,28 @@ func TestInterpretArrayMetering(t *testing.T) { _, err := inter.Invoke("main") require.NoError(t, err) - assert.Equal(t, uint64(1), meter.getMemory(common.MemoryKindBool)) + assert.Equal(t, uint64(2), meter.getMemory(common.MemoryKindArrayBase)) + assert.Equal(t, uint64(1), meter.getMemory(common.MemoryKindArrayLength)) + }) + + t.Run("insert", func(t *testing.T) { + t.Parallel() + + script := ` + pub fun main() { + let x: [Int8] = [] + x.insert(at:0, 3) + } + ` + + meter := newTestMemoryGauge() + inter := parseCheckAndInterpretWithMemoryMetering(t, script, meter) + + _, err := inter.Invoke("main") + require.NoError(t, err) + + assert.Equal(t, uint64(2), meter.getMemory(common.MemoryKindArrayBase)) + assert.Equal(t, uint64(1), meter.getMemory(common.MemoryKindArrayLength)) }) } @@ -147,7 +181,8 @@ func TestInterpretDictionaryMetering(t *testing.T) { require.NoError(t, err) assert.Equal(t, uint64(6), meter.getMemory(common.MemoryKindString)) - assert.Equal(t, uint64(10), meter.getMemory(common.MemoryKindDictionary)) + assert.Equal(t, uint64(10), meter.getMemory(common.MemoryKindDictionaryBase)) + assert.Equal(t, uint64(2), meter.getMemory(common.MemoryKindDictionarySize)) assert.Equal(t, uint64(3), meter.getMemory(common.MemoryKindVariable)) }) @@ -169,7 +204,7 @@ func TestInterpretDictionaryMetering(t *testing.T) { _, err := inter.Invoke("main") require.NoError(t, err) - assert.Equal(t, uint64(30), meter.getMemory(common.MemoryKindDictionary)) + assert.Equal(t, uint64(30), meter.getMemory(common.MemoryKindDictionaryBase)) assert.Equal(t, uint64(6), meter.getMemory(common.MemoryKindVariable)) }) @@ -191,6 +226,26 @@ func TestInterpretDictionaryMetering(t *testing.T) { assert.Equal(t, uint64(1), meter.getMemory(common.MemoryKindBool)) }) + + t.Run("insert", func(t *testing.T) { + t.Parallel() + + script := ` + pub fun main() { + let x: {Int8: String} = {} + x.insert(key: 5, "") + } + ` + + meter := newTestMemoryGauge() + inter := parseCheckAndInterpretWithMemoryMetering(t, script, meter) + + _, err := inter.Invoke("main") + require.NoError(t, err) + + assert.Equal(t, uint64(2), meter.getMemory(common.MemoryKindDictionaryBase)) + assert.Equal(t, uint64(1), meter.getMemory(common.MemoryKindDictionarySize)) + }) } func TestInterpretCompositeMetering(t *testing.T) { @@ -227,7 +282,8 @@ func TestInterpretCompositeMetering(t *testing.T) { assert.Equal(t, uint64(14), meter.getMemory(common.MemoryKindString)) assert.Equal(t, uint64(66), meter.getMemory(common.MemoryKindRawString)) - assert.Equal(t, uint64(4), meter.getMemory(common.MemoryKindComposite)) + assert.Equal(t, uint64(4), meter.getMemory(common.MemoryKindCompositeBase)) + assert.Equal(t, uint64(3), meter.getMemory(common.MemoryKindCompositeSize)) assert.Equal(t, uint64(8), meter.getMemory(common.MemoryKindVariable)) }) @@ -251,7 +307,8 @@ func TestInterpretCompositeMetering(t *testing.T) { _, err := inter.Invoke("main") require.NoError(t, err) - assert.Equal(t, uint64(30), meter.getMemory(common.MemoryKindComposite)) + assert.Equal(t, uint64(30), meter.getMemory(common.MemoryKindCompositeBase)) + assert.Equal(t, uint64(0), meter.getMemory(common.MemoryKindCompositeSize)) assert.Equal(t, uint64(7), meter.getMemory(common.MemoryKindVariable)) }) } @@ -276,7 +333,8 @@ func TestInterpretCompositeFieldMetering(t *testing.T) { require.NoError(t, err) assert.Equal(t, uint64(0), meter.getMemory(common.MemoryKindRawString)) - assert.Equal(t, uint64(2), meter.getMemory(common.MemoryKindComposite)) + assert.Equal(t, uint64(2), meter.getMemory(common.MemoryKindCompositeBase)) + assert.Equal(t, uint64(0), meter.getMemory(common.MemoryKindCompositeSize)) }) t.Run("1 field", func(t *testing.T) { @@ -301,7 +359,8 @@ func TestInterpretCompositeFieldMetering(t *testing.T) { require.NoError(t, err) assert.Equal(t, uint64(16), meter.getMemory(common.MemoryKindRawString)) - assert.Equal(t, uint64(2), meter.getMemory(common.MemoryKindComposite)) + assert.Equal(t, uint64(2), meter.getMemory(common.MemoryKindCompositeBase)) + assert.Equal(t, uint64(1), meter.getMemory(common.MemoryKindCompositeSize)) }) t.Run("2 field", func(t *testing.T) { @@ -328,7 +387,8 @@ func TestInterpretCompositeFieldMetering(t *testing.T) { require.NoError(t, err) assert.Equal(t, uint64(34), meter.getMemory(common.MemoryKindRawString)) - assert.Equal(t, uint64(2), meter.getMemory(common.MemoryKindComposite)) + assert.Equal(t, uint64(2), meter.getMemory(common.MemoryKindCompositeSize)) + assert.Equal(t, uint64(2), meter.getMemory(common.MemoryKindCompositeBase)) }) } @@ -7753,7 +7813,7 @@ func TestInterpreterStringLocationMetering(t *testing.T) { pub fun main(account: AuthAccount) { let s = CompositeType("S.test.S") } - ` + ` meter := newTestMemoryGauge() inter := parseCheckAndInterpretWithMemoryMetering(t, script, meter) account := newTestAuthAccountValue(inter, interpreter.AddressValue{})