From 0ef0f0e200de0a5bb479632d46c62dce7b120b97 Mon Sep 17 00:00:00 2001 From: Branden J Brown Date: Sun, 12 Apr 2020 19:40:38 -0400 Subject: [PATCH] use object addresses as unique IDs Using a global counter for unique IDs means that eventually, every long-running program will reuse IDs of live objects. Go's garbage collection currently is not compacting; if it ever becomes so, we can modify contains.Set or choose a new method to obtain unique IDs. --- go.mod | 4 ++-- go.sum | 7 +++++++ internal/object.go | 26 +++++--------------------- internal/vm.go | 14 +++++++------- 4 files changed, 21 insertions(+), 30 deletions(-) diff --git a/go.mod b/go.mod index a73c54f..e45b532 100644 --- a/go.mod +++ b/go.mod @@ -5,8 +5,8 @@ go 1.14 require ( github.com/zephyrtronium/contains v0.0.0-20191109101209-403ebe7b0b60 gitlab.com/variadico/lctime v0.0.0-20190211022338-49aae8a53d11 - golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527 + golang.org/x/sys v0.0.0-20200409092240-59c9f1ba88fa golang.org/x/text v0.3.2 - golang.org/x/tools v0.0.0-20200313205530-4303120df7d8 + golang.org/x/tools v0.0.0-20200410194907-79a7a3126eef gopkg.in/yaml.v2 v2.2.8 ) diff --git a/go.sum b/go.sum index 9a07c6d..7356665 100644 --- a/go.sum +++ b/go.sum @@ -1,4 +1,5 @@ github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/zephyrtronium/contains v0.0.0-20190813150354-f7df53f08000 h1:rsL4vYsl1EVDklYnVDq2etRQv7jZtFu2gkv4OzKKFbo= github.com/zephyrtronium/contains v0.0.0-20190813150354-f7df53f08000/go.mod h1:9VfULMvEEtBLQ93TyMwEFa2rMZj232ZMs7HA/dx31Eg= github.com/zephyrtronium/contains v0.0.0-20191109101209-403ebe7b0b60 h1:spBs4SQ3oIUAGBh3fZLGWjQ6iAiEtmxmM5o68l5mTH8= @@ -7,6 +8,7 @@ gitlab.com/variadico/lctime v0.0.0-20190211022338-49aae8a53d11 h1:Ly1b+G8N/Hhmty gitlab.com/variadico/lctime v0.0.0-20190211022338-49aae8a53d11/go.mod h1:oBjcCtUE+aWYiW4NuGN+eK3OK3efpcyKphbDv1Y508M= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -19,6 +21,8 @@ golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe h1:6fAMxZRR6sl1Uq8U61gxU+kPT golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527 h1:uYVVQ9WP/Ds2ROhcaGPeIdVq0RIXVLwsHlnvJ+cT1So= golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200409092240-59c9f1ba88fa h1:mQTN3ECqfsViCNBgq+A40vdwhkGykrrQlYe3mPj6BoU= +golang.org/x/sys v0.0.0-20200409092240-59c9f1ba88fa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= @@ -29,8 +33,11 @@ golang.org/x/tools v0.0.0-20191101200257-8dbcdeb83d3f/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200313205530-4303120df7d8 h1:gkI/wGGwpcG5W4hLCzZNGxA4wzWBGGDStRI1MrjDl2Q= golang.org/x/tools v0.0.0-20200313205530-4303120df7d8/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200410194907-79a7a3126eef h1:RHORRhs540cYZYrzgU2CPUyykkwZM78hGdzocOo9P8A= +golang.org/x/tools v0.0.0-20200410194907-79a7a3126eef/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/internal/object.go b/internal/object.go index ea4e3f7..50625e0 100644 --- a/internal/object.go +++ b/internal/object.go @@ -5,16 +5,13 @@ import ( "os" "strings" "sync" - "sync/atomic" "time" + "unsafe" // for UniqueID "github.com/zephyrtronium/contains" ) // Object is the basic type of Io. Everything is an Object. -// -// Always use NewObject, ObjectWith, or a type-specific constructor to obtain -// new objects. Creating objects directly will result in arbitrary failures. type Object struct { // slots is the set of messages to which this object responds. slots actualSlots @@ -29,9 +26,6 @@ type Object struct { Value interface{} // tag is the type indicator of the object. tag Tag - - // id is the object's unique ID. - id uintptr } // Tag is a type indicator for iolang objects. Tag values must be comparable. @@ -86,7 +80,6 @@ func (o *Object) Clone() *Object { protos: protoLink{p: o}, Value: v, tag: o.Tag(), - id: nextObject(), } } @@ -125,7 +118,10 @@ func (o *Object) Tag() Tag { // UniqueID returns the object's unique ID. func (o *Object) UniqueID() uintptr { - return o.id + // This implementation depends on Go's garbage collector remaining + // non-compacting. Should that change, then either this or contains.Set + // will need to change as well. + return uintptr(unsafe.Pointer(o)) } // BasicTag is a special Tag type for basic primitive types which do not have @@ -148,16 +144,6 @@ func (t BasicTag) String() string { return string(t) } -// objcounter is the global counter for object IDs. All accesses to this must -// be atomic. -var objcounter uintptr - -// nextObject increments the object counter and returns its value as a unique -// ID for a new object. -func nextObject() uintptr { - return atomic.AddUintptr(&objcounter, 1) -} - // initObject sets up the "base" object that is the first proto of all other // built-in types. func (vm *VM) initObject() { @@ -254,7 +240,6 @@ func (vm *VM) ObjectWith(slots Slots, protos []*Object, value interface{}, tag T r := &Object{ Value: value, tag: tag, - id: nextObject(), } r.SetProtos(protos...) vm.definitelyNewSlots(r, slots) @@ -266,7 +251,6 @@ func (vm *VM) ObjectWith(slots Slots, protos []*Object, value interface{}, tag T func (vm *VM) NewObject(slots Slots) *Object { r := &Object{ protos: protoLink{p: vm.BaseObject}, - id: nextObject(), } vm.definitelyNewSlots(r, slots) return r diff --git a/internal/vm.go b/internal/vm.go index 1f908ab..aabb76d 100644 --- a/internal/vm.go +++ b/internal/vm.go @@ -77,15 +77,15 @@ func NewVM(args ...string) *VM { haveVM = true // TODO: atomic? vm := VM{ - Lobby: &Object{id: nextObject()}, + Lobby: &Object{}, - Core: &Object{id: nextObject()}, - Addons: &Object{id: nextObject()}, + Core: &Object{}, + Addons: &Object{}, - BaseObject: &Object{id: nextObject()}, - True: &Object{id: nextObject()}, - False: &Object{id: nextObject()}, - Nil: &Object{id: nextObject()}, + BaseObject: &Object{}, + True: &Object{}, + False: &Object{}, + Nil: &Object{}, Control: make(chan RemoteStop, 1),