1 /* 2 * Copyright (c) 2008, 2020, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 #ifndef CPU_ARM_INTERP_MASM_ARM_HPP 26 #define CPU_ARM_INTERP_MASM_ARM_HPP 27 28 #include "asm/macroAssembler.hpp" 29 #include "interpreter/invocationCounter.hpp" 30 #include "runtime/frame.hpp" 31 #include "prims/jvmtiExport.hpp" 32 33 // This file specializes the assember with interpreter-specific macros 34 35 36 class InterpreterMacroAssembler: public MacroAssembler { 37 38 public: 39 40 // allow JvmtiExport checks to be extended can_force_early_return()41 bool can_force_early_return() { return JvmtiExport::can_force_early_return(); } can_post_interpreter_events()42 bool can_post_interpreter_events() { return JvmtiExport::can_post_interpreter_events(); } can_pop_frame()43 bool can_pop_frame() { return JvmtiExport::can_pop_frame(); } can_post_breakpoint()44 bool can_post_breakpoint() { return JvmtiExport::can_post_breakpoint(); } can_post_field_access()45 bool can_post_field_access() { return JvmtiExport::can_post_field_access(); } can_post_field_modification()46 bool can_post_field_modification() { return JvmtiExport::can_post_field_modification(); } 47 // flags controlled by JVMTI settings rewrite_frequent_pairs()48 bool rewrite_frequent_pairs() { return RewriteFrequentPairs; } 49 50 protected: 51 52 // Template interpreter specific version of call_VM_helper 53 virtual void call_VM_helper(Register oop_result, address entry_point, int number_of_arguments, bool check_exceptions); 54 55 // base routine for all dispatches 56 typedef enum { DispatchDefault, DispatchNormal } DispatchTableMode; 57 void dispatch_base(TosState state, DispatchTableMode table_mode, bool verifyoop = true, bool generate_poll = false); 58 59 public: 60 InterpreterMacroAssembler(CodeBuffer* code); 61 62 virtual void check_and_handle_popframe(); 63 virtual void check_and_handle_earlyret(); 64 65 // Interpreter-specific registers 66 check_stack_top()67 inline void check_stack_top() {} check_stack_top_on_expansion()68 inline void check_stack_top_on_expansion() {} check_extended_sp(Register tmp)69 inline void check_extended_sp(Register tmp) {} check_no_cached_stack_top(Register tmp)70 inline void check_no_cached_stack_top(Register tmp) {} 71 72 save_bcp()73 void save_bcp() { str(Rbcp, Address(FP, frame::interpreter_frame_bcp_offset * wordSize)); } restore_bcp()74 void restore_bcp() { ldr(Rbcp, Address(FP, frame::interpreter_frame_bcp_offset * wordSize)); } restore_locals()75 void restore_locals() { ldr(Rlocals, Address(FP, frame::interpreter_frame_locals_offset * wordSize)); } restore_method()76 void restore_method() { ldr(Rmethod, Address(FP, frame::interpreter_frame_method_offset * wordSize)); } 77 void restore_dispatch(); 78 79 80 // Helpers for runtime call arguments/results get_const(Register reg)81 void get_const(Register reg) { ldr(reg, Address(Rmethod, Method::const_offset())); } get_constant_pool(Register reg)82 void get_constant_pool(Register reg) { get_const(reg); ldr(reg, Address(reg, ConstMethod::constants_offset())); } get_constant_pool_cache(Register reg)83 void get_constant_pool_cache(Register reg) { get_constant_pool(reg); ldr(reg, Address(reg, ConstantPool::cache_offset_in_bytes())); } get_cpool_and_tags(Register cpool,Register tags)84 void get_cpool_and_tags(Register cpool, Register tags) { get_constant_pool(cpool); ldr(tags, Address(cpool, ConstantPool::tags_offset_in_bytes())); } 85 86 // Sets reg. Blows Rtemp. 87 void get_unsigned_2_byte_index_at_bcp(Register reg, int bcp_offset); 88 89 // Sets index. Blows reg_tmp. 90 void get_index_at_bcp(Register index, int bcp_offset, Register reg_tmp, size_t index_size = sizeof(u2)); 91 // Sets cache, index. 92 void get_cache_and_index_at_bcp(Register cache, Register index, int bcp_offset, size_t index_size = sizeof(u2)); 93 void get_cache_and_index_and_bytecode_at_bcp(Register cache, Register index, Register bytecode, int byte_no, int bcp_offset, size_t index_size = sizeof(u2)); 94 // Sets cache. Blows reg_tmp. 95 void get_cache_entry_pointer_at_bcp(Register cache, Register reg_tmp, int bcp_offset, size_t index_size = sizeof(u2)); 96 97 // Load object from cpool->resolved_references(*bcp+1) 98 void load_resolved_reference_at_index(Register result, Register tmp); 99 100 // load cpool->resolved_klass_at(index); Rtemp is corrupted upon return 101 void load_resolved_klass_at_offset(Register Rcpool, Register Rindex, Register Rklass); 102 103 void pop_ptr(Register r); 104 void pop_i(Register r = R0_tos); 105 void pop_l(Register lo = R0_tos_lo, Register hi = R1_tos_hi); 106 void pop_f(FloatRegister fd); 107 void pop_d(FloatRegister fd); 108 109 void push_ptr(Register r); 110 void push_i(Register r = R0_tos); 111 void push_l(Register lo = R0_tos_lo, Register hi = R1_tos_hi); 112 void push_f(); 113 void push_d(); 114 115 // Transition vtos -> state. Blows R0, R1. Sets TOS cached value. 116 void pop(TosState state); 117 // Transition state -> vtos. Blows Rtemp. 118 void push(TosState state); 119 120 // The following methods are overridden to allow overloaded calls to 121 // MacroAssembler::push/pop(Register) 122 // MacroAssembler::push/pop(RegisterSet) 123 // InterpreterMacroAssembler::push/pop(TosState) push(Register rd,AsmCondition cond=al)124 void push(Register rd, AsmCondition cond = al) { MacroAssembler::push(rd, cond); } pop(Register rd,AsmCondition cond=al)125 void pop(Register rd, AsmCondition cond = al) { MacroAssembler::pop(rd, cond); } 126 push(RegisterSet reg_set,AsmCondition cond=al)127 void push(RegisterSet reg_set, AsmCondition cond = al) { MacroAssembler::push(reg_set, cond); } pop(RegisterSet reg_set,AsmCondition cond=al)128 void pop(RegisterSet reg_set, AsmCondition cond = al) { MacroAssembler::pop(reg_set, cond); } 129 130 // Converts return value in R0/R1 (interpreter calling conventions) to TOS cached value. 131 void convert_retval_to_tos(TosState state); 132 // Converts TOS cached value to return value in R0/R1 (according to interpreter calling conventions). 133 void convert_tos_to_retval(TosState state); 134 135 // JVMTI ForceEarlyReturn support 136 void load_earlyret_value(TosState state); 137 138 void jump_to_entry(address entry); 139 140 // Blows Rtemp. empty_expression_stack()141 void empty_expression_stack() { 142 ldr(Rstack_top, Address(FP, frame::interpreter_frame_monitor_block_top_offset * wordSize)); 143 check_stack_top(); 144 // NULL last_sp until next java call 145 str(zero_register(Rtemp), Address(FP, frame::interpreter_frame_last_sp_offset * wordSize)); 146 } 147 148 // Helpers for swap and dup 149 void load_ptr(int n, Register val); 150 void store_ptr(int n, Register val); 151 152 // Generate a subtype check: branch to not_subtype if sub_klass is 153 // not a subtype of super_klass. 154 // Profiling code for the subtype check failure (profile_typecheck_failed) 155 // should be explicitly generated by the caller in the not_subtype case. 156 // Blows Rtemp, tmp1, tmp2. 157 void gen_subtype_check(Register Rsub_klass, Register Rsuper_klass, 158 Label ¬_subtype, Register tmp1, Register tmp2); 159 160 // Dispatching 161 void dispatch_prolog(TosState state, int step = 0); 162 void dispatch_epilog(TosState state, int step = 0); 163 void dispatch_only(TosState state, bool generate_poll = false); // dispatch by R3_bytecode 164 void dispatch_only_normal(TosState state); // dispatch normal table by R3_bytecode 165 void dispatch_only_noverify(TosState state); 166 void dispatch_next(TosState state, int step = 0, bool generate_poll = false); // load R3_bytecode from [Rbcp + step] and dispatch by R3_bytecode 167 168 // jump to an invoked target 169 void prepare_to_jump_from_interpreted(); 170 void jump_from_interpreted(Register method); 171 172 void narrow(Register result); 173 174 // Returning from interpreted functions 175 // 176 // Removes the current activation (incl. unlocking of monitors) 177 // and sets up the return address. This code is also used for 178 // exception unwindwing. In that case, we do not want to throw 179 // IllegalMonitorStateExceptions, since that might get us into an 180 // infinite rethrow exception loop. 181 // Additionally this code is used for popFrame and earlyReturn. 182 // In popFrame case we want to skip throwing an exception, 183 // installing an exception, and notifying jvmdi. 184 // In earlyReturn case we only want to skip throwing an exception 185 // and installing an exception. 186 void remove_activation(TosState state, Register ret_addr, 187 bool throw_monitor_exception = true, 188 bool install_monitor_exception = true, 189 bool notify_jvmdi = true); 190 191 // At certain points in the method invocation the monitor of 192 // synchronized methods hasn't been entered yet. 193 // To correctly handle exceptions at these points, we set the thread local 194 // variable _do_not_unlock_if_synchronized to true. The remove_activation will 195 // check this flag. 196 void set_do_not_unlock_if_synchronized(bool flag, Register tmp); 197 198 // Debugging 199 void interp_verify_oop(Register reg, TosState state, const char* file, int line); // only if +VerifyOops && state == atos 200 verify_FPU(int stack_depth,TosState state=ftos)201 void verify_FPU(int stack_depth, TosState state = ftos) { 202 // No VFP state verification is required for ARM 203 } 204 205 // Object locking 206 void lock_object (Register lock_reg); 207 void unlock_object(Register lock_reg); 208 209 // Interpreter profiling operations 210 void set_method_data_pointer_for_bcp(); // Blows R0-R3/R0-R18, Rtemp, LR 211 void test_method_data_pointer(Register mdp, Label& zero_continue); 212 void verify_method_data_pointer(); 213 214 void set_mdp_data_at(Register mdp_in, int offset, Register value); 215 216 // Increments mdp data. Sets bumped_count register to adjusted counter. 217 void increment_mdp_data_at(Address data, Register bumped_count, bool decrement = false); 218 // Increments mdp data. Sets bumped_count register to adjusted counter. 219 void increment_mdp_data_at(Register mdp_in, int offset, Register bumped_count, bool decrement = false); 220 void increment_mask_and_jump(Address counter_addr, 221 int increment, Address mask_addr, 222 Register scratch, Register scratch2, 223 AsmCondition cond, Label* where); 224 void set_mdp_flag_at(Register mdp_in, int flag_constant); 225 226 void test_mdp_data_at(Register mdp_in, int offset, Register value, 227 Register test_value_out, 228 Label& not_equal_continue); 229 230 void record_klass_in_profile(Register receiver, Register mdp, 231 Register reg_tmp, bool is_virtual_call); 232 void record_klass_in_profile_helper(Register receiver, Register mdp, 233 Register reg_tmp, 234 int start_row, Label& done, bool is_virtual_call); 235 236 void update_mdp_by_offset(Register mdp_in, int offset_of_offset, Register reg_tmp); 237 void update_mdp_by_offset(Register mdp_in, Register reg_offset, Register reg_tmp); 238 void update_mdp_by_constant(Register mdp_in, int constant); 239 void update_mdp_for_ret(Register return_bci); // Blows R0-R3/R0-R18, Rtemp, LR 240 241 void profile_taken_branch(Register mdp, Register bumped_count); // Sets mdp, bumped_count registers, blows Rtemp. 242 void profile_not_taken_branch(Register mdp); // Sets mdp, blows Rtemp. 243 244 void profile_call(Register mdp); // Sets mdp, blows Rtemp. 245 void profile_final_call(Register mdp); // Sets mdp, blows Rtemp. 246 void profile_virtual_call(Register mdp, Register receiver, // Sets mdp, blows Rtemp. 247 bool receiver_can_be_null = false); 248 void profile_ret(Register mdp, Register return_bci); // Sets mdp, blows R0-R3/R0-R18, Rtemp, LR 249 void profile_null_seen(Register mdp); // Sets mdp. 250 void profile_typecheck(Register mdp, Register klass); // Sets mdp, blows Rtemp. 251 252 void profile_typecheck_failed(Register mdp); // Sets mdp, blows Rtemp. 253 void profile_switch_default(Register mdp); // Sets mdp, blows Rtemp. 254 255 // Sets mdp. Blows reg_tmp1, reg_tmp2. Index could be the same as reg_tmp2. 256 void profile_switch_case(Register mdp, Register index, Register reg_tmp1, Register reg_tmp2); 257 258 void byteswap_u32(Register r, Register rtmp1, Register rtmp2); 259 260 void inc_global_counter(address address_of_counter, int offset_in_bytes, Register tmp1, Register tmp2, bool avoid_overflow); 261 262 typedef enum { NotifyJVMTI, SkipNotifyJVMTI } NotifyMethodExitMode; 263 264 // support for jvmti 265 void notify_method_entry(); 266 void notify_method_exit(TosState state, NotifyMethodExitMode mode, 267 bool native = false, Register result_lo = noreg, Register result_hi = noreg, FloatRegister result_fp = fnoreg); 268 269 void trace_state(const char* msg) PRODUCT_RETURN; 270 271 void get_method_counters(Register method, 272 Register Rcounters, 273 Label& skip, 274 bool saveRegs = false, 275 Register reg1 = noreg, 276 Register reg2 = noreg, 277 Register reg3 = noreg); 278 }; 279 280 #endif // CPU_ARM_INTERP_MASM_ARM_HPP 281