Skip to content

Commit a17884a

Browse files
liamappelbecommit-bot@chromium.org
authored andcommitted
[vm] Fix late final local variables in AST mode
- Modify setter logic for late final local variables. - Remove extra visitVariableDeclaration in late_var_init_transformer that was causing nodes to be visited multiple times. Bug: #38841 Change-Id: Id39925e4b9560a1da1b01e1cf14ef20c515f3928 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/127720 Commit-Queue: Liam Appelbe <liama@google.com> Reviewed-by: Régis Crelier <regis@google.com> Reviewed-by: Alexander Markov <alexmarkov@google.com>
1 parent 991e55f commit a17884a

File tree

3 files changed

+43
-14
lines changed

3 files changed

+43
-14
lines changed

pkg/vm/lib/transformations/late_var_init_transformer.dart

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,6 @@ class _LateVarInitTransformer extends Transformer {
3939
}
4040

4141
List<Statement> _transformVariableDeclaration(VariableDeclaration node) {
42-
super.visitVariableDeclaration(node);
43-
4442
final fnNode =
4543
FunctionNode(ReturnStatement(node.initializer), returnType: node.type);
4644
final fn = FunctionDeclaration(

runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc

Lines changed: 41 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2194,15 +2194,8 @@ Fragment StreamingFlowGraphBuilder::BuildVariableSet(TokenPosition* p) {
21942194
if (p != NULL) *p = position;
21952195

21962196
intptr_t variable_kernel_position = ReadUInt(); // read kernel position.
2197-
ReadUInt(); // read relative variable index.
2198-
Fragment instructions = BuildExpression(); // read expression.
2199-
2200-
if (NeedsDebugStepCheck(stack(), position)) {
2201-
instructions = DebugStepCheck(position) + instructions;
2202-
}
2203-
instructions +=
2204-
StoreLocal(position, LookupVariable(variable_kernel_position));
2205-
return instructions;
2197+
ReadUInt(); // read relative variable index.
2198+
return BuildVariableSetImpl(position, variable_kernel_position);
22062199
}
22072200

22082201
Fragment StreamingFlowGraphBuilder::BuildVariableSet(uint8_t payload,
@@ -2211,13 +2204,49 @@ Fragment StreamingFlowGraphBuilder::BuildVariableSet(uint8_t payload,
22112204
if (p != NULL) *p = position;
22122205

22132206
intptr_t variable_kernel_position = ReadUInt(); // read kernel position.
2214-
Fragment instructions = BuildExpression(); // read expression.
2207+
return BuildVariableSetImpl(position, variable_kernel_position);
2208+
}
22152209

2210+
Fragment StreamingFlowGraphBuilder::BuildVariableSetImpl(
2211+
TokenPosition position,
2212+
intptr_t variable_kernel_position) {
2213+
Fragment instructions = BuildExpression(); // read expression.
22162214
if (NeedsDebugStepCheck(stack(), position)) {
22172215
instructions = DebugStepCheck(position) + instructions;
22182216
}
2219-
instructions +=
2220-
StoreLocal(position, LookupVariable(variable_kernel_position));
2217+
2218+
LocalVariable* variable = LookupVariable(variable_kernel_position);
2219+
if (variable->is_late() && variable->is_final()) {
2220+
// Late final variable, so check whether it has been initialized.
2221+
LocalVariable* expr_temp = MakeTemporary();
2222+
instructions += LoadLocal(variable);
2223+
TargetEntryInstr *is_uninitialized, *is_initialized;
2224+
instructions += Constant(Object::sentinel());
2225+
instructions += flow_graph_builder_->BranchIfStrictEqual(&is_uninitialized,
2226+
&is_initialized);
2227+
JoinEntryInstr* join = BuildJoinEntry();
2228+
2229+
{
2230+
// The variable is uninitialized, so store the expression value.
2231+
Fragment initialize(is_uninitialized);
2232+
initialize += LoadLocal(expr_temp);
2233+
initialize += StoreLocal(position, variable);
2234+
initialize += Drop();
2235+
initialize += Goto(join);
2236+
}
2237+
2238+
{
2239+
// Already initialized, so throw a LateInitializationError.
2240+
Fragment already_initialized(is_initialized);
2241+
already_initialized += flow_graph_builder_->ThrowLateInitializationError(
2242+
position, variable->name());
2243+
already_initialized += Goto(join);
2244+
}
2245+
2246+
instructions = Fragment(instructions.entry, join);
2247+
} else {
2248+
instructions += StoreLocal(position, variable);
2249+
}
22212250

22222251
return instructions;
22232252
}

runtime/vm/compiler/frontend/kernel_binary_flowgraph.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,8 @@ class StreamingFlowGraphBuilder : public KernelReaderHelper {
282282
TokenPosition position);
283283
Fragment BuildVariableSet(TokenPosition* position);
284284
Fragment BuildVariableSet(uint8_t payload, TokenPosition* position);
285+
Fragment BuildVariableSetImpl(TokenPosition position,
286+
intptr_t variable_kernel_position);
285287
Fragment BuildPropertyGet(TokenPosition* position);
286288
Fragment BuildPropertySet(TokenPosition* position);
287289
Fragment BuildAllocateInvocationMirrorCall(TokenPosition position,

0 commit comments

Comments
 (0)