// Copyright (c) 2012, 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_PARSER_H_ #define RUNTIME_VM_PARSER_H_ #include "include/dart_api.h" #include "lib/invocation_mirror.h" #include "platform/assert.h" #include "platform/globals.h" #include "vm/allocation.h" #include "vm/class_finalizer.h" #include "vm/hash_table.h" #include "vm/kernel.h" #include "vm/object.h" #include "vm/raw_object.h" #include "vm/scopes.h" #include "vm/token.h" namespace dart { // Forward declarations. namespace kernel { class ScopeBuildingResult; } // namespace kernel class ArgumentsDescriptor; class BitVector; class Isolate; class LocalScope; class LocalVariable; struct RegExpCompileData; template class GrowableArray; class Parser; class FieldKeyValueTrait { public: // Typedefs needed for the DirectChainedHashMap template. typedef const Field* Key; typedef const Field* Value; typedef const Field* Pair; static Key KeyOf(Pair kv) { return kv; } static Value ValueOf(Pair kv) { return kv; } static inline uword Hash(Key key) { const TokenPosition token_pos = key->token_pos(); if (token_pos.IsReal()) { return token_pos.Hash(); } return key->kernel_offset(); } static inline bool IsKeyEqual(Pair pair, Key key) { return pair->Original() == key->Original(); } }; typedef DirectChainedHashMap FieldSet; // The class ParsedFunction holds the result of parsing a function. class ParsedFunction : public ZoneObject { public: ParsedFunction(Thread* thread, const Function& function); const Function& function() const { return function_; } LocalScope* scope() const { return scope_; } void set_scope(LocalScope* scope) { ASSERT(scope_ == nullptr); ASSERT(scope != nullptr); scope_ = scope; } RegExpCompileData* regexp_compile_data() const { return regexp_compile_data_; } void SetRegExpCompileData(RegExpCompileData* regexp_compile_data); LocalVariable* function_type_arguments() const { return function_type_arguments_; } void set_function_type_arguments(LocalVariable* function_type_arguments) { ASSERT(function_type_arguments != nullptr); function_type_arguments_ = function_type_arguments; } LocalVariable* parent_type_arguments() const { return parent_type_arguments_; } void set_parent_type_arguments(LocalVariable* parent_type_arguments) { ASSERT(parent_type_arguments != nullptr); parent_type_arguments_ = parent_type_arguments; } LocalVariable* suspend_state_var() const { return suspend_state_var_; } void set_suspend_state_var(LocalVariable* suspend_state_var) { ASSERT(suspend_state_var != nullptr); suspend_state_var_ = suspend_state_var; } void set_default_parameter_values(ZoneGrowableArray* list) { default_parameter_values_ = list; #if defined(DEBUG) if (list == nullptr) return; for (intptr_t i = 0; i < list->length(); i++) { DEBUG_ASSERT(list->At(i)->IsNotTemporaryScopedHandle()); } #endif } const Instance& DefaultParameterValueAt(intptr_t i) const { ASSERT(default_parameter_values_ != nullptr); return *default_parameter_values_->At(i); } ZoneGrowableArray* default_parameter_values() const { return default_parameter_values_; } LocalVariable* current_context_var() const { return current_context_var_; } bool has_arg_desc_var() const { return arg_desc_var_ != nullptr; } LocalVariable* arg_desc_var() const { return arg_desc_var_; } LocalVariable* receiver_var() const { ASSERT(receiver_var_ != nullptr); return receiver_var_; } void set_receiver_var(LocalVariable* value) { ASSERT(receiver_var_ == nullptr); ASSERT(value != nullptr); receiver_var_ = value; } bool has_receiver_var() const { return receiver_var_ != nullptr; } void set_receiver_used() { receiver_used_ = true; } bool is_receiver_used() const { ASSERT(kernel_scopes_ != nullptr); ASSERT(!receiver_used_ || receiver_var() != nullptr); return receiver_used_; } LocalVariable* expression_temp_var() const { ASSERT(has_expression_temp_var()); return expression_temp_var_; } void set_expression_temp_var(LocalVariable* value) { ASSERT(!has_expression_temp_var()); expression_temp_var_ = value; } bool has_expression_temp_var() const { return expression_temp_var_ != nullptr; } LocalVariable* entry_points_temp_var() const { ASSERT(has_entry_points_temp_var()); return entry_points_temp_var_; } void set_entry_points_temp_var(LocalVariable* value) { ASSERT(!has_entry_points_temp_var()); entry_points_temp_var_ = value; } bool has_entry_points_temp_var() const { return entry_points_temp_var_ != nullptr; } LocalVariable* EnsureExpressionTemp(); LocalVariable* EnsureEntryPointsTemp(); const FieldSet* guarded_fields() const { return &guarded_fields_; } VariableIndex first_parameter_index() const { return first_parameter_index_; } int num_stack_locals() const { return num_stack_locals_; } void AllocateVariables(); void record_await() { have_seen_await_expr_ = true; } bool have_seen_await() const { return have_seen_await_expr_; } bool is_forwarding_stub() const { return forwarding_stub_super_target_ != nullptr; } const Function* forwarding_stub_super_target() const { return forwarding_stub_super_target_; } void MarkForwardingStub(const Function* forwarding_target) { forwarding_stub_super_target_ = forwarding_target; } Thread* thread() const { return thread_; } Isolate* isolate() const { return thread_->isolate(); } Zone* zone() const { return thread_->zone(); } // Adds only relevant fields: field must be unique and its guarded_cid() // relevant. void AddToGuardedFields(const Field* field) const; void Bailout(const char* origin, const char* reason) const; kernel::ScopeBuildingResult* EnsureKernelScopes(); LocalVariable* RawTypeArgumentsVariable() const { return raw_type_arguments_var_; } void SetRawTypeArgumentsVariable(LocalVariable* raw_type_arguments_var) { raw_type_arguments_var_ = raw_type_arguments_var; } void SetRawParameters(ZoneGrowableArray* raw_parameters) { raw_parameters_ = raw_parameters; } LocalVariable* RawParameterVariable(intptr_t i) const { return raw_parameters_->At(i); } LocalVariable* ParameterVariable(intptr_t i) const { ASSERT((i >= 0) && (i < function_.NumParameters())); ASSERT(scope() != nullptr); return scope()->VariableAt(i); } // Remembers the set of covariant parameters. // [covariant_parameters] is a bitvector of function.NumParameters() length. void SetCovariantParameters(const BitVector* covariant_parameters); // Remembers the set of generic-covariant-impl parameters. // [covariant_parameters] is a bitvector of function.NumParameters() length. void SetGenericCovariantImplParameters( const BitVector* generic_covariant_impl_parameters); // Returns true if i-th parameter is covariant. // SetCovariantParameters should be called before using this method. bool IsCovariantParameter(intptr_t i) const; // Returns true if i-th parameter is generic-covariant-impl. // SetGenericCovariantImplParameters should be called before using this // method. bool IsGenericCovariantImplParameter(intptr_t i) const; // Variables needed for the InvokeFieldDispatcher for dynamic closure calls, // because they are both read and written to by the builders. struct DynamicClosureCallVars : ZoneObject { DynamicClosureCallVars(Zone* zone, intptr_t num_named) : named_argument_parameter_indices(zone, num_named) {} #define FOR_EACH_DYNAMIC_CLOSURE_CALL_VARIABLE(V) \ V(current_function, Function, CurrentFunction) \ V(current_num_processed, Smi, CurrentNumProcessed) \ V(current_param_index, Smi, CurrentParamIndex) \ V(current_type_param, Dynamic, CurrentTypeParam) \ V(function_type_args, Dynamic, FunctionTypeArgs) \ V(instantiator_type_args, Dynamic, InstantiatorTypeArgs) \ V(parent_function_type_args, Dynamic, ParentFunctionTypeArgs) \ V(delayed_type_args, Dynamic, DelayedTypeArgs) #define DEFINE_FIELD(Name, _, __) LocalVariable* Name = nullptr; FOR_EACH_DYNAMIC_CLOSURE_CALL_VARIABLE(DEFINE_FIELD) #undef DEFINE_FIELD // An array of local variables, one for each named parameter in the // saved arguments descriptor. ZoneGrowableArray named_argument_parameter_indices; }; DynamicClosureCallVars* dynamic_closure_call_vars() const { return dynamic_closure_call_vars_; } DynamicClosureCallVars* EnsureDynamicClosureCallVars(); private: Thread* thread_; const Function& function_; LocalScope* scope_; RegExpCompileData* regexp_compile_data_; LocalVariable* function_type_arguments_; LocalVariable* parent_type_arguments_; LocalVariable* suspend_state_var_ = nullptr; LocalVariable* current_context_var_; LocalVariable* arg_desc_var_; LocalVariable* receiver_var_ = nullptr; LocalVariable* expression_temp_var_; LocalVariable* entry_points_temp_var_; DynamicClosureCallVars* dynamic_closure_call_vars_; mutable FieldSet guarded_fields_; ZoneGrowableArray* default_parameter_values_; bool receiver_used_ = false; LocalVariable* raw_type_arguments_var_; ZoneGrowableArray* raw_parameters_ = nullptr; VariableIndex first_parameter_index_; int num_stack_locals_; bool have_seen_await_expr_; const Function* forwarding_stub_super_target_ = nullptr; kernel::ScopeBuildingResult* kernel_scopes_; const BitVector* generic_covariant_impl_parameters_ = nullptr; friend class Parser; DISALLOW_COPY_AND_ASSIGN(ParsedFunction); }; class Parser : public ValueObject { public: // Parse a function to retrieve parameter information that is not retained in // the Function object. Returns either an error if the parse fails (which // could be the case for local functions), or a flat array of entries for each // parameter. Each parameter entry contains: * a Dart bool indicating whether // the parameter was declared final * its default value (or null if none was // declared) * an array of metadata (or null if no metadata was declared). enum { kParameterIsFinalOffset, kParameterDefaultValueOffset, kParameterMetadataOffset, kParameterEntrySize, }; private: DISALLOW_COPY_AND_ASSIGN(Parser); }; } // namespace dart #endif // RUNTIME_VM_PARSER_H_