// Copyright (c) 2020, 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_AOT_DISPATCH_TABLE_GENERATOR_H_ #define RUNTIME_VM_COMPILER_AOT_DISPATCH_TABLE_GENERATOR_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/kernel_translation_helper.h" #include "vm/object.h" namespace dart { class ClassTable; class Precompiler; class PrecompilerTracer; namespace compiler { class SelectorRow; struct TableSelector { TableSelector(int32_t _id, int32_t _call_count, int32_t _offset, bool _called_on_null, bool _torn_off) : id(_id), call_count(_call_count), offset(_offset), called_on_null(_called_on_null), torn_off(_torn_off) {} bool IsUsed() const { return call_count > 0; } // ID assigned to the selector. int32_t id; // Number of dispatch table call sites with this selector (conservative: // number may be bigger, but not smaller, than actual number of call sites). int32_t call_count; // Table offset assigned to the selector by the dispatch table generator. int32_t offset; // Are there any call sites with this selector where the receiver may be null? bool called_on_null; // Is this method ever torn off, i.e. is its method extractor accessed? bool torn_off; // Is the selector part of the interface on Null (same as Object)? bool on_null_interface = false; // Do any targets of this selector assume that an args descriptor is passed? bool requires_args_descriptor = false; }; class SelectorMap { public: explicit SelectorMap(Zone* zone) : zone_(zone) {} // Get the selector for this interface target, or null if the function does // not have a selector assigned. const TableSelector* GetSelector(const Function& interface_target) const; private: static const int32_t kInvalidSelectorId = kernel::ProcedureAttributesMetadata::kInvalidSelectorId; static const int32_t kInvalidSelectorOffset = -1; int32_t SelectorId(const Function& interface_target) const; void AddSelector(int32_t call_count, bool called_on_null, bool torn_off); void SetSelectorProperties(int32_t sid, bool on_null_interface, bool requires_args_descriptor); int32_t NumIds() const { return selectors_.length(); } friend class dart::Precompiler; friend class dart::PrecompilerTracer; friend class DispatchTableGenerator; friend class SelectorRow; Zone* zone_; GrowableArray selectors_; }; class DispatchTableGenerator { public: explicit DispatchTableGenerator(Zone* zone); SelectorMap* selector_map() { return &selector_map_; } // Find suitable selectors and compute offsets for them. void Initialize(ClassTable* table); // Build up an array of Code objects, used to serialize the information // deserialized as a DispatchTable at runtime. ArrayPtr BuildCodeArray(); private: void ReadTableSelectorInfo(); void NumberSelectors(); void SetupSelectorRows(); void ComputeSelectorOffsets(); Zone* const zone_; ClassTable* classes_; int32_t num_selectors_; int32_t num_classes_; int32_t table_size_; GrowableArray table_rows_; SelectorMap selector_map_; }; } // namespace compiler } // namespace dart #endif // RUNTIME_VM_COMPILER_AOT_DISPATCH_TABLE_GENERATOR_H_