Changeset 220958 in webkit for trunk/Source/JavaScriptCore/assembler/MacroAssemblerARM64.cpp
- Timestamp:
- Aug 20, 2017, 9:26:40 PM (8 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/assembler/MacroAssemblerARM64.cpp
r220921 r220958 29 29 #include "MacroAssembler.h" 30 30 31 #include "ProbeContext.h" 31 32 #include <wtf/InlineASM.h> 32 33 … … 127 128 128 129 #define SAVED_PROBE_RETURN_PC_OFFSET (PROBE_SIZE + (0 * PTR_SIZE)) 129 #define SAVED_PROBE_LR_OFFSET (PROBE_SIZE + (1 * PTR_SIZE))130 #define SAVED_PROBE_ERROR_FUNCTION_OFFSET (PROBE_SIZE + (2 * PTR_SIZE))131 130 #define PROBE_SIZE_PLUS_EXTRAS (PROBE_SIZE + (3 * PTR_SIZE)) 132 131 … … 226 225 227 226 struct IncomingProbeRecord { 228 uintptr_t probeHandlerFunction;229 uintptr_t probeArg;227 uintptr_t x24; 228 uintptr_t x25; 230 229 uintptr_t x26; 231 230 uintptr_t x27; 232 uintptr_t lr; 233 uintptr_t sp; 234 uintptr_t probeErrorFunction; 235 uintptr_t unused; // Padding for alignment. 231 uintptr_t x28; 232 uintptr_t x30; // lr 236 233 }; 237 234 238 #define IN_ HANDLER_FUNCTION_OFFSET (0 * PTR_SIZE)239 #define IN_ ARG_OFFSET(1 * PTR_SIZE)240 #define IN_X26_OFFSET 241 #define IN_X27_OFFSET 242 #define IN_ LR_OFFSET(4 * PTR_SIZE)243 #define IN_ SP_OFFSET(5 * PTR_SIZE)244 #define IN_ ERROR_FUNCTION_OFFSET(6 * PTR_SIZE)245 246 static_assert(IN_ HANDLER_FUNCTION_OFFSET == offsetof(IncomingProbeRecord, probeHandlerFunction), "IN_HANDLER_FUNCTION_OFFSET is incorrect");247 static_assert(IN_ ARG_OFFSET == offsetof(IncomingProbeRecord, probeArg), "IN_ARG_OFFSET is incorrect");235 #define IN_X24_OFFSET (0 * PTR_SIZE) 236 #define IN_X25_OFFSET (1 * PTR_SIZE) 237 #define IN_X26_OFFSET (2 * PTR_SIZE) 238 #define IN_X27_OFFSET (3 * PTR_SIZE) 239 #define IN_X28_OFFSET (4 * PTR_SIZE) 240 #define IN_X30_OFFSET (5 * PTR_SIZE) 241 #define IN_SIZE (6 * PTR_SIZE) 242 243 static_assert(IN_X24_OFFSET == offsetof(IncomingProbeRecord, x24), "IN_X24_OFFSET is incorrect"); 244 static_assert(IN_X25_OFFSET == offsetof(IncomingProbeRecord, x25), "IN_X25_OFFSET is incorrect"); 248 245 static_assert(IN_X26_OFFSET == offsetof(IncomingProbeRecord, x26), "IN_X26_OFFSET is incorrect"); 249 246 static_assert(IN_X27_OFFSET == offsetof(IncomingProbeRecord, x27), "IN_X27_OFFSET is incorrect"); 250 static_assert(IN_ LR_OFFSET == offsetof(IncomingProbeRecord, lr), "IN_LR_OFFSET is incorrect");251 static_assert(IN_ SP_OFFSET == offsetof(IncomingProbeRecord, sp), "IN_SP_OFFSET is incorrect");252 static_assert(IN_ ERROR_FUNCTION_OFFSET == offsetof(IncomingProbeRecord, probeErrorFunction), "IN_ERROR_FUNCTION_OFFSETis incorrect");247 static_assert(IN_X28_OFFSET == offsetof(IncomingProbeRecord, x28), "IN_X22_OFFSET is incorrect"); 248 static_assert(IN_X30_OFFSET == offsetof(IncomingProbeRecord, x30), "IN_X23_OFFSET is incorrect"); 249 static_assert(IN_SIZE == sizeof(IncomingProbeRecord), "IN_SIZE is incorrect"); 253 250 static_assert(!(sizeof(IncomingProbeRecord) & 0xf), "IncomingProbeStack must be 16-byte aligned"); 254 251 … … 279 276 static_assert(!(sizeof(OutgoingProbeRecord) & 0xf), "OutgoingProbeStack must be 16-byte aligned"); 280 277 281 #define STATE_PC_NOT_CHANGED 0 282 #define STATE_PC_CHANGED 1 283 static_assert(STATE_PC_NOT_CHANGED != STATE_PC_CHANGED, "STATE_PC_NOT_CHANGED and STATE_PC_CHANGED should not be equal"); 278 struct LRRestorationRecord { 279 uintptr_t lr; 280 uintptr_t unusedDummyToEnsureSizeIs16ByteAligned; 281 }; 282 283 #define LR_RESTORATION_LR_OFFSET (0 * PTR_SIZE) 284 #define LR_RESTORATION_SIZE (2 * PTR_SIZE) 285 286 static_assert(LR_RESTORATION_LR_OFFSET == offsetof(LRRestorationRecord, lr), "LR_RESTORATION_LR_OFFSET is incorrect"); 287 static_assert(LR_RESTORATION_SIZE == sizeof(LRRestorationRecord), "LR_RESTORATION_SIZE is incorrect"); 288 static_assert(!(sizeof(LRRestorationRecord) & 0xf), "LRRestorationRecord must be 16-byte aligned"); 284 289 285 290 // We use x29 and x30 instead of fp and lr because GCC's inline assembler does not recognize fp and lr. … … 294 299 // MacroAssemblerARM64::probe() has already generated code to store some values in an 295 300 // IncomingProbeRecord. sp points to the IncomingProbeRecord. 301 // 302 // Incoming register values: 303 // x24: probe function 304 // x25: probe arg 305 // x26: scratch, was ctiMasmProbeTrampoline 306 // x27: scratch 307 // x28: Probe::executeProbe 308 // x30: return address 296 309 297 310 "mov x26, sp" "\n" … … 301 314 "bic x27, x27, #0xf" "\n" // The ARM EABI specifies that the stack needs to be 16 byte aligned. 302 315 "mov sp, x27" "\n" // Set the sp to protect the Probe::State from interrupts before we initialize it. 316 317 "stp x24, x25, [sp, #" STRINGIZE_VALUE_OF(PROBE_PROBE_FUNCTION_OFFSET) "]" "\n" // Store the probe handler function and arg (preloaded into x24 and x25 303 318 304 319 "stp x0, x1, [sp, #" STRINGIZE_VALUE_OF(PROBE_CPU_X0_OFFSET) "]" "\n" … … 310 325 "stp x8, x9, [sp, #" STRINGIZE_VALUE_OF(PROBE_CPU_X8_OFFSET) "]" "\n" 311 326 312 "ldp x2, x3, [x26, #" STRINGIZE_VALUE_OF(IN_ HANDLER_FUNCTION_OFFSET) "]" "\n" // Preload probe handler function and probe arg.313 "ldp x4, x5, [x26, #" STRINGIZE_VALUE_OF(IN_X26_OFFSET) "]" "\n" // Preload saved r26 and r27.314 "ldp x6, x7, [x26, #" STRINGIZE_VALUE_OF(IN_ LR_OFFSET) "]" "\n" // Preload saved lr and sp.315 " ldr x8, [x26, #" STRINGIZE_VALUE_OF(IN_ERROR_FUNCTION_OFFSET) "]" "\n" // Preload probe error function.327 "ldp x2, x3, [x26, #" STRINGIZE_VALUE_OF(IN_X24_OFFSET) "]" "\n" // Preload saved x24 and x25. 328 "ldp x4, x5, [x26, #" STRINGIZE_VALUE_OF(IN_X26_OFFSET) "]" "\n" // Preload saved x26 and x27. 329 "ldp x6, x7, [x26, #" STRINGIZE_VALUE_OF(IN_X28_OFFSET) "]" "\n" // Preload saved x28 and lr. 330 "add x26, x26, #" STRINGIZE_VALUE_OF(IN_SIZE) "\n" // Compute the sp before the probe. 316 331 317 332 "stp x10, x11, [sp, #" STRINGIZE_VALUE_OF(PROBE_CPU_X10_OFFSET) "]" "\n" … … 322 337 "stp x20, x21, [sp, #" STRINGIZE_VALUE_OF(PROBE_CPU_X20_OFFSET) "]" "\n" 323 338 "stp x22, x23, [sp, #" STRINGIZE_VALUE_OF(PROBE_CPU_X22_OFFSET) "]" "\n" 324 "stp x2 4, x25, [sp, #" STRINGIZE_VALUE_OF(PROBE_CPU_X24_OFFSET) "]" "\n"339 "stp x2, x3, [sp, #" STRINGIZE_VALUE_OF(PROBE_CPU_X24_OFFSET) "]" "\n" // Store saved r24 and r25 (preloaded into x2 and x3 above). 325 340 "stp x4, x5, [sp, #" STRINGIZE_VALUE_OF(PROBE_CPU_X26_OFFSET) "]" "\n" // Store saved r26 and r27 (preloaded into x4 and x5 above). 326 "stp x28, x29, [sp, #" STRINGIZE_VALUE_OF(PROBE_CPU_X28_OFFSET) "]" "\n" 327 "stp x6, x7, [sp, #" STRINGIZE_VALUE_OF(PROBE_CPU_LR_OFFSET) "]" "\n" // Save values lr and sp (preloaded into x6 and x7 above). 328 329 "str x6, [sp, #" STRINGIZE_VALUE_OF(SAVED_PROBE_LR_OFFSET) "]" "\n" // Save a duplicate copy of lr (in x6). 341 "stp x6, x29, [sp, #" STRINGIZE_VALUE_OF(PROBE_CPU_X28_OFFSET) "]" "\n" 342 "stp x7, x26, [sp, #" STRINGIZE_VALUE_OF(PROBE_CPU_LR_OFFSET) "]" "\n" // Save values lr and sp (original sp value computed into x26 above). 343 330 344 "str x30, [sp, #" STRINGIZE_VALUE_OF(SAVED_PROBE_RETURN_PC_OFFSET) "]" "\n" // Save a duplicate copy of return pc (in lr). 331 345 … … 334 348 335 349 "stp x0, x1, [sp, #" STRINGIZE_VALUE_OF(PROBE_CPU_NZCV_OFFSET) "]" "\n" // Store nzcv and fpsr (preloaded into x0 and x1 above). 336 337 "stp x2, x3, [sp, #" STRINGIZE_VALUE_OF(PROBE_PROBE_FUNCTION_OFFSET) "]" "\n" // Store the probe handler function and arg (preloaded into x2 and x3 above).338 "str x8, [sp, #" STRINGIZE_VALUE_OF(SAVED_PROBE_ERROR_FUNCTION_OFFSET) "]" "\n" // Store the probe handler function and arg (preloaded into x8 above).339 350 340 351 "add x9, sp, #" STRINGIZE_VALUE_OF(PROBE_CPU_Q0_OFFSET) "\n" … … 358 369 "mov x27, sp" "\n" // Save the Probe::State* in a callee saved register. 359 370 360 // Initialize Probe::State::initializeStackFunction to zero.361 "str xzr, [x27, #" STRINGIZE_VALUE_OF(PROBE_INIT_STACK_FUNCTION_OFFSET) "]" "\n"362 363 371 // Note: we haven't changed the value of fp. Hence, it is still pointing to the frame of 364 372 // the caller of the probe (which is what we want in order to play nice with debuggers e.g. lldb). 365 373 "mov x0, sp" "\n" // Set the Probe::State* arg. 366 "blr x2 " "\n" // Call the probe handler function (loaded into x2 above).374 "blr x28" "\n" // Call the probe handler. 367 375 368 376 // Make sure the Probe::State is entirely below the result stack pointer so … … 447 455 // Remaining registers to restore are: fpsr, nzcv, x27, x28, fp, lr, sp, and pc. 448 456 449 "mov x30, #" STRINGIZE_VALUE_OF(STATE_PC_NOT_CHANGED) "\n"450 451 457 // The only way to set the pc on ARM64 (from user space) is via an indirect branch 452 458 // or a ret, which means we'll need a free register to do so. For our purposes, lr … … 455 461 // returns. So, the ARM64 probe implementation will allow the probe handler to 456 462 // either modify lr or pc, but not both in the same probe invocation. The probe 457 // mechanism ensures that we never try to modify both lr and pc , else it will458 // fail with a RELEASE_ASSERT_NOT_REACHED in arm64ProbeError().463 // mechanism ensures that we never try to modify both lr and pc with a RELEASE_ASSERT 464 // in Probe::executeProbe(). 459 465 460 466 // Determine if the probe handler changed the pc. 467 "ldr x30, [sp, #" STRINGIZE_VALUE_OF(PROBE_CPU_SP_OFFSET) "]" "\n" // preload the target sp. 461 468 "ldr x27, [sp, #" STRINGIZE_VALUE_OF(SAVED_PROBE_RETURN_PC_OFFSET) "]" "\n" 462 469 "ldr x28, [sp, #" STRINGIZE_VALUE_OF(PROBE_CPU_PC_OFFSET) "]" "\n" 463 470 "add x27, x27, #" STRINGIZE_VALUE_OF(2 * PTR_SIZE) "\n" 464 471 "cmp x27, x28" "\n" 465 "beq " LOCAL_LABEL_STRING(ctiMasmProbeTrampolinePrepareOutgoingRecords) "\n" 466 467 // pc was changed. Determine if the probe handler also changed lr. 468 "ldr x27, [sp, #" STRINGIZE_VALUE_OF(SAVED_PROBE_LR_OFFSET) "]" "\n" 469 "ldr x28, [sp, #" STRINGIZE_VALUE_OF(PROBE_CPU_LR_OFFSET) "]" "\n" 470 "cmp x27, x28" "\n" 471 "bne " LOCAL_LABEL_STRING(ctiMasmProbeTrampolineError) "\n" 472 473 "mov x30, #" STRINGIZE_VALUE_OF(STATE_PC_CHANGED) "\n" 474 475 LOCAL_LABEL_STRING(ctiMasmProbeTrampolinePrepareOutgoingRecords) ":" "\n" 476 477 "ldr x29, [sp, #" STRINGIZE_VALUE_OF(SAVED_PROBE_RETURN_PC_OFFSET) "]" "\n" // Preload the probe return site pc. 478 479 LOCAL_LABEL_STRING(ctiMasmProbeTrampolineFillOutgoingProbeRecords) ":" "\n" 480 481 "cbnz x30, " LOCAL_LABEL_STRING(ctiMasmProbeTrampolineEnd) "\n" // Skip lr restoration setup if state (in lr) == STATE_PC_CHANGED. 482 483 // In order to restore lr, we need to do the restoration at the probe return site. 484 // The probe return site expects sp to be pointing at an OutgoingProbeRecord such that 485 // popping the OutgoingProbeRecord will yield the desired sp. The probe return site 486 // also expects the lr value to be restored is stashed in the OutgoingProbeRecord. 487 // We can make this happen by pushing 2 OutgoingProbeRecords instead of 1: 488 // 1 for the probe return site, and 1 at ctiMasmProbeTrampolineEnd for returning from 489 // this probe. 490 491 // Fill in the OutgoingProbeStack for the probe return site. 492 "ldr x30, [sp, #" STRINGIZE_VALUE_OF(PROBE_CPU_SP_OFFSET) "]" "\n" 493 "sub x30, x30, #" STRINGIZE_VALUE_OF(OUT_SIZE) "\n" 494 472 "bne " LOCAL_LABEL_STRING(ctiMasmProbeTrampolineEnd) "\n" 473 474 // We didn't change the PC. So, let's prepare for setting a potentially new lr value. 475 476 // 1. Make room for the LRRestorationRecord. The probe site will pop this off later. 477 "sub x30, x30, #" STRINGIZE_VALUE_OF(LR_RESTORATION_SIZE) "\n" 478 // 2. Store the lp value to restore at the probe return site. 495 479 "ldr x27, [sp, #" STRINGIZE_VALUE_OF(PROBE_CPU_LR_OFFSET) "]" "\n" 496 "str x27, [x30, #" STRINGIZE_VALUE_OF(OUT_LR_OFFSET) "]" "\n" 497 498 // Set up the sp and pc values so that ctiMasmProbeTrampolineEnd will return to the probe return site. 499 "str x30, [sp, #" STRINGIZE_VALUE_OF(PROBE_CPU_SP_OFFSET) "]" "\n" 500 "str x29, [sp, #" STRINGIZE_VALUE_OF(PROBE_CPU_PC_OFFSET) "]" "\n" // Store the probe return site pc (preloaded into fp above). 480 "str x27, [x30, #" STRINGIZE_VALUE_OF(LR_RESTORATION_LR_OFFSET) "]" "\n" 481 // 3. Force the return ramp to return to the probe return site. 482 "ldr x27, [sp, #" STRINGIZE_VALUE_OF(SAVED_PROBE_RETURN_PC_OFFSET) "]" "\n" 483 "str x27, [sp, #" STRINGIZE_VALUE_OF(PROBE_CPU_PC_OFFSET) "]" "\n" 501 484 502 485 LOCAL_LABEL_STRING(ctiMasmProbeTrampolineEnd) ":" "\n" 503 486 504 // Fill in the OutgoingProbeStack. 505 "ldr x30, [sp, #" STRINGIZE_VALUE_OF(PROBE_CPU_SP_OFFSET) "]" "\n" 487 // Fill in the OutgoingProbeRecord. 506 488 "sub x30, x30, #" STRINGIZE_VALUE_OF(OUT_SIZE) "\n" 507 489 … … 511 493 "stp x27, x28, [x30, #" STRINGIZE_VALUE_OF(OUT_X27_OFFSET) "]" "\n" 512 494 "ldr x27, [sp, #" STRINGIZE_VALUE_OF(PROBE_CPU_FP_OFFSET) "]" "\n" 513 "ldr x28, [sp, #" STRINGIZE_VALUE_OF(PROBE_CPU_PC_OFFSET) "]" "\n" 495 "ldr x28, [sp, #" STRINGIZE_VALUE_OF(PROBE_CPU_PC_OFFSET) "]" "\n" // Set up the outgoing record so that we'll jump to the new PC. 514 496 "stp x27, x28, [x30, #" STRINGIZE_VALUE_OF(OUT_FP_OFFSET) "]" "\n" 515 497 "mov sp, x30" "\n" 516 498 517 // Restore the remaining registers and pop the OutgoingProbe Stack.499 // Restore the remaining registers and pop the OutgoingProbeRecord. 518 500 "ldp x27, x28, [sp], #" STRINGIZE_VALUE_OF(2 * PTR_SIZE) "\n" 519 501 "msr nzcv, x27" "\n" … … 522 504 "ldp x29, x30, [sp], #" STRINGIZE_VALUE_OF(2 * PTR_SIZE) "\n" 523 505 "ret" "\n" 524 525 LOCAL_LABEL_STRING(ctiMasmProbeTrampolineError) ":" "\n"526 // The probe handler changed both lr and pc. This is not supported for ARM64.527 "ldr x1, [sp, #" STRINGIZE_VALUE_OF(SAVED_PROBE_ERROR_FUNCTION_OFFSET) "]" "\n"528 "mov x0, sp" "\n" // Set the Probe::State* arg.529 "blr x1" "\n"530 "brk #0x1000" // Should never return here.531 506 ); 532 507 #endif // COMPILER(GCC_OR_CLANG) 533 534 static NO_RETURN_DUE_TO_CRASH void arm64ProbeError(Probe::State*)535 {536 dataLog("MacroAssembler probe ERROR: ARM64 does not support the probe changing both LR and PC.\n");537 RELEASE_ASSERT_NOT_REACHED();538 }539 508 540 509 void MacroAssembler::probe(Probe::Function function, void* arg) … … 542 511 sub64(TrustedImm32(sizeof(IncomingProbeRecord)), sp); 543 512 513 storePair64(x24, x25, sp, TrustedImm32(offsetof(IncomingProbeRecord, x24))); 544 514 storePair64(x26, x27, sp, TrustedImm32(offsetof(IncomingProbeRecord, x26))); 545 add64(TrustedImm32(sizeof(IncomingProbeRecord)), sp, x26); 546 storePair64(lr, x26, sp, TrustedImm32(offsetof(IncomingProbeRecord, lr))); // Save lr and original sp value. 547 move(TrustedImmPtr(reinterpret_cast<void*>(function)), x26); 548 move(TrustedImmPtr(arg), x27); 549 storePair64(x26, x27, sp, TrustedImm32(offsetof(IncomingProbeRecord, probeHandlerFunction))); 550 move(TrustedImmPtr(reinterpret_cast<void*>(arm64ProbeError)), x27); 551 store64(x27, Address(sp, offsetof(IncomingProbeRecord, probeErrorFunction))); 552 515 storePair64(x28, x30, sp, TrustedImm32(offsetof(IncomingProbeRecord, x28))); // Note: x30 is lr. 553 516 move(TrustedImmPtr(reinterpret_cast<void*>(ctiMasmProbeTrampoline)), x26); 517 move(TrustedImmPtr(reinterpret_cast<void*>(Probe::executeProbe)), x28); 518 move(TrustedImmPtr(reinterpret_cast<void*>(function)), x24); 519 move(TrustedImmPtr(arg), x25); 554 520 m_assembler.blr(x26); 555 521 556 522 // ctiMasmProbeTrampoline should have restored every register except for lr and the sp. 557 load64(Address(sp, offsetof( OutgoingProbeRecord, lr)), lr);558 add64(TrustedImm32(sizeof( OutgoingProbeRecord)), sp);523 load64(Address(sp, offsetof(LRRestorationRecord, lr)), lr); 524 add64(TrustedImm32(sizeof(LRRestorationRecord)), sp); 559 525 } 560 526
Note:
See TracChangeset
for help on using the changeset viewer.