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 #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/assembler.h" | 8 #include "vm/assembler.h" |
9 #include "vm/assembler_macros.h" | 9 #include "vm/assembler_macros.h" |
10 #include "vm/compiler.h" | 10 #include "vm/compiler.h" |
(...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
240 __ popq(R10); // Restore arguments descriptor array. | 240 __ popq(R10); // Restore arguments descriptor array. |
241 __ movq(RAX, FieldAddress(RAX, Function::code_offset())); | 241 __ movq(RAX, FieldAddress(RAX, Function::code_offset())); |
242 __ movq(RAX, FieldAddress(RAX, Code::instructions_offset())); | 242 __ movq(RAX, FieldAddress(RAX, Code::instructions_offset())); |
243 __ addq(RAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 243 __ addq(RAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
244 __ LeaveFrame(); | 244 __ LeaveFrame(); |
245 __ jmp(RAX); | 245 __ jmp(RAX); |
246 __ int3(); | 246 __ int3(); |
247 } | 247 } |
248 | 248 |
249 | 249 |
250 // Lookup for [function-name, arg count] in 'functions_map_'. | |
251 // Input parameters (to be treated as read only, unless calling to target!): | |
252 // RBX: ic-data. | |
253 // R10: arguments descriptor array (num_args is first Smi element). | |
254 // Stack: return address, arguments. | |
255 // If the lookup succeeds we jump to the target method from here, otherwise | |
256 // we continue in code generated by the caller of 'MegamorphicLookup'. | |
257 static void MegamorphicLookup(Assembler* assembler) { | |
258 const Immediate raw_null = | |
259 Immediate(reinterpret_cast<intptr_t>(Object::null())); | |
260 Label class_in_rax, smi_receiver, null_receiver, not_found; | |
261 // Total number of args is the first Smi in args descriptor array (R10). | |
262 __ movq(RAX, FieldAddress(R10, Array::data_offset())); | |
263 __ movq(RAX, Address(RSP, RAX, TIMES_4, 0)); // Get receiver. RAX is a Smi. | |
264 // TODO(srdjan): Remove the special casing below for null receiver, once | |
265 // NullClass is implemented. | |
266 __ cmpq(RAX, raw_null); | |
267 // Use Object class if receiver is null. | |
268 __ j(EQUAL, &null_receiver, Assembler::kNearJump); | |
269 __ testq(RAX, Immediate(kSmiTagMask)); | |
270 __ j(ZERO, &smi_receiver, Assembler::kNearJump); | |
271 __ LoadClass(RAX, RAX); | |
272 __ jmp(&class_in_rax, Assembler::kNearJump); | |
273 __ Bind(&smi_receiver); | |
274 // For Smis we need to get the class from the isolate. | |
275 // Load current Isolate pointer from Context structure into RAX. | |
276 __ movq(RAX, FieldAddress(CTX, Context::isolate_offset())); | |
277 __ movq(RAX, Address(RAX, Isolate::object_store_offset())); | |
278 __ movq(RAX, Address(RAX, ObjectStore::smi_class_offset())); | |
279 __ jmp(&class_in_rax, Assembler::kNearJump); | |
280 __ Bind(&null_receiver); | |
281 __ movq(RAX, FieldAddress(CTX, Context::isolate_offset())); | |
282 __ movq(RAX, Address(RAX, Isolate::object_store_offset())); | |
283 __ movq(RAX, Address(RAX, ObjectStore::object_class_offset())); | |
284 | |
285 __ Bind(&class_in_rax); | |
286 // Class is in RAX. | |
287 | |
288 Label loop, next_iteration; | |
289 // Get functions_cache, since it is allocated lazily it maybe null. | |
290 __ movq(RAX, FieldAddress(RAX, Class::functions_cache_offset())); | |
291 __ cmpq(RAX, raw_null); | |
292 __ j(EQUAL, ¬_found, Assembler::kNearJump); | |
293 | |
294 // Iterate and search for identical name. | |
295 __ leaq(R12, FieldAddress(RAX, Array::data_offset())); | |
296 | |
297 // R12 is pointing into content of functions_map_ array. | |
298 __ Bind(&loop); | |
299 __ movq(R13, Address(R12, FunctionsCache::kFunctionName * kWordSize)); | |
300 | |
301 __ cmpq(R13, raw_null); | |
302 __ j(EQUAL, ¬_found, Assembler::kNearJump); | |
303 | |
304 __ cmpq(R13, FieldAddress(RBX, ICData::target_name_offset())); | |
305 __ j(NOT_EQUAL, &next_iteration, Assembler::kNearJump); | |
306 | |
307 // Name found, check total argument count and named argument count. | |
308 __ movq(RAX, FieldAddress(R10, Array::data_offset())); | |
309 // RAX is total argument count as Smi. | |
310 __ movq(R13, Address(R12, FunctionsCache::kArgCount * kWordSize)); | |
311 __ cmpq(RAX, R13); // Compare total argument counts. | |
312 __ j(NOT_EQUAL, &next_iteration, Assembler::kNearJump); | |
313 __ subq(RAX, FieldAddress(R10, Array::data_offset() + kWordSize)); | |
314 // RAX is named argument count as Smi. | |
315 __ movq(R13, Address(R12, FunctionsCache::kNamedArgCount * kWordSize)); | |
316 __ cmpq(RAX, R13); // Compare named argument counts. | |
317 __ j(NOT_EQUAL, &next_iteration, Assembler::kNearJump); | |
318 | |
319 // Argument count matches, jump to target. | |
320 // R10: arguments descriptor array. | |
321 __ movq(RBX, Address(R12, FunctionsCache::kFunction * kWordSize)); | |
322 __ movq(RBX, FieldAddress(RBX, Function::code_offset())); | |
323 __ movq(RBX, FieldAddress(RBX, Code::instructions_offset())); | |
324 __ addq(RBX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | |
325 __ jmp(RBX); | |
326 | |
327 __ Bind(&next_iteration); | |
328 __ AddImmediate(R12, Immediate(FunctionsCache::kNumEntries * kWordSize)); | |
329 __ jmp(&loop, Assembler::kNearJump); | |
330 | |
331 __ Bind(¬_found); | |
332 } | |
333 | |
334 | |
335 // Input parameters: | 250 // Input parameters: |
336 // R13: argument count, may be zero. | 251 // R13: argument count, may be zero. |
337 static void PushArgumentsArray(Assembler* assembler, intptr_t arg_offset) { | 252 static void PushArgumentsArray(Assembler* assembler, intptr_t arg_offset) { |
338 const Immediate raw_null = | 253 const Immediate raw_null = |
339 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 254 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
340 | 255 |
341 // Allocate array to store arguments of caller. | 256 // Allocate array to store arguments of caller. |
342 __ movq(R10, R13); // Arguments array length. | 257 __ movq(R10, R13); // Arguments array length. |
343 __ SmiTag(R10); // Convert to Smi. | 258 __ SmiTag(R10); // Convert to Smi. |
344 __ movq(RBX, raw_null); // Null element type for raw Array. | 259 __ movq(RBX, raw_null); // Null element type for raw Array. |
(...skipping 16 matching lines...) Expand all Loading... |
361 __ j(POSITIVE, &loop, Assembler::kNearJump); | 276 __ j(POSITIVE, &loop, Assembler::kNearJump); |
362 } | 277 } |
363 | 278 |
364 | 279 |
365 // Input parameters: | 280 // Input parameters: |
366 // RBX: ic-data. | 281 // RBX: ic-data. |
367 // R10: arguments descriptor array (num_args is first Smi element). | 282 // R10: arguments descriptor array (num_args is first Smi element). |
368 // Note: The receiver object is the first argument to the function being | 283 // Note: The receiver object is the first argument to the function being |
369 // called, the stub accesses the receiver from this location directly | 284 // called, the stub accesses the receiver from this location directly |
370 // when trying to resolve the call. | 285 // when trying to resolve the call. |
371 void StubCode::GenerateMegamorphicLookupStub(Assembler* assembler) { | 286 void StubCode::GenerateInstanceFunctionLookupStub(Assembler* assembler) { |
372 const Immediate raw_null = | 287 const Immediate raw_null = |
373 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 288 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
374 | 289 |
375 MegamorphicLookup(assembler); | |
376 // Lookup in function_table_ failed, resolve, compile and enter function | |
377 // into function_table_. | |
378 | |
379 // Create a stub frame as we are pushing some objects on the stack before | 290 // Create a stub frame as we are pushing some objects on the stack before |
380 // calling into the runtime. | 291 // calling into the runtime. |
381 AssemblerMacros::EnterStubFrame(assembler); | 292 AssemblerMacros::EnterStubFrame(assembler); |
382 | 293 |
383 // Preserve values across call to resolving. | 294 // Preserve values across call to resolving. |
384 // Stack at this point: | 295 // Stack at this point: |
385 // TOS + 0: PC marker => RawInstruction object. | 296 // TOS + 0: PC marker => RawInstruction object. |
386 // TOS + 1: Saved RBP of previous frame. <== RBP | 297 // TOS + 1: Saved RBP of previous frame. <== RBP |
387 // TOS + 2: Dart code return address | 298 // TOS + 2: Dart code return address |
388 // TOS + 3: Last argument of caller. | 299 // TOS + 3: Last argument of caller. |
(...skipping 1285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1674 __ popq(RAX); | 1585 __ popq(RAX); |
1675 } | 1586 } |
1676 __ popq(RAX); // Pop returned code object into RAX (null if not found). | 1587 __ popq(RAX); // Pop returned code object into RAX (null if not found). |
1677 __ popq(RBX); // Restore IC data array. | 1588 __ popq(RBX); // Restore IC data array. |
1678 __ popq(R10); // Restore arguments array. | 1589 __ popq(R10); // Restore arguments array. |
1679 __ LeaveFrame(); | 1590 __ LeaveFrame(); |
1680 Label call_target_function; | 1591 Label call_target_function; |
1681 __ cmpq(RAX, raw_null); | 1592 __ cmpq(RAX, raw_null); |
1682 __ j(NOT_EQUAL, &call_target_function, Assembler::kNearJump); | 1593 __ j(NOT_EQUAL, &call_target_function, Assembler::kNearJump); |
1683 // NoSuchMethod or closure. | 1594 // NoSuchMethod or closure. |
1684 __ jmp(&StubCode::MegamorphicLookupLabel()); | 1595 __ jmp(&StubCode::InstanceFunctionLookupLabel()); |
1685 | 1596 |
1686 __ Bind(&found); | 1597 __ Bind(&found); |
1687 // R12: Pointer to an IC data check group (classes + target) | 1598 // R12: Pointer to an IC data check group (classes + target) |
1688 __ movq(RAX, Address(R12, kWordSize * num_args)); // Target function. | 1599 __ movq(RAX, Address(R12, kWordSize * num_args)); // Target function. |
1689 | 1600 |
1690 __ Bind(&call_target_function); | 1601 __ Bind(&call_target_function); |
1691 // RAX: Target function. | 1602 // RAX: Target function. |
1692 __ movq(RAX, FieldAddress(RAX, Function::code_offset())); | 1603 __ movq(RAX, FieldAddress(RAX, Function::code_offset())); |
1693 __ movq(RAX, FieldAddress(RAX, Code::instructions_offset())); | 1604 __ movq(RAX, FieldAddress(RAX, Code::instructions_offset())); |
1694 __ addq(RAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 1605 __ addq(RAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1936 void StubCode::GenerateJumpToErrorHandlerStub(Assembler* assembler) { | 1847 void StubCode::GenerateJumpToErrorHandlerStub(Assembler* assembler) { |
1937 __ movq(RAX, RCX); // error object. | 1848 __ movq(RAX, RCX); // error object. |
1938 __ movq(RBP, RDX); // target frame_pointer. | 1849 __ movq(RBP, RDX); // target frame_pointer. |
1939 __ movq(RSP, RSI); // target stack_pointer. | 1850 __ movq(RSP, RSI); // target stack_pointer. |
1940 __ jmp(RDI); // Jump to the exception handler code. | 1851 __ jmp(RDI); // Jump to the exception handler code. |
1941 } | 1852 } |
1942 | 1853 |
1943 } // namespace dart | 1854 } // namespace dart |
1944 | 1855 |
1945 #endif // defined TARGET_ARCH_X64 | 1856 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |