Skip to content

Commit

Permalink
Use type-index in the 'New' instruction
Browse files Browse the repository at this point in the history
  • Loading branch information
SupunS committed Nov 6, 2024
1 parent 69a1753 commit 80b7a8c
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 114 deletions.
38 changes: 25 additions & 13 deletions bbq/bytecode_printer.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ type BytecodePrinter struct {
func (p *BytecodePrinter) PrintProgram(program *Program) string {
p.printImports(program.Imports)
p.printConstantPool(program.Constants)
p.printTypePool(program.Types)

for _, function := range program.Functions {
p.printFunction(function)
p.stringBuilder.WriteRune('\n')
Expand Down Expand Up @@ -73,20 +75,10 @@ func (p *BytecodePrinter) printCode(codes []byte) {
p.stringBuilder.WriteString(" " + fmt.Sprint(operand))

case opcode.New:
var kind int
var kind, typeIndex int
kind, i = p.getIntOperand(codes, i)

var location common.Location
location, i = p.getLocation(codes, i)

var typeName string
typeName, i = p.getStringOperand(codes, i)

if location != nil {
typeName = string(location.TypeID(nil, typeName))
}

p.stringBuilder.WriteString(" " + fmt.Sprint(kind) + " " + typeName)
typeIndex, i = p.getIntOperand(codes, i)
p.stringBuilder.WriteString(" " + fmt.Sprint(kind) + " " + fmt.Sprint(typeIndex))

case opcode.Cast:
var typeIndex int
Expand Down Expand Up @@ -190,6 +182,26 @@ func (p *BytecodePrinter) printConstantPool(constants []*Constant) {
p.stringBuilder.WriteRune('\n')
}

func (p *BytecodePrinter) printTypePool(types [][]byte) {
p.stringBuilder.WriteString("-- Type Pool --\n")

for index, typeBytes := range types {
dec := interpreter.CBORDecMode.NewByteStreamDecoder(typeBytes)
typeDecoder := interpreter.NewTypeDecoder(dec, nil)
staticType, err := typeDecoder.DecodeStaticType()
if err != nil {
panic(err)
}

p.stringBuilder.WriteString(fmt.Sprint(index))
p.stringBuilder.WriteString(" | ")
p.stringBuilder.WriteString(string(staticType.ID()))
p.stringBuilder.WriteRune('\n')
}

p.stringBuilder.WriteRune('\n')
}

func (p *BytecodePrinter) getLocation(codes []byte, i int) (location common.Location, endIndex int) {

Check failure on line 205 in bbq/bytecode_printer.go

View workflow job for this annotation

GitHub Actions / Lint

func `(*BytecodePrinter).getLocation` is unused (unused)
locationLen, i := p.getIntOperand(codes, i)
locationBytes := codes[i+1 : i+1+locationLen]
Expand Down
38 changes: 11 additions & 27 deletions bbq/compiler/compiler.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ type Compiler struct {
staticTypes [][]byte

// Cache alike for staticTypes and constants in the pool.
typesInPool map[sema.Type]uint16
typesInPool map[sema.TypeID]uint16
constantsInPool map[constantsCacheKey]*constant

// TODO: initialize
Expand Down Expand Up @@ -104,7 +104,7 @@ func NewCompiler(
Config: &Config{},
globals: make(map[string]*global),
importedGlobals: indexedNativeFunctions,
typesInPool: make(map[sema.Type]uint16),
typesInPool: make(map[sema.TypeID]uint16),
constantsInPool: make(map[constantsCacheKey]*constant),
compositeTypeStack: &Stack[*sema.CompositeType]{
elements: make([]*sema.CompositeType, 0),
Expand Down Expand Up @@ -1087,34 +1087,18 @@ func (c *Compiler) compileInitializer(declaration *ast.SpecialFunctionDeclaratio
// i.e: `self = New()`

enclosingCompositeType := c.compositeTypeStack.top()
locationBytes, err := commons.LocationToBytes(enclosingCompositeType.Location)
if err != nil {
panic(err)
}

byteSize := 2 + // two bytes for composite kind
2 + // 2 bytes for location size
len(locationBytes) + // location
2 + // 2 bytes for type name size
len(enclosingCompositeTypeName) // type name

args := make([]byte, 0, byteSize)

// Write composite kind
kindFirst, kindSecond := encodeUint16(uint16(enclosingCompositeType.Kind))
args = append(args, kindFirst, kindSecond)

// Write location
locationSizeFirst, locationSizeSecond := encodeUint16(uint16(len(locationBytes)))
args = append(args, locationSizeFirst, locationSizeSecond)
args = append(args, locationBytes...)

// Write composite name
typeNameSizeFirst, typeNameSizeSecond := encodeUint16(uint16(len(enclosingCompositeTypeName)))
args = append(args, typeNameSizeFirst, typeNameSizeSecond)
args = append(args, enclosingCompositeTypeName...)
index := c.getOrAddType(enclosingCompositeType)
typeFirst, typeSecond := encodeUint16(index)

c.emit(opcode.New, args...)
c.emit(
opcode.New,
kindFirst, kindSecond,
typeFirst, typeSecond,
)

if enclosingType.Kind == common.CompositeKindContract {
// During contract init, update the global variable with the newly initialized contract value.
Expand Down Expand Up @@ -1290,15 +1274,15 @@ func (c *Compiler) emitCheckType(targetType sema.Type) {

func (c *Compiler) getOrAddType(targetType sema.Type) uint16 {
// Optimization: Re-use types in the pool.
index, ok := c.typesInPool[targetType]
index, ok := c.typesInPool[targetType.ID()]
if !ok {
staticType := interpreter.ConvertSemaToStaticType(c.memoryGauge, targetType)
bytes, err := interpreter.StaticTypeToBytes(staticType)
if err != nil {
panic(err)
}
index = c.addType(bytes)
c.typesInPool[targetType] = index
c.typesInPool[targetType.ID()] = index
}
return index
}
Expand Down
8 changes: 5 additions & 3 deletions bbq/vm/test/vm_bench_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,10 +169,12 @@ func BenchmarkNewStructRaw(b *testing.B) {
for i := 0; i < b.N; i++ {
for j := 0; j < 1; j++ {
structValue := vm.NewCompositeValue(
nil,
"Foo",
common.CompositeKindStructure,
common.Address{},
interpreter.NewCompositeStaticTypeComputeTypeID(
nil,
common.NewAddressLocation(nil, common.ZeroAddress, "Foo"),
"Foo",
),
storage.BasicSlabStorage,
)
structValue.SetMember(vmConfig, "id", fieldValue)
Expand Down
3 changes: 2 additions & 1 deletion bbq/vm/test/vm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -269,8 +269,9 @@ func TestNewStruct(t *testing.T) {

require.IsType(t, &vm.CompositeValue{}, result)
structValue := result.(*vm.CompositeValue)
compositeType := structValue.CompositeType

require.Equal(t, "Foo", structValue.QualifiedIdentifier)
require.Equal(t, "Foo", compositeType.QualifiedIdentifier)
require.Equal(
t,
vm.IntValue{SmallInt: 12},
Expand Down
81 changes: 25 additions & 56 deletions bbq/vm/value_composite.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,34 +29,35 @@ import (
)

type CompositeValue struct {
dictionary *atree.OrderedMap
Location common.Location
QualifiedIdentifier string
typeID common.TypeID
staticType StaticType
Kind common.CompositeKind
dictionary *atree.OrderedMap
CompositeType *interpreter.CompositeStaticType
Kind common.CompositeKind
}

var _ Value = &CompositeValue{}
var _ MemberAccessibleValue = &CompositeValue{}
var _ ReferenceTrackedResourceKindedValue = &CompositeValue{}

func NewCompositeValue(
location common.Location,
qualifiedIdentifier string,
kind common.CompositeKind,
address common.Address,
staticType *interpreter.CompositeStaticType,
storage atree.SlabStorage,
) *CompositeValue {

// Newly created values are always on stack.
// Need to 'Transfer' if needed to be stored in an account.
address := common.ZeroAddress

dictionary, err := atree.NewMap(
storage,

atree.Address(address),

atree.NewDefaultDigesterBuilder(),
interpreter.NewCompositeTypeInfo(
nil,
location,
qualifiedIdentifier,
staticType.Location,
staticType.QualifiedIdentifier,
kind,
),
)
Expand All @@ -66,41 +67,28 @@ func NewCompositeValue(
}

return &CompositeValue{
QualifiedIdentifier: qualifiedIdentifier,
Location: location,
dictionary: dictionary,
Kind: kind,
CompositeType: staticType,
dictionary: dictionary,
Kind: kind,
}
}

func newCompositeValueFromOrderedMap(
dict *atree.OrderedMap,
location common.Location,
qualifiedIdentifier string,
staticType *interpreter.CompositeStaticType,
kind common.CompositeKind,
) *CompositeValue {
return &CompositeValue{
dictionary: dict,
Location: location,
QualifiedIdentifier: qualifiedIdentifier,
Kind: kind,
dictionary: dict,
CompositeType: staticType,
Kind: kind,
}
}

func (*CompositeValue) isValue() {}

func (v *CompositeValue) StaticType(memoryGauge common.MemoryGauge) StaticType {
if v.staticType == nil {
// NOTE: Instead of using NewCompositeStaticType, which always generates the type ID,
// use the TypeID accessor, which may return an already computed type ID
v.staticType = interpreter.NewCompositeStaticType(
memoryGauge,
v.Location,
v.QualifiedIdentifier,
v.TypeID(),
)
}
return v.staticType
func (v *CompositeValue) StaticType(common.MemoryGauge) StaticType {
return v.CompositeType
}

func (v *CompositeValue) GetMember(config *Config, name string) Value {
Expand Down Expand Up @@ -164,17 +152,7 @@ func (v *CompositeValue) SlabID() atree.SlabID {
}

func (v *CompositeValue) TypeID() common.TypeID {
if v.typeID == "" {
location := v.Location
qualifiedIdentifier := v.QualifiedIdentifier
if location == nil {
return common.TypeID(qualifiedIdentifier)
}

// TODO: TypeID metering
v.typeID = location.TypeID(nil, qualifiedIdentifier)
}
return v.typeID
return v.CompositeType.TypeID
}

func (v *CompositeValue) IsResourceKinded() bool {
Expand Down Expand Up @@ -311,20 +289,11 @@ func (v *CompositeValue) Transfer(
}

if res == nil {
typeInfo := interpreter.NewCompositeTypeInfo(
config.MemoryGauge,
v.Location,
v.QualifiedIdentifier,
res = newCompositeValueFromOrderedMap(
dictionary,
v.CompositeType,
v.Kind,
)
res = &CompositeValue{
dictionary: dictionary,
Location: typeInfo.Location,
QualifiedIdentifier: typeInfo.QualifiedIdentifier,
Kind: typeInfo.Kind,
typeID: v.typeID,
staticType: v.staticType,
}

//res.InjectedFields = v.InjectedFields
//res.ComputedFields = v.ComputedFields
Expand Down
8 changes: 4 additions & 4 deletions bbq/vm/value_conversions.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,7 @@ func InterpreterValueToVMValue(storage interpreter.Storage, value interpreter.Va
case *interpreter.CompositeValue:
return newCompositeValueFromOrderedMap(
value.AtreeMap(),
value.Location,
value.QualifiedIdentifier,
value.StaticType(nil).(*interpreter.CompositeStaticType),
value.Kind,
)
//case interpreter.LinkValue:
Expand Down Expand Up @@ -112,11 +111,12 @@ func VMValueToInterpreterValue(config *Config, value Value) interpreter.Value {
case StringValue:
return interpreter.NewUnmeteredStringValue(string(value.Str))
case *CompositeValue:
compositeType := value.CompositeType
return interpreter.NewCompositeValueFromAtreeMap(
nil,
interpreter.CompositeTypeInfo{
Location: value.Location,
QualifiedIdentifier: value.QualifiedIdentifier,
Location: compositeType.Location,
QualifiedIdentifier: compositeType.QualifiedIdentifier,
Kind: value.Kind,
},
value.dictionary,
Expand Down
17 changes: 7 additions & 10 deletions bbq/vm/vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -429,9 +429,10 @@ func opInvokeDynamic(vm *VM) {
}

compositeValue := receiver.(*CompositeValue)
compositeType := compositeValue.CompositeType

qualifiedFuncName := commons.TypeQualifiedName(compositeValue.QualifiedIdentifier, funcName)
var functionValue = vm.lookupFunction(compositeValue.Location, qualifiedFuncName)
qualifiedFuncName := commons.TypeQualifiedName(compositeType.QualifiedIdentifier, funcName)
var functionValue = vm.lookupFunction(compositeType.Location, qualifiedFuncName)

parameterCount := int(functionValue.Function.ParameterCount)
arguments := vm.stack[stackHeight-parameterCount:]
Expand All @@ -455,18 +456,14 @@ func opNew(vm *VM) {
compositeKind := common.CompositeKind(kind)

// decode location
locationLen := callframe.getUint16()
locationBytes := callframe.function.Code[callframe.ip : callframe.ip+locationLen]
callframe.ip = callframe.ip + locationLen
location := decodeLocation(locationBytes)
staticType := vm.loadType()

typeName := callframe.getString()
// TODO: Support inclusive-range type
compositeStaticType := staticType.(*interpreter.CompositeStaticType)

value := NewCompositeValue(
location,
typeName,
compositeKind,
common.Address{},
compositeStaticType,
vm.config.Storage,
)
vm.push(value)
Expand Down

0 comments on commit 80b7a8c

Please sign in to comment.