Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/cpu/aarch32/vm/interpreter_aarch32.cpp
32285 views
/*1* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.2* Copyright (c) 2014, Red Hat Inc. All rights reserved.3* Copyright (c) 2015, Linaro Ltd. All rights reserved.4* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.5*6* This code is free software; you can redistribute it and/or modify it7* under the terms of the GNU General Public License version 2 only, as8* published by the Free Software Foundation.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*24*/2526#include "precompiled.hpp"27#include "asm/macroAssembler.hpp"28#include "interp_masm_aarch32.hpp"29#include "interpreter/bytecodeHistogram.hpp"30#include "interpreter/interpreter.hpp"31#include "interpreter/interpreterGenerator.hpp"32#include "interpreter/interpreterRuntime.hpp"33#include "interpreter/templateTable.hpp"34#include "oops/arrayOop.hpp"35#include "oops/method.hpp"36#include "oops/methodData.hpp"37#include "oops/oop.inline.hpp"38#include "prims/jvmtiExport.hpp"39#include "prims/jvmtiThreadState.hpp"40#include "prims/methodHandles.hpp"41#include "runtime/arguments.hpp"42#include "runtime/deoptimization.hpp"43#include "runtime/frame.inline.hpp"44#include "runtime/sharedRuntime.hpp"45#include "runtime/stubRoutines.hpp"46#include "runtime/synchronizer.hpp"47#include "runtime/timer.hpp"48#include "runtime/vframeArray.hpp"49#include "utilities/debug.hpp"50#include "vm_version_aarch32.hpp"51#ifdef COMPILER152#include "c1/c1_Runtime1.hpp"53#endif5455#define __ _masm->565758address AbstractInterpreterGenerator::generate_slow_signature_handler() {59address entry = __ pc();6061// The sp should be aligned on entry to the bottom of where the integer args62// need to be copied to.6364// rmethod65// rlocals66// c_rarg3: first stack arg - wordSize6768__ mov(c_rarg3, sp);69__ sub(sp, sp, 22 * wordSize);70__ str(lr, sp);71__ call_VM(noreg,72CAST_FROM_FN_PTR(address,73InterpreterRuntime::slow_signature_handler),74rmethod, rlocals, c_rarg3);7576// r0: result handler7778// Stack layout:79// rsp: return address <- sp (lowest addr)80// 1 float/double identifiers with the following structure:81// 16 bit - 2 bits per word free/in use indication (0==in use)82// 8 bits - 1 bit per word, double/float indication (0==double)83// 4 integer args (if static first is unused)84// 8 double args (defined by ARM calling convention spec)85// stack args <- sp (on entry)86// garbage87// expression stack bottom88// bcp (NULL)89// ...90// If this changes, update interpreterRt_aarch32.cpp slowpath!9192// Restore LR93__ ldr(lr, sp);9495#ifdef HARD_FLOAT_CC96// Do FP first so we can use c_rarg3 as temp97__ ldr(c_rarg3, Address(sp, wordSize)); // float/double identifiers9899{100Label fp_done;101// each iteration covers either single double register or up to 2 float registers102for (int i = 0; i < Argument::n_float_register_parameters_c; i++) {103Label d, done;104105__ tst(c_rarg3, 1 << i+16);106__ b(d, __ EQ);107__ tst(c_rarg3, 1 << i*2);108__ b(fp_done, __ NE);109__ vldr_f32(as_FloatRegister(i*2), Address(sp, (6 + 2 * i) * wordSize));110__ tst(c_rarg3, 1 << i*2+1);111__ vldr_f32(as_FloatRegister(i*2+1), Address(sp, (7 + 2 * i) * wordSize), __ EQ);112__ b(done);113__ bind(d);114__ vldr_f64(as_DoubleFloatRegister(i), Address(sp, (6 + 2 * i) * wordSize));115__ bind(done);116}117__ bind(fp_done);118}119#endif // HARD_FLOAT_CC120121// c_rarg0 contains the result from the call of122// InterpreterRuntime::slow_signature_handler so we don't touch it123// here. It will be loaded with the JNIEnv* later.124__ ldr(c_rarg1, Address(sp, 2 * wordSize));125__ ldrd(c_rarg2, c_rarg3, Address(sp, 3 * wordSize));126127__ add(sp, sp, 22 * wordSize);128__ b(lr);129130return entry;131}132133134//135// Various method entries136//137138address InterpreterGenerator::generate_math_entry(AbstractInterpreter::MethodKind kind) {139// rmethod: Method*140// r4: sender sp141// sp: args142143//if (!InlineIntrinsics) return NULL; // Generate a vanilla entry144// FIXME currently ignoring this flag and inlining anyway145146// These don't need a safepoint check because they aren't virtually147// callable. We won't enter these intrinsics from compiled code.148// If in the future we added an intrinsic which was virtually callable149// we'd have to worry about how to safepoint so that this code is used.150151// mathematical functions inlined by compiler152// (interpreter must provide identical implementation153// in order to avoid monotonicity bugs when switching154// from interpreter to compiler in the middle of some155// computation)156//157// stack:158// [ arg ] <-- sp159// [ arg ]160// retaddr in lr161162address entry_point = NULL;163Register continuation = lr;164bool transcendental_entry = false;165166switch (kind) {167case Interpreter::java_lang_math_abs:168entry_point = __ pc();169if(hasFPU()) {170__ vldr_f64(d0, Address(sp));171__ vabs_f64(d0, d0);172} else {173__ ldrd(r0, Address(sp));174transcendental_entry = true;175}176break;177case Interpreter::java_lang_math_sqrt:178entry_point = __ pc();179if(hasFPU()) {180__ vldr_f64(d0, Address(sp));181__ vsqrt_f64(d0, d0);182} else {183__ ldrd(r0, Address(sp));184transcendental_entry = true;185}186break;187case Interpreter::java_lang_math_sin :188case Interpreter::java_lang_math_cos :189case Interpreter::java_lang_math_tan :190case Interpreter::java_lang_math_log :191case Interpreter::java_lang_math_log10 :192case Interpreter::java_lang_math_exp :193entry_point = __ pc();194transcendental_entry = true;195#ifndef HARD_FLOAT_CC196__ ldrd(r0, Address(sp));197#else198__ vldr_f64(d0, Address(sp));199#endif //HARD_FLOAT_CC200break;201case Interpreter::java_lang_math_pow :202entry_point = __ pc();203transcendental_entry = true;204#ifndef HARD_FLOAT_CC205__ ldrd(r0, Address(sp, 2*Interpreter::stackElementSize));206__ ldrd(r2, Address(sp));207#else208__ vldr_f64(d0, Address(sp, 2*Interpreter::stackElementSize));209__ vldr_f64(d1, Address(sp));210#endif //HARD_FLOAT_CC211break;212default:213ShouldNotReachHere();214}215216__ mov(sp, r4);217if(transcendental_entry) {218__ mov(r4, lr);219continuation = r4;220generate_transcendental_entry(kind);221#ifndef HARD_FLOAT_CC222if(hasFPU()) {223__ vmov_f64(d0, r0, r1);224}225#endif226}227228if (entry_point) {229__ b(continuation);230}231232return entry_point;233}234235// double trigonometrics and transcendentals236// static jdouble dsin(jdouble x);237// static jdouble dcos(jdouble x);238// static jdouble dtan(jdouble x);239// static jdouble dlog(jdouble x);240// static jdouble dlog10(jdouble x);241// static jdouble dexp(jdouble x);242// static jdouble dpow(jdouble x, jdouble y);243244void InterpreterGenerator::generate_transcendental_entry(AbstractInterpreter::MethodKind kind) {245address fn;246switch (kind) {247#ifdef __SOFTFP__248case Interpreter::java_lang_math_abs:249fn = CAST_FROM_FN_PTR(address, SharedRuntime::dabs);250break;251case Interpreter::java_lang_math_sqrt:252fn = CAST_FROM_FN_PTR(address, SharedRuntime::dsqrt);253break;254#endif //__SOFTFP__255case Interpreter::java_lang_math_sin :256fn = CAST_FROM_FN_PTR(address, SharedRuntime::dsin);257break;258case Interpreter::java_lang_math_cos :259fn = CAST_FROM_FN_PTR(address, SharedRuntime::dcos);260break;261case Interpreter::java_lang_math_tan :262fn = CAST_FROM_FN_PTR(address, SharedRuntime::dtan);263break;264case Interpreter::java_lang_math_log :265fn = CAST_FROM_FN_PTR(address, SharedRuntime::dlog);266break;267case Interpreter::java_lang_math_log10 :268fn = CAST_FROM_FN_PTR(address, SharedRuntime::dlog10);269break;270case Interpreter::java_lang_math_exp :271fn = CAST_FROM_FN_PTR(address, SharedRuntime::dexp);272break;273case Interpreter::java_lang_math_pow :274fn = CAST_FROM_FN_PTR(address, SharedRuntime::dpow);275break;276default:277ShouldNotReachHere();278}279__ align_stack();280__ mov(rscratch1, fn);281__ bl(rscratch1);282}283284// Jump into normal path for accessor and empty entry to jump to normal entry285// The "fast" optimization don't update compilation count therefore can disable inlining286// for these functions that should be inlined.287address InterpreterGenerator::generate_jump_to_normal_entry(void) {288address entry_point = __ pc();289290assert(Interpreter::entry_for_kind(Interpreter::zerolocals) != NULL, "should already be generated");291__ b(Interpreter::entry_for_kind(Interpreter::zerolocals));292return entry_point;293}294295// Abstract method entry296// Attempt to execute abstract method. Throw exception297address InterpreterGenerator::generate_abstract_entry(void) {298// rmethod: Method*299// r13: sender SP300301address entry_point = __ pc();302303// abstract method entry304305// pop return address, reset last_sp to NULL306__ empty_expression_stack();307__ restore_bcp(); // bcp must be correct for exception handler (was destroyed)308__ restore_locals(); // make sure locals pointer is correct as well (was destroyed)309310// throw exception311__ call_VM(noreg, CAST_FROM_FN_PTR(address,312InterpreterRuntime::throw_AbstractMethodError));313// the call_VM checks for exception, so we should never return here.314__ should_not_reach_here();315316return entry_point;317}318319320void Deoptimization::unwind_callee_save_values(frame* f, vframeArray* vframe_array) {321322// This code is sort of the equivalent of C2IAdapter::setup_stack_frame back in323// the days we had adapter frames. When we deoptimize a situation where a324// compiled caller calls a compiled caller will have registers it expects325// to survive the call to the callee. If we deoptimize the callee the only326// way we can restore these registers is to have the oldest interpreter327// frame that we create restore these values. That is what this routine328// will accomplish.329330// At the moment we have modified c2 to not have any callee save registers331// so this problem does not exist and this routine is just a place holder.332333assert(f->is_interpreted_frame(), "must be interpreted");334}335336337