|
29 | 29 | #include "asm/assembler.hpp" |
30 | 30 | #include "asm/assembler.inline.hpp" |
31 | 31 | #include "ci/ciEnv.hpp" |
| 32 | +#include "code/compiledIC.hpp" |
32 | 33 | #include "compiler/compileTask.hpp" |
33 | 34 | #include "compiler/disassembler.hpp" |
34 | 35 | #include "compiler/oopMap.hpp" |
@@ -965,7 +966,7 @@ int MacroAssembler::max_trampoline_stub_size() { |
965 | 966 | } |
966 | 967 |
|
967 | 968 | void MacroAssembler::emit_static_call_stub() { |
968 | | - // CompiledDirectStaticCall::set_to_interpreted knows the |
| 969 | + // CompiledDirectCall::set_to_interpreted knows the |
969 | 970 | // exact layout of this stub. |
970 | 971 |
|
971 | 972 | isb(); |
@@ -995,10 +996,51 @@ address MacroAssembler::ic_call(address entry, jint method_index) { |
995 | 996 | // address const_ptr = long_constant((jlong)Universe::non_oop_word()); |
996 | 997 | // uintptr_t offset; |
997 | 998 | // ldr_constant(rscratch2, const_ptr); |
998 | | - movptr(rscratch2, (uintptr_t)Universe::non_oop_word()); |
| 999 | + movptr(rscratch2, (intptr_t)Universe::non_oop_word()); |
999 | 1000 | return trampoline_call(Address(entry, rh)); |
1000 | 1001 | } |
1001 | 1002 |
|
| 1003 | +int MacroAssembler::ic_check_size() { |
| 1004 | + if (target_needs_far_branch(CAST_FROM_FN_PTR(address, SharedRuntime::get_ic_miss_stub()))) { |
| 1005 | + return NativeInstruction::instruction_size * 7; |
| 1006 | + } else { |
| 1007 | + return NativeInstruction::instruction_size * 5; |
| 1008 | + } |
| 1009 | +} |
| 1010 | + |
| 1011 | +int MacroAssembler::ic_check(int end_alignment) { |
| 1012 | + Register receiver = j_rarg0; |
| 1013 | + Register data = rscratch2; |
| 1014 | + Register tmp1 = rscratch1; |
| 1015 | + Register tmp2 = r10; |
| 1016 | + |
| 1017 | + // The UEP of a code blob ensures that the VEP is padded. However, the padding of the UEP is placed |
| 1018 | + // before the inline cache check, so we don't have to execute any nop instructions when dispatching |
| 1019 | + // through the UEP, yet we can ensure that the VEP is aligned appropriately. That's why we align |
| 1020 | + // before the inline cache check here, and not after |
| 1021 | + align(end_alignment, offset() + ic_check_size()); |
| 1022 | + |
| 1023 | + int uep_offset = offset(); |
| 1024 | + |
| 1025 | + if (UseCompressedClassPointers) { |
| 1026 | + ldrw(tmp1, Address(receiver, oopDesc::klass_offset_in_bytes())); |
| 1027 | + ldrw(tmp2, Address(data, CompiledICData::speculated_klass_offset())); |
| 1028 | + cmpw(tmp1, tmp2); |
| 1029 | + } else { |
| 1030 | + ldr(tmp1, Address(receiver, oopDesc::klass_offset_in_bytes())); |
| 1031 | + ldr(tmp2, Address(data, CompiledICData::speculated_klass_offset())); |
| 1032 | + cmp(tmp1, tmp2); |
| 1033 | + } |
| 1034 | + |
| 1035 | + Label dont; |
| 1036 | + br(Assembler::EQ, dont); |
| 1037 | + far_jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub())); |
| 1038 | + bind(dont); |
| 1039 | + assert((offset() % end_alignment) == 0, "Misaligned verified entry point"); |
| 1040 | + |
| 1041 | + return uep_offset; |
| 1042 | +} |
| 1043 | + |
1002 | 1044 | // Implementation of call_VM versions |
1003 | 1045 |
|
1004 | 1046 | void MacroAssembler::call_VM(Register oop_result, |
@@ -1100,7 +1142,14 @@ void MacroAssembler::get_vm_result_2(Register metadata_result, Register java_thr |
1100 | 1142 | } |
1101 | 1143 |
|
1102 | 1144 | void MacroAssembler::align(int modulus) { |
1103 | | - while (offset() % modulus != 0) nop(); |
| 1145 | + align(modulus, offset()); |
| 1146 | +} |
| 1147 | + |
| 1148 | +// Ensure that the code at target bytes offset from the current offset() is aligned |
| 1149 | +// according to modulus. |
| 1150 | +void MacroAssembler::align(int modulus, int target) { |
| 1151 | + int delta = target - offset(); |
| 1152 | + while ((offset() + delta) % modulus != 0) nop(); |
1104 | 1153 | } |
1105 | 1154 |
|
1106 | 1155 | void MacroAssembler::post_call_nop() { |
@@ -1197,7 +1246,7 @@ void MacroAssembler::lookup_interface_method(Register recv_klass, |
1197 | 1246 | } |
1198 | 1247 |
|
1199 | 1248 | // Look up the method for a megamorphic invokeinterface call in a single pass over itable: |
1200 | | -// - check recv_klass (actual object class) is a subtype of resolved_klass from CompiledICHolder |
| 1249 | +// - check recv_klass (actual object class) is a subtype of resolved_klass from CompiledICData |
1201 | 1250 | // - find a holder_klass (class that implements the method) vtable offset and get the method from vtable by index |
1202 | 1251 | // The target method is determined by <holder_klass, itable_index>. |
1203 | 1252 | // The receiver klass is in recv_klass. |
|
0 commit comments