1 | // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
2 | // for details. All rights reserved. Use of this source code is governed by a |
3 | // BSD-style license that can be found in the LICENSE file. |
4 | |
5 | #ifndef RUNTIME_VM_NATIVE_ENTRY_H_ |
6 | #define RUNTIME_VM_NATIVE_ENTRY_H_ |
7 | |
8 | #include "platform/memory_sanitizer.h" |
9 | |
10 | #include "vm/allocation.h" |
11 | #include "vm/exceptions.h" |
12 | #include "vm/heap/verifier.h" |
13 | #include "vm/log.h" |
14 | #include "vm/native_arguments.h" |
15 | #include "vm/native_function.h" |
16 | #include "vm/runtime_entry.h" |
17 | |
18 | |
19 | namespace dart { |
20 | |
21 | // Forward declarations. |
22 | class Class; |
23 | class String; |
24 | |
25 | #ifdef DEBUG |
26 | #define TRACE_NATIVE_CALL(format, name) \ |
27 | if (FLAG_trace_natives) { \ |
28 | THR_Print("Calling native: " format "\n", name); \ |
29 | } |
30 | #else |
31 | #define TRACE_NATIVE_CALL(format, name) \ |
32 | do { \ |
33 | } while (0) |
34 | #endif |
35 | |
36 | typedef ObjectPtr (*BootstrapNativeFunction)(Thread* thread, |
37 | Zone* zone, |
38 | NativeArguments* arguments); |
39 | |
40 | #define NATIVE_ENTRY_FUNCTION(name) BootstrapNatives::DN_##name |
41 | |
42 | #define DEFINE_NATIVE_ENTRY(name, type_argument_count, argument_count) \ |
43 | static ObjectPtr DN_Helper##name(Isolate* isolate, Thread* thread, \ |
44 | Zone* zone, NativeArguments* arguments); \ |
45 | ObjectPtr NATIVE_ENTRY_FUNCTION(name)(Thread * thread, Zone * zone, \ |
46 | NativeArguments * arguments) { \ |
47 | TRACE_NATIVE_CALL("%s", "" #name); \ |
48 | ASSERT(arguments->NativeArgCount() == argument_count); \ |
49 | /* Note: a longer type arguments vector may be passed */ \ |
50 | ASSERT(arguments->NativeTypeArgCount() >= type_argument_count); \ |
51 | return DN_Helper##name(thread->isolate(), thread, zone, arguments); \ |
52 | } \ |
53 | static ObjectPtr DN_Helper##name(Isolate* isolate, Thread* thread, \ |
54 | Zone* zone, NativeArguments* arguments) |
55 | |
56 | // Helpers that throw an argument exception. |
57 | void DartNativeThrowTypeArgumentCountException(int num_type_args, |
58 | int num_type_args_expected); |
59 | void DartNativeThrowArgumentException(const Instance& instance); |
60 | |
61 | // Native should throw an exception if the wrong number of type arguments is |
62 | // passed. |
63 | #define NATIVE_TYPE_ARGUMENT_COUNT(expected) \ |
64 | int __num_type_arguments = arguments->NativeTypeArgCount(); \ |
65 | if (__num_type_arguments != expected) { \ |
66 | DartNativeThrowTypeArgumentCountException(__num_type_arguments, expected); \ |
67 | } |
68 | |
69 | #define GET_NATIVE_TYPE_ARGUMENT(name, value) \ |
70 | AbstractType& name = AbstractType::Handle(value); |
71 | |
72 | // Natives should throw an exception if an illegal argument or null is passed. |
73 | // type name = value. |
74 | #define GET_NON_NULL_NATIVE_ARGUMENT(type, name, value) \ |
75 | const Instance& __##name##_instance__ = \ |
76 | Instance::CheckedHandle(zone, value); \ |
77 | if (!__##name##_instance__.Is##type()) { \ |
78 | DartNativeThrowArgumentException(__##name##_instance__); \ |
79 | } \ |
80 | const type& name = type::Cast(__##name##_instance__); |
81 | |
82 | // Natives should throw an exception if an illegal argument is passed. |
83 | // type name = value. |
84 | #define GET_NATIVE_ARGUMENT(type, name, value) \ |
85 | const Instance& __##name##_instance__ = \ |
86 | Instance::CheckedHandle(zone, value); \ |
87 | type& name = type::Handle(zone); \ |
88 | if (!__##name##_instance__.IsNull()) { \ |
89 | if (!__##name##_instance__.Is##type()) { \ |
90 | DartNativeThrowArgumentException(__##name##_instance__); \ |
91 | } \ |
92 | } \ |
93 | name ^= value; |
94 | |
95 | // Helper class for resolving and handling native functions. |
96 | class NativeEntry : public AllStatic { |
97 | public: |
98 | static const intptr_t kNumArguments = 1; |
99 | static const intptr_t kNumCallWrapperArguments = 2; |
100 | |
101 | // Resolve specified dart native function to the actual native entrypoint. |
102 | static NativeFunction ResolveNative(const Library& library, |
103 | const String& function_name, |
104 | int number_of_arguments, |
105 | bool* auto_setup_scope); |
106 | static const uint8_t* ResolveSymbolInLibrary(const Library& library, |
107 | uword pc); |
108 | static const uint8_t* ResolveSymbol(uword pc); |
109 | |
110 | static uword BootstrapNativeCallWrapperEntry(); |
111 | static void BootstrapNativeCallWrapper(Dart_NativeArguments args, |
112 | Dart_NativeFunction func); |
113 | |
114 | static uword NoScopeNativeCallWrapperEntry(); |
115 | static void NoScopeNativeCallWrapper(Dart_NativeArguments args, |
116 | Dart_NativeFunction func); |
117 | |
118 | static uword AutoScopeNativeCallWrapperEntry(); |
119 | static void AutoScopeNativeCallWrapper(Dart_NativeArguments args, |
120 | Dart_NativeFunction func); |
121 | |
122 | static uword LinkNativeCallEntry(); |
123 | static void LinkNativeCall(Dart_NativeArguments args); |
124 | |
125 | private: |
126 | static void NoScopeNativeCallWrapperNoStackCheck(Dart_NativeArguments args, |
127 | Dart_NativeFunction func); |
128 | static void AutoScopeNativeCallWrapperNoStackCheck(Dart_NativeArguments args, |
129 | Dart_NativeFunction func); |
130 | |
131 | static bool ReturnValueIsError(NativeArguments* arguments); |
132 | static void PropagateErrors(NativeArguments* arguments); |
133 | }; |
134 | |
135 | #if !defined(DART_PRECOMPILED_RUNTIME) |
136 | |
137 | class NativeEntryData : public ValueObject { |
138 | public: |
139 | explicit NativeEntryData(const TypedData& data) : data_(data) {} |
140 | |
141 | MethodRecognizer::Kind kind() const; |
142 | void set_kind(MethodRecognizer::Kind value) const; |
143 | static MethodRecognizer::Kind GetKind(TypedDataPtr data); |
144 | |
145 | NativeFunctionWrapper trampoline() const; |
146 | void set_trampoline(NativeFunctionWrapper value) const; |
147 | static NativeFunctionWrapper GetTrampoline(TypedDataPtr data); |
148 | |
149 | NativeFunction native_function() const; |
150 | void set_native_function(NativeFunction value) const; |
151 | static NativeFunction GetNativeFunction(TypedDataPtr data); |
152 | |
153 | intptr_t argc_tag() const; |
154 | void set_argc_tag(intptr_t value) const; |
155 | static intptr_t GetArgcTag(TypedDataPtr data); |
156 | |
157 | static TypedDataPtr New(MethodRecognizer::Kind kind, |
158 | NativeFunctionWrapper trampoline, |
159 | NativeFunction native_function, |
160 | intptr_t argc_tag); |
161 | |
162 | private: |
163 | struct Payload { |
164 | NativeFunctionWrapper trampoline; |
165 | NativeFunction native_function; |
166 | intptr_t argc_tag; |
167 | MethodRecognizer::Kind kind; |
168 | }; |
169 | |
170 | static Payload* FromTypedArray(TypedDataPtr data); |
171 | |
172 | const TypedData& data_; |
173 | |
174 | friend class Interpreter; |
175 | friend class ObjectPoolSerializationCluster; |
176 | DISALLOW_COPY_AND_ASSIGN(NativeEntryData); |
177 | }; |
178 | |
179 | #endif // !defined(DART_PRECOMPILED_RUNTIME) |
180 | |
181 | } // namespace dart |
182 | |
183 | #endif // RUNTIME_VM_NATIVE_ENTRY_H_ |
184 | |