Skip to content

Commit 82282b6

Browse files
osa1Commit Queue
authored andcommitted
[dart2wasm] Generate local names in the names section
Local names for function value parameters and for "precise this", return values are generated, state indices in `async` and `sync*` functions are generated. We can generate names for more locals as needed. Change-Id: Ie919f030f0bfae8adbca90408509dd04a7414278 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/419200 Commit-Queue: Ömer Ağacan <[email protected]> Reviewed-by: Martin Kustermann <[email protected]>
1 parent 52da6a0 commit 82282b6

File tree

8 files changed

+92
-32
lines changed

8 files changed

+92
-32
lines changed

pkg/dart2wasm/lib/async.dart

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,9 @@ mixin AsyncCodeGeneratorMixin on StateMachineEntryAstCodeGenerator {
2626

2727
// (1) Create async state.
2828

29-
final asyncStateLocal =
30-
b.addLocal(w.RefType(asyncSuspendStateInfo.struct, nullable: false));
29+
final asyncStateLocal = b.addLocal(
30+
w.RefType(asyncSuspendStateInfo.struct, nullable: false),
31+
name: "asyncState");
3132

3233
// AsyncResumeFun _resume
3334
translator.globals.readGlobal(b, translator.makeFunctionRef(resumeFun));
@@ -195,13 +196,16 @@ class AsyncStateMachineCodeGenerator extends StateMachineCodeGenerator {
195196
Context? localContext = context;
196197
while (localContext != null) {
197198
if (!localContext.isEmpty) {
198-
localContext.currentLocal =
199-
b.addLocal(w.RefType.def(localContext.struct, nullable: true));
199+
localContext.currentLocal = b.addLocal(
200+
w.RefType.def(localContext.struct, nullable: true),
201+
name: "context");
200202
if (localContext.containsThis) {
201203
assert(thisLocal == null);
202-
thisLocal = b.addLocal(localContext
203-
.struct.fields[localContext.thisFieldIndex].type.unpacked
204-
.withNullability(false));
204+
thisLocal = b.addLocal(
205+
localContext
206+
.struct.fields[localContext.thisFieldIndex].type.unpacked
207+
.withNullability(false),
208+
name: "this");
205209
translator
206210
.getDummyValuesCollectorForModule(b.module)
207211
.instantiateDummyValue(b, thisLocal!.type);
@@ -214,7 +218,7 @@ class AsyncStateMachineCodeGenerator extends StateMachineCodeGenerator {
214218
}
215219

216220
// Read target index from the suspend state.
217-
targetIndexLocal = addLocal(w.NumType.i32);
221+
targetIndexLocal = addLocal(w.NumType.i32, name: "targetIndex");
218222
b.local_get(_suspendStateLocal);
219223
b.struct_get(
220224
asyncSuspendStateInfo.struct, FieldIndex.asyncSuspendStateTargetIndex);

pkg/dart2wasm/lib/code_generator.dart

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -115,9 +115,8 @@ abstract class AstCodeGenerator
115115

116116
w.ValueType translateType(DartType type) => translator.translateType(type);
117117

118-
w.Local addLocal(w.ValueType type) {
119-
return b.addLocal(type);
120-
}
118+
w.Local addLocal(w.ValueType type, {String? name}) =>
119+
b.addLocal(type, name: name);
121120

122121
DartType dartTypeOf(Expression exp) {
123122
if (exp is ConstantExpression) {
@@ -257,7 +256,12 @@ abstract class AstCodeGenerator
257256
int index,
258257
Constant? defaultValue,
259258
bool isRequired) {
260-
w.Local local = paramLocals[implicitParams + index];
259+
final localIndex = implicitParams + index;
260+
w.Local local = paramLocals[localIndex];
261+
final variableName = variable.name;
262+
if (variableName != null) {
263+
b.localNames[local.index] = variableName;
264+
}
261265
if (defaultValue == ParameterInfo.defaultValueSentinel) {
262266
// The default value for this parameter differs between implementations
263267
// within the same selector. This means that callers will pass the
@@ -357,7 +361,8 @@ abstract class AstCodeGenerator
357361
if (local.type == w.RefType.extern(nullable: true) &&
358362
!(parameterType is InterfaceType &&
359363
parameterType.classNode == translator.wasmExternRefClass)) {
360-
w.Local newLocal = addLocal(translateType(parameterType));
364+
w.Local newLocal =
365+
addLocal(translateType(parameterType), name: parameter.name);
361366
b.local_get(local);
362367
translator.convertType(b, local.type, newLocal.type);
363368
b.local_set(newLocal);
@@ -490,9 +495,10 @@ abstract class AstCodeGenerator
490495
member.isInstanceMember || reference.isConstructorBodyReference;
491496
if (hasThis) {
492497
thisLocal = paramLocals[0];
498+
b.localNames[thisLocal!.index] = "this";
493499
final preciseThisType = translator.preciseThisFor(member);
494500
if (translator.needsConversion(thisLocal!.type, preciseThisType)) {
495-
preciseThisLocal = addLocal(preciseThisType);
501+
preciseThisLocal = addLocal(preciseThisType, name: "preciseThis");
496502
b.local_get(thisLocal!);
497503
translator.convertType(b, thisLocal!.type, preciseThisType);
498504
b.local_set(preciseThisLocal!);
@@ -537,9 +543,10 @@ abstract class AstCodeGenerator
537543
}
538544

539545
if (context.containsThis) {
540-
thisLocal = addLocal(context
541-
.struct.fields[context.thisFieldIndex].type.unpacked
542-
.withNullability(false));
546+
thisLocal = addLocal(
547+
context.struct.fields[context.thisFieldIndex].type.unpacked
548+
.withNullability(false),
549+
name: "this");
543550
preciseThisLocal = thisLocal;
544551

545552
b.struct_get(context.struct, context.thisFieldIndex);
@@ -794,7 +801,7 @@ abstract class AstCodeGenerator
794801
w.Local? local;
795802
Capture? capture = closures.captures[node];
796803
if (capture == null || !capture.written) {
797-
local = addLocal(type);
804+
local = addLocal(type, name: node.name);
798805
locals[node] = local;
799806
}
800807

@@ -836,7 +843,7 @@ abstract class AstCodeGenerator
836843
w.Local? local;
837844
final Capture? capture = closures.captures[node];
838845
if (capture == null || !capture.written) {
839-
local = addLocal(type);
846+
local = addLocal(type, name: node.name);
840847
locals[node] = local;
841848
}
842849

@@ -1352,7 +1359,8 @@ abstract class AstCodeGenerator
13521359
// Since the flow of the return value through the returnValueLocal
13531360
// crosses control-flow constructs, the local needs to always have a
13541361
// defaultable type in order for the Wasm code to validate.
1355-
returnValueLocal ??= addLocal(returnType.withNullability(true));
1362+
returnValueLocal ??=
1363+
addLocal(returnType.withNullability(true), name: "returnValue");
13561364
b.local_set(returnValueLocal!);
13571365
}
13581366
b.br(returnFinalizers.last.label);

pkg/dart2wasm/lib/intrinsics.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1761,7 +1761,8 @@ class Intrinsifier {
17611761
w.ArrayType arrayType =
17621762
(functionType.outputs.single as w.RefType).heapType as w.ArrayType;
17631763
w.Local object = paramLocals[0];
1764-
w.Local preciseObject = codeGen.addLocal(classInfo.nonNullableType);
1764+
w.Local preciseObject =
1765+
codeGen.addLocal(classInfo.nonNullableType, name: "this");
17651766
b.local_get(object);
17661767
b.ref_cast(classInfo.nonNullableType);
17671768
b.local_set(preciseObject);

pkg/dart2wasm/lib/sync_star.dart

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -168,13 +168,16 @@ class SyncStarStateMachineCodeGenerator extends StateMachineCodeGenerator {
168168
Context? localContext = context;
169169
while (localContext != null) {
170170
if (!localContext.isEmpty) {
171-
localContext.currentLocal =
172-
b.addLocal(w.RefType.def(localContext.struct, nullable: true));
171+
localContext.currentLocal = b.addLocal(
172+
w.RefType.def(localContext.struct, nullable: true),
173+
name: "context");
173174
if (localContext.containsThis) {
174175
assert(thisLocal == null);
175-
thisLocal = b.addLocal(localContext
176-
.struct.fields[localContext.thisFieldIndex].type.unpacked
177-
.withNullability(false));
176+
thisLocal = b.addLocal(
177+
localContext
178+
.struct.fields[localContext.thisFieldIndex].type.unpacked
179+
.withNullability(false),
180+
name: "this");
178181
translator
179182
.getDummyValuesCollectorForModule(b.module)
180183
.instantiateDummyValue(b, thisLocal!.type);
@@ -187,7 +190,7 @@ class SyncStarStateMachineCodeGenerator extends StateMachineCodeGenerator {
187190
}
188191

189192
// Read target index from the suspend state.
190-
targetIndexLocal = addLocal(w.NumType.i32);
193+
targetIndexLocal = addLocal(w.NumType.i32, name: "targetIndex");
191194
b.local_get(_suspendStateLocal);
192195
b.struct_get(suspendStateInfo.struct, FieldIndex.suspendStateTargetIndex);
193196
b.local_set(targetIndexLocal);

pkg/wasm_builder/lib/src/builder/instructions.dart

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,12 @@ class InstructionsBuilder with Builder<ir.Instructions> {
171171
/// Locals declared in this body, including parameters.
172172
final List<ir.Local> locals = [];
173173

174+
/// Names of the locals in `locals`.
175+
///
176+
/// Most of the locals won't have names, so this is a [Map] instead of [List]
177+
/// like [locals], with local indices as keys and names as values.
178+
final Map<int, String> localNames = {};
179+
174180
/// Whether a textual trace of the instruction stream should be recorded when
175181
/// emitting instructions (provided asserts are enabled).
176182
///
@@ -251,8 +257,8 @@ class InstructionsBuilder with Builder<ir.Instructions> {
251257
}
252258

253259
@override
254-
ir.Instructions forceBuild() => ir.Instructions(
255-
locals, _instructions, _stackTraces, _traceLines, _sourceMappings);
260+
ir.Instructions forceBuild() => ir.Instructions(locals, localNames,
261+
_instructions, _stackTraces, _traceLines, _sourceMappings);
256262

257263
void _add(ir.Instruction i) {
258264
assert(!_constantExpression || i.isConstant,
@@ -271,7 +277,11 @@ class InstructionsBuilder with Builder<ir.Instructions> {
271277
return local;
272278
}
273279

274-
ir.Local addLocal(ir.ValueType type) {
280+
ir.Local addLocal(ir.ValueType type, {String? name}) {
281+
if (name != null) {
282+
final index = locals.length;
283+
localNames[index] = name;
284+
}
275285
final local = ir.Local(locals.length, type);
276286
locals.add(local);
277287
_localInitialized.add(type.defaultable);

pkg/wasm_builder/lib/src/ir/function.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ class DefinedFunction extends BaseFunction implements Serializable {
4646
/// All local variables defined in the function, including its inputs.
4747
List<Local> get locals => body.locals;
4848

49+
Map<int, String> get localNames => body.localNames;
50+
4951
DefinedFunction(
5052
super.enclosingModule, this.body, super.finalizableIndex, super.type,
5153
[super.functionName]);

pkg/wasm_builder/lib/src/ir/instructions.dart

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,12 @@ class Instructions implements Serializable {
1010
/// The locals used by this group of instructions.
1111
final List<Local> locals;
1212

13+
/// Names of the locals in `locals`.
14+
///
15+
/// Most of the locals won't have names, so this is a [Map] instead of [List]
16+
/// like [locals], with local indices as keys and names as values.
17+
final Map<int, String> localNames;
18+
1319
/// A sequence of Wasm instructions.
1420
final List<Instruction> instructions;
1521

@@ -27,8 +33,8 @@ class Instructions implements Serializable {
2733
final List<SourceMapping>? _sourceMappings;
2834

2935
/// Create a new instruction sequence.
30-
Instructions(this.locals, this.instructions, this._stackTraces,
31-
this._traceLines, this._sourceMappings);
36+
Instructions(this.locals, this.localNames, this.instructions,
37+
this._stackTraces, this._traceLines, this._sourceMappings);
3238

3339
@override
3440
void serialize(Serializer s) {

pkg/wasm_builder/lib/src/serialize/sections.dart

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,28 @@ class NameSection extends CustomSection {
471471
}
472472
}
473473

474+
final localNameSubsection = Serializer();
475+
List<ir.DefinedFunction> functionsWithLocalNames = [];
476+
for (final function in functions) {
477+
if (function is ir.DefinedFunction) {
478+
if (function.localNames.isNotEmpty) {
479+
functionsWithLocalNames.add(function);
480+
}
481+
}
482+
}
483+
localNameSubsection.writeUnsigned(functionsWithLocalNames.length);
484+
485+
if (functionsWithLocalNames.isNotEmpty) {
486+
for (final function in functionsWithLocalNames) {
487+
localNameSubsection.writeUnsigned(function.finalizableIndex.value);
488+
localNameSubsection.writeUnsigned(function.localNames.length);
489+
for (final entry in function.localNames.entries) {
490+
localNameSubsection.writeUnsigned(entry.key);
491+
localNameSubsection.writeName(entry.value);
492+
}
493+
}
494+
}
495+
474496
s.writeByte(0); // Module name subsection
475497
s.writeUnsigned(moduleNameSubsection.data.length);
476498
s.writeData(moduleNameSubsection);
@@ -479,6 +501,10 @@ class NameSection extends CustomSection {
479501
s.writeUnsigned(functionNameSubsection.data.length);
480502
s.writeData(functionNameSubsection);
481503

504+
s.writeByte(2); // Local names substion
505+
s.writeUnsigned(localNameSubsection.data.length);
506+
s.writeData(localNameSubsection);
507+
482508
s.writeByte(4); // Type names subsection
483509
s.writeUnsigned(typeNameSubsection.data.length);
484510
s.writeData(typeNameSubsection);

0 commit comments

Comments
 (0)