OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #ifndef RUNTIME_VM_NATIVE_ARGUMENTS_H_ | 5 #ifndef RUNTIME_VM_NATIVE_ARGUMENTS_H_ |
6 #define RUNTIME_VM_NATIVE_ARGUMENTS_H_ | 6 #define RUNTIME_VM_NATIVE_ARGUMENTS_H_ |
7 | 7 |
8 #include "platform/assert.h" | 8 #include "platform/assert.h" |
9 #include "platform/memory_sanitizer.h" | 9 #include "platform/memory_sanitizer.h" |
10 #include "vm/globals.h" | 10 #include "vm/globals.h" |
(...skipping 10 matching lines...) Expand all Loading... |
21 class RawObject; | 21 class RawObject; |
22 class Simulator; | 22 class Simulator; |
23 class Thread; | 23 class Thread; |
24 | 24 |
25 #if defined(TESTING) || defined(DEBUG) | 25 #if defined(TESTING) || defined(DEBUG) |
26 | 26 |
27 #if defined(TARGET_ARCH_DBC) | 27 #if defined(TARGET_ARCH_DBC) |
28 // C-stack is always aligned on DBC because we don't have any native code. | 28 // C-stack is always aligned on DBC because we don't have any native code. |
29 #define CHECK_STACK_ALIGNMENT | 29 #define CHECK_STACK_ALIGNMENT |
30 #elif defined(USING_SIMULATOR) | 30 #elif defined(USING_SIMULATOR) |
31 #define CHECK_STACK_ALIGNMENT { \ | 31 #define CHECK_STACK_ALIGNMENT \ |
32 uword current_sp = Simulator::Current()->get_register(SPREG); \ | 32 { \ |
33 ASSERT(Utils::IsAligned(current_sp, OS::ActivationFrameAlignment())); \ | 33 uword current_sp = Simulator::Current()->get_register(SPREG); \ |
34 } | 34 ASSERT(Utils::IsAligned(current_sp, OS::ActivationFrameAlignment())); \ |
| 35 } |
35 #elif defined(TARGET_OS_WINDOWS) | 36 #elif defined(TARGET_OS_WINDOWS) |
36 // The compiler may dynamically align the stack on Windows, so do not check. | 37 // The compiler may dynamically align the stack on Windows, so do not check. |
37 #define CHECK_STACK_ALIGNMENT { } | 38 #define CHECK_STACK_ALIGNMENT \ |
| 39 {} |
38 #else | 40 #else |
39 #define CHECK_STACK_ALIGNMENT { \ | 41 #define CHECK_STACK_ALIGNMENT \ |
40 uword (*func)() = reinterpret_cast<uword (*)()>( \ | 42 { \ |
41 StubCode::GetStackPointer_entry()->EntryPoint()); \ | 43 uword (*func)() = reinterpret_cast<uword (*)()>( \ |
42 uword current_sp = func(); \ | 44 StubCode::GetStackPointer_entry()->EntryPoint()); \ |
43 ASSERT(Utils::IsAligned(current_sp, OS::ActivationFrameAlignment())); \ | 45 uword current_sp = func(); \ |
44 } | 46 ASSERT(Utils::IsAligned(current_sp, OS::ActivationFrameAlignment())); \ |
| 47 } |
45 #endif | 48 #endif |
46 | 49 |
47 void VerifyOnTransition(); | 50 void VerifyOnTransition(); |
48 | 51 |
49 #define VERIFY_ON_TRANSITION \ | 52 #define VERIFY_ON_TRANSITION \ |
50 if (FLAG_verify_on_transition) { \ | 53 if (FLAG_verify_on_transition) { \ |
51 VerifyOnTransition(); \ | 54 VerifyOnTransition(); \ |
52 } | 55 } |
53 #define DEOPTIMIZE_ALOT \ | 56 #define DEOPTIMIZE_ALOT \ |
54 if (FLAG_deoptimize_alot) { \ | 57 if (FLAG_deoptimize_alot) { \ |
55 DeoptimizeFunctionsOnStack(); \ | 58 DeoptimizeFunctionsOnStack(); \ |
56 } | 59 } |
57 | 60 |
58 #else | 61 #else |
59 | 62 |
60 #define CHECK_STACK_ALIGNMENT { } | 63 #define CHECK_STACK_ALIGNMENT \ |
61 #define VERIFY_ON_TRANSITION { } | 64 {} |
62 #define DEOPTIMIZE_ALOT { } | 65 #define VERIFY_ON_TRANSITION \ |
| 66 {} |
| 67 #define DEOPTIMIZE_ALOT \ |
| 68 {} |
63 | 69 |
64 #endif | 70 #endif |
65 | 71 |
66 #ifndef PRODUCT | 72 #ifndef PRODUCT |
67 #define TRACE_NATIVE_CALL(format, name) \ | 73 #define TRACE_NATIVE_CALL(format, name) \ |
68 if (FLAG_trace_natives) { \ | 74 if (FLAG_trace_natives) { \ |
69 OS::Print("Calling native: " format "\n", name); \ | 75 OS::Print("Calling native: " format "\n", name); \ |
70 } | 76 } |
71 #else | 77 #else |
72 #define TRACE_NATIVE_CALL(format, name) \ | 78 #define TRACE_NATIVE_CALL(format, name) \ |
73 do { } while (0) | 79 do { \ |
| 80 } while (0) |
74 #endif | 81 #endif |
75 | 82 |
76 // Class NativeArguments is used to access arguments passed in from | 83 // Class NativeArguments is used to access arguments passed in from |
77 // generated dart code to a runtime function or a dart library native | 84 // generated dart code to a runtime function or a dart library native |
78 // function. It is also used to set the return value if any at the slot | 85 // function. It is also used to set the return value if any at the slot |
79 // reserved for return values. | 86 // reserved for return values. |
80 // All runtime function/dart library native functions have the | 87 // All runtime function/dart library native functions have the |
81 // following signature: | 88 // following signature: |
82 // void function_name(NativeArguments arguments); | 89 // void function_name(NativeArguments arguments); |
83 // Inside the function, arguments are accessed as follows: | 90 // Inside the function, arguments are accessed as follows: |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
131 RawObject* NativeArgAt(int index) const { | 138 RawObject* NativeArgAt(int index) const { |
132 ASSERT((index >= 0) && (index < NativeArgCount())); | 139 ASSERT((index >= 0) && (index < NativeArgCount())); |
133 if (index == 0) { | 140 if (index == 0) { |
134 return NativeArg0(); | 141 return NativeArg0(); |
135 } | 142 } |
136 int function_bits = FunctionBits::decode(argc_tag_); | 143 int function_bits = FunctionBits::decode(argc_tag_); |
137 const int actual_index = index + NumHiddenArgs(function_bits); | 144 const int actual_index = index + NumHiddenArgs(function_bits); |
138 return ArgAt(actual_index); | 145 return ArgAt(actual_index); |
139 } | 146 } |
140 | 147 |
141 void SetReturn(const Object& value) const { | 148 void SetReturn(const Object& value) const { *retval_ = value.raw(); } |
142 *retval_ = value.raw(); | |
143 } | |
144 | 149 |
145 RawObject* ReturnValue() const { | 150 RawObject* ReturnValue() const { |
146 // Tell MemorySanitizer the retval_ was initialized (by generated code). | 151 // Tell MemorySanitizer the retval_ was initialized (by generated code). |
147 MSAN_UNPOISON(retval_, kWordSize); | 152 MSAN_UNPOISON(retval_, kWordSize); |
148 return *retval_; | 153 return *retval_; |
149 } | 154 } |
150 | 155 |
151 static intptr_t thread_offset() { | 156 static intptr_t thread_offset() { |
152 return OFFSET_OF(NativeArguments, thread_); | 157 return OFFSET_OF(NativeArguments, thread_); |
153 } | 158 } |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
200 kClosureFunctionBit = 2, | 205 kClosureFunctionBit = 2, |
201 }; | 206 }; |
202 enum ArgcTagBits { | 207 enum ArgcTagBits { |
203 kArgcBit = 0, | 208 kArgcBit = 0, |
204 kArgcSize = 24, | 209 kArgcSize = 24, |
205 kFunctionBit = 24, | 210 kFunctionBit = 24, |
206 kFunctionSize = 2, | 211 kFunctionSize = 2, |
207 kAutoSetupScopeBit = 26, | 212 kAutoSetupScopeBit = 26, |
208 }; | 213 }; |
209 class ArgcBits : public BitField<intptr_t, int32_t, kArgcBit, kArgcSize> {}; | 214 class ArgcBits : public BitField<intptr_t, int32_t, kArgcBit, kArgcSize> {}; |
210 class FunctionBits : | 215 class FunctionBits |
211 public BitField<intptr_t, int, kFunctionBit, kFunctionSize> {}; | 216 : public BitField<intptr_t, int, kFunctionBit, kFunctionSize> {}; |
212 class AutoSetupScopeBits : | 217 class AutoSetupScopeBits |
213 public BitField<intptr_t, int, kAutoSetupScopeBit, 1> {}; | 218 : public BitField<intptr_t, int, kAutoSetupScopeBit, 1> {}; |
214 friend class Api; | 219 friend class Api; |
215 friend class BootstrapNatives; | 220 friend class BootstrapNatives; |
216 friend class Simulator; | 221 friend class Simulator; |
217 | 222 |
218 #if defined(TARGET_ARCH_DBC) | 223 #if defined(TARGET_ARCH_DBC) |
219 // Allow simulator to create NativeArguments on the stack. | 224 // Allow simulator to create NativeArguments on the stack. |
220 NativeArguments(Thread* thread, | 225 NativeArguments(Thread* thread, |
221 int argc_tag, | 226 int argc_tag, |
222 RawObject** argv, | 227 RawObject** argv, |
223 RawObject** retval) | 228 RawObject** retval) |
224 : thread_(thread), argc_tag_(argc_tag), argv_(argv), retval_(retval) { | 229 : thread_(thread), argc_tag_(argc_tag), argv_(argv), retval_(retval) {} |
225 } | |
226 #endif | 230 #endif |
227 | 231 |
228 // Since this function is passed a RawObject directly, we need to be | 232 // Since this function is passed a RawObject directly, we need to be |
229 // exceedingly careful when we use it. If there are any other side | 233 // exceedingly careful when we use it. If there are any other side |
230 // effects in the statement that may cause GC, it could lead to | 234 // effects in the statement that may cause GC, it could lead to |
231 // bugs. | 235 // bugs. |
232 void SetReturnUnsafe(RawObject* value) const { | 236 void SetReturnUnsafe(RawObject* value) const { *retval_ = value; } |
233 *retval_ = value; | |
234 } | |
235 | 237 |
236 // Returns true if the arguments are those of an instance function call. | 238 // Returns true if the arguments are those of an instance function call. |
237 bool ToInstanceFunction() const { | 239 bool ToInstanceFunction() const { |
238 return (FunctionBits::decode(argc_tag_) & kInstanceFunctionBit); | 240 return (FunctionBits::decode(argc_tag_) & kInstanceFunctionBit); |
239 } | 241 } |
240 | 242 |
241 // Returns true if the arguments are those of a closure function call. | 243 // Returns true if the arguments are those of a closure function call. |
242 bool ToClosureFunction() const { | 244 bool ToClosureFunction() const { |
243 return (FunctionBits::decode(argc_tag_) & kClosureFunctionBit); | 245 return (FunctionBits::decode(argc_tag_) & kClosureFunctionBit); |
244 } | 246 } |
245 | 247 |
246 int NumHiddenArgs(int function_bits) const { | 248 int NumHiddenArgs(int function_bits) const { |
247 // For static closure functions, the closure at index 0 is hidden. | 249 // For static closure functions, the closure at index 0 is hidden. |
248 // In the instance closure function case, the receiver is accessed from | 250 // In the instance closure function case, the receiver is accessed from |
249 // the context and the closure at index 0 is hidden, so the apparent | 251 // the context and the closure at index 0 is hidden, so the apparent |
250 // argument count remains unchanged. | 252 // argument count remains unchanged. |
251 if (function_bits == kClosureFunctionBit) { | 253 if (function_bits == kClosureFunctionBit) { |
252 return 1; | 254 return 1; |
253 } | 255 } |
254 return 0; | 256 return 0; |
255 } | 257 } |
256 | 258 |
257 Thread* thread_; // Current thread pointer. | 259 Thread* thread_; // Current thread pointer. |
258 intptr_t argc_tag_; // Encodes argument count and invoked native call type. | 260 intptr_t argc_tag_; // Encodes argument count and invoked native call type. |
259 RawObject** argv_; // Pointer to an array of arguments to runtime call. | 261 RawObject** argv_; // Pointer to an array of arguments to runtime call. |
260 RawObject** retval_; // Pointer to the return value area. | 262 RawObject** retval_; // Pointer to the return value area. |
261 }; | 263 }; |
262 | 264 |
263 } // namespace dart | 265 } // namespace dart |
264 | 266 |
265 #endif // RUNTIME_VM_NATIVE_ARGUMENTS_H_ | 267 #endif // RUNTIME_VM_NATIVE_ARGUMENTS_H_ |
OLD | NEW |