Skip to content

Commit 3be0d61

Browse files
rakudramacommit-bot@chromium.org
authored andcommitted
Split installTearOff into static and instance versions
We will move other methods into `hunkHelpers` at a later stage. Change-Id: Id37a0bddb81cc47af55baa2896dc5716ccacf3e1 Reviewed-on: https://dart-review.googlesource.com/c/83220 Reviewed-by: Sigmund Cherem <[email protected]> Commit-Queue: Stephen Adams <[email protected]>
1 parent e9ba30a commit 3be0d61

File tree

1 file changed

+147
-73
lines changed

1 file changed

+147
-73
lines changed

pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart

+147-73
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,29 @@ function installTearOff(
250250
}
251251
}
252252
253+
function installStaticTearOff(
254+
container, getterName,
255+
requiredParameterCount, optionalParameterDefaultValues,
256+
callNames, funsOrNames, funType, applyIndex) {
257+
// TODO(sra): Specialize installTearOff for static methods. It might be
258+
// possible to handle some very common simple cases directly.
259+
return installTearOff(
260+
container, getterName, true, false,
261+
requiredParameterCount, optionalParameterDefaultValues,
262+
callNames, funsOrNames, funType, applyIndex);
263+
}
264+
265+
function installInstanceTearOff(
266+
container, getterName, isIntercepted,
267+
requiredParameterCount, optionalParameterDefaultValues,
268+
callNames, funsOrNames, funType, applyIndex) {
269+
// TODO(sra): Specialize installTearOff for instance methods.
270+
return installTearOff(
271+
container, getterName, false, isIntercepted,
272+
requiredParameterCount, optionalParameterDefaultValues,
273+
callNames, funsOrNames, funType, applyIndex);
274+
}
275+
253276
// Instead of setting the interceptor tags directly we use this update
254277
// function. This makes it easier for deferred fragments to contribute to the
255278
// embedded global.
@@ -292,14 +315,21 @@ function updateHolder(holder, newHolder) {
292315
return holder;
293316
}
294317
318+
// TODO(sra): Minify properties of 'hunkHelpers'.
319+
var #hunkHelpers = {
320+
installStaticTearOff: installStaticTearOff,
321+
installInstanceTearOff: installInstanceTearOff,
322+
};
323+
295324
// Every deferred hunk (i.e. fragment) is a function that we can invoke to
296325
// initialize it. At this moment it contributes its data to the main hunk.
297326
function initializeDeferredHunk(hunk) {
298327
// Update the typesOffset for the next deferred library.
299328
typesOffset = #embeddedTypes.length;
300329
301330
// TODO(floitsch): extend natives.
302-
hunk(inherit, inheritMany, mixin, lazy, makeConstList, convertToFastObject, installTearOff,
331+
hunk(inherit, inheritMany, mixin, lazy, makeConstList, convertToFastObject,
332+
hunkHelpers,
303333
setFunctionNamesIfNecessary, updateHolder, updateTypes,
304334
setOrUpdateInterceptorsByTag, setOrUpdateLeafTags,
305335
#embeddedGlobalsObject, holders, #staticState);
@@ -326,7 +356,7 @@ if (#hasSoftDeferredClasses) {
326356
#deferredGlobal[#softId](
327357
holders, #embeddedGlobalsObject, #staticState,
328358
inherit, inheritMany, mixin,
329-
installTearOff);
359+
hunkHelpers);
330360
if (o != null) {
331361
// TODO(29574): should we do something different for Firefox?
332362
// If we recommend that the program triggers the load by itself before
@@ -425,7 +455,7 @@ const String directAccessTestExpression = r'''
425455
/// This template is used for Dart 2.
426456
const String deferredBoilerplateDart2 = '''
427457
function(inherit, inheritMany, mixin, lazy, makeConstList, convertToFastObject,
428-
installTearOff, setFunctionNamesIfNecessary, updateHolder, updateTypes,
458+
hunkHelpers, setFunctionNamesIfNecessary, updateHolder, updateTypes,
429459
setOrUpdateInterceptorsByTag, setOrUpdateLeafTags,
430460
#embeddedGlobalsObject, holdersList, #staticState) {
431461
@@ -476,7 +506,7 @@ const String softDeferredBoilerplate = '''
476506
#deferredGlobal[#softId] =
477507
function(holdersList, #embeddedGlobalsObject, #staticState,
478508
inherit, inheritMany, mixin,
479-
installTearOff) {
509+
hunkHelpers) {
480510
481511
// Installs the holders as local variables.
482512
#installHoldersAsLocals;
@@ -532,6 +562,8 @@ class FragmentEmitter {
532562
emitHolders(program.holders, fragment, initializeEmptyHolders: true);
533563

534564
js.Statement mainCode = js.js.statement(mainBoilerplate, {
565+
// TODO(29455): 'hunkHelpers' displaces other names, so don't minify it.
566+
'hunkHelpers': js.VariableDeclaration('hunkHelpers', allowRename: false),
535567
'directAccessTestExpression': js.js(directAccessTestExpression),
536568
'cyclicThrow': backend.emitter
537569
.staticFunctionAccess(_closedWorld.commonElements.cyclicThrowHelper),
@@ -1204,75 +1236,6 @@ class FragmentEmitter {
12041236
}
12051237
}
12061238

1207-
/// Emits the statement that installs a tear off for a method.
1208-
///
1209-
/// Tear-offs might be passed to `Function.apply` which means that all
1210-
/// calling-conventions (with or without optional positional/named arguments)
1211-
/// are possible. As such, the tear-off needs enough information to fill in
1212-
/// missing parameters.
1213-
js.Statement emitInstallTearOff(js.Expression container, DartMethod method) {
1214-
List<js.Name> callNames = [];
1215-
List<js.Expression> funsOrNames = [];
1216-
1217-
/// Adds the stub-method's code or name to the [funsOrNames] array.
1218-
///
1219-
/// Static methods don't need stub-methods except for tear-offs. As such,
1220-
/// they are not emitted in the prototype, but directly passed here.
1221-
///
1222-
/// Instance-methods install the stub-methods in their prototype, and we
1223-
/// use string-based redirections to find them there.
1224-
void addFunOrName(StubMethod stubMethod) {
1225-
if (method.isStatic) {
1226-
funsOrNames.add(stubMethod.code);
1227-
} else {
1228-
funsOrNames.add(js.quoteName(stubMethod.name));
1229-
}
1230-
}
1231-
1232-
callNames.add(method.callName);
1233-
// The first entry in the funsOrNames-array must be a string.
1234-
funsOrNames.add(js.quoteName(method.name));
1235-
for (ParameterStubMethod stubMethod in method.parameterStubs) {
1236-
callNames.add(stubMethod.callName);
1237-
addFunOrName(stubMethod);
1238-
}
1239-
1240-
js.ArrayInitializer callNameArray =
1241-
new js.ArrayInitializer(callNames.map(js.quoteName).toList());
1242-
js.ArrayInitializer funsOrNamesArray = new js.ArrayInitializer(funsOrNames);
1243-
1244-
bool isIntercepted = false;
1245-
if (method is InstanceMethod) {
1246-
isIntercepted = method.isIntercepted;
1247-
}
1248-
int requiredParameterCount = 0;
1249-
js.Expression optionalParameterDefaultValues = new js.LiteralNull();
1250-
if (method.canBeApplied) {
1251-
requiredParameterCount = method.requiredParameterCount;
1252-
optionalParameterDefaultValues =
1253-
_encodeOptionalParameterDefaultValues(method);
1254-
}
1255-
1256-
var applyIndex = js.number(method.applyIndex);
1257-
1258-
return js.js.statement('''
1259-
installTearOff(#container, #getterName, #isStatic, #isIntercepted,
1260-
#requiredParameterCount, #optionalParameterDefaultValues,
1261-
#callNames, #funsOrNames, #funType, #applyIndex)''', {
1262-
"container": container,
1263-
"getterName": js.quoteName(method.tearOffName),
1264-
// 'Truthy' values are ok for `isStatic` and `isIntercepted`.
1265-
"isStatic": js.number(method.isStatic ? 1 : 0),
1266-
"isIntercepted": js.number(isIntercepted ? 1 : 0),
1267-
"requiredParameterCount": js.number(requiredParameterCount),
1268-
"optionalParameterDefaultValues": optionalParameterDefaultValues,
1269-
"callNames": callNameArray,
1270-
"funsOrNames": funsOrNamesArray,
1271-
"funType": method.functionType,
1272-
"applyIndex": applyIndex,
1273-
});
1274-
}
1275-
12761239
/// Wraps the statement in a named function to that it shows up as a unit in
12771240
/// profiles.
12781241
// TODO(sra): Should this be conditional?
@@ -1292,6 +1255,100 @@ class FragmentEmitter {
12921255
/// Emits the section that installs tear-off getters.
12931256
js.Statement emitInstallTearOffs(Fragment fragment,
12941257
{bool softDeferred = false}) {
1258+
var aliasForInstallStaticTearOff;
1259+
var aliasForInstallInstanceTearOff;
1260+
1261+
/// Emits the statement that installs a tear off for a method.
1262+
///
1263+
/// Tear-offs might be passed to `Function.apply` which means that all
1264+
/// calling-conventions (with or without optional positional/named
1265+
/// arguments) are possible. As such, the tear-off needs enough information
1266+
/// to fill in missing parameters.
1267+
js.Statement emitInstallTearOff(
1268+
js.Expression container, DartMethod method) {
1269+
List<js.Name> callNames = [];
1270+
List<js.Expression> funsOrNames = [];
1271+
1272+
/// Adds the stub-method's code or name to the [funsOrNames] array.
1273+
///
1274+
/// Static methods don't need stub-methods except for tear-offs. As such,
1275+
/// they are not emitted in the prototype, but directly passed here.
1276+
///
1277+
/// Instance-methods install the stub-methods in their prototype, and we
1278+
/// use string-based redirections to find them there.
1279+
void addFunOrName(StubMethod stubMethod) {
1280+
if (method.isStatic) {
1281+
funsOrNames.add(stubMethod.code);
1282+
} else {
1283+
funsOrNames.add(js.quoteName(stubMethod.name));
1284+
}
1285+
}
1286+
1287+
callNames.add(method.callName);
1288+
// The first entry in the funsOrNames-array must be a string.
1289+
funsOrNames.add(js.quoteName(method.name));
1290+
for (ParameterStubMethod stubMethod in method.parameterStubs) {
1291+
callNames.add(stubMethod.callName);
1292+
addFunOrName(stubMethod);
1293+
}
1294+
1295+
js.ArrayInitializer callNameArray =
1296+
new js.ArrayInitializer(callNames.map(js.quoteName).toList());
1297+
js.ArrayInitializer funsOrNamesArray =
1298+
new js.ArrayInitializer(funsOrNames);
1299+
1300+
bool isIntercepted = false;
1301+
if (method is InstanceMethod) {
1302+
isIntercepted = method.isIntercepted;
1303+
}
1304+
1305+
int requiredParameterCount = 0;
1306+
js.Expression optionalParameterDefaultValues = new js.LiteralNull();
1307+
if (method.canBeApplied) {
1308+
requiredParameterCount = method.requiredParameterCount;
1309+
optionalParameterDefaultValues =
1310+
_encodeOptionalParameterDefaultValues(method);
1311+
}
1312+
1313+
var applyIndex = js.number(method.applyIndex);
1314+
1315+
if (method.isStatic) {
1316+
aliasForInstallStaticTearOff ??= '_static';
1317+
return js.js.statement('''
1318+
#install(#container, #getterName,
1319+
#requiredParameterCount, #optionalParameterDefaultValues,
1320+
#callNames, #funsOrNames, #funType, #applyIndex)''', {
1321+
"install": aliasForInstallStaticTearOff,
1322+
"container": container,
1323+
"getterName": js.quoteName(method.tearOffName),
1324+
"requiredParameterCount": js.number(requiredParameterCount),
1325+
"optionalParameterDefaultValues": optionalParameterDefaultValues,
1326+
"callNames": callNameArray,
1327+
"funsOrNames": funsOrNamesArray,
1328+
"funType": method.functionType,
1329+
"applyIndex": applyIndex,
1330+
});
1331+
} else {
1332+
aliasForInstallInstanceTearOff ??= '_instance';
1333+
return js.js.statement('''
1334+
#install(#container, #getterName, #isIntercepted,
1335+
#requiredParameterCount, #optionalParameterDefaultValues,
1336+
#callNames, #funsOrNames, #funType, #applyIndex)''', {
1337+
"install": aliasForInstallInstanceTearOff,
1338+
"container": container,
1339+
"getterName": js.quoteName(method.tearOffName),
1340+
// 'Truthy' values are ok for `isIntercepted`.
1341+
"isIntercepted": js.number(isIntercepted ? 1 : 0),
1342+
"requiredParameterCount": js.number(requiredParameterCount),
1343+
"optionalParameterDefaultValues": optionalParameterDefaultValues,
1344+
"callNames": callNameArray,
1345+
"funsOrNames": funsOrNamesArray,
1346+
"funType": method.functionType,
1347+
"applyIndex": applyIndex,
1348+
});
1349+
}
1350+
}
1351+
12951352
List<js.Statement> inits = [];
12961353
js.Expression temp;
12971354

@@ -1325,6 +1382,23 @@ class FragmentEmitter {
13251382
}
13261383
}
13271384
}
1385+
1386+
List<js.VariableInitialization> locals = [];
1387+
if (aliasForInstallStaticTearOff != null) {
1388+
locals.add(js.VariableInitialization(
1389+
js.VariableDeclaration(aliasForInstallStaticTearOff),
1390+
js.js('hunkHelpers.installStaticTearOff')));
1391+
}
1392+
if (aliasForInstallInstanceTearOff != null) {
1393+
locals.add(js.VariableInitialization(
1394+
js.VariableDeclaration(aliasForInstallInstanceTearOff),
1395+
js.js('hunkHelpers.installInstanceTearOff')));
1396+
}
1397+
if (locals.isNotEmpty) {
1398+
inits.insert(
1399+
0, js.ExpressionStatement(js.VariableDeclarationList(locals)));
1400+
}
1401+
13281402
return wrapPhase('installTearOffs', inits);
13291403
}
13301404

0 commit comments

Comments
 (0)