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_RUNTIME_ENTRY_H_ |
6 | #define RUNTIME_VM_RUNTIME_ENTRY_H_ |
7 | |
8 | #include "vm/allocation.h" |
9 | #if !defined(DART_PRECOMPILED_RUNTIME) |
10 | #include "vm/compiler/runtime_api.h" |
11 | #endif |
12 | #include "vm/flags.h" |
13 | #include "vm/heap/safepoint.h" |
14 | #include "vm/log.h" |
15 | #include "vm/native_arguments.h" |
16 | #include "vm/runtime_entry_list.h" |
17 | |
18 | namespace dart { |
19 | |
20 | typedef void (*RuntimeFunction)(NativeArguments arguments); |
21 | |
22 | #if !defined(DART_PRECOMPILED_RUNTIME) |
23 | using BaseRuntimeEntry = compiler::RuntimeEntry; |
24 | #else |
25 | using BaseRuntimeEntry = ValueObject; |
26 | #endif |
27 | |
28 | // Class RuntimeEntry is used to encapsulate runtime functions, it includes |
29 | // the entry point for the runtime function and the number of arguments expected |
30 | // by the function. |
31 | class RuntimeEntry : public BaseRuntimeEntry { |
32 | public: |
33 | RuntimeEntry(const char* name, |
34 | RuntimeFunction function, |
35 | intptr_t argument_count, |
36 | bool is_leaf, |
37 | bool is_float) |
38 | : |
39 | #if !defined(DART_PRECOMPILED_RUNTIME) |
40 | compiler::RuntimeEntry(this, &CallInternal), |
41 | #endif |
42 | name_(name), |
43 | function_(function), |
44 | argument_count_(argument_count), |
45 | is_leaf_(is_leaf), |
46 | is_float_(is_float) { |
47 | } |
48 | |
49 | const char* name() const { return name_; } |
50 | RuntimeFunction function() const { return function_; } |
51 | intptr_t argument_count() const { return argument_count_; } |
52 | bool is_leaf() const { return is_leaf_; } |
53 | bool is_float() const { return is_float_; } |
54 | uword GetEntryPoint() const; |
55 | |
56 | // Generate code to call the runtime entry. |
57 | NOT_IN_PRECOMPILED(void Call(compiler::Assembler* assembler, |
58 | intptr_t argument_count) const); |
59 | |
60 | static uword InterpretCallEntry(); |
61 | |
62 | protected: |
63 | NOT_IN_PRECOMPILED(static void CallInternal(const RuntimeEntry* runtime_entry, |
64 | compiler::Assembler* assembler, |
65 | intptr_t argument_count)); |
66 | |
67 | private: |
68 | const char* const name_; |
69 | const RuntimeFunction function_; |
70 | const intptr_t argument_count_; |
71 | const bool is_leaf_; |
72 | const bool is_float_; |
73 | |
74 | DISALLOW_COPY_AND_ASSIGN(RuntimeEntry); |
75 | }; |
76 | |
77 | #ifdef DEBUG |
78 | #define TRACE_RUNTIME_CALL(format, name) \ |
79 | if (FLAG_trace_runtime_calls) { \ |
80 | THR_Print("Runtime call: " format "\n", name); \ |
81 | } |
82 | #else |
83 | #define TRACE_RUNTIME_CALL(format, name) \ |
84 | do { \ |
85 | } while (0) |
86 | #endif |
87 | |
88 | #if defined(USING_SIMULATOR) |
89 | #define CHECK_SIMULATOR_STACK_OVERFLOW() \ |
90 | if (!OSThread::Current()->HasStackHeadroom()) { \ |
91 | Exceptions::ThrowStackOverflow(); \ |
92 | } |
93 | #else |
94 | #define CHECK_SIMULATOR_STACK_OVERFLOW() |
95 | #endif // defined(USING_SIMULATOR) |
96 | |
97 | // Helper macros for declaring and defining runtime entries. |
98 | |
99 | #define DEFINE_RUNTIME_ENTRY(name, argument_count) \ |
100 | extern void DRT_##name(NativeArguments arguments); \ |
101 | extern const RuntimeEntry k##name##RuntimeEntry( \ |
102 | "DRT_" #name, &DRT_##name, argument_count, false, false); \ |
103 | static void DRT_Helper##name(Isolate* isolate, Thread* thread, Zone* zone, \ |
104 | NativeArguments arguments); \ |
105 | void DRT_##name(NativeArguments arguments) { \ |
106 | CHECK_STACK_ALIGNMENT; \ |
107 | /* Tell MemorySanitizer 'arguments' is initialized by generated code. */ \ |
108 | MSAN_UNPOISON(&arguments, sizeof(arguments)); \ |
109 | ASSERT(arguments.ArgCount() == argument_count); \ |
110 | TRACE_RUNTIME_CALL("%s", "" #name); \ |
111 | { \ |
112 | Thread* thread = arguments.thread(); \ |
113 | ASSERT(thread == Thread::Current()); \ |
114 | Isolate* isolate = thread->isolate(); \ |
115 | TransitionGeneratedToVM transition(thread); \ |
116 | StackZone zone(thread); \ |
117 | HANDLESCOPE(thread); \ |
118 | CHECK_SIMULATOR_STACK_OVERFLOW(); \ |
119 | DRT_Helper##name(isolate, thread, zone.GetZone(), arguments); \ |
120 | } \ |
121 | } \ |
122 | static void DRT_Helper##name(Isolate* isolate, Thread* thread, Zone* zone, \ |
123 | NativeArguments arguments) |
124 | |
125 | #define DECLARE_RUNTIME_ENTRY(name) \ |
126 | extern const RuntimeEntry k##name##RuntimeEntry; \ |
127 | extern void DRT_##name(NativeArguments arguments); |
128 | |
129 | #define DEFINE_LEAF_RUNTIME_ENTRY(type, name, argument_count, ...) \ |
130 | extern "C" type DLRT_##name(__VA_ARGS__); \ |
131 | extern const RuntimeEntry k##name##RuntimeEntry( \ |
132 | "DLRT_" #name, reinterpret_cast<RuntimeFunction>(&DLRT_##name), \ |
133 | argument_count, true, false); \ |
134 | type DLRT_##name(__VA_ARGS__) { \ |
135 | CHECK_STACK_ALIGNMENT; \ |
136 | NoSafepointScope no_safepoint_scope; |
137 | |
138 | #define END_LEAF_RUNTIME_ENTRY } |
139 | |
140 | // TODO(rmacnak): Fix alignment issue on simarm and use |
141 | // DEFINE_LEAF_RUNTIME_ENTRY instead. |
142 | #define DEFINE_RAW_LEAF_RUNTIME_ENTRY(name, argument_count, is_float, func) \ |
143 | extern const RuntimeEntry k##name##RuntimeEntry( \ |
144 | "DFLRT_" #name, func, argument_count, true, is_float) |
145 | |
146 | #define DECLARE_LEAF_RUNTIME_ENTRY(type, name, ...) \ |
147 | extern const RuntimeEntry k##name##RuntimeEntry; \ |
148 | extern "C" type DLRT_##name(__VA_ARGS__); |
149 | |
150 | // Declare all runtime functions here. |
151 | RUNTIME_ENTRY_LIST(DECLARE_RUNTIME_ENTRY) |
152 | LEAF_RUNTIME_ENTRY_LIST(DECLARE_LEAF_RUNTIME_ENTRY) |
153 | |
154 | // Expected to be called inside a safepoint. |
155 | extern "C" Thread* DLRT_GetThreadForNativeCallback(uword callback_id); |
156 | extern "C" Thread* DLRT_GetThreadForNativeCallbackTrampoline(uword callback_id); |
157 | |
158 | // For creating scoped handles in FFI trampolines. |
159 | extern "C" ApiLocalScope* DLRT_EnterHandleScope(Thread* thread); |
160 | extern "C" void DLRT_ExitHandleScope(Thread* thread); |
161 | extern "C" LocalHandle* DLRT_AllocateHandle(ApiLocalScope* scope); |
162 | |
163 | const char* DeoptReasonToCString(ICData::DeoptReasonId deopt_reason); |
164 | |
165 | void DeoptimizeAt(const Code& optimized_code, StackFrame* frame); |
166 | void DeoptimizeFunctionsOnStack(); |
167 | |
168 | double DartModulo(double a, double b); |
169 | |
170 | } // namespace dart |
171 | |
172 | #endif // RUNTIME_VM_RUNTIME_ENTRY_H_ |
173 | |