a04691a8a8
This adds serialization of the new local variables, VariableStatement and VariableDeclaration. This prepares for replacing LegacyVariable with the new variables in all backends. TEST=existing Change-Id: I9bbebfbfd372042d6b7027f0fabd24c165699832 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/506240 Reviewed-by: Martin Kustermann <kustermann@google.com> Reviewed-by: Jens Johansen <jensj@google.com> Commit-Queue: Johnni Winther <johnniwinther@google.com>
238 lines
7.4 KiB
C++
238 lines
7.4 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 VisitListOfExpressions();
|
|
void VisitListOfNamedExpressions();
|
|
void VisitArguments();
|
|
void VisitVariableDeclaration();
|
|
void VisitVariable();
|
|
void VisitVariableGet(intptr_t declaration_binary_offset);
|
|
void VisitDartType();
|
|
void VisitInterfaceType(bool simple);
|
|
void VisitFunctionType(bool simple);
|
|
void VisitRecordType();
|
|
void VisitTypeParameterType();
|
|
void VisitIntersectionType();
|
|
void VisitExtensionType();
|
|
void VisitFutureOrType();
|
|
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 requiring 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. Variable).
|
|
void AddParameter(intptr_t pos,
|
|
ParameterTypeCheckMode type_check_mode,
|
|
const ProcedureAttributesMetadata& attrs);
|
|
|
|
LocalVariable* MakeVariable(
|
|
TokenPosition declaration_pos,
|
|
TokenPosition token_pos,
|
|
const String& name,
|
|
const AbstractType& type,
|
|
intptr_t kernel_offset = LocalVariable::kNoKernelOffset,
|
|
bool is_late = false,
|
|
const InferredTypeMetadata* inferred_type_md = nullptr,
|
|
const InferredTypeMetadata* inferred_arg_type_md = nullptr);
|
|
|
|
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 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);
|
|
|
|
const String& GenerateName(const char* prefix, intptr_t suffix);
|
|
|
|
void HandleLoadReceiver();
|
|
void HandleSpecialLoad(LocalVariable** variable,
|
|
const String& symbol,
|
|
intptr_t kernel_offset);
|
|
|
|
ScriptPtr Script() { return active_class_.ActiveScript(); }
|
|
|
|
struct DepthState {
|
|
explicit DepthState(intptr_t function)
|
|
: 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_;
|
|
};
|
|
|
|
ScopeBuildingResult* result_;
|
|
ParsedFunction* parsed_function_;
|
|
|
|
ActiveClass active_class_;
|
|
|
|
TranslationHelper translation_helper_;
|
|
Zone* zone_;
|
|
|
|
LocalScope* current_function_scope_;
|
|
LocalScope* scope_;
|
|
DepthState depth_;
|
|
|
|
bool needs_expr_temp_;
|
|
TokenPosition first_body_token_position_ = TokenPosition::kNoSource;
|
|
|
|
KernelReaderHelper helper_;
|
|
ConstantReader constant_reader_;
|
|
TypeTranslator type_translator_;
|
|
InferredTypeMetadataHelper inferred_type_metadata_helper_;
|
|
InferredTypeMetadataHelper inferred_arg_type_metadata_helper_;
|
|
ProcedureAttributesMetadataHelper procedure_attributes_metadata_helper_;
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(ScopeBuilder);
|
|
};
|
|
|
|
struct FunctionScope {
|
|
intptr_t kernel_offset;
|
|
LocalScope* scope;
|
|
};
|
|
|
|
class ScopeBuildingResult : public ZoneObject {
|
|
public:
|
|
ScopeBuildingResult()
|
|
: switch_variable(nullptr),
|
|
finally_return_variable(nullptr),
|
|
setter_value(nullptr),
|
|
raw_variable_counter_(0) {}
|
|
|
|
bool IsClosureWithEmptyContext(intptr_t function_node_offset) {
|
|
for (intptr_t i = 0; i < closure_offsets_without_captures.length(); ++i) {
|
|
if (closure_offsets_without_captures[i] == function_node_offset) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
IntMap<LocalVariable*> locals;
|
|
IntMap<LocalScope*> scopes;
|
|
GrowableArray<FunctionScope> function_scopes;
|
|
|
|
// Non-nullptr when the function contains a switch statement.
|
|
LocalVariable* switch_variable;
|
|
|
|
// Non-nullptr when the function contains a return inside a finally block.
|
|
LocalVariable* finally_return_variable;
|
|
|
|
// Non-nullptr when the function is a setter.
|
|
LocalVariable* setter_value;
|
|
|
|
// 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_;
|
|
|
|
// Remembers closure function kernel offsets that do not capture any
|
|
// variables.
|
|
GrowableArray<intptr_t> closure_offsets_without_captures;
|
|
|
|
void PrintTo(BaseTextBuffer* f) const;
|
|
const char* ToCString() const;
|
|
|
|
private:
|
|
DISALLOW_COPY_AND_ASSIGN(ScopeBuildingResult);
|
|
};
|
|
|
|
} // namespace kernel
|
|
} // namespace dart
|
|
|
|
#endif // RUNTIME_VM_COMPILER_FRONTEND_SCOPE_BUILDER_H_
|