mirror of
https://github.com/dart-lang/sdk
synced 2024-09-15 22:00:09 +00:00
[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:
parent
47bc86cdc6
commit
6ca7cca807
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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_) {
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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 =
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue