Skip to content

Commit c0470c7

Browse files
authored
Remove fastcomp-only EMULATED_FUNCTION_POINTERS setting (#11864)
See #11860
1 parent 2b6e3af commit c0470c7

14 files changed

+46
-1110
lines changed

emcc.py

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1564,8 +1564,6 @@ def check(input_file):
15641564
exit_with_error('Cannot set GLOBAL_BASE when building SIDE_MODULE')
15651565

15661566
if shared.Settings.RELOCATABLE:
1567-
if 'EMULATED_FUNCTION_POINTERS' not in settings_key_changes and not shared.Settings.WASM_BACKEND:
1568-
shared.Settings.EMULATED_FUNCTION_POINTERS = 2 # by default, use optimized function pointer emulation
15691567
shared.Settings.ERROR_ON_UNDEFINED_SYMBOLS = 0
15701568
shared.Settings.WARN_ON_UNDEFINED_SYMBOLS = 0
15711569

@@ -1975,9 +1973,6 @@ def include_and_export(name):
19751973
if shared.Settings.EMULATE_FUNCTION_POINTER_CASTS:
19761974
# emulated function pointer casts is emulated in fastcomp wasm using a binaryen pass
19771975
options.binaryen_passes += ['--fpcast-emu']
1978-
# we also need emulated function pointers for that, as we need a single flat
1979-
# table, as is standard in wasm, and not asm.js split ones.
1980-
shared.Settings.EMULATED_FUNCTION_POINTERS = 1
19811976

19821977
if shared.Settings.WASM2JS:
19831978
if not shared.Settings.WASM_BACKEND:
@@ -3194,7 +3189,7 @@ def do_binaryen(target, asm_target, options, memfile, wasm_binary_target,
31943189
cmd += ['--mem-base=' + str(shared.Settings.GLOBAL_BASE)]
31953190
# various options imply that the imported table may not be the exact size as
31963191
# the wasm module's own table segments
3197-
if shared.Settings.RELOCATABLE or shared.Settings.RESERVED_FUNCTION_POINTERS > 0 or shared.Settings.EMULATED_FUNCTION_POINTERS:
3192+
if shared.Settings.RELOCATABLE or shared.Settings.RESERVED_FUNCTION_POINTERS > 0:
31983193
cmd += ['--table-max=-1']
31993194
if shared.Settings.SIDE_MODULE:
32003195
cmd += ['--mem-max=-1']

emscripten.py

Lines changed: 5 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -414,14 +414,6 @@ def define_asmjs_import_names(imports):
414414

415415
function_tables_impls = make_function_tables_impls(function_table_data)
416416
final_function_tables = '\n'.join(function_tables_impls) + '\n' + function_tables_defs
417-
if shared.Settings.EMULATED_FUNCTION_POINTERS:
418-
final_function_tables = (
419-
final_function_tables
420-
.replace("asm['", '')
421-
.replace("']", '')
422-
.replace('var SIDE_FUNCTION_TABLE_', 'var FUNCTION_TABLE_')
423-
.replace('var dynCall_', '//')
424-
)
425417

426418
if DEBUG:
427419
logger.debug('asm text sizes' + str([
@@ -580,8 +572,6 @@ def create_backend_cmd(infile, temp_js):
580572
args += ['-emscripten-assertions=%d' % shared.Settings.ASSERTIONS]
581573
if shared.Settings.ALIASING_FUNCTION_POINTERS == 0:
582574
args += ['-emscripten-no-aliasing-function-pointers']
583-
if shared.Settings.EMULATED_FUNCTION_POINTERS:
584-
args += ['-emscripten-emulated-function-pointers']
585575
if shared.Settings.EMULATE_FUNCTION_POINTER_CASTS:
586576
args += ['-emscripten-emulate-function-pointer-casts']
587577
if shared.Settings.RELOCATABLE:
@@ -1119,17 +1109,6 @@ def make_bad(target=None):
11191109
start = raw.index('[')
11201110
end = raw.rindex(']')
11211111
body = raw[start + 1:end].split(',')
1122-
if shared.Settings.EMULATED_FUNCTION_POINTERS:
1123-
def receive(item):
1124-
if item == '0':
1125-
return item
1126-
if item not in all_implemented:
1127-
# this is not implemented; it would normally be wrapped, but with emulation, we just use it directly outside
1128-
return item
1129-
in_table.add(item)
1130-
return "asm['" + item + "']"
1131-
1132-
body = [receive(b) for b in body]
11331112
for j in range(shared.Settings.RESERVED_FUNCTION_POINTERS):
11341113
curr = 'jsCall_%s_%s' % (sig, j)
11351114
body[1 + j] = curr
@@ -1144,9 +1123,6 @@ def fix_item(item):
11441123
# emulate all non-null pointer calls, if asked to
11451124
if j > 0 and shared.Settings.EMULATE_FUNCTION_POINTER_CASTS and not shared.Settings.WASM and j in function_pointer_targets:
11461125
proper_sig, proper_target = function_pointer_targets[j]
1147-
if shared.Settings.EMULATED_FUNCTION_POINTERS:
1148-
if proper_target in all_implemented:
1149-
proper_target = "asm['" + proper_target + "']"
11501126

11511127
def make_emulated_param(i):
11521128
if i >= len(sig):
@@ -1182,7 +1158,7 @@ def make_emulated_param(i):
11821158
# when emulating function pointers, we don't need wrappers
11831159
# but if relocating, then we also have the copies in-module, and do
11841160
# in wasm we never need wrappers though
1185-
if clean_item not in implemented_functions and not (shared.Settings.EMULATED_FUNCTION_POINTERS and not shared.Settings.RELOCATABLE) and not shared.Settings.WASM:
1161+
if clean_item not in implemented_functions and shared.Settings.RELOCATABLE and not shared.Settings.WASM:
11861162
# this is imported into asm, we must wrap it
11871163
call_ident = clean_item
11881164
if call_ident in metadata['redirects']:
@@ -1223,38 +1199,22 @@ def math_fix(g):
12231199
return g if not g.startswith('Math_') else g.split('_')[1]
12241200

12251201

1226-
# asm.js function tables have one table in each linked asm.js module, so we
1227-
# can't just dynCall into them - ftCall exists for that purpose. In wasm,
1228-
# even linked modules share the table, so it's all fine.
1229-
def asm_js_emulated_function_pointers():
1230-
return shared.Settings.EMULATED_FUNCTION_POINTERS and not shared.Settings.WASM
1231-
1232-
12331202
def make_function_tables_impls(function_table_data):
12341203
function_tables_impls = []
12351204
for sig, table in function_table_data.items():
12361205
args = ','.join(['a' + str(i) for i in range(1, len(sig))])
12371206
arg_coercions = ' '.join(['a' + str(i) + '=' + shared.JS.make_coercion('a' + str(i), sig[i]) + ';' for i in range(1, len(sig))])
12381207
coerced_args = ','.join([shared.JS.make_coercion('a' + str(i), sig[i]) for i in range(1, len(sig))])
12391208
sig_mask = str(table.count(','))
1240-
if not (shared.Settings.WASM and shared.Settings.EMULATED_FUNCTION_POINTERS):
1241-
ret = 'FUNCTION_TABLE_%s[index&%s](%s)' % (sig, sig_mask, coerced_args)
1242-
else:
1243-
# for wasm with emulated function pointers, emit an mft_SIG(..) call, we avoid asm.js function tables there.
1244-
ret = 'mftCall_%s(index%s%s)' % (sig, ',' if len(sig) > 1 else '', coerced_args)
1209+
ret = 'FUNCTION_TABLE_%s[index&%s](%s)' % (sig, sig_mask, coerced_args)
12451210
ret = ('return ' if sig[0] != 'v' else '') + shared.JS.make_coercion(ret, sig[0])
1246-
if not asm_js_emulated_function_pointers():
1247-
function_tables_impls.append('''
1211+
function_tables_impls.append('''
12481212
function dynCall_%s(index%s%s) {
12491213
index = index|0;
12501214
%s
12511215
%s;
12521216
}
12531217
''' % (sig, ',' if len(sig) > 1 else '', args, arg_coercions, ret))
1254-
else:
1255-
function_tables_impls.append('''
1256-
var dynCall_%s = ftCall_%s;
1257-
''' % (sig, sig))
12581218

12591219
ffi_args = ','.join([shared.JS.make_coercion('a' + str(i), sig[i], ffi_arg=True) for i in range(1, len(sig))])
12601220
for i in range(shared.Settings.RESERVED_FUNCTION_POINTERS):
@@ -1270,33 +1230,7 @@ def make_function_tables_impls(function_table_data):
12701230

12711231

12721232
def create_mftCall_funcs(function_table_data):
1273-
if not asm_js_emulated_function_pointers():
1274-
return []
1275-
if shared.Settings.WASM or not shared.Settings.RELOCATABLE:
1276-
return []
1277-
1278-
mftCall_funcs = []
1279-
# in wasm, emulated function pointers are just simple table calls
1280-
for sig, table in function_table_data.items():
1281-
return_type, sig_args = sig[0], sig[1:]
1282-
num_args = len(sig_args)
1283-
params = ','.join(['ptr'] + ['p%d' % i for i in range(num_args)])
1284-
coerced_params = ','.join([shared.JS.make_coercion('ptr', 'i')] + [shared.JS.make_coercion('p%d' % i, unfloat(sig_args[i])) for i in range(num_args)])
1285-
coercions = ';'.join(['ptr = ptr | 0'] + ['p%d = %s' % (i, shared.JS.make_coercion('p%d' % i, unfloat(sig_args[i]))) for i in range(num_args)]) + ';'
1286-
mini_coerced_params = ','.join([shared.JS.make_coercion('p%d' % i, sig_args[i]) for i in range(num_args)])
1287-
maybe_return = '' if return_type == 'v' else 'return'
1288-
final_return = maybe_return + ' ' + shared.JS.make_coercion('ftCall_' + sig + '(' + coerced_params + ')', unfloat(return_type)) + ';'
1289-
if shared.Settings.EMULATED_FUNCTION_POINTERS == 1:
1290-
body = final_return
1291-
else:
1292-
sig_mask = str(table.count(','))
1293-
body = ('if (((ptr|0) >= (fb|0)) & ((ptr|0) < (fb + ' + sig_mask + ' | 0))) { ' + maybe_return + ' ' +
1294-
shared.JS.make_coercion(
1295-
'FUNCTION_TABLE_' + sig + '[(ptr-fb)&' + sig_mask + '](' +
1296-
mini_coerced_params + ')', return_type, ffi_arg=True
1297-
) + '; ' + ('return;' if return_type == 'v' else '') + ' }' + final_return)
1298-
mftCall_funcs.append(make_func('mftCall_' + sig, body, params, coercions) + '\n')
1299-
return mftCall_funcs
1233+
return []
13001234

13011235

13021236
def get_function_pointer_error(sig, function_table_sigs):
@@ -1416,10 +1350,6 @@ def check(extern):
14161350
asm_setup += create_invoke_wrappers(invoke_function_names)
14171351
asm_setup += setup_function_pointers(function_table_sigs)
14181352

1419-
if shared.Settings.EMULATED_FUNCTION_POINTERS:
1420-
function_tables_impls = make_function_tables_impls(function_table_data)
1421-
asm_setup += '\n' + '\n'.join(function_tables_impls) + '\n'
1422-
14231353
return asm_setup
14241354

14251355

@@ -1428,24 +1358,6 @@ def setup_function_pointers(function_table_sigs):
14281358
for sig in function_table_sigs:
14291359
if shared.Settings.RESERVED_FUNCTION_POINTERS:
14301360
asm_setup += '\n' + shared.JS.make_jscall(sig) + '\n'
1431-
# nothing special to do here for wasm, we just use dynCalls
1432-
if not shared.Settings.WASM:
1433-
if shared.Settings.EMULATED_FUNCTION_POINTERS:
1434-
args = ['a%d' % i for i in range(len(sig) - 1)]
1435-
full_args = ['x'] + args
1436-
table_access = 'FUNCTION_TABLE_' + sig
1437-
if shared.Settings.SIDE_MODULE:
1438-
table_access = 'parentModule["' + table_access + '"]' # side module tables were merged into the parent, we need to access the global one
1439-
table_read = table_access + '[x]'
1440-
prelude = ''
1441-
if shared.Settings.ASSERTIONS:
1442-
prelude = '''
1443-
if (x < 0 || x >= %s.length) { err("Function table mask error (out of range)"); %s ; abort(x) }''' % (table_access, get_function_pointer_error(sig, function_table_sigs))
1444-
asm_setup += '''
1445-
function ftCall_%s(%s) {%s
1446-
return %s(%s);
1447-
}
1448-
''' % (sig, ', '.join(full_args), prelude, table_read, ', '.join(args))
14491361
return asm_setup
14501362

14511363

@@ -1471,8 +1383,6 @@ def create_basic_funcs(function_table_sigs, invoke_function_names):
14711383
for sig in function_table_sigs:
14721384
if shared.Settings.RESERVED_FUNCTION_POINTERS:
14731385
basic_funcs.append('jsCall_%s' % sig)
1474-
if asm_js_emulated_function_pointers():
1475-
basic_funcs.append('ftCall_%s' % sig)
14761386
return basic_funcs
14771387

14781388

@@ -1493,12 +1403,6 @@ def create_basic_vars(exported_implemented_functions, forwarded_json, metadata):
14931403

14941404
def create_exports(exported_implemented_functions, in_table, function_table_data, metadata):
14951405
all_exported = exported_implemented_functions + function_tables(function_table_data)
1496-
# In asm.js + emulated function pointers, export all the table because we use
1497-
# JS to add the asm.js module's functions to the table (which is external
1498-
# in this mode). In wasm, we don't need that since wasm modules can
1499-
# directly add functions to the imported Table.
1500-
if not shared.Settings.WASM and shared.Settings.EMULATED_FUNCTION_POINTERS:
1501-
all_exported += in_table
15021406
exports = []
15031407
for export in sorted(set(all_exported)):
15041408
exports.append(quote(export) + ": " + export)
@@ -1518,10 +1422,7 @@ def create_exports(exported_implemented_functions, in_table, function_table_data
15181422

15191423

15201424
def function_tables(function_table_data):
1521-
if not asm_js_emulated_function_pointers():
1522-
return ['dynCall_' + table for table in function_table_data]
1523-
else:
1524-
return []
1425+
return ['dynCall_' + table for table in function_table_data]
15251426

15261427

15271428
def create_the_global(metadata):
@@ -1577,20 +1478,6 @@ def create_receiving(function_table_data, function_tables_defs, exported_impleme
15771478
table = table.replace('var ' + tableName, 'var ' + tableName + ' = Module["' + tableName + '"]')
15781479
receiving += table + '\n'
15791480

1580-
if shared.Settings.EMULATED_FUNCTION_POINTERS:
1581-
# in asm.js emulated function tables, emit the table on the outside, where
1582-
# JS can manage it (for wasm, a native wasm Table is used directly, and we
1583-
# don't need this)
1584-
if not shared.Settings.WASM:
1585-
receiving += '\n' + function_tables_defs.replace('// EMSCRIPTEN_END_FUNCS\n', '')
1586-
# wasm still needs definitions for dyncalls on the outside, for JS
1587-
receiving += '\n' + ''.join(['Module["dynCall_%s"] = dynCall_%s\n' % (sig, sig) for sig in function_table_data])
1588-
if not shared.Settings.WASM:
1589-
for sig in function_table_data.keys():
1590-
name = 'FUNCTION_TABLE_' + sig
1591-
fullname = name if not shared.Settings.SIDE_MODULE else ('SIDE_' + name)
1592-
receiving += 'Module["' + name + '"] = ' + fullname + ';\n'
1593-
15941481
return receiving
15951482

15961483

src/parseTools.js

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1466,14 +1466,7 @@ function asmFFICoercion(value, type) {
14661466
}
14671467

14681468
function makeDynCall(sig) {
1469-
// asm.js function tables have one table in each linked asm.js module, so we
1470-
// can't just dynCall into them - ftCall exists for that purpose. In wasm,
1471-
// even linked modules share the table, so it's all fine.
1472-
if (EMULATED_FUNCTION_POINTERS && !WASM) {
1473-
return 'ftCall_' + sig;
1474-
} else {
1475-
return 'dynCall_' + sig;
1476-
}
1469+
return 'dynCall_' + sig;
14771470
}
14781471

14791472
function heapAndOffset(heap, ptr) { // given HEAP8, ptr , we return splitChunk, relptr

src/runtime_functions.js

Lines changed: 2 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44
* SPDX-License-Identifier: MIT
55
*/
66

7-
#if !WASM_BACKEND && EMULATED_FUNCTION_POINTERS == 0
7+
#if !WASM_BACKEND
88
var jsCallStartIndex = 1;
99
var functionPointers = new Array({{{ RESERVED_FUNCTION_POINTERS }}});
10-
#endif // !WASM_BACKEND && EMULATED_FUNCTION_POINTERS == 0
10+
#endif // !WASM_BACKEND
1111

1212
#if WASM
1313
// Wraps a JS function as a wasm function with a given signature.
@@ -197,7 +197,6 @@ function addFunction(func, sig) {
197197
return addFunctionWasm(func, sig);
198198
#else
199199

200-
#if EMULATED_FUNCTION_POINTERS == 0
201200
var base = 0;
202201
for (var i = base; i < base + {{{ RESERVED_FUNCTION_POINTERS }}}; i++) {
203202
if (!functionPointers[i]) {
@@ -207,45 +206,13 @@ function addFunction(func, sig) {
207206
}
208207
throw 'Finished up all reserved function pointers. Use a higher value for RESERVED_FUNCTION_POINTERS.';
209208

210-
#else // EMULATED_FUNCTION_POINTERS == 0
211-
212-
#if WASM
213-
return addFunctionWasm(func, sig);
214-
#else
215-
alignFunctionTables(); // TODO: we should rely on this being an invariant
216-
var tables = getFunctionTables();
217-
var ret = -1;
218-
for (var signature in tables) {
219-
var table = tables[signature];
220-
if (ret < 0) ret = table.length;
221-
else assert(ret === table.length);
222-
table.push(func);
223-
}
224-
return ret;
225-
#endif // WASM
226-
227-
#endif // EMULATED_FUNCTION_POINTERS == 0
228209
#endif // WASM_BACKEND
229210
}
230211

231212
function removeFunction(index) {
232213
#if WASM_BACKEND
233214
removeFunctionWasm(index);
234215
#else
235-
236-
#if EMULATED_FUNCTION_POINTERS == 0
237216
functionPointers[index-jsCallStartIndex] = null;
238-
#else
239-
#if WASM
240-
removeFunctionWasm(index);
241-
#else
242-
alignFunctionTables(); // XXX we should rely on this being an invariant
243-
var tables = getFunctionTables();
244-
for (var sig in tables) {
245-
tables[sig][index] = null;
246-
}
247-
#endif // WASM
248-
249-
#endif // EMULATE_FUNCTION_POINTER_CASTS == 0
250217
#endif // WASM_BACKEND
251218
}

src/settings.js

Lines changed: 1 addition & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -313,8 +313,7 @@ var SAFE_HEAP = 0;
313313
var SAFE_HEAP_LOG = 0;
314314

315315
// In asm.js mode, we cannot simply add function pointers to function tables, so
316-
// we reserve some slots for them. An alternative to this is to use
317-
// EMULATED_FUNCTION_POINTERS, in which case we don't need to reserve.
316+
// we reserve some slots for them.
318317
// [fastcomp-only]
319318
var RESERVED_FUNCTION_POINTERS = 0;
320319

@@ -324,27 +323,6 @@ var RESERVED_FUNCTION_POINTERS = 0;
324323
// [fastcomp-only]
325324
var ALIASING_FUNCTION_POINTERS = 0;
326325

327-
// asm.js: By default we implement function pointers using asm.js function
328-
// tables, which is very fast. With this option, we implement them more flexibly
329-
// by emulating them: we call out into JS, which handles the function tables.
330-
// 1: Full emulation. This means you can modify the
331-
// table in JS fully dynamically, not just add to
332-
// the end.
333-
// 2: Optimized emulation. Assumes once something is
334-
// added to the table, it will not change. This allows
335-
// dynamic linking while keeping performance fast,
336-
// as we can do a fast call into the internal table
337-
// if the fp is in the right range. Shared modules
338-
// (MAIN_MODULE, SIDE_MODULE) do this by default.
339-
// This requires RELOCATABLE to be set.
340-
// wasm:
341-
// By default we use a wasm Table for function pointers, which is fast and
342-
// efficient. When enabling emulation, we also use the Table *outside* the wasm
343-
// module, exactly as when emulating in asm.js, just replacing the plain JS
344-
// array with a Table.
345-
// [fastcomp-only]
346-
var EMULATED_FUNCTION_POINTERS = 0;
347-
348326
// Allows function pointers to be cast, wraps each call of an incorrect type
349327
// with a runtime correction. This adds overhead and should not be used
350328
// normally. It also forces ALIASING_FUNCTION_POINTERS to 0. Aside from making

0 commit comments

Comments
 (0)