| // 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_NATIVE_ENTRY_H_ | |
| #define RUNTIME_VM_NATIVE_ENTRY_H_ | |
| #include "vm/allocation.h" | |
| #include "vm/log.h" | |
| #include "vm/native_arguments.h" | |
| #include "vm/native_function.h" | |
| namespace dart { | |
| // Forward declarations. | |
| class Class; | |
| class String; | |
| #ifdef DEBUG | |
| #define TRACE_NATIVE_CALL(format, name) \ | |
| if (FLAG_trace_natives) { \ | |
| THR_Print("Calling native: " format "\n", name); \ | |
| } | |
| #else | |
| #define TRACE_NATIVE_CALL(format, name) \ | |
| do { \ | |
| } while (0) | |
| #endif | |
| typedef ObjectPtr (*BootstrapNativeFunction)(Thread* thread, | |
| Zone* zone, | |
| NativeArguments* arguments); | |
| #define DEFINE_NATIVE_ENTRY(name, type_argument_count, argument_count) \ | |
| static ObjectPtr DN_Helper##name(Isolate* isolate, Thread* thread, \ | |
| Zone* zone, NativeArguments* arguments); \ | |
| ObjectPtr BootstrapNatives::DN_##name(Thread* thread, Zone* zone, \ | |
| NativeArguments* arguments) { \ | |
| TRACE_NATIVE_CALL("%s", "" #name); \ | |
| ASSERT(arguments->NativeArgCount() == argument_count); \ | |
| /* Note: a longer type arguments vector may be passed */ \ | |
| ASSERT(arguments->NativeTypeArgCount() >= type_argument_count); \ | |
| return DN_Helper##name(thread->isolate(), thread, zone, arguments); \ | |
| } \ | |
| static ObjectPtr DN_Helper##name(Isolate* isolate, Thread* thread, \ | |
| Zone* zone, NativeArguments* arguments) | |
| #define DEFINE_FFI_NATIVE_ENTRY(name, return_type, argument_types) \ | |
| return_type BootstrapNatives::FN_##name argument_types | |
| // Helpers that throw an argument exception. | |
| void DartNativeThrowTypeArgumentCountException(int num_type_args, | |
| int num_type_args_expected); | |
| void DartNativeThrowArgumentException(const Instance& instance); | |
| // Native should throw an exception if the wrong number of type arguments is | |
| // passed. | |
| #define NATIVE_TYPE_ARGUMENT_COUNT(expected) \ | |
| int __num_type_arguments = arguments->NativeTypeArgCount(); \ | |
| if (__num_type_arguments != expected) { \ | |
| DartNativeThrowTypeArgumentCountException(__num_type_arguments, expected); \ | |
| } | |
| #define GET_NATIVE_TYPE_ARGUMENT(name, value) \ | |
| AbstractType& name = AbstractType::Handle(value); | |
| // Natives should throw an exception if an illegal argument or null is passed. | |
| // type name = value. | |
| #define GET_NON_NULL_NATIVE_ARGUMENT(type, name, value) \ | |
| const Instance& __##name##_instance__ = \ | |
| Instance::CheckedHandle(zone, value); \ | |
| if (!__##name##_instance__.Is##type()) { \ | |
| DartNativeThrowArgumentException(__##name##_instance__); \ | |
| } \ | |
| const type& name = type::Cast(__##name##_instance__); | |
| // Natives should throw an exception if an illegal argument is passed. | |
| // type name = value. | |
| #define GET_NATIVE_ARGUMENT(type, name, value) \ | |
| const Instance& __##name##_instance__ = \ | |
| Instance::CheckedHandle(zone, value); \ | |
| type& name = type::Handle(zone); \ | |
| if (!__##name##_instance__.IsNull()) { \ | |
| if (!__##name##_instance__.Is##type()) { \ | |
| DartNativeThrowArgumentException(__##name##_instance__); \ | |
| } \ | |
| } \ | |
| name ^= value; | |
| // Helper class for resolving and handling native functions. | |
| class NativeEntry : public AllStatic { | |
| public: | |
| static constexpr intptr_t kNumArguments = 1; | |
| static constexpr intptr_t kNumCallWrapperArguments = 2; | |
| // Resolve specified dart native function to the actual native entrypoint. | |
| static NativeFunction ResolveNative(const Library& library, | |
| const String& function_name, | |
| int number_of_arguments, | |
| bool* auto_setup_scope); | |
| static const uint8_t* ResolveSymbolInLibrary(const Library& library, | |
| uword pc); | |
| static const uint8_t* ResolveSymbol(uword pc); | |
| static uword BootstrapNativeCallWrapperEntry(); | |
| static void BootstrapNativeCallWrapper(Dart_NativeArguments args, | |
| Dart_NativeFunction func); | |
| static uword NoScopeNativeCallWrapperEntry(); | |
| static void NoScopeNativeCallWrapper(Dart_NativeArguments args, | |
| Dart_NativeFunction func); | |
| static uword AutoScopeNativeCallWrapperEntry(); | |
| static void AutoScopeNativeCallWrapper(Dart_NativeArguments args, | |
| Dart_NativeFunction func); | |
| static uword LinkNativeCallEntry(); | |
| static void LinkNativeCall(Dart_NativeArguments args); | |
| private: | |
| static void MaybePropagateError(NativeArguments* arguments); | |
| }; | |
| #if !defined(DART_PRECOMPILED_RUNTIME) | |
| class NativeEntryData : public ValueObject { | |
| public: | |
| explicit NativeEntryData(const TypedData& data) : data_(data) {} | |
| MethodRecognizer::Kind kind() const; | |
| void set_kind(MethodRecognizer::Kind value) const; | |
| static MethodRecognizer::Kind GetKind(TypedDataPtr data); | |
| NativeFunctionWrapper trampoline() const; | |
| void set_trampoline(NativeFunctionWrapper value) const; | |
| static NativeFunctionWrapper GetTrampoline(TypedDataPtr data); | |
| NativeFunction native_function() const; | |
| void set_native_function(NativeFunction value) const; | |
| static NativeFunction GetNativeFunction(TypedDataPtr data); | |
| intptr_t argc_tag() const; | |
| void set_argc_tag(intptr_t value) const; | |
| static intptr_t GetArgcTag(TypedDataPtr data); | |
| static TypedDataPtr New(MethodRecognizer::Kind kind, | |
| NativeFunctionWrapper trampoline, | |
| NativeFunction native_function, | |
| intptr_t argc_tag); | |
| private: | |
| struct Payload { | |
| NativeFunctionWrapper trampoline; | |
| NativeFunction native_function; | |
| intptr_t argc_tag; | |
| MethodRecognizer::Kind kind; | |
| }; | |
| static Payload* FromTypedArray(TypedDataPtr data); | |
| const TypedData& data_; | |
| friend class ObjectPoolSerializationCluster; | |
| DISALLOW_COPY_AND_ASSIGN(NativeEntryData); | |
| }; | |
| #endif // !defined(DART_PRECOMPILED_RUNTIME) | |
| } // namespace dart | |
| #endif // RUNTIME_VM_NATIVE_ENTRY_H_ |