| // Copyright (c) 2011, 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_DART_ENTRY_H_ | |
| #define RUNTIME_VM_DART_ENTRY_H_ | |
| #include "vm/allocation.h" | |
| #include "vm/growable_array.h" | |
| #include "vm/object.h" | |
| #include "vm/raw_object.h" | |
| namespace dart { | |
| // Forward declarations. | |
| class Array; | |
| class Closure; | |
| class FlowGraphDeserializer; | |
| class FlowGraphSerializer; | |
| class Function; | |
| class Instance; | |
| class Integer; | |
| class Library; | |
| class Object; | |
| class String; | |
| // An arguments descriptor array consists of the type argument vector length (0 | |
| // if none); total argument count (not counting type argument vector); total | |
| // arguments size (not counting type argument vector); the positional argument | |
| // count; a sequence of (name, position) pairs, sorted by name, for each named | |
| // optional argument; and a terminating null to simplify iterating in generated | |
| // code. | |
| class ArgumentsDescriptor : public ValueObject { | |
| public: | |
| explicit ArgumentsDescriptor(const Array& array); | |
| // Accessors. | |
| intptr_t TypeArgsLen() const; // 0 if no type argument vector is passed. | |
| intptr_t FirstArgIndex() const { return TypeArgsLen() > 0 ? 1 : 0; } | |
| intptr_t CountWithTypeArgs() const { return FirstArgIndex() + Count(); } | |
| intptr_t Count() const; // Excluding type arguments vector. | |
| intptr_t Size() const; // Excluding type arguments vector. | |
| intptr_t SizeWithTypeArgs() const { return FirstArgIndex() + Size(); } | |
| intptr_t PositionalCount() const; // Excluding type arguments vector. | |
| intptr_t NamedCount() const { return Count() - PositionalCount(); } | |
| StringPtr NameAt(intptr_t i) const; | |
| intptr_t PositionAt(intptr_t i) const; | |
| // Returns array of argument names in the arguments order. | |
| ArrayPtr GetArgumentNames() const; | |
| void PrintTo(BaseTextBuffer* buffer, bool show_named_positions = false) const; | |
| const char* ToCString() const; | |
| // Generated code support. | |
| static intptr_t type_args_len_offset() { | |
| return Array::element_offset(kTypeArgsLenIndex); | |
| } | |
| static intptr_t count_offset() { return Array::element_offset(kCountIndex); } | |
| static intptr_t size_offset() { return Array::element_offset(kSizeIndex); } | |
| static intptr_t positional_count_offset() { | |
| return Array::element_offset(kPositionalCountIndex); | |
| } | |
| static intptr_t first_named_entry_offset() { | |
| return Array::element_offset(kFirstNamedEntryIndex); | |
| } | |
| static intptr_t name_offset() { return kNameOffset * kCompressedWordSize; } | |
| static intptr_t position_offset() { | |
| return kPositionOffset * kCompressedWordSize; | |
| } | |
| static intptr_t named_entry_size() { | |
| return kNamedEntrySize * kCompressedWordSize; | |
| } | |
| // Constructs an argument descriptor where all arguments are boxed and | |
| // therefore number of parameters equals parameter size. | |
| // | |
| // Right now this is for example the case for all closure functions. | |
| // Functions marked as entry-points may also be created by NewUnboxed because | |
| // we rely that TFA will mark the arguments as nullable for such cases. | |
| static ArrayPtr NewBoxed(intptr_t type_args_len, | |
| intptr_t num_arguments, | |
| const Array& optional_arguments_names, | |
| Heap::Space space = Heap::kOld) { | |
| return New(type_args_len, num_arguments, num_arguments, | |
| optional_arguments_names, space); | |
| } | |
| // Allocate and return an arguments descriptor. The first | |
| // (num_arguments - optional_arguments_names.Length()) arguments are | |
| // positional and the remaining ones are named optional arguments. | |
| // The presence of a type argument vector as first argument (not counted in | |
| // num_arguments) is indicated by a non-zero type_args_len. | |
| static ArrayPtr New(intptr_t type_args_len, | |
| intptr_t num_arguments, | |
| intptr_t size_arguments, | |
| const Array& optional_arguments_names, | |
| Heap::Space space = Heap::kOld); | |
| // Constructs an argument descriptor where all arguments are boxed and | |
| // therefore number of parameters equals parameter size. | |
| // | |
| // Right now this is for example the case for all closure functions. | |
| static ArrayPtr NewBoxed(intptr_t type_args_len, | |
| intptr_t num_arguments, | |
| Heap::Space space = Heap::kOld) { | |
| return New(type_args_len, num_arguments, num_arguments, space); | |
| } | |
| // Allocate and return an arguments descriptor that has no optional | |
| // arguments. All arguments are positional. The presence of a type argument | |
| // vector as first argument (not counted in num_arguments) is indicated | |
| // by a non-zero type_args_len. | |
| static ArrayPtr New(intptr_t type_args_len, | |
| intptr_t num_arguments, | |
| intptr_t size_arguments, | |
| Heap::Space space = Heap::kOld); | |
| // Initialize the preallocated fixed length arguments descriptors cache. | |
| static void Init(); | |
| // Clear the preallocated fixed length arguments descriptors cache. | |
| static void Cleanup(); | |
| static constexpr intptr_t kMaxTypeArgsForCachedDescriptor = 1; | |
| static constexpr intptr_t | |
| kMaxNumArgumentsForCachedDescriptor[kMaxTypeArgsForCachedDescriptor + 1] = | |
| {31, 2}; | |
| static constexpr intptr_t kCachedDescriptorCount = []() -> intptr_t { | |
| intptr_t result = 0; | |
| for (intptr_t i = 0; i <= kMaxTypeArgsForCachedDescriptor; ++i) { | |
| result += kMaxNumArgumentsForCachedDescriptor[i] + 1; | |
| } | |
| return result; | |
| }(); | |
| // For creating ArgumentDescriptor Slots. | |
| static constexpr bool ContainsCompressedPointers() { | |
| // Use the same state as the backing store. | |
| return Array::ContainsCompressedPointers(); | |
| } | |
| void Write(FlowGraphSerializer* s) const; | |
| static ArrayPtr Read(FlowGraphDeserializer* d); | |
| private: | |
| // Absolute indices into the array. | |
| // Keep these in sync with the constants in invocation_mirror_patch.dart. | |
| enum { | |
| kTypeArgsLenIndex, | |
| kCountIndex, | |
| kSizeIndex, | |
| kPositionalCountIndex, | |
| kFirstNamedEntryIndex, | |
| }; | |
| private: | |
| // Relative indexes into each named argument entry. | |
| enum { | |
| kNameOffset, | |
| // The least significant bit of the entry in 'kPositionOffset' (second | |
| // least-significant after Smi-encoding) holds the strong-mode checking bit | |
| // for the named argument. | |
| kPositionOffset, | |
| kNamedEntrySize, | |
| }; | |
| static intptr_t LengthFor(intptr_t num_named_arguments) { | |
| // Add 1 for the terminating null. | |
| return kFirstNamedEntryIndex + (kNamedEntrySize * num_named_arguments) + 1; | |
| } | |
| static ArrayPtr NewNonCached(intptr_t type_args_len, | |
| intptr_t num_arguments, | |
| intptr_t size_arguments, | |
| bool canonicalize, | |
| Heap::Space space); | |
| // Used by Simulator to parse argument descriptors. | |
| static intptr_t name_index(intptr_t index) { | |
| return kFirstNamedEntryIndex + (index * kNamedEntrySize) + kNameOffset; | |
| } | |
| static intptr_t position_index(intptr_t index) { | |
| return kFirstNamedEntryIndex + (index * kNamedEntrySize) + kPositionOffset; | |
| } | |
| bool IsCached() const; | |
| static intptr_t CacheIndexFor(intptr_t type_args_len, intptr_t num_arguments); | |
| static bool CanUseCachedDescriptor(intptr_t type_args_len, | |
| intptr_t num_arguments); | |
| const Array& array_; | |
| friend class Interpreter; | |
| friend class InterpreterHelpers; | |
| friend class VMSerializationRoots; | |
| friend class VMDeserializationRoots; | |
| DISALLOW_COPY_AND_ASSIGN(ArgumentsDescriptor); | |
| }; | |
| // DartEntry abstracts functionality needed to resolve dart functions | |
| // and invoke them from C++. | |
| class DartEntry : public AllStatic { | |
| public: | |
| // Invokes the specified instance function or static function. | |
| // The first argument of an instance function is the receiver. | |
| // On success, returns an InstancePtr. On failure, an ErrorPtr. | |
| // This is used when there is no type argument vector and | |
| // no named arguments in the call. | |
| static ObjectPtr InvokeFunction(const Function& function, | |
| const Array& arguments); | |
| #if defined(TESTING) | |
| // Invokes the specified code as if it was a Dart function. | |
| // On success, returns an InstancePtr. On failure, an ErrorPtr. | |
| static ObjectPtr InvokeCode(const Code& code, | |
| const Array& arguments_descriptor, | |
| const Array& arguments, | |
| Thread* thread); | |
| #endif | |
| // Invokes the specified instance, static, or closure function. | |
| // On success, returns an InstancePtr. On failure, an ErrorPtr. | |
| static ObjectPtr InvokeFunction(const Function& function, | |
| const Array& arguments, | |
| const Array& arguments_descriptor); | |
| // Invokes the first argument in the provided arguments array as a callable | |
| // object, performing any needed dynamic checks if the callable cannot receive | |
| // dynamic invocation. | |
| // | |
| // On success, returns an InstancePtr. On failure, an ErrorPtr. | |
| // | |
| // Used when an ArgumentsDescriptor is not required, that is, when there | |
| // are no type arguments or named arguments. | |
| static ObjectPtr InvokeClosure(Thread* thread, const Array& arguments); | |
| // Invokes the first argument in the provided arguments array as a callable | |
| // object, performing any needed dynamic checks if the callable cannot receive | |
| // dynamic invocation. | |
| // | |
| // On success, returns an InstancePtr. On failure, an ErrorPtr. | |
| static ObjectPtr InvokeClosure(Thread* thread, | |
| const Array& arguments, | |
| const Array& arguments_descriptor); | |
| // Invokes the noSuchMethod instance function on the receiver. | |
| // On success, returns an InstancePtr. On failure, an ErrorPtr. | |
| static ObjectPtr InvokeNoSuchMethod(Thread* thread, | |
| const Instance& receiver, | |
| const String& target_name, | |
| const Array& arguments, | |
| const Array& arguments_descriptor); | |
| private: | |
| // Resolves the first argument in the provided arguments array to a callable | |
| // compatible with the arguments. Helper method used within InvokeClosure. | |
| // | |
| // If no errors occur, the first argument is changed to be either the resolved | |
| // callable or, if Function::null() is returned, an appropriate target for | |
| // invoking noSuchMethod. | |
| // | |
| // On success, returns a FunctionPtr. On failure, an ErrorPtr. | |
| static ObjectPtr ResolveCallable(Thread* thread, | |
| const Array& arguments, | |
| const Array& arguments_descriptor); | |
| // Invokes a function returned by ResolveCallable, performing any dynamic | |
| // checks needed if the function cannot receive dynamic invocation. Helper | |
| // method used within InvokeClosure. | |
| // | |
| // On success, returns an InstancePtr. On failure, an ErrorPtr. | |
| static ObjectPtr InvokeCallable(Thread* thread, | |
| const Function& callable_function, | |
| const Array& arguments, | |
| const Array& arguments_descriptor); | |
| }; | |
| // Utility functions to call from VM into Dart bootstrap libraries. | |
| // Each may return an exception object. | |
| class DartLibraryCalls : public AllStatic { | |
| public: | |
| // On success, returns an InstancePtr. On failure, an ErrorPtr. | |
| static ObjectPtr InstanceCreate(const Library& library, | |
| const String& exception_name, | |
| const String& constructor_name, | |
| const Array& arguments); | |
| // On success, returns an InstancePtr. On failure, an ErrorPtr. | |
| static ObjectPtr ToString(const Instance& receiver); | |
| // On success, returns an InstancePtr. On failure, an ErrorPtr. | |
| static ObjectPtr HashCode(const Instance& receiver); | |
| // On success, returns an InstancePtr. On failure, an ErrorPtr. | |
| static ObjectPtr Equals(const Instance& left, const Instance& right); | |
| // Returns the handler if one has been registered for this port id. | |
| static ObjectPtr LookupHandler(Dart_Port port_id); | |
| // Returns handler on success, an ErrorPtr on failure, null if can't find | |
| // handler for this port id. | |
| static ObjectPtr HandleMessage(Dart_Port port_id, const Instance& message); | |
| // Invokes the finalizer to run its callbacks. | |
| static ObjectPtr HandleFinalizerMessage(const FinalizerBase& finalizer); | |
| // Returns a list of open ReceivePorts. | |
| static ObjectPtr LookupOpenPorts(); | |
| // Returns null on success, an ErrorPtr on failure. | |
| // | |
| // On an error, the caller should continue to drain the microtask | |
| // queue after processing the error. | |
| static ObjectPtr DrainMicrotaskQueue(); | |
| // Runs the `_rehashObjects()` function in `dart:compact_hash`. | |
| static ObjectPtr RehashObjectsInDartCompactHash( | |
| Thread* thread, | |
| const Object& array_or_growable_array); | |
| // Runs the `_rehashObjects()` function in `dart:core`. | |
| static ObjectPtr RehashObjectsInDartCore( | |
| Thread* thread, | |
| const Object& array_or_growable_array); | |
| }; | |
| } // namespace dart | |
| #endif // RUNTIME_VM_DART_ENTRY_H_ |