[vm] Cleanup handling of for-in statements

For-in statements are desugared on kernel AST, so handling of these
statements in the VM is a dead code and can be removed.

TEST=ci

Change-Id: Ic06080ee5d1b2ab74c55c400746f38a420668531
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/321560
Reviewed-by: Martin Kustermann <kustermann@google.com>
Commit-Queue: Alexander Markov <alexmarkov@google.com>
This commit is contained in:
Alexander Markov 2023-08-17 19:58:39 +00:00 committed by Commit Queue
parent 47bc86cdc6
commit 6ca7cca807
8 changed files with 11 additions and 181 deletions

View file

@ -1221,10 +1221,6 @@ Fragment StreamingFlowGraphBuilder::BuildStatement(TokenPosition* position) {
return BuildDoStatement(position);
case kForStatement:
return BuildForStatement(position);
case kForInStatement:
return BuildForInStatement(false, position);
case kAsyncForInStatement:
return BuildForInStatement(true, position);
case kSwitchStatement:
return BuildSwitchStatement(position);
case kContinueSwitchStatement:
@ -1243,6 +1239,8 @@ Fragment StreamingFlowGraphBuilder::BuildStatement(TokenPosition* position) {
return BuildVariableDeclaration(position);
case kFunctionDeclaration:
return BuildFunctionDeclaration(offset, position);
case kForInStatement:
case kAsyncForInStatement:
case kIfCaseStatement:
case kPatternSwitchStatement:
case kPatternVariableDeclaration:
@ -1302,18 +1300,6 @@ void StreamingFlowGraphBuilder::loop_depth_dec() {
--flow_graph_builder_->loop_depth_;
}
intptr_t StreamingFlowGraphBuilder::for_in_depth() {
return flow_graph_builder_->for_in_depth_;
}
void StreamingFlowGraphBuilder::for_in_depth_inc() {
++flow_graph_builder_->for_in_depth_;
}
void StreamingFlowGraphBuilder::for_in_depth_dec() {
--flow_graph_builder_->for_in_depth_;
}
void StreamingFlowGraphBuilder::catch_depth_inc() {
++flow_graph_builder_->catch_depth_;
}
@ -1722,8 +1708,8 @@ Fragment StreamingFlowGraphBuilder::TranslateFinallyFinalizers(
TryCatchBlock* const saved_try_catch_block = B->CurrentTryCatchBlock();
const intptr_t saved_context_depth = B->context_depth_;
const ProgramState state(B->breakable_block_, B->switch_block_,
B->loop_depth_, B->for_in_depth_, B->try_depth_,
B->catch_depth_, B->block_expression_depth_);
B->loop_depth_, B->try_depth_, B->catch_depth_,
B->block_expression_depth_);
Fragment instructions;
@ -4842,68 +4828,6 @@ Fragment StreamingFlowGraphBuilder::BuildForStatement(TokenPosition* position) {
return loop;
}
Fragment StreamingFlowGraphBuilder::BuildForInStatement(
bool async,
TokenPosition* position) {
intptr_t offset = ReaderOffset() - 1; // Include the tag.
const TokenPosition pos = ReadPosition(); // read position.
if (position != nullptr) *position = pos;
TokenPosition body_position = ReadPosition(); // read body position.
intptr_t variable_kernel_position = ReaderOffset() + data_program_offset_;
SkipVariableDeclaration(); // read variable.
TokenPosition iterable_position = TokenPosition::kNoSource;
Fragment instructions =
BuildExpression(&iterable_position); // read iterable.
const String& iterator_getter =
String::ZoneHandle(Z, Field::GetterSymbol(Symbols::Iterator()));
instructions +=
InstanceCall(iterable_position, iterator_getter, Token::kGET, 1);
LocalVariable* iterator = scopes()->iterator_variables[for_in_depth()];
instructions += StoreLocal(TokenPosition::kNoSource, iterator);
instructions += Drop();
for_in_depth_inc();
loop_depth_inc();
Fragment condition = LoadLocal(iterator);
condition +=
InstanceCall(iterable_position, Symbols::MoveNext(), Token::kILLEGAL, 1);
TargetEntryInstr* body_entry;
TargetEntryInstr* loop_exit;
condition += BranchIfTrue(&body_entry, &loop_exit, false);
Fragment body(body_entry);
body += EnterScope(offset);
body += LoadLocal(iterator);
const String& current_getter =
String::ZoneHandle(Z, Field::GetterSymbol(Symbols::Current()));
body += InstanceCall(body_position, current_getter, Token::kGET, 1);
body += StoreLocal(TokenPosition::kNoSource,
LookupVariable(variable_kernel_position));
body += Drop();
body += BuildStatementWithBranchCoverage(); // read body.
body += ExitScope(offset);
if (body.is_open()) {
JoinEntryInstr* join = BuildJoinEntry();
instructions += Goto(join);
body += Goto(join);
Fragment loop(join);
loop += CheckStackOverflow(pos); // may have non-empty stack
loop += condition;
} else {
instructions += condition;
}
loop_depth_dec();
for_in_depth_dec();
return Fragment(instructions.entry, loop_exit);
}
Fragment StreamingFlowGraphBuilder::BuildSwitchStatement(
TokenPosition* position) {
const TokenPosition pos = ReadPosition(); // read position.

View file

@ -105,9 +105,6 @@ class StreamingFlowGraphBuilder : public KernelReaderHelper {
void loop_depth_inc();
void loop_depth_dec();
intptr_t for_in_depth();
void for_in_depth_inc();
void for_in_depth_dec();
void catch_depth_inc();
void catch_depth_dec();
void try_depth_inc();
@ -354,7 +351,6 @@ class StreamingFlowGraphBuilder : public KernelReaderHelper {
Fragment BuildWhileStatement(TokenPosition* position);
Fragment BuildDoStatement(TokenPosition* position);
Fragment BuildForStatement(TokenPosition* position);
Fragment BuildForInStatement(bool async, TokenPosition* position);
Fragment BuildSwitchStatement(TokenPosition* position);
Fragment BuildSwitchCase(SwitchHelper* helper, intptr_t case_index);
Fragment BuildLinearScanSwitch(SwitchHelper* helper);

View file

@ -761,14 +761,6 @@ void KernelFingerprintHelper::CalculateStatementFingerprint() {
CalculateStatementFingerprint(); // read body.
return;
}
case kForInStatement:
case kAsyncForInStatement:
ReadPosition(); // read position.
ReadPosition(); // read body position.
CalculateVariableDeclarationFingerprint(); // read variable.
CalculateExpressionFingerprint(); // read iterable.
CalculateStatementFingerprint(); // read body.
return;
case kSwitchStatement: {
ReadPosition(); // read position.
ReadBool(); // read exhaustive flag.
@ -844,6 +836,8 @@ void KernelFingerprintHelper::CalculateStatementFingerprint() {
CalculateVariableDeclarationFingerprint(); // read variable.
CalculateFunctionNodeFingerprint(); // read function node.
return;
case kForInStatement:
case kAsyncForInStatement:
case kIfCaseStatement:
case kPatternSwitchStatement:
case kPatternVariableDeclaration:

View file

@ -84,7 +84,6 @@ FlowGraphBuilder::FlowGraphBuilder(
loop_depth_(0),
try_depth_(0),
catch_depth_(0),
for_in_depth_(0),
block_expression_depth_(0),
graph_entry_(nullptr),
scopes_(nullptr),

View file

@ -608,7 +608,6 @@ class FlowGraphBuilder : public BaseFlowGraphBuilder {
intptr_t loop_depth_;
intptr_t try_depth_;
intptr_t catch_depth_;
intptr_t for_in_depth_;
intptr_t block_expression_depth_;
GraphEntryInstr* graph_entry_;
@ -691,14 +690,12 @@ class ProgramState {
ProgramState(BreakableBlock* breakable_block,
SwitchBlock* switch_block,
intptr_t loop_depth,
intptr_t for_in_depth,
intptr_t try_depth,
intptr_t catch_depth,
intptr_t block_expression_depth)
: breakable_block_(breakable_block),
switch_block_(switch_block),
loop_depth_(loop_depth),
for_in_depth_(for_in_depth),
try_depth_(try_depth),
catch_depth_(catch_depth),
block_expression_depth_(block_expression_depth) {}
@ -707,7 +704,6 @@ class ProgramState {
builder->breakable_block_ = breakable_block_;
builder->switch_block_ = switch_block_;
builder->loop_depth_ = loop_depth_;
builder->for_in_depth_ = for_in_depth_;
builder->try_depth_ = try_depth_;
builder->catch_depth_ = catch_depth_;
builder->block_expression_depth_ = block_expression_depth_;
@ -717,7 +713,6 @@ class ProgramState {
BreakableBlock* const breakable_block_;
SwitchBlock* const switch_block_;
const intptr_t loop_depth_;
const intptr_t for_in_depth_;
const intptr_t try_depth_;
const intptr_t catch_depth_;
const intptr_t block_expression_depth_;
@ -845,7 +840,6 @@ class TryFinallyBlock {
state_(builder_->breakable_block_,
builder_->switch_block_,
builder_->loop_depth_,
builder_->for_in_depth_,
builder_->try_depth_ - 1,
builder_->catch_depth_,
builder_->block_expression_depth_) {

View file

@ -2843,14 +2843,6 @@ void KernelReaderHelper::SkipStatement() {
SkipStatement(); // read body.
return;
}
case kForInStatement:
case kAsyncForInStatement:
ReadPosition(); // read position.
ReadPosition(); // read body position.
SkipVariableDeclaration(); // read variable.
SkipExpression(); // read iterable.
SkipStatement(); // read body.
return;
case kSwitchStatement: {
ReadPosition(); // read position.
ReadBool(); // read exhaustive flag.
@ -2923,6 +2915,8 @@ void KernelReaderHelper::SkipStatement() {
SkipVariableDeclaration(); // read variable.
SkipFunctionNode(); // read function node.
return;
case kForInStatement:
case kAsyncForInStatement:
case kIfCaseStatement:
case kPatternSwitchStatement:
case kPatternVariableDeclaration:

View file

@ -1118,44 +1118,6 @@ void ScopeBuilder::VisitStatement() {
--depth_.loop_;
return;
}
case kForInStatement:
case kAsyncForInStatement: {
PositionScope scope(&helper_.reader_);
intptr_t start_offset =
helper_.ReaderOffset() - 1; // -1 to include tag byte.
helper_.ReadPosition(); // read position.
TokenPosition body_position =
helper_.ReadPosition(); // read body position.
// Notice the ordering: We skip the variable, read the iterable, go back,
// re-read the variable, go forward to after having read the iterable.
intptr_t offset = helper_.ReaderOffset();
helper_.SkipVariableDeclaration(); // read variable.
VisitExpression(); // read iterable.
++depth_.for_in_;
AddIteratorVariable();
++depth_.loop_;
EnterScope(start_offset);
{
AlternativeReadingScope alt(&helper_.reader_, offset);
VisitVariableDeclaration(); // read variable.
}
VisitStatement(); // read body.
if (!body_position.IsReal()) {
body_position = helper_.reader_.min_position();
}
// TODO(jensj): From kernel_binary.cc
// forinstmt->variable_->set_end_position(forinstmt->position_);
ExitScope(body_position, helper_.reader_.max_position());
--depth_.loop_;
--depth_.for_in_;
return;
}
case kSwitchStatement: {
AddSwitchVariable();
helper_.ReadPosition(); // read position.
@ -1277,6 +1239,8 @@ void ScopeBuilder::VisitStatement() {
HandleLocalFunction(offset); // read function node.
return;
}
case kForInStatement:
case kAsyncForInStatement:
case kIfCaseStatement:
case kPatternSwitchStatement:
case kPatternVariableDeclaration:
@ -1817,19 +1781,6 @@ void ScopeBuilder::FinalizeCatchVariables() {
GenerateName(":raw_stacktrace", unique_id), depth_.catch_);
}
void ScopeBuilder::AddIteratorVariable() {
if (depth_.function_ > 0) return;
if (result_->iterator_variables.length() >= depth_.for_in_) return;
ASSERT(result_->iterator_variables.length() == depth_.for_in_ - 1);
LocalVariable* iterator =
MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
GenerateName(":iterator", depth_.for_in_ - 1),
AbstractType::dynamic_type());
current_function_scope_->AddVariable(iterator);
result_->iterator_variables.Add(iterator);
}
void ScopeBuilder::AddSwitchVariable() {
if ((depth_.function_ == 0) && (result_->switch_variable == nullptr)) {
LocalVariable* variable =

View file

@ -119,7 +119,6 @@ class ScopeBuilder {
void AddTryVariables();
void AddCatchVariables();
void FinalizeCatchVariables();
void AddIteratorVariable();
void AddSwitchVariable();
// Record an assignment or reference to a variable. If the occurrence is
@ -141,19 +140,13 @@ class ScopeBuilder {
struct DepthState {
explicit DepthState(intptr_t function)
: loop_(0),
function_(function),
try_(0),
catch_(0),
finally_(0),
for_in_(0) {}
: loop_(0), function_(function), try_(0), catch_(0), finally_(0) {}
intptr_t loop_;
intptr_t function_;
intptr_t try_;
intptr_t catch_;
intptr_t finally_;
intptr_t for_in_;
};
ScopeBuildingResult* result_;
@ -195,8 +188,6 @@ class ScopeBuildingResult : public ZoneAllocated {
switch_variable(nullptr),
finally_return_variable(nullptr),
setter_value(nullptr),
yield_jump_variable(nullptr),
yield_context_variable(nullptr),
raw_variable_counter_(0) {}
bool IsClosureWithEmptyContext(intptr_t function_node_offset) {
@ -224,16 +215,6 @@ class ScopeBuildingResult : public ZoneAllocated {
// Non-nullptr when the function is a setter.
LocalVariable* setter_value;
// Non-nullptr if the function contains yield statement.
// TODO(27590) actual variable is called :await_jump_var, we should rename
// it to reflect the fact that it is used for both await and yield.
LocalVariable* yield_jump_variable;
// Non-nullptr if the function contains yield statement.
// TODO(27590) actual variable is called :await_ctx_var, we should rename
// it to reflect the fact that it is used for both await and yield.
LocalVariable* yield_context_variable;
// Variables used in exception handlers, one per exception handler nesting
// level.
GrowableArray<LocalVariable*> exception_variables;
@ -246,9 +227,6 @@ class ScopeBuildingResult : public ZoneAllocated {
GrowableArray<LocalVariable*> raw_stack_trace_variables;
intptr_t raw_variable_counter_;
// For-in iterators, one per for-in nesting level.
GrowableArray<LocalVariable*> iterator_variables;
// Remembers closure function kernel offsets that do not capture any
// variables.
GrowableArray<intptr_t> closure_offsets_without_captures;