Skip to content

Commit 4ae9f49

Browse files
authored
Refactor and simplify asyncify logic for calling back in (#12081)
This removes callStackIdToFunc, the map of ids to functions. Instead it makes us always use the map of ids to function names. That removes one of the two mechanisms and makes the code simpler, which will help in a followup PR that adds support for direct table calls, which we need for #12059. I think we kept both mechanisms because I was worried about performance, but I think I was wrong. After debugging for #12059 I think I have a better understanding of things and it seems fine to use names - it's just a single JS map lookup for asyncify operation, which is small compared to the actual asyncify overhead. Move some code to maybeStopUnwind, with no changes. That code will be useful in the followup as well. Also clean up some debugging code to make it more useful.
1 parent 3e2c107 commit 4ae9f49

File tree

1 file changed

+31
-38
lines changed

1 file changed

+31
-38
lines changed

src/library_async.js

Lines changed: 31 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,7 @@ mergeInto(LibraryManager.library, {
4040
// which is where we must call to rewind it.
4141
exportCallStack: [],
4242
callStackNameToId: {},
43-
callStackIdToFunc: {},
44-
#if ASYNCIFY_LAZY_LOAD_CODE
4543
callStackIdToName: {},
46-
#endif
4744
callStackId: 0,
4845
afterUnwind: null,
4946
asyncFinalizers: [], // functions to run when *all* asynchronicity is done
@@ -54,11 +51,7 @@ mergeInto(LibraryManager.library, {
5451
if (id === undefined) {
5552
id = Asyncify.callStackId++;
5653
Asyncify.callStackNameToId[funcName] = id;
57-
#if ASYNCIFY_LAZY_LOAD_CODE
5854
Asyncify.callStackIdToName[id] = funcName;
59-
#else
60-
Asyncify.callStackIdToFunc[id] = Module['asm'][funcName];
61-
#endif
6255
}
6356
return id;
6457
},
@@ -100,36 +93,20 @@ mergeInto(LibraryManager.library, {
10093
var original = exports[x];
10194
if (typeof original === 'function') {
10295
ret[x] = function() {
103-
Asyncify.exportCallStack.push(x);
10496
#if ASYNCIFY_DEBUG >= 2
105-
err('ASYNCIFY: ' + ' '.repeat(Asyncify.exportCallStack.length) + ' try', x);
97+
err('ASYNCIFY: ' + ' '.repeat(Asyncify.exportCallStack.length) + ' try ' + x);
10698
#endif
99+
Asyncify.exportCallStack.push(x);
107100
try {
108101
return original.apply(null, arguments);
109102
} finally {
110103
if (ABORT) return;
111-
var y = Asyncify.exportCallStack.pop(x);
104+
var y = Asyncify.exportCallStack.pop();
112105
assert(y === x);
113106
#if ASYNCIFY_DEBUG >= 2
114-
err('ASYNCIFY: ' + ' '.repeat(Asyncify.exportCallStack.length + 1) + ' finally', x);
115-
#endif
116-
if (Asyncify.currData &&
117-
Asyncify.state === Asyncify.State.Unwinding &&
118-
Asyncify.exportCallStack.length === 0) {
119-
// We just finished unwinding.
120-
#if ASYNCIFY_DEBUG
121-
err('ASYNCIFY: stop unwind');
107+
err('ASYNCIFY: ' + ' '.repeat(Asyncify.exportCallStack.length) + ' finally ' + x);
122108
#endif
123-
Asyncify.state = Asyncify.State.Normal;
124-
runAndAbortIfError(Module['_asyncify_stop_unwind']);
125-
if (typeof Fibers !== 'undefined') {
126-
Fibers.trampoline();
127-
}
128-
if (Asyncify.afterUnwind) {
129-
Asyncify.afterUnwind();
130-
Asyncify.afterUnwind = null;
131-
}
132-
}
109+
Asyncify.maybeStopUnwind();
133110
}
134111
};
135112
} else {
@@ -140,11 +117,34 @@ mergeInto(LibraryManager.library, {
140117
return ret;
141118
},
142119

120+
maybeStopUnwind: function() {
121+
#if ASYNCIFY_DEBUG
122+
err('ASYNCIFY: maybe stop unwind', Asyncify.exportCallStack);
123+
#endif
124+
if (Asyncify.currData &&
125+
Asyncify.state === Asyncify.State.Unwinding &&
126+
Asyncify.exportCallStack.length === 0) {
127+
// We just finished unwinding.
128+
#if ASYNCIFY_DEBUG
129+
err('ASYNCIFY: stop unwind');
130+
#endif
131+
Asyncify.state = Asyncify.State.Normal;
132+
runAndAbortIfError(Module['_asyncify_stop_unwind']);
133+
if (typeof Fibers !== 'undefined') {
134+
Fibers.trampoline();
135+
}
136+
if (Asyncify.afterUnwind) {
137+
Asyncify.afterUnwind();
138+
Asyncify.afterUnwind = null;
139+
}
140+
}
141+
},
142+
143143
allocateData: function() {
144144
// An asyncify data structure has three fields:
145145
// 0 current stack pos
146146
// 4 max stack pos
147-
// 8 id of function at bottom of the call stack (callStackIdToFunc[id] == js function)
147+
// 8 id of function at bottom of the call stack (callStackIdToName[id] == name of js function)
148148
//
149149
// The Asyncify ABI only interprets the first two fields, the rest is for the runtime.
150150
// We also embed a stack in the same memory region here, right next to the structure.
@@ -171,15 +171,8 @@ mergeInto(LibraryManager.library, {
171171

172172
getDataRewindFunc: function(ptr) {
173173
var id = {{{ makeGetValue('ptr', C_STRUCTS.asyncify_data_s.rewind_id, 'i32') }}};
174-
var func = Asyncify.callStackIdToFunc[id];
175-
176-
#if ASYNCIFY_LAZY_LOAD_CODE
177-
if (func === undefined) {
178-
func = Module['asm'][Asyncify.callStackIdToName[id]];
179-
Asyncify.callStackIdToFunc[id] = func;
180-
}
181-
#endif
182-
174+
var name = Asyncify.callStackIdToName[id];
175+
var func = Module['asm'][name];
183176
return func;
184177
},
185178

0 commit comments

Comments
 (0)