Skip to content

Commit

Permalink
Fixed requested changes
Browse files Browse the repository at this point in the history
  • Loading branch information
grantnelson-wf committed Oct 23, 2024
1 parent 948c73a commit 40b7fe4
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 38 deletions.
10 changes: 5 additions & 5 deletions compiler/functions.go
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ func (fc *funcContext) translateFunctionBody(typ *ast.FuncType, recv *ast.Ident,
}

bodyOutput := string(fc.CatchOutput(1, func() {
if fc.HasBlocking() {
if fc.IsBlocking() {
fc.pkgCtx.Scopes[body] = fc.pkgCtx.Scopes[typ]
fc.handleEscapingVars(body)
}
Expand Down Expand Up @@ -283,14 +283,14 @@ func (fc *funcContext) translateFunctionBody(typ *ast.FuncType, recv *ast.Ident,
if fc.HasDefer {
fc.localVars = append(fc.localVars, "$deferred")
suffix = " }" + suffix
if fc.HasBlocking() {
if fc.IsBlocking() {
suffix = " }" + suffix
}
}

localVarDefs := "" // Function-local var declaration at the top.

if fc.HasBlocking() {
if fc.IsBlocking() {
localVars := append([]string{}, fc.localVars...)
// There are several special variables involved in handling blocking functions:
// $r is sometimes used as a temporary variable to store blocking call result.
Expand All @@ -314,7 +314,7 @@ func (fc *funcContext) translateFunctionBody(typ *ast.FuncType, recv *ast.Ident,
if fc.HasDefer {
prefix = prefix + " var $err = null; try {"
deferSuffix := " } catch(err) { $err = err;"
if fc.HasBlocking() {
if fc.IsBlocking() {
deferSuffix += " $s = -1;"
}
if fc.resultNames == nil && fc.sig.HasResults() {
Expand All @@ -324,7 +324,7 @@ func (fc *funcContext) translateFunctionBody(typ *ast.FuncType, recv *ast.Ident,
if fc.resultNames != nil {
deferSuffix += fmt.Sprintf(" if (!$curGoroutine.asleep) { return %s; }", fc.translateResults(fc.resultNames))
}
if fc.HasBlocking() {
if fc.IsBlocking() {
deferSuffix += " if($curGoroutine.asleep) {"
}
suffix = deferSuffix + suffix
Expand Down
64 changes: 35 additions & 29 deletions compiler/internal/analysis/info.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ func (info *Info) newFuncInfoInstances(fd *ast.FuncDecl) []*FuncInfo {
// IsBlocking returns true if the function may contain blocking calls or operations.
func (info *Info) IsBlocking(inst typeparams.Instance) bool {
if funInfo := info.FuncInfo(inst); funInfo != nil {
return funInfo.HasBlocking()
return funInfo.IsBlocking()
}
panic(fmt.Errorf(`info did not have function declaration instance for %q`, inst))
}
Expand Down Expand Up @@ -193,7 +193,7 @@ func AnalyzePkg(files []*ast.File, fileSet *token.FileSet, typesInfo *types.Info
for _, caller := range info.allInfos {
// Check calls to named functions and function-typed variables.
caller.localInstCallees.Iterate(func(callee typeparams.Instance, callSites []astPath) {
if info.FuncInfo(callee).HasBlocking() {
if info.FuncInfo(callee).IsBlocking() {
for _, callSite := range callSites {
caller.markBlocking(callSite)
}
Expand All @@ -204,7 +204,7 @@ func AnalyzePkg(files []*ast.File, fileSet *token.FileSet, typesInfo *types.Info

// Check direct calls to function literals.
for callee, callSites := range caller.literalFuncCallees {
if info.FuncLitInfo(callee).HasBlocking() {
if info.FuncLitInfo(callee).IsBlocking() {
for _, callSite := range callSites {
caller.markBlocking(callSite)
}
Expand Down Expand Up @@ -267,11 +267,11 @@ type FuncInfo struct {
visitorStack astPath
}

// HasBlocking indicates if this function may block goroutine execution.
// IsBlocking indicates if this function may block goroutine execution.
//
// For example, a channel operation in a function or a call to another
// possibly blocking function may block the function.
func (fi *FuncInfo) HasBlocking() bool {
func (fi *FuncInfo) IsBlocking() bool {
return fi == nil || len(fi.Blocking) != 0
}

Expand Down Expand Up @@ -397,19 +397,22 @@ func (fi *FuncInfo) visitCallExpr(n *ast.CallExpr) ast.Visitor {
switch f := astutil.RemoveParens(n.Fun).(type) {
case *ast.Ident:
fi.callToNamedFunc(fi.instanceForIdent(f))
return fi
case *ast.SelectorExpr:
if sel := fi.pkgInfo.Selections[f]; sel != nil {
if typesutil.IsJsObject(sel.Recv()) {
// js.Object methods are known to be non-blocking, but we still must
// check its arguments.
} else {
// selection is a method call like `foo.Bar()`, where `foo` might
// be generic and needs to be substituted with the type argument.
fi.callToNamedFunc(fi.instanceFoSelection(sel))
return fi
}
} else {
fi.callToNamedFunc(fi.instanceForIdent(f.Sel))
// selection is a method call like `foo.Bar()`, where `foo` might
// be generic and needs to be substituted with the type argument.
fi.callToNamedFunc(fi.instanceForSelection(sel))
return fi
}

fi.callToNamedFunc(fi.instanceForIdent(f.Sel))
return fi
case *ast.FuncLit:
// Collect info about the function literal itself.
ast.Walk(fi, n.Fun)
Expand All @@ -427,40 +430,43 @@ func (fi *FuncInfo) visitCallExpr(n *ast.CallExpr) ast.Visitor {
// This is a type conversion to an instance of a generic type,
// not a call. Type assertion itself is not blocking, but we will
// visit the input expression.
} else if astutil.IsTypeExpr(f.Index, fi.pkgInfo.Info) {
return fi
}
if astutil.IsTypeExpr(f.Index, fi.pkgInfo.Info) {
// This is a call of an instantiation of a generic function,
// e.g. `foo[int]` in `func foo[T any]() { ... }; func main() { foo[int]() }`
fi.callToNamedFunc(fi.instanceForIdent(f.X.(*ast.Ident)))
} else {
// The called function is gotten with an index or key from a map, array, or slice.
// e.g. `m := map[string]func(){}; m["key"]()`, `s := []func(); s[0]()`.
// Since we can't predict if the returned function will be blocking
// or not, we have to be conservative and assume that function might be blocking.
fi.markBlocking(fi.visitorStack)
return fi
}
// The called function is gotten with an index or key from a map, array, or slice.
// e.g. `m := map[string]func(){}; m["key"]()`, `s := []func(); s[0]()`.
// Since we can't predict if the returned function will be blocking
// or not, we have to be conservative and assume that function might be blocking.
fi.markBlocking(fi.visitorStack)
return fi
case *ast.IndexListExpr:
// Collect info about the instantiated type or function.
if astutil.IsTypeExpr(f, fi.pkgInfo.Info) {
// This is a type conversion to an instance of a generic type,
// not a call. Type assertion itself is not blocking, but we will
// visit the input expression.
} else {
// This is a call of an instantiation of a generic function,
// e.g. `foo[int, bool]` in `func foo[T1, T2 any]() { ... }; func main() { foo[int, bool]() }`
fi.callToNamedFunc(fi.instanceForIdent(f.X.(*ast.Ident)))
return fi
}
// This is a call of an instantiation of a generic function,
// e.g. `foo[int, bool]` in `func foo[T1, T2 any]() { ... }; func main() { foo[int, bool]() }`
fi.callToNamedFunc(fi.instanceForIdent(f.X.(*ast.Ident)))
return fi
default:
if astutil.IsTypeExpr(f, fi.pkgInfo.Info) {
// This is a type conversion, not a call. Type assertion itself is not
// blocking, but we will visit the input expression.
} else {
// The function is returned by a non-trivial expression. We have to be
// conservative and assume that function might be blocking.
fi.markBlocking(fi.visitorStack)
return fi
}
// The function is returned by a non-trivial expression. We have to be
// conservative and assume that function might be blocking.
fi.markBlocking(fi.visitorStack)
return fi
}

return fi
}

func (fi *FuncInfo) instanceForIdent(fnId *ast.Ident) typeparams.Instance {
Expand All @@ -471,7 +477,7 @@ func (fi *FuncInfo) instanceForIdent(fnId *ast.Ident) typeparams.Instance {
}
}

func (fi *FuncInfo) instanceFoSelection(sel *types.Selection) typeparams.Instance {
func (fi *FuncInfo) instanceForSelection(sel *types.Selection) typeparams.Instance {
if _, ok := sel.Obj().Type().(*types.Signature); ok {
// Substitute the selection to ensure that the receiver has the correct
// type arguments propagated down from the caller.
Expand Down
4 changes: 2 additions & 2 deletions compiler/internal/analysis/info_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1211,7 +1211,7 @@ func (bt *blockingTest) isFuncLitBlocking(lineNo int) bool {
if fnLit == nil {
bt.f.T.Fatalf(`FuncLit found on line %d not found in the AST.`, lineNo)
}
return bt.pkgInfo.FuncLitInfo(fnLit).HasBlocking()
return bt.pkgInfo.FuncLitInfo(fnLit).IsBlocking()
}

func (bt *blockingTest) assertBlockingInst(instanceStr string) {
Expand All @@ -1230,7 +1230,7 @@ func (bt *blockingTest) isFuncInstBlocking(instanceStr string) bool {
instances := bt.pkgInfo.funcInstInfos.Keys()
for _, inst := range instances {
if inst.TypeString() == instanceStr {
return bt.pkgInfo.FuncInfo(inst).HasBlocking()
return bt.pkgInfo.FuncInfo(inst).IsBlocking()
}
}
bt.f.T.Logf(`Function instances found in package info:`)
Expand Down
4 changes: 2 additions & 2 deletions compiler/internal/typeparams/instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,8 +147,8 @@ func (iset *InstanceSet) ByObj() map[types.Object][]Instance {
return result
}

// ForObj returns instances for a given object type belong to. Order is not specified.
// This returns the same values as `ByObj()[obj]`.
// ForObj returns the instances that belong to the given object type.
// Order is not specified. This returns the same values as `ByObj()[obj]`.
func (iset *InstanceSet) ForObj(obj types.Object) []Instance {
result := []Instance{}
for _, inst := range iset.values {
Expand Down

0 comments on commit 40b7fe4

Please sign in to comment.