Skip to content

Commit 6de2f92

Browse files
alexmarkovcommit-bot@chromium.org
authored andcommitted
[vm,bytecode] Allocate objects lazily in bytecode generator
Previously, bytecode generator was allocating a bunch of objects eagerly when starting bytecode generation for a member. Most of these objects are maps and lists which are needed only under certain circumstances. With this change these objects are allocated more lazily, only when needed. Also, this CL fixes crash in LinkReader.setOffset when reading/dumping bytecode. Change-Id: I11c561e4f00c456e92f42530d3d4e6008b5f5daf Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/122407 Reviewed-by: Ryan Macnak <rmacnak@google.com> Commit-Queue: Alexander Markov <alexmarkov@google.com>
1 parent 929a306 commit 6de2f92

File tree

3 files changed

+43
-26
lines changed

3 files changed

+43
-26
lines changed

pkg/vm/lib/bytecode/bytecode_serialization.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -457,7 +457,7 @@ class LinkWriter {
457457
class LinkReader {
458458
final _map = <Type, Map<int, BytecodeDeclaration>>{};
459459

460-
void setOffset<T>(BytecodeDeclaration target, int offset) {
460+
void setOffset<T extends BytecodeDeclaration>(T target, int offset) {
461461
final offsetToObject = (_map[T] ??= <int, BytecodeDeclaration>{});
462462
final previous = offsetToObject[offset];
463463
if (previous != null) {

pkg/vm/lib/bytecode/gen_bytecode.dart

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1656,18 +1656,18 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
16561656
return;
16571657
}
16581658

1659-
labeledStatements = <LabeledStatement, Label>{};
1660-
switchCases = <SwitchCase, Label>{};
1661-
tryCatches = <TryCatch, TryBlock>{};
1662-
finallyBlocks = <TryFinally, List<FinallyBlock>>{};
1659+
labeledStatements = null;
1660+
switchCases = null;
1661+
tryCatches = null;
1662+
finallyBlocks = null;
16631663
yieldPoints = null; // Initialized when entering sync-yielding closure.
1664-
contextLevels = <TreeNode, int>{};
1665-
closures = <ClosureDeclaration>[];
1664+
contextLevels = null;
1665+
closures = null;
16661666
initializedFields = null; // Tracked for constructors only.
16671667
nullableFields = const <ObjectHandle>[];
16681668
cp = new ConstantPool(stringTable, objectTable);
16691669
asm = new BytecodeAssembler(options);
1670-
savedAssemblers = <BytecodeAssembler>[];
1670+
savedAssemblers = null;
16711671
currentLoopDepth = 0;
16721672
savedMaxSourcePositions = <int>[];
16731673
maxSourcePosition = node.fileOffset;
@@ -1780,7 +1780,7 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
17801780
finalizeSourcePositions(),
17811781
finalizeLocalVariables(),
17821782
nullableFields,
1783-
closures,
1783+
closures ?? const <ClosureDeclaration>[],
17841784
parameterFlags,
17851785
forwardingStubTargetCpIndex,
17861786
defaultFunctionTypeArgsCpIndex);
@@ -2344,6 +2344,7 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
23442344
}
23452345

23462346
void _pushAssemblerState() {
2347+
savedAssemblers ??= <BytecodeAssembler>[];
23472348
savedAssemblers.add(asm);
23482349
asm = new BytecodeAssembler(options);
23492350
}
@@ -2377,6 +2378,7 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
23772378
List<Label> savedYieldPoints = yieldPoints;
23782379
yieldPoints = locals.isSyncYieldingFrame ? <Label>[] : null;
23792380

2381+
closures ??= <ClosureDeclaration>[];
23802382
final int closureIndex = closures.length;
23812383
final closure = getClosureDeclaration(node, function, name, closureIndex,
23822384
savedIsClosure ? parentFunction : enclosingMember);
@@ -4014,7 +4016,9 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
40144016
@override
40154017
visitLabeledStatement(LabeledStatement node) {
40164018
final label = new Label();
4019+
labeledStatements ??= new Map<LabeledStatement, Label>();
40174020
labeledStatements[node] = label;
4021+
contextLevels ??= new Map<TreeNode, int>();
40184022
contextLevels[node] = locals.currentContextLevel;
40194023
_generateNode(node.body);
40204024
asm.bind(label);
@@ -4057,6 +4061,7 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
40574061

40584062
@override
40594063
visitSwitchStatement(SwitchStatement node) {
4064+
contextLevels ??= new Map<TreeNode, int>();
40604065
contextLevels[node] = locals.currentContextLevel;
40614066

40624067
_generateNode(node.expression);
@@ -4075,6 +4080,8 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
40754080
node.cases.length, (_) => new Label(allowsBackwardJumps: true));
40764081
final equalsArgDesc = objectTable.getArgDescHandle(2);
40774082

4083+
switchCases ??= new Map<SwitchCase, Label>();
4084+
40784085
Label defaultLabel = done;
40794086
for (int i = 0; i < node.cases.length; i++) {
40804087
final SwitchCase switchCase = node.cases[i];
@@ -4244,6 +4251,7 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
42444251

42454252
final TryBlock tryBlock = _startTryBlock(node);
42464253
tryBlock.isSynthetic = node.isSynthetic;
4254+
tryCatches ??= new Map<TryCatch, TryBlock>();
42474255
tryCatches[node] = tryBlock; // Used by rethrow.
42484256

42494257
_generateNode(node.body);
@@ -4315,6 +4323,7 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
43154323

43164324
final TryBlock tryBlock = _startTryBlock(node);
43174325
tryBlock.isSynthetic = true;
4326+
finallyBlocks ??= new Map<TryFinally, List<FinallyBlock>>();
43184327
finallyBlocks[node] = <FinallyBlock>[];
43194328

43204329
_generateNode(node.body);

pkg/vm/lib/bytecode/local_vars.dart

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,13 @@ import 'options.dart' show BytecodeOptions;
1717
import '../metadata/direct_call.dart' show DirectCallMetadata;
1818

1919
class LocalVariables {
20-
final Map<TreeNode, Scope> _scopes = <TreeNode, Scope>{};
21-
final Map<VariableDeclaration, VarDesc> _vars =
22-
<VariableDeclaration, VarDesc>{};
23-
final Map<TreeNode, List<int>> _temps = <TreeNode, List<int>>{};
24-
final Map<TreeNode, VariableDeclaration> _capturedSavedContextVars =
25-
<TreeNode, VariableDeclaration>{};
26-
final Map<TreeNode, VariableDeclaration> _capturedExceptionVars =
27-
<TreeNode, VariableDeclaration>{};
28-
final Map<TreeNode, VariableDeclaration> _capturedStackTraceVars =
29-
<TreeNode, VariableDeclaration>{};
30-
final Map<ForInStatement, VariableDeclaration> _capturedIteratorVars =
31-
<ForInStatement, VariableDeclaration>{};
20+
final _scopes = new Map<TreeNode, Scope>();
21+
final _vars = new Map<VariableDeclaration, VarDesc>();
22+
Map<TreeNode, List<int>> _temps;
23+
Map<TreeNode, VariableDeclaration> _capturedSavedContextVars;
24+
Map<TreeNode, VariableDeclaration> _capturedExceptionVars;
25+
Map<TreeNode, VariableDeclaration> _capturedStackTraceVars;
26+
Map<ForInStatement, VariableDeclaration> _capturedIteratorVars;
3227
final BytecodeOptions options;
3328
final TypeEnvironment typeEnvironment;
3429
final Map<TreeNode, DirectCallMetadata> directCallMetadata;
@@ -155,13 +150,15 @@ class LocalVariables {
155150
}
156151

157152
VariableDeclaration capturedSavedContextVar(TreeNode node) =>
158-
_capturedSavedContextVars[node];
153+
_capturedSavedContextVars != null
154+
? _capturedSavedContextVars[node]
155+
: null;
159156
VariableDeclaration capturedExceptionVar(TreeNode node) =>
160-
_capturedExceptionVars[node];
157+
_capturedExceptionVars != null ? _capturedExceptionVars[node] : null;
161158
VariableDeclaration capturedStackTraceVar(TreeNode node) =>
162-
_capturedStackTraceVars[node];
159+
_capturedStackTraceVars != null ? _capturedStackTraceVars[node] : null;
163160
VariableDeclaration capturedIteratorVar(ForInStatement node) =>
164-
_capturedIteratorVars[node];
161+
_capturedIteratorVars != null ? _capturedIteratorVars[node] : null;
165162

166163
int get asyncExceptionParamIndexInFrame {
167164
assert(_currentFrame.isSyncYielding);
@@ -521,12 +518,18 @@ class _ScopeBuilder extends RecursiveVisitor<Null> {
521518
void _captureSyntheticVariables() {
522519
int depth = 0;
523520
for (TreeNode tryBlock in _enclosingTryBlocks) {
521+
locals._capturedSavedContextVars ??=
522+
new Map<TreeNode, VariableDeclaration>();
524523
_captureSyntheticVariable(ContinuationVariables.savedTryContextVar(depth),
525524
tryBlock, locals._capturedSavedContextVars);
526525
++depth;
527526
}
528527
depth = 0;
529528
for (TreeNode tryBlock in _enclosingTryCatches) {
529+
locals._capturedExceptionVars ??=
530+
new Map<TreeNode, VariableDeclaration>();
531+
locals._capturedStackTraceVars ??=
532+
new Map<TreeNode, VariableDeclaration>();
530533
_captureSyntheticVariable(ContinuationVariables.exceptionVar(depth),
531534
tryBlock, locals._capturedExceptionVars);
532535
_captureSyntheticVariable(ContinuationVariables.stackTraceVar(depth),
@@ -685,6 +688,8 @@ class _ScopeBuilder extends RecursiveVisitor<Null> {
685688
// Declare a variable to hold 'iterator' so it could be captured.
686689
iteratorVar = new VariableDeclaration(':iterator');
687690
_declareVariable(iteratorVar);
691+
locals._capturedIteratorVars ??=
692+
new Map<ForInStatement, VariableDeclaration>();
688693
locals._capturedIteratorVars[node] = iteratorVar;
689694
}
690695

@@ -886,6 +891,7 @@ class _Allocator extends RecursiveVisitor<Null> {
886891
}
887892

888893
void _allocateTemp(TreeNode node, {int count: 1}) {
894+
locals._temps ??= new Map<TreeNode, List<int>>();
889895
assert(locals._temps[node] == null);
890896
if (_currentScope.tempsUsed + count > _currentFrame.temporaries.length) {
891897
// Allocate new local slots for temporary variables.
@@ -1143,7 +1149,9 @@ class _Allocator extends RecursiveVisitor<Null> {
11431149
@override
11441150
visitForInStatement(ForInStatement node) {
11451151
_allocateTemp(node);
1146-
_ensureVariableAllocated(locals._capturedIteratorVars[node]);
1152+
if (locals._capturedIteratorVars != null) {
1153+
_ensureVariableAllocated(locals._capturedIteratorVars[node]);
1154+
}
11471155

11481156
node.iterable.accept(this);
11491157

0 commit comments

Comments
 (0)