Files
sdk/runtime/vm/compiler/frontend/scope_builder.h
T
Tess Strickland e2df4d30a0 [vm] Remove non-private uses of TokenPosition::value().
Instead, split each old use into the following cases:

* If the TokenPosition value is expected to be a real token position,
  then use TokenPosition::Pos().

* If the TokenPosition is being serialized in some way, then use
  TokenPosition::Serialize() and change the place where the
  TokenPosition is recreated to use TokenPosition::Deserialize().

* If the value of the TokenPosition is being printed for debugging
  purposes, then just use TokenPosition::ToCString() instead.

That is, we try to pin down when token positions are expected to
be real vs. when other types of token positions can be found.

Another source of possible error when using token positions is to
convert between synthetic and real token positions. In the past,
synthetic token positions may have been based off real token positions,
but that is no longer the case. Thus, all methods that allow
that conversion have been removed, and instead there is a new static
method for constructing synthetic tokens from valid nonces.

This CL also makes it so that Pos() and relational operators on token
positions are only defined on real token positions, to avoid any
assumptions about what the value encoded in synthetic positions mean. To
help with cases where non-real token positions may occur, four helper
methods are added:

* TokenPosition::Min(a, b): A static method that returns the smallest
  real token position provided. If neither `a` or `b` are real,
  returns `a`.

* TokenPosition::Max(a, b): A static method that returns the largest
  real token position provided. If neither `a` or `b` are real,
  returns `a`.

* TokenPosition::IsWithin(start, end): Determines whether `this` falls
  between `start` and `end` (inclusive). If `this` is non-real, then it
  must be either `start` or `end` if synthetic, otherwise false.
  Otherwise, we mimic the old style of range checking, which means that
  non-real starts and ends are treated as less than every real token.

* TokenPosition::CompareForSorting(other): Unlike the relational
  operators, provides a comparison between any types of token positions
  for purposes such as sorting.  Currently only used in the profiler.

It also changes TokenPosition::ToCString() to tag synthetic token
positions, so they can be distinguished from real ones at a glance.

TEST=Existing test suite on trybots, especially the observatory tests
which make heavy use of the debugger and the unit tests for the
profiler/source report modules.

Bug: https://github.com/dart-lang/sdk/issues/44436

Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-nnbd-linux-debug-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-nnbd-linux-debug-x64-try,vm-kernel-linux-debug-x64-try,vm-kernel-linux-release-x64-try,vm-kernel-nnbd-linux-release-x64-try,vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-nnbd-linux-release-x64-try,vm-kernel-linux-product-x64-try,vm-kernel-precomp-linux-product-x64-try
Change-Id: Ic06aa0bc7a1f0fbac7257ed22ca5e7e0ccd7f3f2
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/174924
Commit-Queue: Tess Strickland <sstrickl@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
Reviewed-by: Daco Harkes <dacoharkes@google.com>
2020-12-16 08:27:32 +00:00

241 lines
7.7 KiB
C++

// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef RUNTIME_VM_COMPILER_FRONTEND_SCOPE_BUILDER_H_
#define RUNTIME_VM_COMPILER_FRONTEND_SCOPE_BUILDER_H_
#if defined(DART_PRECOMPILED_RUNTIME)
#error "AOT runtime should not use compiler sources (including header files)"
#endif // defined(DART_PRECOMPILED_RUNTIME)
#include "vm/compiler/frontend/constant_reader.h"
#include "vm/compiler/frontend/kernel_translation_helper.h"
#include "vm/hash_map.h"
#include "vm/object.h"
#include "vm/parser.h" // For ParsedFunction.
namespace dart {
namespace kernel {
class ScopeBuildingResult;
class ScopeBuilder {
public:
explicit ScopeBuilder(ParsedFunction* parsed_function);
virtual ~ScopeBuilder() = default;
ScopeBuildingResult* BuildScopes();
private:
void VisitField();
void VisitProcedure();
void VisitConstructor();
void VisitFunctionNode();
void VisitNode();
void VisitInitializer();
void VisitExpression();
void VisitStatement();
void VisitArguments();
void VisitVariableDeclaration();
void VisitVariableGet(intptr_t declaration_binary_offset);
void VisitDartType();
void VisitInterfaceType(bool simple);
void VisitFunctionType(bool simple);
void VisitTypeParameterType();
void HandleLocalFunction(intptr_t parent_kernel_offset);
AbstractType& BuildAndVisitVariableType();
void EnterScope(intptr_t kernel_offset);
void ExitScope(TokenPosition start_position, TokenPosition end_position);
virtual void ReportUnexpectedTag(const char* variant, Tag tag);
// This enum controls which parameters would be marked as requring type
// check on the callee side.
enum ParameterTypeCheckMode {
// All parameters will be checked.
kTypeCheckAllParameters,
// Only parameters marked as covariant or generic-covariant-impl will be
// checked.
kTypeCheckForNonDynamicallyInvokedMethod,
// Only parameters *not* marked as covariant or generic-covariant-impl will
// be checked. The rest would be checked in the method itself.
// Inverse of kTypeCheckForNonDynamicallyInvokedMethod.
kTypeCheckEverythingNotCheckedInNonDynamicallyInvokedMethod,
// No parameters will be checked.
kTypeCheckForStaticFunction,
// No non-covariant checks are performed, and any covariant checks are
// performed by the target.
kTypeCheckForImplicitClosureFunction,
};
// This assumes that the reader is at a FunctionNode,
// about to read the positional parameters.
void AddPositionalAndNamedParameters(
intptr_t pos,
ParameterTypeCheckMode type_check_mode,
const ProcedureAttributesMetadata& attrs);
// This assumes that the reader is at a FunctionNode,
// about to read a parameter (i.e. VariableDeclaration).
void AddVariableDeclarationParameter(
intptr_t pos,
ParameterTypeCheckMode type_check_mode,
const ProcedureAttributesMetadata& attrs);
LocalVariable* MakeVariable(TokenPosition declaration_pos,
TokenPosition token_pos,
const String& name,
const AbstractType& type,
const InferredTypeMetadata* param_type_md = NULL);
void AddExceptionVariable(GrowableArray<LocalVariable*>* variables,
const char* prefix,
intptr_t nesting_depth);
void FinalizeExceptionVariable(GrowableArray<LocalVariable*>* variables,
GrowableArray<LocalVariable*>* raw_variables,
const String& symbol,
intptr_t nesting_depth);
void AddTryVariables();
void AddCatchVariables();
void FinalizeCatchVariables();
void AddIteratorVariable();
void AddSwitchVariable();
// Record an assignment or reference to a variable. If the occurrence is
// in a nested function, ensure that the variable is handled properly as a
// captured variable.
LocalVariable* LookupVariable(intptr_t declaration_binary_offset);
StringIndex GetNameFromVariableDeclaration(intptr_t kernel_offset,
const Function& function);
const String& GenerateName(const char* prefix, intptr_t suffix);
void HandleLoadReceiver();
void HandleSpecialLoad(LocalVariable** variable, const String& symbol);
void LookupCapturedVariableByName(LocalVariable** variable,
const String& name);
struct DepthState {
explicit DepthState(intptr_t function)
: loop_(0),
function_(function),
try_(0),
catch_(0),
finally_(0),
for_in_(0) {}
intptr_t loop_;
intptr_t function_;
intptr_t try_;
intptr_t catch_;
intptr_t finally_;
intptr_t for_in_;
};
ScopeBuildingResult* result_;
ParsedFunction* parsed_function_;
ActiveClass active_class_;
TranslationHelper translation_helper_;
Zone* zone_;
FunctionNodeHelper::AsyncMarker current_function_async_marker_;
LocalScope* current_function_scope_;
LocalScope* scope_;
DepthState depth_;
intptr_t name_index_;
bool needs_expr_temp_;
TokenPosition first_body_token_position_ = TokenPosition::kNoSource;
KernelReaderHelper helper_;
ConstantReader constant_reader_;
InferredTypeMetadataHelper inferred_type_metadata_helper_;
ProcedureAttributesMetadataHelper procedure_attributes_metadata_helper_;
TypeTranslator type_translator_;
DISALLOW_COPY_AND_ASSIGN(ScopeBuilder);
};
struct FunctionScope {
intptr_t kernel_offset;
LocalScope* scope;
};
class ScopeBuildingResult : public ZoneAllocated {
public:
ScopeBuildingResult()
: type_arguments_variable(NULL),
switch_variable(NULL),
finally_return_variable(NULL),
setter_value(NULL),
yield_jump_variable(NULL),
yield_context_variable(NULL),
raw_variable_counter_(0) {}
IntMap<LocalVariable*> locals;
IntMap<LocalScope*> scopes;
GrowableArray<FunctionScope> function_scopes;
// Only non-NULL for factory constructor functions.
LocalVariable* type_arguments_variable;
// Non-NULL when the function contains a switch statement.
LocalVariable* switch_variable;
// Non-NULL when the function contains a return inside a finally block.
LocalVariable* finally_return_variable;
// Non-NULL when the function is a setter.
LocalVariable* setter_value;
// Non-NULL 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-NULL 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;
GrowableArray<LocalVariable*> stack_trace_variables;
GrowableArray<LocalVariable*> catch_context_variables;
// These are used to access the raw exception/stacktrace variables (and are
// used to put them into the captured variables in the context).
GrowableArray<LocalVariable*> raw_exception_variables;
GrowableArray<LocalVariable*> raw_stack_trace_variables;
intptr_t raw_variable_counter_;
// For-in iterators, one per for-in nesting level.
GrowableArray<LocalVariable*> iterator_variables;
private:
DISALLOW_COPY_AND_ASSIGN(ScopeBuildingResult);
};
} // namespace kernel
} // namespace dart
#endif // RUNTIME_VM_COMPILER_FRONTEND_SCOPE_BUILDER_H_