src/cpu/aarch64/vm/templateInterpreterGenerator_aarch64.cpp

Print this page




  40 #include "prims/jvmtiThreadState.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 <sys/types.h>
  51 
  52 #ifndef PRODUCT
  53 #include "oops/method.hpp"
  54 #endif // !PRODUCT
  55 
  56 #ifdef BUILTIN_SIM
  57 #include "../../../../../../simulator/simulator.hpp"
  58 #endif
  59 







  60 #define __ _masm->
  61 
  62 //-----------------------------------------------------------------------------
  63 
  64 extern "C" void entry(CodeBuffer*);
  65 
  66 //-----------------------------------------------------------------------------
  67 














































































































































































































  68 address TemplateInterpreterGenerator::generate_StackOverflowError_handler() {
  69   address entry = __ pc();
  70 
  71 #ifdef ASSERT
  72   {
  73     Label L;
  74     __ ldr(rscratch1, Address(rfp,
  75                        frame::interpreter_frame_monitor_block_top_offset *
  76                        wordSize));
  77     __ mov(rscratch2, sp);
  78     __ cmp(rscratch1, rscratch2); // maximal rsp for current rfp (stack
  79                            // grows negative)
  80     __ br(Assembler::HS, L); // check if frame is complete
  81     __ stop ("interpreter frame not set up");
  82     __ bind(L);
  83   }
  84 #endif // ASSERT
  85   // Restore bcp under the assumption that the current frame is still
  86   // interpreted
  87   __ restore_bcp();


 807     __ ldrw(len, Address(esp, 0x0)); // Length
 808 
 809     __ andr(sp, r13, -16); // Restore the caller's SP
 810 
 811     // We are frameless so we can just jump to the stub.
 812     __ b(CAST_FROM_FN_PTR(address, StubRoutines::updateBytesCRC32()));
 813 
 814     // generate a vanilla native entry as the slow path
 815     __ bind(slow_path);
 816     __ jump_to_entry(Interpreter::entry_for_kind(Interpreter::native));
 817     return entry;
 818   }
 819   return NULL;
 820 }
 821 
 822 // Not supported
 823 address TemplateInterpreterGenerator::generate_CRC32C_updateBytes_entry(AbstractInterpreter::MethodKind kind) {
 824   return NULL;
 825 }
 826 



 827 void TemplateInterpreterGenerator::bang_stack_shadow_pages(bool native_call) {
 828   // Bang each page in the shadow zone. We can't assume it's been done for
 829   // an interpreter frame with greater than a page of locals, so each page
 830   // needs to be checked.  Only true for non-native.
 831   if (UseStackBanging) {
 832     const int size_t n_shadow_pages = JavaThread::stack_shadow_zone_size() / os::vm_page_size();
 833     const int start_page = native_call ? n_shadow_pages : 1;
 834     const int page_size = os::vm_page_size();
 835     for (int pages = start_page; pages <= n_shadow_pages ; pages++) {
 836       __ sub(rscratch2, sp, pages*page_size);
 837       __ str(zr, Address(rscratch2));
 838     }
 839   }
 840 }

 841 
 842 
 843 // Interpreter stub for calling a native method. (asm interpreter)
 844 // This sets up a somewhat different looking stack for calling the
 845 // native method than the typical interpreter frame setup.
 846 address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) {
 847   // determine code generation flags
 848   bool inc_counter  = UseCompiler || CountCompiledCalls || LogTouchedMethods;
 849 
 850   // r1: Method*
 851   // rscratch1: sender sp
 852 
 853   address entry_point = __ pc();
 854 
 855   const Address constMethod       (rmethod, Method::const_offset());
 856   const Address access_flags      (rmethod, Method::access_flags_offset());
 857   const Address size_of_parameters(r2, ConstMethod::
 858                                        size_of_parameters_offset());
 859 
 860   // get parameter size (always needed)




  40 #include "prims/jvmtiThreadState.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 <sys/types.h>
  51 
  52 #ifndef PRODUCT
  53 #include "oops/method.hpp"
  54 #endif // !PRODUCT
  55 
  56 #ifdef BUILTIN_SIM
  57 #include "../../../../../../simulator/simulator.hpp"
  58 #endif
  59 
  60 // Size of interpreter code.  Increase if too small.  Interpreter will
  61 // fail with a guarantee ("not enough space for interpreter generation");
  62 // if too small.
  63 // Run with +PrintInterpreter to get the VM to print out the size.
  64 // Max size with JVMTI
  65 int TemplateInterpreter::InterpreterCodeSize = 200 * 1024;
  66 
  67 #define __ _masm->
  68 
  69 //-----------------------------------------------------------------------------
  70 
  71 extern "C" void entry(CodeBuffer*);
  72 
  73 //-----------------------------------------------------------------------------
  74 
  75 address TemplateInterpreterGenerator::generate_slow_signature_handler() {
  76   address entry = __ pc();
  77 
  78   __ andr(esp, esp, -16);
  79   __ mov(c_rarg3, esp);
  80   // rmethod
  81   // rlocals
  82   // c_rarg3: first stack arg - wordSize
  83 
  84   // adjust sp
  85   __ sub(sp, c_rarg3, 18 * wordSize);
  86   __ str(lr, Address(__ pre(sp, -2 * wordSize)));
  87   __ call_VM(noreg,
  88              CAST_FROM_FN_PTR(address,
  89                               InterpreterRuntime::slow_signature_handler),
  90              rmethod, rlocals, c_rarg3);
  91 
  92   // r0: result handler
  93 
  94   // Stack layout:
  95   // rsp: return address           <- sp
  96   //      1 garbage
  97   //      8 integer args (if static first is unused)
  98   //      1 float/double identifiers
  99   //      8 double args
 100   //        stack args              <- esp
 101   //        garbage
 102   //        expression stack bottom
 103   //        bcp (NULL)
 104   //        ...
 105 
 106   // Restore LR
 107   __ ldr(lr, Address(__ post(sp, 2 * wordSize)));
 108 
 109   // Do FP first so we can use c_rarg3 as temp
 110   __ ldrw(c_rarg3, Address(sp, 9 * wordSize)); // float/double identifiers
 111 
 112   for (int i = 0; i < Argument::n_float_register_parameters_c; i++) {
 113     const FloatRegister r = as_FloatRegister(i);
 114 
 115     Label d, done;
 116 
 117     __ tbnz(c_rarg3, i, d);
 118     __ ldrs(r, Address(sp, (10 + i) * wordSize));
 119     __ b(done);
 120     __ bind(d);
 121     __ ldrd(r, Address(sp, (10 + i) * wordSize));
 122     __ bind(done);
 123   }
 124 
 125   // c_rarg0 contains the result from the call of
 126   // InterpreterRuntime::slow_signature_handler so we don't touch it
 127   // here.  It will be loaded with the JNIEnv* later.
 128   __ ldr(c_rarg1, Address(sp, 1 * wordSize));
 129   for (int i = c_rarg2->encoding(); i <= c_rarg7->encoding(); i += 2) {
 130     Register rm = as_Register(i), rn = as_Register(i+1);
 131     __ ldp(rm, rn, Address(sp, i * wordSize));
 132   }
 133 
 134   __ add(sp, sp, 18 * wordSize);
 135   __ ret(lr);
 136 
 137   return entry;
 138 }
 139 
 140 
 141 //
 142 // Various method entries
 143 //
 144 
 145 address TemplateInterpreterGenerator::generate_math_entry(AbstractInterpreter::MethodKind kind) {
 146   // rmethod: Method*
 147   // r13: sender sp
 148   // esp: args
 149 
 150   if (!InlineIntrinsics) return NULL; // Generate a vanilla entry
 151 
 152   // These don't need a safepoint check because they aren't virtually
 153   // callable. We won't enter these intrinsics from compiled code.
 154   // If in the future we added an intrinsic which was virtually callable
 155   // we'd have to worry about how to safepoint so that this code is used.
 156 
 157   // mathematical functions inlined by compiler
 158   // (interpreter must provide identical implementation
 159   // in order to avoid monotonicity bugs when switching
 160   // from interpreter to compiler in the middle of some
 161   // computation)
 162   //
 163   // stack:
 164   //        [ arg ] <-- esp
 165   //        [ arg ]
 166   // retaddr in lr
 167 
 168   address entry_point = NULL;
 169   Register continuation = lr;
 170   switch (kind) {
 171   case Interpreter::java_lang_math_abs:
 172     entry_point = __ pc();
 173     __ ldrd(v0, Address(esp));
 174     __ fabsd(v0, v0);
 175     __ mov(sp, r13); // Restore caller's SP
 176     break;
 177   case Interpreter::java_lang_math_sqrt:
 178     entry_point = __ pc();
 179     __ ldrd(v0, Address(esp));
 180     __ fsqrtd(v0, v0);
 181     __ mov(sp, r13);
 182     break;
 183   case Interpreter::java_lang_math_sin :
 184   case Interpreter::java_lang_math_cos :
 185   case Interpreter::java_lang_math_tan :
 186   case Interpreter::java_lang_math_log :
 187   case Interpreter::java_lang_math_log10 :
 188   case Interpreter::java_lang_math_exp :
 189     entry_point = __ pc();
 190     __ ldrd(v0, Address(esp));
 191     __ mov(sp, r13);
 192     __ mov(r19, lr);
 193     continuation = r19;  // The first callee-saved register
 194     generate_transcendental_entry(kind, 1);
 195     break;
 196   case Interpreter::java_lang_math_pow :
 197     entry_point = __ pc();
 198     __ mov(r19, lr);
 199     continuation = r19;
 200     __ ldrd(v0, Address(esp, 2 * Interpreter::stackElementSize));
 201     __ ldrd(v1, Address(esp));
 202     __ mov(sp, r13);
 203     generate_transcendental_entry(kind, 2);
 204     break;
 205   default:
 206     ;
 207   }
 208   if (entry_point) {
 209     __ br(continuation);
 210   }
 211 
 212   return entry_point;
 213 }
 214 
 215   // double trigonometrics and transcendentals
 216   // static jdouble dsin(jdouble x);
 217   // static jdouble dcos(jdouble x);
 218   // static jdouble dtan(jdouble x);
 219   // static jdouble dlog(jdouble x);
 220   // static jdouble dlog10(jdouble x);
 221   // static jdouble dexp(jdouble x);
 222   // static jdouble dpow(jdouble x, jdouble y);
 223 
 224 void TemplateInterpreterGenerator::generate_transcendental_entry(AbstractInterpreter::MethodKind kind, int fpargs) {
 225   address fn;
 226   switch (kind) {
 227   case Interpreter::java_lang_math_sin :
 228     fn = CAST_FROM_FN_PTR(address, SharedRuntime::dsin);
 229     break;
 230   case Interpreter::java_lang_math_cos :
 231     fn = CAST_FROM_FN_PTR(address, SharedRuntime::dcos);
 232     break;
 233   case Interpreter::java_lang_math_tan :
 234     fn = CAST_FROM_FN_PTR(address, SharedRuntime::dtan);
 235     break;
 236   case Interpreter::java_lang_math_log :
 237     fn = CAST_FROM_FN_PTR(address, SharedRuntime::dlog);
 238     break;
 239   case Interpreter::java_lang_math_log10 :
 240     fn = CAST_FROM_FN_PTR(address, SharedRuntime::dlog10);
 241     break;
 242   case Interpreter::java_lang_math_exp :
 243     fn = CAST_FROM_FN_PTR(address, SharedRuntime::dexp);
 244     break;
 245   case Interpreter::java_lang_math_pow :
 246     fpargs = 2;
 247     fn = CAST_FROM_FN_PTR(address, SharedRuntime::dpow);
 248     break;
 249   default:
 250     ShouldNotReachHere();
 251   }
 252   const int gpargs = 0, rtype = 3;
 253   __ mov(rscratch1, fn);
 254   __ blrt(rscratch1, gpargs, fpargs, rtype);
 255 }
 256 
 257 // Abstract method entry
 258 // Attempt to execute abstract method. Throw exception
 259 address TemplateInterpreterGenerator::generate_abstract_entry(void) {
 260   // rmethod: Method*
 261   // r13: sender SP
 262 
 263   address entry_point = __ pc();
 264 
 265   // abstract method entry
 266 
 267   //  pop return address, reset last_sp to NULL
 268   __ empty_expression_stack();
 269   __ restore_bcp();      // bcp must be correct for exception handler   (was destroyed)
 270   __ restore_locals();   // make sure locals pointer is correct as well (was destroyed)
 271 
 272   // throw exception
 273   __ call_VM(noreg, CAST_FROM_FN_PTR(address,
 274                              InterpreterRuntime::throw_AbstractMethodError));
 275   // the call_VM checks for exception, so we should never return here.
 276   __ should_not_reach_here();
 277 
 278   return entry_point;
 279 }
 280 
 281 address TemplateInterpreterGenerator::generate_StackOverflowError_handler() {
 282   address entry = __ pc();
 283 
 284 #ifdef ASSERT
 285   {
 286     Label L;
 287     __ ldr(rscratch1, Address(rfp,
 288                        frame::interpreter_frame_monitor_block_top_offset *
 289                        wordSize));
 290     __ mov(rscratch2, sp);
 291     __ cmp(rscratch1, rscratch2); // maximal rsp for current rfp (stack
 292                            // grows negative)
 293     __ br(Assembler::HS, L); // check if frame is complete
 294     __ stop ("interpreter frame not set up");
 295     __ bind(L);
 296   }
 297 #endif // ASSERT
 298   // Restore bcp under the assumption that the current frame is still
 299   // interpreted
 300   __ restore_bcp();


1020     __ ldrw(len, Address(esp, 0x0)); // Length
1021 
1022     __ andr(sp, r13, -16); // Restore the caller's SP
1023 
1024     // We are frameless so we can just jump to the stub.
1025     __ b(CAST_FROM_FN_PTR(address, StubRoutines::updateBytesCRC32()));
1026 
1027     // generate a vanilla native entry as the slow path
1028     __ bind(slow_path);
1029     __ jump_to_entry(Interpreter::entry_for_kind(Interpreter::native));
1030     return entry;
1031   }
1032   return NULL;
1033 }
1034 
1035 // Not supported
1036 address TemplateInterpreterGenerator::generate_CRC32C_updateBytes_entry(AbstractInterpreter::MethodKind kind) {
1037   return NULL;
1038 }
1039 
1040 #if 0
1041 // This is the same one as in the shared version instructions look equivalent to bang_stack_with_offset.
1042 // Not sure why this definition was added.
1043 void TemplateInterpreterGenerator::bang_stack_shadow_pages(bool native_call) {
1044   // Bang each page in the shadow zone. We can't assume it's been done for
1045   // an interpreter frame with greater than a page of locals, so each page
1046   // needs to be checked.  Only true for non-native.
1047   if (UseStackBanging) {
1048     const int size_t n_shadow_pages = JavaThread::stack_shadow_zone_size() / os::vm_page_size();
1049     const int start_page = native_call ? n_shadow_pages : 1;
1050     const int page_size = os::vm_page_size();
1051     for (int pages = start_page; pages <= n_shadow_pages ; pages++) {
1052       __ sub(rscratch2, sp, pages*page_size);
1053       __ str(zr, Address(rscratch2));
1054     }
1055   }
1056 }
1057 #endif
1058 
1059 
1060 // Interpreter stub for calling a native method. (asm interpreter)
1061 // This sets up a somewhat different looking stack for calling the
1062 // native method than the typical interpreter frame setup.
1063 address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) {
1064   // determine code generation flags
1065   bool inc_counter  = UseCompiler || CountCompiledCalls || LogTouchedMethods;
1066 
1067   // r1: Method*
1068   // rscratch1: sender sp
1069 
1070   address entry_point = __ pc();
1071 
1072   const Address constMethod       (rmethod, Method::const_offset());
1073   const Address access_flags      (rmethod, Method::access_flags_offset());
1074   const Address size_of_parameters(r2, ConstMethod::
1075                                        size_of_parameters_offset());
1076 
1077   // get parameter size (always needed)