| // 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 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; |
| bool MatchesNameAt(intptr_t i, const String& other) 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(); |
| |
| enum { kCachedDescriptorCount = 32 }; |
| |
| // For creating ArgumentDescriptor Slots. |
| static constexpr bool ContainsCompressedPointers() { |
| // Use the same state as the backing store. |
| return Array::ContainsCompressedPointers(); |
| } |
| |
| 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, |
| }; |
| |
| public: |
| 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; |
| } |
| |
| const Array& array_; |
| |
| // A cache of VM heap allocated arguments descriptors. |
| static ArrayPtr cached_args_descriptors_[kCachedDescriptorCount]; |
| |
| friend class SnapshotReader; |
| friend class SnapshotWriter; |
| friend class Serializer; |
| friend class Deserializer; |
| friend class Simulator; |
| friend class SimulatorHelpers; |
| 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); |
| |
| // 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, |
| uword entry_point, |
| const Array& arguments_descriptor, |
| const Array& arguments, |
| Thread* thread); |
| |
| // 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, |
| uword current_sp = OSThread::GetCurrentStackPointer()); |
| |
| // 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); |
| |
| // On success, returns an InstancePtr. On failure, an ErrorPtr. |
| static ObjectPtr IdentityHashCode(const Instance& object); |
| |
| // Returns the handler if one has been registered for this port id. |
| static ObjectPtr LookupHandler(Dart_Port port_id); |
| |
| // Returns a list of open ReceivePorts. |
| static ObjectPtr LookupOpenPorts(); |
| |
| // Returns null on success, an ErrorPtr on failure. |
| static ObjectPtr HandleMessage(const Object& handler, |
| const Instance& dart_message); |
| |
| // Returns null on success, an ErrorPtr on failure. |
| static ObjectPtr DrainMicrotaskQueue(); |
| |
| // Ensures that the isolate's _pendingImmediateCallback is set to |
| // _startMicrotaskLoop from dart:async. |
| // Returns null on success, an ErrorPtr on failure. |
| static ObjectPtr EnsureScheduleImmediate(); |
| |
| // Runs the `_rehashObjects()` function. |
| static ObjectPtr RehashObjects(Thread* thread, |
| const Object& array_or_growable_array); |
| }; |
| |
| } // namespace dart |
| |
| #endif // RUNTIME_VM_DART_ENTRY_H_ |