comparison src/share/vm/graal/graalCodeInstaller.cpp @ 3563:8780fa370aab

Support runtime calls to targets that don't fit in a 32-bit immediate: allow to query the maximum offset of a CiRuntimeCall target to determine the required immediate size and patch call sites with a mov/call instruction pair for indirect calls
author Peter Hofer <peter.hofer@jku.at>
date Wed, 31 Aug 2011 14:55:40 +0200
parents bea018622324
children 409ef3a68dc8
comparison
equal deleted inserted replaced
3562:549b9bcb8db6 3563:8780fa370aab
584 584
585 oop debug_info = CiTargetMethod_Call::debugInfo(site); 585 oop debug_info = CiTargetMethod_Call::debugInfo(site);
586 586
587 assert((runtime_call ? 1 : 0) + (hotspot_method ? 1 : 0) + (global_stub ? 1 : 0) == 1, "Call site needs exactly one type"); 587 assert((runtime_call ? 1 : 0) + (hotspot_method ? 1 : 0) + (global_stub ? 1 : 0) == 1, "Call site needs exactly one type");
588 588
589 assert(NativeCall::instruction_size == (int)NativeJump::instruction_size, "unexpected size)"); 589 NativeInstruction* inst = nativeInstruction_at(_instructions->start() + pc_offset);
590 jint next_pc_offset = pc_offset + NativeCall::instruction_size; 590 jint next_pc_offset = 0x0;
591 if (inst->is_call() || inst->is_jump()) {
592 assert(NativeCall::instruction_size == (int)NativeJump::instruction_size, "unexpected size");
593 next_pc_offset = pc_offset + NativeCall::instruction_size;
594 } else if (inst->is_mov_literal64()) {
595 // mov+call instruction pair
596 next_pc_offset = pc_offset + NativeMovConstReg::instruction_size;
597 u_char* call = (u_char*) (_instructions->start() + next_pc_offset);
598 assert((call[0] == 0x40 || call[0] == 0x41) && call[1] == 0xFF, "expected call with rex/rexb prefix byte");
599 next_pc_offset += 3; /* prefix byte + opcode byte + modrm byte */
600 } else {
601 runtime_call->print();
602 fatal("unsupported type of instruction for call site");
603 }
591 604
592 if (debug_info != NULL) { 605 if (debug_info != NULL) {
593 _debug_recorder->add_safepoint(next_pc_offset, create_oop_map(_frame_size, _parameter_count, debug_info)); 606 _debug_recorder->add_safepoint(next_pc_offset, create_oop_map(_frame_size, _parameter_count, debug_info));
594 oop code_pos = CiDebugInfo::codePos(debug_info); 607 oop code_pos = CiDebugInfo::codePos(debug_info);
595 record_scope(next_pc_offset, code_pos, new GrowableArray<ScopeValue*>()); 608 record_scope(next_pc_offset, code_pos, new GrowableArray<ScopeValue*>());
596 } 609 }
597 610
598 if (runtime_call != NULL) { 611 if (runtime_call != NULL) {
599 NativeCall* call = nativeCall_at(_instructions->start() + pc_offset); 612 address target_addr = 0x0;
600 if (runtime_call == CiRuntimeCall::Debug()) { 613 if (runtime_call == CiRuntimeCall::Debug()) {
601 TRACE_graal_3("CiRuntimeCall::Debug()"); 614 TRACE_graal_3("CiRuntimeCall::Debug()");
602 } else if (runtime_call == CiRuntimeCall::UnwindException()) { 615 } else if (runtime_call == CiRuntimeCall::UnwindException()) {
603 call->set_destination(Runtime1::entry_for(Runtime1::graal_unwind_exception_call_id)); 616 target_addr = Runtime1::entry_for(Runtime1::graal_unwind_exception_call_id);
604 _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand);
605 TRACE_graal_3("CiRuntimeCall::UnwindException()"); 617 TRACE_graal_3("CiRuntimeCall::UnwindException()");
606 } else if (runtime_call == CiRuntimeCall::HandleException()) { 618 } else if (runtime_call == CiRuntimeCall::HandleException()) {
607 call->set_destination(Runtime1::entry_for(Runtime1::graal_handle_exception_id)); 619 target_addr = Runtime1::entry_for(Runtime1::graal_handle_exception_id);
608 _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand);
609 TRACE_graal_3("CiRuntimeCall::HandleException()"); 620 TRACE_graal_3("CiRuntimeCall::HandleException()");
610 } else if (runtime_call == CiRuntimeCall::SetDeoptInfo()) { 621 } else if (runtime_call == CiRuntimeCall::SetDeoptInfo()) {
611 call->set_destination(Runtime1::entry_for(Runtime1::graal_set_deopt_info_id)); 622 target_addr = Runtime1::entry_for(Runtime1::graal_set_deopt_info_id);
612 _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand);
613 TRACE_graal_3("CiRuntimeCall::SetDeoptInfo()"); 623 TRACE_graal_3("CiRuntimeCall::SetDeoptInfo()");
614 } else if (runtime_call == CiRuntimeCall::CreateNullPointerException()) { 624 } else if (runtime_call == CiRuntimeCall::CreateNullPointerException()) {
615 call->set_destination(Runtime1::entry_for(Runtime1::graal_create_null_pointer_exception_id)); 625 target_addr = Runtime1::entry_for(Runtime1::graal_create_null_pointer_exception_id);
616 _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand);
617 TRACE_graal_3("CiRuntimeCall::CreateNullPointerException()"); 626 TRACE_graal_3("CiRuntimeCall::CreateNullPointerException()");
618 } else if (runtime_call == CiRuntimeCall::CreateOutOfBoundsException()) { 627 } else if (runtime_call == CiRuntimeCall::CreateOutOfBoundsException()) {
619 call->set_destination(Runtime1::entry_for(Runtime1::graal_create_out_of_bounds_exception_id)); 628 target_addr = Runtime1::entry_for(Runtime1::graal_create_out_of_bounds_exception_id);
620 _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand);
621 TRACE_graal_3("CiRuntimeCall::CreateOutOfBoundsException()"); 629 TRACE_graal_3("CiRuntimeCall::CreateOutOfBoundsException()");
622 } else if (runtime_call == CiRuntimeCall::JavaTimeMillis()) { 630 } else if (runtime_call == CiRuntimeCall::JavaTimeMillis()) {
623 call->set_destination(CAST_FROM_FN_PTR(address, os::javaTimeMillis)); 631 target_addr = CAST_FROM_FN_PTR(address, os::javaTimeMillis);
624 _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand);
625 TRACE_graal_3("CiRuntimeCall::JavaTimeMillis()"); 632 TRACE_graal_3("CiRuntimeCall::JavaTimeMillis()");
626 } else if (runtime_call == CiRuntimeCall::JavaTimeNanos()) { 633 } else if (runtime_call == CiRuntimeCall::JavaTimeNanos()) {
627 call->set_destination(CAST_FROM_FN_PTR(address, os::javaTimeNanos)); 634 target_addr = CAST_FROM_FN_PTR(address, os::javaTimeNanos);
628 _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand);
629 TRACE_graal_3("CiRuntimeCall::JavaTimeNanos()"); 635 TRACE_graal_3("CiRuntimeCall::JavaTimeNanos()");
630 } else if (runtime_call == CiRuntimeCall::ArithmeticFrem()) { 636 } else if (runtime_call == CiRuntimeCall::ArithmeticFrem()) {
631 call->set_destination(Runtime1::entry_for(Runtime1::graal_arithmetic_frem_id)); 637 target_addr = Runtime1::entry_for(Runtime1::graal_arithmetic_frem_id);
632 _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand);
633 TRACE_graal_3("CiRuntimeCall::ArithmeticFrem()"); 638 TRACE_graal_3("CiRuntimeCall::ArithmeticFrem()");
634 } else if (runtime_call == CiRuntimeCall::ArithmeticDrem()) { 639 } else if (runtime_call == CiRuntimeCall::ArithmeticDrem()) {
635 call->set_destination(Runtime1::entry_for(Runtime1::graal_arithmetic_drem_id)); 640 target_addr = Runtime1::entry_for(Runtime1::graal_arithmetic_drem_id);
636 _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand);
637 TRACE_graal_3("CiRuntimeCall::ArithmeticDrem()"); 641 TRACE_graal_3("CiRuntimeCall::ArithmeticDrem()");
638 } else if (runtime_call == CiRuntimeCall::ArithmeticSin()) { 642 } else if (runtime_call == CiRuntimeCall::ArithmeticSin()) {
639 call->set_destination(CAST_FROM_FN_PTR(address, SharedRuntime::dsin)); 643 target_addr = CAST_FROM_FN_PTR(address, SharedRuntime::dsin);
640 _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand);
641 TRACE_graal_3("CiRuntimeCall::ArithmeticSin()"); 644 TRACE_graal_3("CiRuntimeCall::ArithmeticSin()");
642 } else if (runtime_call == CiRuntimeCall::ArithmeticCos()) { 645 } else if (runtime_call == CiRuntimeCall::ArithmeticCos()) {
643 call->set_destination(CAST_FROM_FN_PTR(address, SharedRuntime::dcos)); 646 target_addr = CAST_FROM_FN_PTR(address, SharedRuntime::dcos);
644 _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand);
645 TRACE_graal_3("CiRuntimeCall::ArithmeticCos()"); 647 TRACE_graal_3("CiRuntimeCall::ArithmeticCos()");
646 } else if (runtime_call == CiRuntimeCall::ArithmeticTan()) { 648 } else if (runtime_call == CiRuntimeCall::ArithmeticTan()) {
647 call->set_destination(CAST_FROM_FN_PTR(address, SharedRuntime::dtan)); 649 target_addr = CAST_FROM_FN_PTR(address, SharedRuntime::dtan);
648 _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand);
649 TRACE_graal_3("CiRuntimeCall::ArithmeticTan()"); 650 TRACE_graal_3("CiRuntimeCall::ArithmeticTan()");
650 } else if (runtime_call == CiRuntimeCall::RegisterFinalizer()) { 651 } else if (runtime_call == CiRuntimeCall::RegisterFinalizer()) {
651 call->set_destination(Runtime1::entry_for(Runtime1::register_finalizer_id)); 652 target_addr = Runtime1::entry_for(Runtime1::register_finalizer_id);
652 _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand);
653 } else if (runtime_call == CiRuntimeCall::Deoptimize()) { 653 } else if (runtime_call == CiRuntimeCall::Deoptimize()) {
654 call->set_destination(SharedRuntime::deopt_blob()->uncommon_trap()); 654 target_addr = SharedRuntime::deopt_blob()->uncommon_trap();
655 _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand);
656 } else { 655 } else {
657 runtime_call->print(); 656 runtime_call->print();
658 fatal("runtime_call not implemented"); 657 fatal("runtime_call not implemented");
659 } 658 }
659
660 if (inst->is_call()) {
661 // NOTE: for call without a mov, the offset must fit a 32-bit immediate
662 // see also VMEntries.getMaxCallTargetOffset()
663 NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
664 call->set_destination(target_addr);
665 _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand);
666 } else if (inst->is_mov_literal64()) {
667 NativeMovConstReg* mov = nativeMovConstReg_at(_instructions->start() + pc_offset);
668 mov->set_data((intptr_t) target_addr);
669 _instructions->relocate(mov->instruction_address(), runtime_call_Relocation::spec(), Assembler::imm_operand);
670 } else {
671 runtime_call->print();
672 fatal("unknown type of instruction for runtime call");
673 }
660 } else if (global_stub != NULL) { 674 } else if (global_stub != NULL) {
661 NativeInstruction* inst = nativeInstruction_at(_instructions->start() + pc_offset);
662 assert(java_lang_boxing_object::is_instance(global_stub, T_LONG), "global_stub needs to be of type Long"); 675 assert(java_lang_boxing_object::is_instance(global_stub, T_LONG), "global_stub needs to be of type Long");
663 676
664 if (inst->is_call()) { 677 if (inst->is_call()) {
665 nativeCall_at((address)inst)->set_destination(VmIds::getStub(global_stub)); 678 nativeCall_at((address)inst)->set_destination(VmIds::getStub(global_stub));
666 } else { 679 } else {