Path: blob/master/src/hotspot/cpu/arm/interp_masm_arm.hpp
40930 views
/*1* Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#ifndef CPU_ARM_INTERP_MASM_ARM_HPP25#define CPU_ARM_INTERP_MASM_ARM_HPP2627#include "asm/macroAssembler.hpp"28#include "interpreter/invocationCounter.hpp"29#include "oops/method.hpp"30#include "runtime/frame.hpp"31#include "prims/jvmtiExport.hpp"3233// This file specializes the assember with interpreter-specific macros343536class InterpreterMacroAssembler: public MacroAssembler {3738public:3940// allow JvmtiExport checks to be extended41bool can_force_early_return() { return JvmtiExport::can_force_early_return(); }42bool can_post_interpreter_events() { return JvmtiExport::can_post_interpreter_events(); }43bool can_pop_frame() { return JvmtiExport::can_pop_frame(); }44bool can_post_breakpoint() { return JvmtiExport::can_post_breakpoint(); }45bool can_post_field_access() { return JvmtiExport::can_post_field_access(); }46bool can_post_field_modification() { return JvmtiExport::can_post_field_modification(); }47// flags controlled by JVMTI settings48bool rewrite_frequent_pairs() { return RewriteFrequentPairs; }4950protected:5152// Template interpreter specific version of call_VM_helper53virtual void call_VM_helper(Register oop_result, address entry_point, int number_of_arguments, bool check_exceptions);5455// base routine for all dispatches56typedef enum { DispatchDefault, DispatchNormal } DispatchTableMode;57void dispatch_base(TosState state, DispatchTableMode table_mode, bool verifyoop = true, bool generate_poll = false);5859public:60InterpreterMacroAssembler(CodeBuffer* code);6162virtual void check_and_handle_popframe();63virtual void check_and_handle_earlyret();6465// Interpreter-specific registers6667inline void check_stack_top() {}68inline void check_stack_top_on_expansion() {}69inline void check_extended_sp(Register tmp) {}70inline void check_no_cached_stack_top(Register tmp) {}717273void save_bcp() { str(Rbcp, Address(FP, frame::interpreter_frame_bcp_offset * wordSize)); }74void restore_bcp() { ldr(Rbcp, Address(FP, frame::interpreter_frame_bcp_offset * wordSize)); }75void restore_locals() { ldr(Rlocals, Address(FP, frame::interpreter_frame_locals_offset * wordSize)); }76void restore_method() { ldr(Rmethod, Address(FP, frame::interpreter_frame_method_offset * wordSize)); }77void restore_dispatch();787980// Helpers for runtime call arguments/results81void get_const(Register reg) { ldr(reg, Address(Rmethod, Method::const_offset())); }82void get_constant_pool(Register reg) { get_const(reg); ldr(reg, Address(reg, ConstMethod::constants_offset())); }83void get_constant_pool_cache(Register reg) { get_constant_pool(reg); ldr(reg, Address(reg, ConstantPool::cache_offset_in_bytes())); }84void get_cpool_and_tags(Register cpool, Register tags) { get_constant_pool(cpool); ldr(tags, Address(cpool, ConstantPool::tags_offset_in_bytes())); }8586// Sets reg. Blows Rtemp.87void get_unsigned_2_byte_index_at_bcp(Register reg, int bcp_offset);8889// Sets index. Blows reg_tmp.90void get_index_at_bcp(Register index, int bcp_offset, Register reg_tmp, size_t index_size = sizeof(u2));91// Sets cache, index.92void get_cache_and_index_at_bcp(Register cache, Register index, int bcp_offset, size_t index_size = sizeof(u2));93void 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.95void get_cache_entry_pointer_at_bcp(Register cache, Register reg_tmp, int bcp_offset, size_t index_size = sizeof(u2));9697// Load object from cpool->resolved_references(*bcp+1)98void load_resolved_reference_at_index(Register result, Register tmp);99100// load cpool->resolved_klass_at(index); Rtemp is corrupted upon return101void load_resolved_klass_at_offset(Register Rcpool, Register Rindex, Register Rklass);102103void pop_ptr(Register r);104void pop_i(Register r = R0_tos);105void pop_l(Register lo = R0_tos_lo, Register hi = R1_tos_hi);106void pop_f(FloatRegister fd);107void pop_d(FloatRegister fd);108109void push_ptr(Register r);110void push_i(Register r = R0_tos);111void push_l(Register lo = R0_tos_lo, Register hi = R1_tos_hi);112void push_f();113void push_d();114115// Transition vtos -> state. Blows R0, R1. Sets TOS cached value.116void pop(TosState state);117// Transition state -> vtos. Blows Rtemp.118void push(TosState state);119120// The following methods are overridden to allow overloaded calls to121// MacroAssembler::push/pop(Register)122// MacroAssembler::push/pop(RegisterSet)123// InterpreterMacroAssembler::push/pop(TosState)124void push(Register rd, AsmCondition cond = al) { MacroAssembler::push(rd, cond); }125void pop(Register rd, AsmCondition cond = al) { MacroAssembler::pop(rd, cond); }126127void push(RegisterSet reg_set, AsmCondition cond = al) { MacroAssembler::push(reg_set, cond); }128void pop(RegisterSet reg_set, AsmCondition cond = al) { MacroAssembler::pop(reg_set, cond); }129130// Converts return value in R0/R1 (interpreter calling conventions) to TOS cached value.131void convert_retval_to_tos(TosState state);132// Converts TOS cached value to return value in R0/R1 (according to interpreter calling conventions).133void convert_tos_to_retval(TosState state);134135// JVMTI ForceEarlyReturn support136void load_earlyret_value(TosState state);137138void jump_to_entry(address entry);139140// Blows Rtemp.141void empty_expression_stack() {142ldr(Rstack_top, Address(FP, frame::interpreter_frame_monitor_block_top_offset * wordSize));143check_stack_top();144// NULL last_sp until next java call145str(zero_register(Rtemp), Address(FP, frame::interpreter_frame_last_sp_offset * wordSize));146}147148// Helpers for swap and dup149void load_ptr(int n, Register val);150void store_ptr(int n, Register val);151152// Generate a subtype check: branch to not_subtype if sub_klass is153// 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.157void gen_subtype_check(Register Rsub_klass, Register Rsuper_klass,158Label ¬_subtype, Register tmp1, Register tmp2);159160// Dispatching161void dispatch_prolog(TosState state, int step = 0);162void dispatch_epilog(TosState state, int step = 0);163void dispatch_only(TosState state, bool generate_poll = false); // dispatch by R3_bytecode164void dispatch_only_normal(TosState state); // dispatch normal table by R3_bytecode165void dispatch_only_noverify(TosState state);166void dispatch_next(TosState state, int step = 0, bool generate_poll = false); // load R3_bytecode from [Rbcp + step] and dispatch by R3_bytecode167168// jump to an invoked target169void prepare_to_jump_from_interpreted();170void jump_from_interpreted(Register method);171172void narrow(Register result);173174// Returning from interpreted functions175//176// Removes the current activation (incl. unlocking of monitors)177// and sets up the return address. This code is also used for178// exception unwindwing. In that case, we do not want to throw179// IllegalMonitorStateExceptions, since that might get us into an180// 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 exception185// and installing an exception.186void remove_activation(TosState state, Register ret_addr,187bool throw_monitor_exception = true,188bool install_monitor_exception = true,189bool notify_jvmdi = true);190191// At certain points in the method invocation the monitor of192// synchronized methods hasn't been entered yet.193// To correctly handle exceptions at these points, we set the thread local194// variable _do_not_unlock_if_synchronized to true. The remove_activation will195// check this flag.196void set_do_not_unlock_if_synchronized(bool flag, Register tmp);197198// Debugging199void interp_verify_oop(Register reg, TosState state, const char* file, int line); // only if +VerifyOops && state == atos200201void verify_FPU(int stack_depth, TosState state = ftos) {202// No VFP state verification is required for ARM203}204205// Object locking206void lock_object (Register lock_reg);207void unlock_object(Register lock_reg);208209// Interpreter profiling operations210void set_method_data_pointer_for_bcp(); // Blows R0-R3/R0-R18, Rtemp, LR211void test_method_data_pointer(Register mdp, Label& zero_continue);212void verify_method_data_pointer();213214void set_mdp_data_at(Register mdp_in, int offset, Register value);215216// Increments mdp data. Sets bumped_count register to adjusted counter.217void increment_mdp_data_at(Address data, Register bumped_count, bool decrement = false);218// Increments mdp data. Sets bumped_count register to adjusted counter.219void increment_mdp_data_at(Register mdp_in, int offset, Register bumped_count, bool decrement = false);220void increment_mask_and_jump(Address counter_addr,221int increment, Address mask_addr,222Register scratch, Register scratch2,223AsmCondition cond, Label* where);224void set_mdp_flag_at(Register mdp_in, int flag_constant);225226void test_mdp_data_at(Register mdp_in, int offset, Register value,227Register test_value_out,228Label& not_equal_continue);229230void record_klass_in_profile(Register receiver, Register mdp,231Register reg_tmp, bool is_virtual_call);232void record_klass_in_profile_helper(Register receiver, Register mdp,233Register reg_tmp,234int start_row, Label& done, bool is_virtual_call);235236void update_mdp_by_offset(Register mdp_in, int offset_of_offset, Register reg_tmp);237void update_mdp_by_offset(Register mdp_in, Register reg_offset, Register reg_tmp);238void update_mdp_by_constant(Register mdp_in, int constant);239void update_mdp_for_ret(Register return_bci); // Blows R0-R3/R0-R18, Rtemp, LR240241void profile_taken_branch(Register mdp, Register bumped_count); // Sets mdp, bumped_count registers, blows Rtemp.242void profile_not_taken_branch(Register mdp); // Sets mdp, blows Rtemp.243244void profile_call(Register mdp); // Sets mdp, blows Rtemp.245void profile_final_call(Register mdp); // Sets mdp, blows Rtemp.246void profile_virtual_call(Register mdp, Register receiver, // Sets mdp, blows Rtemp.247bool receiver_can_be_null = false);248void profile_ret(Register mdp, Register return_bci); // Sets mdp, blows R0-R3/R0-R18, Rtemp, LR249void profile_null_seen(Register mdp); // Sets mdp.250void profile_typecheck(Register mdp, Register klass); // Sets mdp, blows Rtemp.251252void profile_typecheck_failed(Register mdp); // Sets mdp, blows Rtemp.253void profile_switch_default(Register mdp); // Sets mdp, blows Rtemp.254255// Sets mdp. Blows reg_tmp1, reg_tmp2. Index could be the same as reg_tmp2.256void profile_switch_case(Register mdp, Register index, Register reg_tmp1, Register reg_tmp2);257258void byteswap_u32(Register r, Register rtmp1, Register rtmp2);259260void inc_global_counter(address address_of_counter, int offset_in_bytes, Register tmp1, Register tmp2, bool avoid_overflow);261262typedef enum { NotifyJVMTI, SkipNotifyJVMTI } NotifyMethodExitMode;263264// support for jvmti265void notify_method_entry();266void notify_method_exit(TosState state, NotifyMethodExitMode mode,267bool native = false, Register result_lo = noreg, Register result_hi = noreg, FloatRegister result_fp = fnoreg);268269void trace_state(const char* msg) PRODUCT_RETURN;270271void get_method_counters(Register method,272Register Rcounters,273Label& skip,274bool saveRegs = false,275Register reg1 = noreg,276Register reg2 = noreg,277Register reg3 = noreg);278};279280#endif // CPU_ARM_INTERP_MASM_ARM_HPP281282283