1 /*
   2  * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
   3  * Copyright (c) 2016 SAP SE. 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 it
   7  * under the terms of the GNU General Public License version 2 only, as
   8  * published by the Free Software Foundation.
   9  *
  10  * This code is distributed in the hope that it will be useful, but WITHOUT
  11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  13  * version 2 for more details (a copy is included in the LICENSE file that
  14  * accompanied this code).
  15  *
  16  * You should have received a copy of the GNU General Public License version
  17  * 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 USA
  21  * or visit www.oracle.com if you need additional information or have any
  22  * questions.
  23  *
  24  */
  25 
  26 #include "precompiled.hpp"
  27 #ifdef COMPILER2
  28 #include "asm/macroAssembler.inline.hpp"
  29 #include "classfile/systemDictionary.hpp"
  30 #include "code/vmreg.hpp"
  31 #include "interpreter/interpreter.hpp"
  32 #include "memory/resourceArea.hpp"
  33 #include "nativeInst_s390.hpp"
  34 #include "opto/runtime.hpp"
  35 #include "runtime/interfaceSupport.hpp"
  36 #include "runtime/sharedRuntime.hpp"
  37 #include "runtime/stubRoutines.hpp"
  38 #include "runtime/vframeArray.hpp"
  39 #include "utilities/globalDefinitions.hpp"
  40 #include "vmreg_s390.inline.hpp"
  41 #endif
  42 
  43 #define __ masm->
  44 
  45 
  46 //------------------------------generate_exception_blob---------------------------
  47 // creates exception blob at the end
  48 // Using exception blob, this code is jumped from a compiled method.
  49 // (see emit_exception_handler in s390.ad file)
  50 //
  51 // Given an exception pc at a call we call into the runtime for the
  52 // handler in this method. This handler might merely restore state
  53 // (i.e. callee save registers), unwind the frame, and jump to the
  54 // exception handler for the nmethod if there is no Java level handler
  55 // for the nmethod.
  56 //
  57 // This code is entered with a branch.
  58 //
  59 // Arguments:
  60 //   Z_R2(=Z_ARG1): exception oop
  61 //   Z_R3(=Z_ARG2): exception pc
  62 //
  63 // Results:
  64 //   Z_R2: exception oop
  65 //   Z_R3: exception pc in caller
  66 //   destination: exception handler of caller
  67 //
  68 // Note: the exception pc MUST be at a call (precise debug information)
  69 
  70 void OptoRuntime::generate_exception_blob() {
  71 
  72   // Allocate space for the code
  73   ResourceMark rm;
  74   // Setup code generation tools
  75   CodeBuffer buffer("exception_blob", 2048, 1024);
  76   MacroAssembler* masm = new MacroAssembler(&buffer);
  77 
  78   Register handle_exception = Z_ARG5;
  79 
  80   __ verify_thread();
  81   __ z_stg(Z_ARG1/*exception oop*/, Address(Z_thread, JavaThread::exception_oop_offset()));
  82   __ z_stg(Z_ARG2/*issuing pc*/,    Address(Z_thread, JavaThread::exception_pc_offset()));
  83 
  84   // Store issuing pc as return pc into
  85   // caller's frame. stack-walking needs it. R14 is not valid here,
  86   // because this code gets entered with a jump.
  87   __ z_stg(Z_ARG2/*issuing pc*/, _z_abi(return_pc), Z_SP);
  88 
  89   // The following call to function OptoRuntime::handle_exception_C
  90   // does all the hard work. It checks if an
  91   // exception catch exists in the method. If so, it returns the
  92   // handler address. If the nmethod has been deoptimized and it had
  93   // a handler the handler address is the deopt blob's
  94   // unpack_with_exception entry.
  95 
  96   // push a C frame for the exception blob. it is needed for the
  97   // C call later on.
  98 
  99   Register saved_sp = Z_R11;
 100 
 101   __ z_lgr(saved_sp, Z_SP);
 102 
 103   // push frame for blob.
 104   int frame_size = __ push_frame_abi160(0);
 105 
 106   __ get_PC(Z_R1/*scratch*/);
 107   __ set_last_Java_frame(/*sp=*/Z_SP, /*pc=*/Z_R1);
 108 
 109   // This call can lead to deoptimization of the nmethod holding the handler.
 110   __ z_lgr(Z_ARG1, Z_thread);   // argument of C function
 111   __ call_c(CAST_FROM_FN_PTR(address, OptoRuntime::handle_exception_C));
 112 
 113   __ z_lgr(handle_exception, Z_RET);
 114   __ reset_last_Java_frame();
 115 
 116   // Pop the exception blob's C frame that has been pushed before.
 117   __ z_lgr(Z_SP, saved_sp);
 118 
 119   // [Z_RET]!=NULL was possible in hotspot5 but not in sapjvm6.
 120   // C2I adapter extensions are now removed by a resize in the frame manager
 121   // (unwind_initial_activation_pending_exception).
 122 #ifdef ASSERT
 123   __ z_ltgr(handle_exception, handle_exception);
 124   __ asm_assert_ne("handler must not be NULL", 0x852);
 125 #endif
 126 
 127   // Handle_exception contains the handler address. If the associated frame
 128   // has been deoptimized then the handler has been patched to jump to
 129   // the deoptimization blob.
 130 
 131   // If the exception handler jumps to the deoptimization blob, the
 132   // exception pc will be read from there.
 133   __ z_lg(Z_ARG2, Address(Z_thread, JavaThread::exception_pc_offset()));
 134 
 135   __ z_lg(Z_ARG1, Address(Z_thread, JavaThread::exception_oop_offset()));
 136 
 137   // Clear the exception oop so GC no longer processes it as a root.
 138   __ clear_mem(Address(Z_thread, JavaThread::exception_oop_offset()),sizeof(intptr_t));
 139 #ifdef ASSERT
 140   __ clear_mem(Address(Z_thread, JavaThread::exception_handler_pc_offset()), sizeof(intptr_t));
 141   __ clear_mem(Address(Z_thread, JavaThread::exception_pc_offset()), sizeof(intptr_t));
 142 #endif
 143 
 144   __ z_br(handle_exception);
 145 
 146   // Make sure all code is generated.
 147   masm->flush();
 148 
 149   // Set exception blob.
 150   OopMapSet *oop_maps = NULL;
 151   _exception_blob =  ExceptionBlob::create(&buffer, oop_maps, frame_size/wordSize);
 152 }