Mercurial > hg > graal-compiler
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 { |