OLD | NEW |
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 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 | 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 #include "vm/globals.h" | 5 #include "vm/globals.h" |
6 #if defined(TARGET_ARCH_X64) | 6 #if defined(TARGET_ARCH_X64) |
7 | 7 |
| 8 #include "vm/native_entry.h" |
8 #include "vm/stub_code.h" | 9 #include "vm/stub_code.h" |
9 | 10 |
10 #define __ assembler-> | 11 #define __ assembler-> |
11 | 12 |
12 namespace dart { | 13 namespace dart { |
13 | 14 |
14 void StubCode::GenerateDartCallToRuntimeStub(Assembler* assembler) { | 15 // Input parameters: |
15 __ Unimplemented("DartCallToRuntime stub"); | 16 // RSP : points to return address. |
| 17 // RSP + 8 : address of last argument in argument array. |
| 18 // RSP + 8*R10 : address of first argument in argument array. |
| 19 // RSP + 8*R10 + 8 : address of return value. |
| 20 // RBX : address of the runtime function to call. |
| 21 // R10 : number of arguments to the call. |
| 22 static void GenerateCallRuntimeStub(Assembler* assembler) { |
| 23 const intptr_t isolate_offset = NativeArguments::isolate_offset(); |
| 24 const intptr_t argc_offset = NativeArguments::argc_offset(); |
| 25 const intptr_t argv_offset = NativeArguments::argv_offset(); |
| 26 const intptr_t retval_offset = NativeArguments::retval_offset(); |
| 27 |
| 28 __ EnterFrame(0); |
| 29 |
| 30 // Load current Isolate pointer from Context structure into RAX. |
| 31 __ movq(RAX, FieldAddress(CTX, Context::isolate_offset())); |
| 32 |
| 33 // Save exit frame information to enable stack walking as we are about |
| 34 // to transition to dart VM code. |
| 35 __ movq(Address(RAX, Isolate::top_exit_frame_info_offset()), RSP); |
| 36 |
| 37 // Save current Context pointer into Isolate structure. |
| 38 __ movq(Address(RAX, Isolate::top_context_offset()), CTX); |
| 39 |
| 40 // Cache Isolate pointer into CTX while executing runtime code. |
| 41 __ movq(CTX, RAX); |
| 42 |
| 43 // Reserve space for arguments and align frame before entering C++ world. |
| 44 __ AddImmediate(RSP, Immediate(-sizeof(NativeArguments))); |
| 45 if (OS::ActivationFrameAlignment() > 0) { |
| 46 __ andq(RSP, Immediate(~(OS::ActivationFrameAlignment() - 1))); |
| 47 } |
| 48 |
| 49 // Pass NativeArguments structure by value and call runtime. |
| 50 __ movq(Address(RSP, isolate_offset), CTX); // Set isolate in NativeArgs. |
| 51 __ movq(Address(RSP, argc_offset), R10); // Set argc in NativeArguments. |
| 52 __ leaq(RAX, Address(RBP, R10, TIMES_8, 1 * kWordSize)); // Compute argv. |
| 53 __ movq(Address(RSP, argv_offset), RAX); // Set argv in NativeArguments. |
| 54 __ addq(RAX, Immediate(1 * kWordSize)); // Retval is next to 1st argument. |
| 55 __ movq(Address(RSP, retval_offset), RAX); // Set retval in NativeArguments. |
| 56 __ call(RBX); |
| 57 |
| 58 // Reset exit frame information in Isolate structure. |
| 59 __ movq(Address(CTX, Isolate::top_exit_frame_info_offset()), Immediate(0)); |
| 60 |
| 61 // Load Context pointer from Isolate structure into RBX. |
| 62 __ movq(RBX, Address(CTX, Isolate::top_context_offset())); |
| 63 |
| 64 // Reset Context pointer in Isolate structure. |
| 65 const Immediate raw_null = |
| 66 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 67 __ movq(Address(CTX, Isolate::top_context_offset()), raw_null); |
| 68 |
| 69 // Cache Context pointer into CTX while executing dart code. |
| 70 __ movq(CTX, RBX); |
| 71 |
| 72 __ LeaveFrame(); |
| 73 __ ret(); |
16 } | 74 } |
17 | 75 |
18 | 76 |
19 void StubCode::GenerateStubCallToRuntimeStub(Assembler* assembler) { | 77 // Input parameters: |
20 __ Unimplemented("StubCallToRuntime stub"); | 78 // RSP : points to return address. |
| 79 // RSP + 8 : address of last argument in argument array. |
| 80 // RSP + 8*R10 : address of first argument in argument array. |
| 81 // RSP + 8*R10 + 8 : address of return value. |
| 82 // RBX : address of the runtime function to call. |
| 83 // R10 : number of arguments to the call. |
| 84 void StubCode::GenerateDartCallToRuntimeStub(Assembler* assembler) { |
| 85 GenerateCallRuntimeStub(assembler); |
21 } | 86 } |
22 | 87 |
23 | 88 |
24 void StubCode::GenerateCallNativeCFunctionStub(Assembler* assembler) { | 89 // Input parameters: |
25 __ Unimplemented("CallNativeCFunction stub"); | 90 // RSP : points to return address. |
| 91 // RSP + 8 : address of last argument in argument array. |
| 92 // RSP + 8*R10 : address of first argument in argument array. |
| 93 // RSP + 8*R10 + 8 : address of return value. |
| 94 // RBX : address of the runtime function to call. |
| 95 // R10 : number of arguments to the call. |
| 96 void StubCode::GenerateStubCallToRuntimeStub(Assembler* assembler) { |
| 97 GenerateCallRuntimeStub(assembler); |
26 } | 98 } |
27 | 99 |
28 | 100 |
29 void StubCode::GenerateCallNoSuchMethodFunctionStub(Assembler* assembler) { | 101 // Input parameters: |
30 __ Unimplemented("CallNoSuchMethodFunction stub"); | 102 // RSP : points to return address. |
| 103 // RSP + 8 : address of return value. |
| 104 // RAX : address of first argument in argument array. |
| 105 // RAX - 8*R10 + 8 : address of last argument in argument array. |
| 106 // RBX : address of the native function to call. |
| 107 // R10 : number of arguments to the call. |
| 108 void StubCode::GenerateCallNativeCFunctionStub(Assembler* assembler) { |
| 109 const intptr_t native_args_struct_offset = 0; |
| 110 const intptr_t isolate_offset = |
| 111 NativeArguments::isolate_offset() + native_args_struct_offset; |
| 112 const intptr_t argc_offset = |
| 113 NativeArguments::argc_offset() + native_args_struct_offset; |
| 114 const intptr_t argv_offset = |
| 115 NativeArguments::argv_offset() + native_args_struct_offset; |
| 116 const intptr_t retval_offset = |
| 117 NativeArguments::retval_offset() + native_args_struct_offset; |
| 118 |
| 119 __ EnterFrame(0); |
| 120 |
| 121 // Load current Isolate pointer from Context structure into R8. |
| 122 __ movq(R8, FieldAddress(CTX, Context::isolate_offset())); |
| 123 |
| 124 // Save exit frame information to enable stack walking as we are about |
| 125 // to transition to dart VM code. |
| 126 __ movq(Address(R8, Isolate::top_exit_frame_info_offset()), RSP); |
| 127 |
| 128 // Save current Context pointer into Isolate structure. |
| 129 __ movq(Address(R8, Isolate::top_context_offset()), CTX); |
| 130 |
| 131 // Cache Isolate pointer into CTX while executing native code. |
| 132 __ movq(CTX, R8); |
| 133 |
| 134 // Reserve space for the native arguments structure passed on the stack (the |
| 135 // outgoing pointer parameter to the native arguments structure is passed in |
| 136 // RDI) and align frame before entering the C++ world. |
| 137 __ AddImmediate(RSP, Immediate(-sizeof(NativeArguments))); |
| 138 if (OS::ActivationFrameAlignment() > 0) { |
| 139 __ andq(RSP, Immediate(~(OS::ActivationFrameAlignment() - 1))); |
| 140 } |
| 141 |
| 142 // Pass NativeArguments structure by value and call runtime. |
| 143 __ movq(Address(RSP, isolate_offset), CTX); // Set isolate in NativeArgs. |
| 144 __ movq(Address(RSP, argc_offset), R10); // Set argc in NativeArguments. |
| 145 __ movq(Address(RSP, argv_offset), RAX); // Set argv in NativeArguments. |
| 146 __ leaq(RAX, Address(RBP, 2 * kWordSize)); // Compute return value addr. |
| 147 __ movq(Address(RSP, retval_offset), RAX); // Set retval in NativeArguments. |
| 148 __ movq(RDI, RSP); // Pass the pointer to the NativeArguments. |
| 149 __ call(RBX); |
| 150 |
| 151 // Reset exit frame information in Isolate structure. |
| 152 __ movq(Address(CTX, Isolate::top_exit_frame_info_offset()), Immediate(0)); |
| 153 |
| 154 // Load Context pointer from Isolate structure into R8. |
| 155 __ movq(R8, Address(CTX, Isolate::top_context_offset())); |
| 156 |
| 157 // Reset Context pointer in Isolate structure. |
| 158 const Immediate raw_null = |
| 159 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 160 __ movq(Address(CTX, Isolate::top_context_offset()), raw_null); |
| 161 |
| 162 // Cache Context pointer into CTX while executing dart code. |
| 163 __ movq(CTX, R8); |
| 164 |
| 165 __ LeaveFrame(); |
| 166 __ ret(); |
31 } | 167 } |
32 | 168 |
33 | 169 |
34 void StubCode::GenerateInvokeDartCodeStub(Assembler* assembler) { | |
35 __ Unimplemented("InvokeDartCode stub"); | |
36 } | |
37 | |
38 | |
39 void StubCode::GenerateCallStaticFunctionStub(Assembler* assembler) { | 170 void StubCode::GenerateCallStaticFunctionStub(Assembler* assembler) { |
40 __ Unimplemented("CallStaticFunction stub"); | 171 __ Unimplemented("CallStaticFunction stub"); |
41 } | 172 } |
42 | 173 |
43 | 174 |
| 175 void StubCode::GenerateStackOverflowStub(Assembler* assembler) { |
| 176 __ Unimplemented("StackOverflow stub"); |
| 177 } |
| 178 |
| 179 |
| 180 void StubCode::GenerateOptimizeInvokedFunctionStub(Assembler* assembler) { |
| 181 __ Unimplemented("OptimizeInvokedFunction stub"); |
| 182 } |
| 183 |
| 184 |
| 185 void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) { |
| 186 __ Unimplemented("FixCallersTarget stub"); |
| 187 } |
| 188 |
| 189 |
44 void StubCode::GenerateMegamorphicLookupStub(Assembler* assembler) { | 190 void StubCode::GenerateMegamorphicLookupStub(Assembler* assembler) { |
45 __ Unimplemented("MegamorphicLookup stub"); | 191 __ Unimplemented("MegamorphicLookup stub"); |
46 } | 192 } |
47 | 193 |
48 | 194 |
| 195 void StubCode::GenerateDeoptimizeStub(Assembler* assembler) { |
| 196 __ Unimplemented("Deoptimize stub"); |
| 197 } |
| 198 |
| 199 |
| 200 void StubCode::GenerateAllocateArrayStub(Assembler* assembler) { |
| 201 __ Unimplemented("AllocateArray stub"); |
| 202 } |
| 203 |
| 204 |
49 void StubCode::GenerateCallClosureFunctionStub(Assembler* assembler) { | 205 void StubCode::GenerateCallClosureFunctionStub(Assembler* assembler) { |
50 __ Unimplemented("CallClosureFunction stub"); | 206 __ Unimplemented("CallClosureFunction stub"); |
51 } | 207 } |
52 | 208 |
53 | 209 |
| 210 // Called when invoking dart code from C++ (VM code). |
| 211 // Input parameters: |
| 212 // RSP : points to return address. |
| 213 // RDI : entrypoint of the dart function to call. |
| 214 // RSI : arguments descriptor array. |
| 215 // RDX : pointer to the argument array. |
| 216 // RCX : new context containing the current isolate pointer. |
| 217 void StubCode::GenerateInvokeDartCodeStub(Assembler* assembler) { |
| 218 // Save frame pointer coming in. |
| 219 __ EnterFrame(0); |
| 220 |
| 221 // Save arguments descriptor array and new context. |
| 222 const intptr_t kArgumentsDescOffset = -1 * kWordSize; |
| 223 __ pushq(RSI); |
| 224 const intptr_t kNewContextOffset = -2 * kWordSize; |
| 225 __ pushq(RCX); |
| 226 |
| 227 // Save C++ ABI callee-saved registers. |
| 228 __ pushq(RBX); |
| 229 __ pushq(R12); |
| 230 __ pushq(R13); |
| 231 __ pushq(R14); |
| 232 __ pushq(R15); |
| 233 |
| 234 // The new Context structure contains a pointer to the current Isolate |
| 235 // structure. Cache the Context pointer in the CTX register so that it is |
| 236 // available in generated code and calls to Isolate::Current() need not be |
| 237 // done. The assumption is that this register will never be clobbered by |
| 238 // compiled or runtime stub code. |
| 239 |
| 240 // Cache the new Context pointer into CTX while executing dart code. |
| 241 __ movq(CTX, Address(RCX, VMHandles::kOffsetOfRawPtrInHandle)); |
| 242 |
| 243 // Load Isolate pointer from Context structure into R8. |
| 244 __ movq(R8, FieldAddress(CTX, Context::isolate_offset())); |
| 245 |
| 246 // Save the top exit frame info. Use RAX as a temporary register. |
| 247 __ movq(RAX, Address(R8, Isolate::top_exit_frame_info_offset())); |
| 248 __ pushq(RAX); |
| 249 __ movq(Address(R8, Isolate::top_exit_frame_info_offset()), Immediate(0)); |
| 250 |
| 251 // StackFrameIterator reads the top exit frame info saved in this frame. |
| 252 // The constant kExitLinkOffsetInEntryFrame must be kept in sync with the |
| 253 // code above: kExitLinkOffsetInEntryFrame = -8 * kWordSize. |
| 254 |
| 255 // Save the old Context pointer. Use RAX as a temporary register. |
| 256 // Note that VisitObjectPointers will find this saved Context pointer during |
| 257 // GC marking, since it traverses any information between SP and |
| 258 // FP - kExitLinkOffsetInEntryFrame. |
| 259 __ movq(RAX, Address(R8, Isolate::top_context_offset())); |
| 260 __ pushq(RAX); |
| 261 |
| 262 // Load arguments descriptor array into R10, which is passed to Dart code. |
| 263 __ movq(R10, Address(RSI, VMHandles::kOffsetOfRawPtrInHandle)); |
| 264 |
| 265 // Load number of arguments into RBX. |
| 266 __ movq(RBX, FieldAddress(R10, Array::data_offset())); |
| 267 __ SmiUntag(RBX); |
| 268 |
| 269 // Set up arguments for the dart call. |
| 270 Label push_arguments; |
| 271 Label done_push_arguments; |
| 272 __ testq(RBX, RBX); // check if there are arguments. |
| 273 __ j(ZERO, &done_push_arguments, Assembler::kNearJump); |
| 274 __ movq(RAX, Immediate(0)); |
| 275 __ Bind(&push_arguments); |
| 276 __ movq(RCX, Address(RDX, RAX, TIMES_8, 0)); // RDX is start of arguments. |
| 277 __ movq(RCX, Address(RCX, VMHandles::kOffsetOfRawPtrInHandle)); |
| 278 __ pushq(RCX); |
| 279 __ incq(RAX); |
| 280 __ cmpq(RAX, RBX); |
| 281 __ j(LESS, &push_arguments, Assembler::kNearJump); |
| 282 __ Bind(&done_push_arguments); |
| 283 |
| 284 // Call the dart code entrypoint. |
| 285 __ call(RDI); // R10 is the arguments descriptor array. |
| 286 |
| 287 // Read the saved new Context pointer. |
| 288 __ movq(CTX, Address(RBP, kNewContextOffset)); |
| 289 __ movq(CTX, Address(CTX, VMHandles::kOffsetOfRawPtrInHandle)); |
| 290 |
| 291 // Read the saved arguments descriptor array to obtain the number of passed |
| 292 // arguments, which is the first element of the array, a Smi. |
| 293 __ movq(RSI, Address(RBP, kArgumentsDescOffset)); |
| 294 __ movq(R10, Address(RSI, VMHandles::kOffsetOfRawPtrInHandle)); |
| 295 __ movq(RDX, FieldAddress(R10, Array::data_offset())); |
| 296 // Get rid of arguments pushed on the stack. |
| 297 __ leaq(RSP, Address(RSP, RDX, TIMES_4, 0)); // RDX is a Smi. |
| 298 |
| 299 // Load Isolate pointer from Context structure into CTX. Drop Context. |
| 300 __ movq(CTX, FieldAddress(CTX, Context::isolate_offset())); |
| 301 |
| 302 // Restore the saved Context pointer into the Isolate structure. |
| 303 // Uses RCX as a temporary register for this. |
| 304 __ popq(RCX); |
| 305 __ movq(Address(CTX, Isolate::top_context_offset()), RCX); |
| 306 |
| 307 // Restore the saved top exit frame info back into the Isolate structure. |
| 308 // Uses RDX as a temporary register for this. |
| 309 __ popq(RDX); |
| 310 __ movq(Address(CTX, Isolate::top_exit_frame_info_offset()), RDX); |
| 311 |
| 312 // Restore C++ ABI callee-saved registers. |
| 313 __ popq(R15); |
| 314 __ popq(R14); |
| 315 __ popq(R13); |
| 316 __ popq(R12); |
| 317 __ popq(RBX); |
| 318 |
| 319 // Restore the frame pointer. |
| 320 __ LeaveFrame(); |
| 321 |
| 322 __ ret(); |
| 323 } |
| 324 |
| 325 |
54 void StubCode::GenerateAllocateContextStub(Assembler* assembler) { | 326 void StubCode::GenerateAllocateContextStub(Assembler* assembler) { |
55 __ Unimplemented("AllocateContext stub"); | 327 __ Unimplemented("AllocateContext stub"); |
56 } | 328 } |
57 | 329 |
58 | 330 |
59 void StubCode::GenerateAllocationStubForClass(Assembler* assembler, | 331 void StubCode::GenerateAllocationStubForClass(Assembler* assembler, |
60 const Class& cls) { | 332 const Class& cls) { |
61 __ Unimplemented("AllocateObject stub"); | 333 __ Unimplemented("AllocateObject stub"); |
62 } | 334 } |
63 | 335 |
64 | 336 |
65 void StubCode::GenerateAllocationStubForClosure(Assembler* assembler, | 337 void StubCode::GenerateAllocationStubForClosure(Assembler* assembler, |
66 const Function& func) { | 338 const Function& func) { |
67 __ Unimplemented("AllocateClosure stub"); | 339 __ Unimplemented("AllocateClosure stub"); |
68 } | 340 } |
69 | 341 |
| 342 |
| 343 void StubCode::GenerateCallNoSuchMethodFunctionStub(Assembler* assembler) { |
| 344 __ Unimplemented("CallNoSuchMethodFunction stub"); |
| 345 } |
| 346 |
| 347 |
| 348 void StubCode::GenerateInlineCacheStub(Assembler* assembler) { |
| 349 __ Unimplemented("InlineCache stub"); |
| 350 } |
| 351 |
| 352 |
| 353 void StubCode::GenerateBreakpointStaticStub(Assembler* assembler) { |
| 354 __ Unimplemented("BreakpointStatic stub"); |
| 355 } |
| 356 |
| 357 |
| 358 void StubCode::GenerateBreakpointDynamicStub(Assembler* assembler) { |
| 359 __ Unimplemented("BreakpointDynamic stub"); |
| 360 } |
| 361 |
70 } // namespace dart | 362 } // namespace dart |
71 | 363 |
72 #endif // defined TARGET_ARCH_X64 | 364 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |