src/cpu/x86/vm/interp_masm_x86_64.cpp
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File 6829192 Sdiff src/cpu/x86/vm

src/cpu/x86/vm/interp_masm_x86_64.cpp

Print this page
rev 1022 : 6829192: JSR 292 needs to support 64-bit x86
Summary: changes for method handles and invokedynamic
Reviewed-by: ?, ?


 168     // same-named entrypoint in the generated interpreter code.
 169     movptr(c_rarg0, Address(r15_thread, JavaThread::jvmti_thread_state_offset()));
 170     movl(c_rarg0, Address(c_rarg0, JvmtiThreadState::earlyret_tos_offset()));
 171     call_VM_leaf(CAST_FROM_FN_PTR(address, Interpreter::remove_activation_early_entry), c_rarg0);
 172     jmp(rax);
 173     bind(L);
 174   }
 175 }
 176 
 177 
 178 void InterpreterMacroAssembler::get_unsigned_2_byte_index_at_bcp(
 179   Register reg,
 180   int bcp_offset) {
 181   assert(bcp_offset >= 0, "bcp is still pointing to start of bytecode");
 182   movl(reg, Address(r13, bcp_offset));
 183   bswapl(reg);
 184   shrl(reg, 16);
 185 }
 186 
 187 


















 188 void InterpreterMacroAssembler::get_cache_and_index_at_bcp(Register cache,
 189                                                            Register index,
 190                                                            int bcp_offset) {
 191   assert(bcp_offset > 0, "bcp is still pointing to start of bytecode");
 192   assert(cache != index, "must use different registers");
 193   load_unsigned_short(index, Address(r13, bcp_offset));
 194   movptr(cache, Address(rbp, frame::interpreter_frame_cache_offset * wordSize));
 195   assert(sizeof(ConstantPoolCacheEntry) == 4 * wordSize, "adjust code below");
 196   // convert from field index to ConstantPoolCacheEntry index
 197   shll(index, 2);
 198 }
 199 
 200 
 201 void InterpreterMacroAssembler::get_cache_entry_pointer_at_bcp(Register cache,
 202                                                                Register tmp,
 203                                                                int bcp_offset) {
 204   assert(bcp_offset > 0, "bcp is still pointing to start of bytecode");
 205   assert(cache != tmp, "must use different register");
 206   load_unsigned_short(tmp, Address(r13, bcp_offset));
 207   assert(sizeof(ConstantPoolCacheEntry) == 4 * wordSize, "adjust code below");
 208   // convert from field index to ConstantPoolCacheEntry index
 209   // and from word offset to byte offset
 210   shll(tmp, 2 + LogBytesPerWord);
 211   movptr(cache, Address(rbp, frame::interpreter_frame_cache_offset * wordSize));
 212   // skip past the header
 213   addptr(cache, in_bytes(constantPoolCacheOopDesc::base_offset()));
 214   addptr(cache, tmp);  // construct pointer to cache entry
 215 }
 216 
 217 
 218 // Generate a subtype check: branch to ok_is_subtype if sub_klass is a
 219 // subtype of super_klass.
 220 //
 221 // Args:
 222 //      rax: superklass
 223 //      Rsub_klass: subklass
 224 //
 225 // Kills:
 226 //      rcx, rdi


1219   if (ProfileInterpreter) {
1220     Label profile_continue;
1221 
1222     // If no method data exists, go to profile_continue.
1223     test_method_data_pointer(mdp, profile_continue);
1224 
1225     // We are making a call.  Increment the count.
1226     increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset()));
1227 
1228     // The method data pointer needs to be updated to reflect the new target.
1229     update_mdp_by_constant(mdp,
1230                            in_bytes(VirtualCallData::
1231                                     virtual_call_data_size()));
1232     bind(profile_continue);
1233   }
1234 }
1235 
1236 
1237 void InterpreterMacroAssembler::profile_virtual_call(Register receiver,
1238                                                      Register mdp,
1239                                                      Register reg2) {

1240   if (ProfileInterpreter) {
1241     Label profile_continue;
1242 
1243     // If no method data exists, go to profile_continue.
1244     test_method_data_pointer(mdp, profile_continue);
1245 
1246     // We are making a call.  Increment the count.
1247     increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset()));
1248 






1249     // Record the receiver type.
1250     record_klass_in_profile(receiver, mdp, reg2);

1251 
1252     // The method data pointer needs to be updated to reflect the new target.
1253     update_mdp_by_constant(mdp,
1254                            in_bytes(VirtualCallData::
1255                                     virtual_call_data_size()));
1256     bind(profile_continue);
1257   }
1258 }
1259 
1260 // This routine creates a state machine for updating the multi-row
1261 // type profile at a virtual call site (or other type-sensitive bytecode).
1262 // The machine visits each row (of receiver/count) until the receiver type
1263 // is found, or until it runs out of rows.  At the same time, it remembers
1264 // the location of the first empty row.  (An empty row records null for its
1265 // receiver, and can be allocated for a newly-observed receiver type.)
1266 // Because there are two degrees of freedom in the state, a simple linear
1267 // search will not work; it must be a decision tree.  Hence this helper
1268 // function is recursive, to generate the required tree structured code.
1269 // It's the interpreter, so we are trading off code space for speed.
1270 // See below for example code.




 168     // same-named entrypoint in the generated interpreter code.
 169     movptr(c_rarg0, Address(r15_thread, JavaThread::jvmti_thread_state_offset()));
 170     movl(c_rarg0, Address(c_rarg0, JvmtiThreadState::earlyret_tos_offset()));
 171     call_VM_leaf(CAST_FROM_FN_PTR(address, Interpreter::remove_activation_early_entry), c_rarg0);
 172     jmp(rax);
 173     bind(L);
 174   }
 175 }
 176 
 177 
 178 void InterpreterMacroAssembler::get_unsigned_2_byte_index_at_bcp(
 179   Register reg,
 180   int bcp_offset) {
 181   assert(bcp_offset >= 0, "bcp is still pointing to start of bytecode");
 182   movl(reg, Address(r13, bcp_offset));
 183   bswapl(reg);
 184   shrl(reg, 16);
 185 }
 186 
 187 
 188 void InterpreterMacroAssembler::get_cache_index_at_bcp(Register index,
 189                                                        int bcp_offset,
 190                                                        bool giant_index) {
 191   assert(bcp_offset > 0, "bcp is still pointing to start of bytecode");
 192   if (!giant_index) {
 193     load_unsigned_short(index, Address(r13, bcp_offset));
 194   } else {
 195     assert(EnableInvokeDynamic, "giant index used only for EnableInvokeDynamic");
 196     movl(index, Address(r13, bcp_offset));
 197     // Check if the secondary index definition is still ~x, otherwise
 198     // we have to change the following assembler code to calculate the
 199     // plain index.
 200     assert(constantPoolCacheOopDesc::decode_secondary_index(~123) == 123, "else change next line");
 201     notl(index);  // convert to plain index
 202   }
 203 }
 204 
 205 
 206 void InterpreterMacroAssembler::get_cache_and_index_at_bcp(Register cache,
 207                                                            Register index,
 208                                                            int bcp_offset,
 209                                                            bool giant_index) {
 210   assert(cache != index, "must use different registers");
 211   get_cache_index_at_bcp(index, bcp_offset, giant_index);
 212   movptr(cache, Address(rbp, frame::interpreter_frame_cache_offset * wordSize));
 213   assert(sizeof(ConstantPoolCacheEntry) == 4 * wordSize, "adjust code below");
 214   // convert from field index to ConstantPoolCacheEntry index
 215   shll(index, 2);
 216 }
 217 
 218 
 219 void InterpreterMacroAssembler::get_cache_entry_pointer_at_bcp(Register cache,
 220                                                                Register tmp,
 221                                                                int bcp_offset,
 222                                                                bool giant_index) {
 223   assert(cache != tmp, "must use different register");
 224   get_cache_index_at_bcp(tmp, bcp_offset, giant_index);
 225   assert(sizeof(ConstantPoolCacheEntry) == 4 * wordSize, "adjust code below");
 226   // convert from field index to ConstantPoolCacheEntry index
 227   // and from word offset to byte offset
 228   shll(tmp, 2 + LogBytesPerWord);
 229   movptr(cache, Address(rbp, frame::interpreter_frame_cache_offset * wordSize));
 230   // skip past the header
 231   addptr(cache, in_bytes(constantPoolCacheOopDesc::base_offset()));
 232   addptr(cache, tmp);  // construct pointer to cache entry
 233 }
 234 
 235 
 236 // Generate a subtype check: branch to ok_is_subtype if sub_klass is a
 237 // subtype of super_klass.
 238 //
 239 // Args:
 240 //      rax: superklass
 241 //      Rsub_klass: subklass
 242 //
 243 // Kills:
 244 //      rcx, rdi


1237   if (ProfileInterpreter) {
1238     Label profile_continue;
1239 
1240     // If no method data exists, go to profile_continue.
1241     test_method_data_pointer(mdp, profile_continue);
1242 
1243     // We are making a call.  Increment the count.
1244     increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset()));
1245 
1246     // The method data pointer needs to be updated to reflect the new target.
1247     update_mdp_by_constant(mdp,
1248                            in_bytes(VirtualCallData::
1249                                     virtual_call_data_size()));
1250     bind(profile_continue);
1251   }
1252 }
1253 
1254 
1255 void InterpreterMacroAssembler::profile_virtual_call(Register receiver,
1256                                                      Register mdp,
1257                                                      Register reg2,
1258                                                      bool receiver_can_be_null) {
1259   if (ProfileInterpreter) {
1260     Label profile_continue;
1261 
1262     // If no method data exists, go to profile_continue.
1263     test_method_data_pointer(mdp, profile_continue);
1264 
1265     // We are making a call.  Increment the count.
1266     increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset()));
1267 
1268     Label skip_receiver_profile;
1269     if (receiver_can_be_null) {
1270       testptr(receiver, receiver);
1271       jcc(Assembler::zero, skip_receiver_profile);
1272     }
1273 
1274     // Record the receiver type.
1275     record_klass_in_profile(receiver, mdp, reg2);
1276     bind(skip_receiver_profile);
1277 
1278     // The method data pointer needs to be updated to reflect the new target.
1279     update_mdp_by_constant(mdp,
1280                            in_bytes(VirtualCallData::
1281                                     virtual_call_data_size()));
1282     bind(profile_continue);
1283   }
1284 }
1285 
1286 // This routine creates a state machine for updating the multi-row
1287 // type profile at a virtual call site (or other type-sensitive bytecode).
1288 // The machine visits each row (of receiver/count) until the receiver type
1289 // is found, or until it runs out of rows.  At the same time, it remembers
1290 // the location of the first empty row.  (An empty row records null for its
1291 // receiver, and can be allocated for a newly-observed receiver type.)
1292 // Because there are two degrees of freedom in the state, a simple linear
1293 // search will not work; it must be a decision tree.  Hence this helper
1294 // function is recursive, to generate the required tree structured code.
1295 // It's the interpreter, so we are trading off code space for speed.
1296 // See below for example code.


src/cpu/x86/vm/interp_masm_x86_64.cpp
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File