Skip to content

Commit cea2ae1

Browse files
committed
Further compactify blocking function context save/restore code.
This change deduplicates variable declaration with restoration from saved context for blocking functions. This removes a significant source of duplicated code in each blocking function intro. We also introduce a helper function $restore to eliminate some repetitive snippets of generated code.
1 parent 2dc0286 commit cea2ae1

File tree

3 files changed

+35
-10
lines changed

3 files changed

+35
-10
lines changed

compiler/package.go

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -805,7 +805,7 @@ func translateFunction(typ *ast.FuncType, recv *ast.Ident, body *ast.BlockStmt,
805805

806806
if len(c.Flattened) != 0 {
807807
c.localVars = append(c.localVars, "$s")
808-
prefix = prefix + " $s = 0;"
808+
prefix = prefix + " $s = $s || 0;"
809809
}
810810

811811
if c.HasDefer {
@@ -816,17 +816,27 @@ func translateFunction(typ *ast.FuncType, recv *ast.Ident, body *ast.BlockStmt,
816816
}
817817
}
818818

819+
localVarDefs := "" // Function-local var declaration at the top.
820+
819821
if len(c.Blocking) != 0 {
820-
c.localVars = append(c.localVars, "$r")
822+
localVars := append([]string{}, c.localVars...)
823+
// $r is sometimes used as a temporary variable to store blocking call result.
824+
// $c indicates that a function is being resumed after a blocking call when set to true.
825+
// $f is an object used to save and restore function context for blocking calls.
826+
localVars = append(localVars, "$r", "$c", "$f")
827+
// If a blocking function is being resumed, initialize local variables from the saved context.
828+
localVarDefs = fmt.Sprintf("var {%s} = $restore(this, {%s});\n", strings.Join(localVars, ", "), strings.Join(params, ", "))
829+
// If the function gets blocked, save local variables for future.
830+
saveContext := fmt.Sprintf("$f = {...$f, $r, %s};", strings.Join(c.localVars, ", "))
831+
821832
if funcRef == "" {
822833
funcRef = "$b"
823834
functionName = " $b"
824835
}
825-
var stores, loads string
826-
loads = fmt.Sprintf("({%s} = $f); ", strings.Join(c.localVars, ", "))
827-
stores = fmt.Sprintf("$f = {...$f, %s};", strings.Join(c.localVars, ", "))
828-
prefix = prefix + " var $f, $c = false; if (this !== undefined && this.$blk !== undefined) { $f = this; $c = true; " + loads + "}"
829-
suffix = " if ($f === undefined) { $f = { $blk: " + funcRef + " }; } " + stores + "return $f;" + suffix
836+
suffix = " if ($f === undefined) { $f = { $blk: " + funcRef + " }; } " + saveContext + "return $f;" + suffix
837+
} else if len(c.localVars) > 0 {
838+
// Non-blocking functions simply declare local variables with no need for restore support.
839+
localVarDefs = fmt.Sprintf("var %s;\n", strings.Join(c.localVars, ", "))
830840
}
831841

832842
if c.HasDefer {
@@ -863,8 +873,8 @@ func translateFunction(typ *ast.FuncType, recv *ast.Ident, body *ast.BlockStmt,
863873
if suffix != "" {
864874
bodyOutput = bodyOutput + strings.Repeat("\t", c.pkgCtx.indentation+1) + "/* */" + suffix + "\n"
865875
}
866-
if len(c.localVars) != 0 {
867-
bodyOutput = fmt.Sprintf("%svar %s;\n", strings.Repeat("\t", c.pkgCtx.indentation+1), strings.Join(c.localVars, ", ")) + bodyOutput
876+
if localVarDefs != "" {
877+
bodyOutput = strings.Repeat("\t", c.pkgCtx.indentation+1) + localVarDefs + bodyOutput
868878
}
869879

870880
c.pkgCtx.escapingVars = prevEV

compiler/prelude/goroutines.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,21 @@ var $block = function() {
223223
$curGoroutine.asleep = true;
224224
};
225225
226+
var $restore = function(context, params) {
227+
if (context !== undefined && context.$blk !== undefined) {
228+
return {
229+
$f: context,
230+
$c: true,
231+
...context,
232+
};
233+
} else {
234+
return {
235+
$c: false,
236+
...params,
237+
};
238+
}
239+
}
240+
226241
var $send = function(chan, value) {
227242
if (chan.$closed) {
228243
$throwRuntimeError("send on closed channel");

0 commit comments

Comments
 (0)