| 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 |