|  | // 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 "platform/memory_sanitizer.h" | 
|  |  | 
|  | #include "vm/allocation.h" | 
|  | #include "vm/exceptions.h" | 
|  | #include "vm/heap/verifier.h" | 
|  | #include "vm/log.h" | 
|  | #include "vm/native_arguments.h" | 
|  | #include "vm/native_function.h" | 
|  | #include "vm/runtime_entry.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 NoScopeNativeCallWrapperNoStackCheck(Dart_NativeArguments args, | 
|  | Dart_NativeFunction func); | 
|  | static void AutoScopeNativeCallWrapperNoStackCheck(Dart_NativeArguments args, | 
|  | Dart_NativeFunction func); | 
|  |  | 
|  | 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_ |