Path: blob/master/src/hotspot/cpu/aarch64/abstractInterpreter_aarch64.cpp
40930 views
/*1* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.2* Copyright (c) 2014, Red Hat Inc. 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 it6* under the terms of the GNU General Public License version 2 only, as7* published by the Free Software Foundation.8*9* This code is distributed in the hope that it will be useful, but WITHOUT10* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or11* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License12* version 2 for more details (a copy is included in the LICENSE file that13* accompanied this code).14*15* You should have received a copy of the GNU General Public License version16* 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 USA20* or visit www.oracle.com if you need additional information or have any21* questions.22*23*/2425#include "precompiled.hpp"26#include "interpreter/interpreter.hpp"27#include "oops/constMethod.hpp"28#include "oops/klass.inline.hpp"29#include "oops/method.hpp"30#include "runtime/frame.inline.hpp"31#include "utilities/align.hpp"32#include "utilities/debug.hpp"33#include "utilities/macros.hpp"343536int AbstractInterpreter::BasicType_as_index(BasicType type) {37int i = 0;38switch (type) {39case T_BOOLEAN: i = 0; break;40case T_CHAR : i = 1; break;41case T_BYTE : i = 2; break;42case T_SHORT : i = 3; break;43case T_INT : i = 4; break;44case T_LONG : i = 5; break;45case T_VOID : i = 6; break;46case T_FLOAT : i = 7; break;47case T_DOUBLE : i = 8; break;48case T_OBJECT : i = 9; break;49case T_ARRAY : i = 9; break;50default : ShouldNotReachHere();51}52assert(0 <= i && i < AbstractInterpreter::number_of_result_handlers,53"index out of bounds");54return i;55}5657// How much stack a method activation needs in words.58int AbstractInterpreter::size_top_interpreter_activation(Method* method) {59const int entry_size = frame::interpreter_frame_monitor_size();6061// total overhead size: entry_size + (saved rfp thru expr stack62// bottom). be sure to change this if you add/subtract anything63// to/from the overhead area64const int overhead_size =65-(frame::interpreter_frame_initial_sp_offset) + entry_size;6667const int stub_code = frame::entry_frame_after_call_words;68const int method_stack = (method->max_locals() + method->max_stack()) *69Interpreter::stackElementWords;70return (overhead_size + method_stack + stub_code);71}7273// asm based interpreter deoptimization helpers74int AbstractInterpreter::size_activation(int max_stack,75int temps,76int extra_args,77int monitors,78int callee_params,79int callee_locals,80bool is_top_frame) {81// Note: This calculation must exactly parallel the frame setup82// in TemplateInterpreterGenerator::generate_method_entry.8384// fixed size of an interpreter frame:85int overhead = frame::sender_sp_offset -86frame::interpreter_frame_initial_sp_offset;87// Our locals were accounted for by the caller (or last_frame_adjust88// on the transistion) Since the callee parameters already account89// for the callee's params we only need to account for the extra90// locals.91int size = overhead +92(callee_locals - callee_params) +93monitors * frame::interpreter_frame_monitor_size() +94// On the top frame, at all times SP <= ESP, and SP is95// 16-aligned. We ensure this by adjusting SP on method96// entry and re-entry to allow room for the maximum size of97// the expression stack. When we call another method we bump98// SP so that no stack space is wasted. So, only on the top99// frame do we need to allow max_stack words.100(is_top_frame ? max_stack : temps + extra_args);101102// On AArch64 we always keep the stack pointer 16-aligned, so we103// must round up here.104size = align_up(size, 2);105106return size;107}108109void AbstractInterpreter::layout_activation(Method* method,110int tempcount,111int popframe_extra_args,112int moncount,113int caller_actual_parameters,114int callee_param_count,115int callee_locals,116frame* caller,117frame* interpreter_frame,118bool is_top_frame,119bool is_bottom_frame) {120// The frame interpreter_frame is guaranteed to be the right size,121// as determined by a previous call to the size_activation() method.122// It is also guaranteed to be walkable even though it is in a123// skeletal state124125int max_locals = method->max_locals() * Interpreter::stackElementWords;126int extra_locals = (method->max_locals() - method->size_of_parameters()) *127Interpreter::stackElementWords;128129#ifdef ASSERT130assert(caller->sp() == interpreter_frame->sender_sp(), "Frame not properly walkable");131#endif132133interpreter_frame->interpreter_frame_set_method(method);134// NOTE the difference in using sender_sp and135// interpreter_frame_sender_sp interpreter_frame_sender_sp is136// the original sp of the caller (the unextended_sp) and137// sender_sp is fp+8/16 (32bit/64bit) XXX138//139// The interpreted method entry on AArch64 aligns SP to 16 bytes140// before generating the fixed part of the activation frame. So there141// may be a gap between the locals block and the saved sender SP. For142// an interpreted caller we need to recreate this gap and exactly143// align the incoming parameters with the caller's temporary144// expression stack. For other types of caller frame it doesn't145// matter.146intptr_t* locals;147if (caller->is_interpreted_frame()) {148locals = caller->interpreter_frame_last_sp() + caller_actual_parameters - 1;149} else {150locals = interpreter_frame->sender_sp() + max_locals - 1;151}152153#ifdef ASSERT154if (caller->is_interpreted_frame()) {155assert(locals < caller->fp() + frame::interpreter_frame_initial_sp_offset, "bad placement");156}157#endif158159interpreter_frame->interpreter_frame_set_locals(locals);160BasicObjectLock* montop = interpreter_frame->interpreter_frame_monitor_begin();161BasicObjectLock* monbot = montop - moncount;162interpreter_frame->interpreter_frame_set_monitor_end(monbot);163164// Set last_sp165intptr_t* esp = (intptr_t*) monbot -166tempcount*Interpreter::stackElementWords -167popframe_extra_args;168interpreter_frame->interpreter_frame_set_last_sp(esp);169170// All frames but the initial (oldest) interpreter frame we fill in have171// a value for sender_sp that allows walking the stack but isn't172// truly correct. Correct the value here.173if (extra_locals != 0 &&174interpreter_frame->sender_sp() ==175interpreter_frame->interpreter_frame_sender_sp()) {176interpreter_frame->set_interpreter_frame_sender_sp(caller->sp() +177extra_locals);178}179*interpreter_frame->interpreter_frame_cache_addr() =180method->constants()->cache();181*interpreter_frame->interpreter_frame_mirror_addr() =182method->method_holder()->java_mirror();183}184185186