b1a3629547
This refactoring moves receiver variable (previously known as this_variable) from ScopeBuildingResult into ParsedFunction, like other special variables. This is done as ScopeBuildingResult is AST-specific and not available in bytecode, but certain flow graph builders use receiver variable (for example to load instantiator type arguments for type arguments checks). This CL also introduces convenience ParsedFunction::ParameterVariable() method to reduce repetitive incantations parsed_function->node_sequence()->scope()->VariableAt(..) to a more readable parsed_function->ParameterVariable(..) Change-Id: I427536abfa412de9916b79cf2e56e06f2f2f1d71 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/96842 Commit-Queue: Alexander Markov <alexmarkov@google.com> Auto-Submit: Alexander Markov <alexmarkov@google.com> Reviewed-by: Aart Bik <ajcbik@google.com>
239 lines
7.6 KiB
C++
239 lines
7.6 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)
|
|
|
|
#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 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,
|
|
};
|
|
|
|
// 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.
|
|
void 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_;
|
|
|
|
KernelReaderHelper helper_;
|
|
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);
|
|
};
|
|
|
|
// Returns true if the given method can skip type checks for all arguments
|
|
// that are not covariant or generic covariant in its implementation.
|
|
bool MethodCanSkipTypeChecksForNonCovariantArguments(
|
|
const Function& method,
|
|
const ProcedureAttributesMetadata& attrs);
|
|
|
|
} // namespace kernel
|
|
} // namespace dart
|
|
|
|
#endif // !defined(DART_PRECOMPILED_RUNTIME)
|
|
#endif // RUNTIME_VM_COMPILER_FRONTEND_SCOPE_BUILDER_H_
|