340 341 // Generates a register specific stub for calling 342 // ZBarrierSetRuntime::load_barrier_on_oop_field_preloaded() or 343 // ZBarrierSetRuntime::load_barrier_on_weak_oop_field_preloaded(). 344 // 345 // The raddr register serves as both input and output for this stub. When the stub is 346 // called the raddr register contains the object field address (oop*) where the bad oop 347 // was loaded from, which caused the slow path to be taken. On return from the stub the 348 // raddr register contains the good/healed oop returned from 349 // ZBarrierSetRuntime::load_barrier_on_oop_field_preloaded() or 350 // ZBarrierSetRuntime::load_barrier_on_weak_oop_field_preloaded(). 351 static address generate_load_barrier_stub(StubCodeGenerator* cgen, Register raddr, DecoratorSet decorators) { 352 // Don't generate stub for invalid registers 353 if (raddr == rsp || raddr == r12 || raddr == r15) { 354 return NULL; 355 } 356 357 // Create stub name 358 char name[64]; 359 const bool weak = (decorators & ON_WEAK_OOP_REF) != 0; 360 os::snprintf(name, sizeof(name), "load_barrier%s_stub_%s", weak ? "_weak" : "", raddr->name()); 361 362 __ align(CodeEntryAlignment); 363 StubCodeMark mark(cgen, "StubRoutines", os::strdup(name, mtCode)); 364 address start = __ pc(); 365 366 // Save live registers 367 if (raddr != rax) { 368 __ push(rax); 369 } 370 if (raddr != rcx) { 371 __ push(rcx); 372 } 373 if (raddr != rdx) { 374 __ push(rdx); 375 } 376 if (raddr != rsi) { 377 __ push(rsi); 378 } 379 if (raddr != rdi) { 380 __ push(rdi); 381 } 382 if (raddr != r8) { 383 __ push(r8); 384 } 385 if (raddr != r9) { 386 __ push(r9); 387 } 388 if (raddr != r10) { 389 __ push(r10); 390 } 391 if (raddr != r11) { 392 __ push(r11); 393 } 394 395 // Setup arguments 396 if (c_rarg1 != raddr) { 397 __ movq(c_rarg1, raddr); 398 } 399 __ movq(c_rarg0, Address(raddr, 0)); 400 401 // Call barrier function 402 __ call_VM_leaf(ZBarrierSetRuntime::load_barrier_on_oop_field_preloaded_addr(decorators), c_rarg0, c_rarg1); 403 404 // Move result returned in rax to raddr, if needed 405 if (raddr != rax) { 406 __ movq(raddr, rax); 407 } 408 409 // Restore saved registers 410 if (raddr != r11) { 411 __ pop(r11); 412 } 413 if (raddr != r10) { 414 __ pop(r10); 415 } 416 if (raddr != r9) { 425 if (raddr != rsi) { 426 __ pop(rsi); 427 } 428 if (raddr != rdx) { 429 __ pop(rdx); 430 } 431 if (raddr != rcx) { 432 __ pop(rcx); 433 } 434 if (raddr != rax) { 435 __ pop(rax); 436 } 437 438 __ ret(0); 439 440 return start; 441 } 442 443 #undef __ 444 445 void ZBarrierSetAssembler::barrier_stubs_init() { 446 // Load barrier stubs 447 int stub_code_size = 256 * 16; // Rough estimate of code size 448 449 ResourceMark rm; 450 BufferBlob* bb = BufferBlob::create("zgc_load_barrier_stubs", stub_code_size); 451 CodeBuffer buf(bb); 452 StubCodeGenerator cgen(&buf); 453 454 Register rr = as_Register(0); 455 for (int i = 0; i < RegisterImpl::number_of_registers; i++) { 456 _load_barrier_slow_stub[i] = generate_load_barrier_stub(&cgen, rr, ON_STRONG_OOP_REF); 457 _load_barrier_weak_slow_stub[i] = generate_load_barrier_stub(&cgen, rr, ON_WEAK_OOP_REF); 458 rr = rr->successor(); 459 } 460 } | 340 341 // Generates a register specific stub for calling 342 // ZBarrierSetRuntime::load_barrier_on_oop_field_preloaded() or 343 // ZBarrierSetRuntime::load_barrier_on_weak_oop_field_preloaded(). 344 // 345 // The raddr register serves as both input and output for this stub. When the stub is 346 // called the raddr register contains the object field address (oop*) where the bad oop 347 // was loaded from, which caused the slow path to be taken. On return from the stub the 348 // raddr register contains the good/healed oop returned from 349 // ZBarrierSetRuntime::load_barrier_on_oop_field_preloaded() or 350 // ZBarrierSetRuntime::load_barrier_on_weak_oop_field_preloaded(). 351 static address generate_load_barrier_stub(StubCodeGenerator* cgen, Register raddr, DecoratorSet decorators) { 352 // Don't generate stub for invalid registers 353 if (raddr == rsp || raddr == r12 || raddr == r15) { 354 return NULL; 355 } 356 357 // Create stub name 358 char name[64]; 359 const bool weak = (decorators & ON_WEAK_OOP_REF) != 0; 360 os::snprintf(name, sizeof(name), "zgc_load_barrier%s_stub_%s", weak ? "_weak" : "", raddr->name()); 361 362 __ align(CodeEntryAlignment); 363 StubCodeMark mark(cgen, "StubRoutines", os::strdup(name, mtCode)); 364 address start = __ pc(); 365 366 // Save live registers 367 if (raddr != rax) { 368 __ push(rax); 369 } 370 if (raddr != rcx) { 371 __ push(rcx); 372 } 373 if (raddr != rdx) { 374 __ push(rdx); 375 } 376 if (raddr != rsi) { 377 __ push(rsi); 378 } 379 if (raddr != rdi) { 380 __ push(rdi); 381 } 382 if (raddr != r8) { 383 __ push(r8); 384 } 385 if (raddr != r9) { 386 __ push(r9); 387 } 388 if (raddr != r10) { 389 __ push(r10); 390 } 391 if (raddr != r11) { 392 __ push(r11); 393 } 394 395 // Setup arguments 396 if (raddr != c_rarg1) { 397 __ movq(c_rarg1, raddr); 398 } 399 __ movq(c_rarg0, Address(raddr, 0)); 400 401 // Call barrier function 402 __ call_VM_leaf(ZBarrierSetRuntime::load_barrier_on_oop_field_preloaded_addr(decorators), c_rarg0, c_rarg1); 403 404 // Move result returned in rax to raddr, if needed 405 if (raddr != rax) { 406 __ movq(raddr, rax); 407 } 408 409 // Restore saved registers 410 if (raddr != r11) { 411 __ pop(r11); 412 } 413 if (raddr != r10) { 414 __ pop(r10); 415 } 416 if (raddr != r9) { 425 if (raddr != rsi) { 426 __ pop(rsi); 427 } 428 if (raddr != rdx) { 429 __ pop(rdx); 430 } 431 if (raddr != rcx) { 432 __ pop(rcx); 433 } 434 if (raddr != rax) { 435 __ pop(rax); 436 } 437 438 __ ret(0); 439 440 return start; 441 } 442 443 #undef __ 444 445 static void barrier_stubs_init_inner(const char* label, const DecoratorSet decorators, address* stub) { 446 const int nregs = RegisterImpl::number_of_registers; 447 const int code_size = nregs * 128; // Rough estimate of code size 448 449 ResourceMark rm; 450 451 CodeBuffer buf(BufferBlob::create(label, code_size)); 452 StubCodeGenerator cgen(&buf); 453 454 for (int i = 0; i < nregs; i++) { 455 const Register reg = as_Register(i); 456 stub[i] = generate_load_barrier_stub(&cgen, reg, decorators); 457 } 458 } 459 460 void ZBarrierSetAssembler::barrier_stubs_init() { 461 barrier_stubs_init_inner("zgc_load_barrier_stubs", ON_STRONG_OOP_REF, _load_barrier_slow_stub); 462 barrier_stubs_init_inner("zgc_load_barrier_weak_stubs", ON_WEAK_OOP_REF, _load_barrier_weak_slow_stub); 463 } |