go/ssa/interp: add intrinsic for runtime.NumGoroutine

...which is used by $GOROOT/test/goprint.go.

Change-Id: I4626b8fae3f87d9c8dd8cdcd8c05036955a36262
Reviewed-on: https://go-review.googlesource.com/22560
Reviewed-by: Robert Griesemer <gri@golang.org>
This commit is contained in:
Alan Donovan 2016-04-28 13:44:44 -04:00
parent 50ff896a1c
commit 56005b4126
2 changed files with 18 additions and 5 deletions

View File

@ -15,6 +15,7 @@ import (
"os" "os"
"runtime" "runtime"
"strings" "strings"
"sync/atomic"
"syscall" "syscall"
"time" "time"
"unsafe" "unsafe"
@ -104,6 +105,7 @@ func init() {
"runtime.Gosched": ext۰runtime۰Gosched, "runtime.Gosched": ext۰runtime۰Gosched,
"runtime.init": ext۰runtime۰init, "runtime.init": ext۰runtime۰init,
"runtime.NumCPU": ext۰runtime۰NumCPU, "runtime.NumCPU": ext۰runtime۰NumCPU,
"runtime.NumGoroutine": ext۰runtime۰NumGoroutine,
"runtime.ReadMemStats": ext۰runtime۰ReadMemStats, "runtime.ReadMemStats": ext۰runtime۰ReadMemStats,
"runtime.SetFinalizer": ext۰runtime۰SetFinalizer, "runtime.SetFinalizer": ext۰runtime۰SetFinalizer,
"(*runtime.Func).Entry": ext۰runtime۰Func۰Entry, "(*runtime.Func).Entry": ext۰runtime۰Func۰Entry,
@ -387,6 +389,10 @@ func ext۰runtime۰NumCPU(fr *frame, args []value) value {
return runtime.NumCPU() return runtime.NumCPU()
} }
func ext۰runtime۰NumGoroutine(fr *frame, args []value) value {
return int(atomic.LoadInt32(&fr.i.goroutines))
}
func ext۰runtime۰ReadMemStats(fr *frame, args []value) value { func ext۰runtime۰ReadMemStats(fr *frame, args []value) value {
// TODO(adonovan): populate args[0].(Struct) // TODO(adonovan): populate args[0].(Struct)
return nil return nil

View File

@ -53,6 +53,7 @@ import (
"os" "os"
"reflect" "reflect"
"runtime" "runtime"
"sync/atomic"
"golang.org/x/tools/go/ssa" "golang.org/x/tools/go/ssa"
) )
@ -86,6 +87,7 @@ type interpreter struct {
rtypeMethods methodSet // the method set of rtype, which implements the reflect.Type interface. rtypeMethods methodSet // the method set of rtype, which implements the reflect.Type interface.
runtimeErrorString types.Type // the runtime.errorString type runtimeErrorString types.Type // the runtime.errorString type
sizes types.Sizes // the effective type-sizing function sizes types.Sizes // the effective type-sizing function
goroutines int32 // atomically updated
} }
type deferred struct { type deferred struct {
@ -269,7 +271,11 @@ func visitInstr(fr *frame, instr ssa.Instruction) continuation {
case *ssa.Go: case *ssa.Go:
fn, args := prepareCall(fr, &instr.Call) fn, args := prepareCall(fr, &instr.Call)
go call(fr.i, nil, instr.Pos(), fn, args) atomic.AddInt32(&fr.i.goroutines, 1)
go func() {
call(fr.i, nil, instr.Pos(), fn, args)
atomic.AddInt32(&fr.i.goroutines, -1)
}()
case *ssa.MakeChan: case *ssa.MakeChan:
fr.env[instr] = make(chan value, asInt(fr.get(instr.Size))) fr.env[instr] = make(chan value, asInt(fr.get(instr.Size)))
@ -660,10 +666,11 @@ func deleteBodies(pkg *ssa.Package, except ...string) {
// //
func Interpret(mainpkg *ssa.Package, mode Mode, sizes types.Sizes, filename string, args []string) (exitCode int) { func Interpret(mainpkg *ssa.Package, mode Mode, sizes types.Sizes, filename string, args []string) (exitCode int) {
i := &interpreter{ i := &interpreter{
prog: mainpkg.Prog, prog: mainpkg.Prog,
globals: make(map[ssa.Value]*value), globals: make(map[ssa.Value]*value),
mode: mode, mode: mode,
sizes: sizes, sizes: sizes,
goroutines: 1,
} }
runtimePkg := i.prog.ImportedPackage("runtime") runtimePkg := i.prog.ImportedPackage("runtime")
if runtimePkg == nil { if runtimePkg == nil {