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
19namespace dart {
20
21// Forward declarations.
22class Class;
23class 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
36typedef 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.
57void DartNativeThrowTypeArgumentCountException(int num_type_args,
58 int num_type_args_expected);
59void 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.
96class 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
137class 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