hotspot/src/cpu/arm/vm/runtime_arm.cpp
changeset 42664 29142a56c193
equal deleted inserted replaced
42663:2335df372367 42664:29142a56c193
       
     1 /*
       
     2  * Copyright (c) 2008, 2016, Oracle and/or its affiliates. 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 it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.
       
     8  *
       
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    12  * version 2 for more details (a copy is included in the LICENSE file that
       
    13  * accompanied this code).
       
    14  *
       
    15  * You should have received a copy of the GNU General Public License version
       
    16  * 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 USA
       
    20  * or visit www.oracle.com if you need additional information or have any
       
    21  * questions.
       
    22  *
       
    23  */
       
    24 
       
    25 #include "precompiled.hpp"
       
    26 #ifdef COMPILER2
       
    27 #include "asm/assembler.hpp"
       
    28 #include "assembler_arm.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_arm.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_arm.inline.hpp"
       
    41 #endif
       
    42 
       
    43 #define __ masm->
       
    44 
       
    45 //------------------------------ generate_exception_blob ---------------------------
       
    46 // creates exception blob at the end
       
    47 // Using exception blob, this code is jumped from a compiled method.
       
    48 // (see emit_exception_handler in sparc.ad file)
       
    49 //
       
    50 // Given an exception pc at a call we call into the runtime for the
       
    51 // handler in this method. This handler might merely restore state
       
    52 // (i.e. callee save registers) unwind the frame and jump to the
       
    53 // exception handler for the nmethod if there is no Java level handler
       
    54 // for the nmethod.
       
    55 //
       
    56 // This code is entered with a jmp.
       
    57 //
       
    58 // Arguments:
       
    59 //   Rexception_obj (R4/R19): exception oop
       
    60 //   Rexception_pc  (R5/R20): exception pc
       
    61 //
       
    62 // Results:
       
    63 //   Rexception_obj (R4/R19): exception oop
       
    64 //   O1: exception pc in caller or ???
       
    65 //   destination: exception handler of caller
       
    66 //
       
    67 // Note: the exception pc MUST be at a call (precise debug information)
       
    68 //
       
    69 void OptoRuntime::generate_exception_blob() {
       
    70   // allocate space for code
       
    71   ResourceMark rm;
       
    72   int pad = VerifyThread ? 256 : 0;// Extra slop space for more verify code
       
    73 
       
    74   // setup code generation tools
       
    75   // Measured 8/7/03 at 256 in 32bit debug build (no VerifyThread)
       
    76   // Measured 8/7/03 at 528 in 32bit debug build (VerifyThread)
       
    77   CodeBuffer buffer("exception_blob", 600+pad, 512);
       
    78   MacroAssembler* masm     = new MacroAssembler(&buffer);
       
    79 
       
    80   int framesize_in_words = 2; // FP + LR
       
    81   int framesize_in_bytes = framesize_in_words * wordSize;
       
    82   int framesize_in_slots = framesize_in_bytes / sizeof(jint);
       
    83 
       
    84   int start = __ offset();
       
    85 
       
    86   __ str(Rexception_obj, Address(Rthread, JavaThread::exception_oop_offset()));
       
    87   __ str(Rexception_pc, Address(Rthread, JavaThread::exception_pc_offset()));
       
    88 
       
    89   // This call does all the hard work. It checks if an exception catch
       
    90   // exists in the method.
       
    91   // If so, it returns the handler address.
       
    92   // If the nmethod has been deoptimized and it had a handler the handler
       
    93   // address is the deopt blob unpack_with_exception entry.
       
    94   //
       
    95   // If no handler exists it prepares for stack-unwinding, restoring the callee-save
       
    96   // registers of the frame being removed.
       
    97   //
       
    98   __ mov(LR, Rexception_pc);
       
    99   __ raw_push(FP, LR);
       
   100   int pc_offset = __ set_last_Java_frame(SP, FP, false, Rtemp);
       
   101 
       
   102   __ mov(R0, Rthread);
       
   103 
       
   104   // This call can block at exit and nmethod can be deoptimized at that
       
   105   // point. If the nmethod had a catch point we would jump to the
       
   106   // now deoptimized catch point and fall thru the vanilla deopt
       
   107   // path and lose the exception
       
   108   // Sure would be simpler if this call didn't block!
       
   109   __ call(CAST_FROM_FN_PTR(address, OptoRuntime::handle_exception_C));
       
   110   if (pc_offset == -1) {
       
   111     pc_offset = __ offset();
       
   112   }
       
   113 
       
   114   // Set an oopmap for the call site.  This oopmap will only be used if we
       
   115   // are unwinding the stack.  Hence, all locations will be dead.
       
   116   // Callee-saved registers will be the same as the frame above (i.e.,
       
   117   // handle_exception_stub), since they were restored when we got the
       
   118   // exception.
       
   119 
       
   120   OopMapSet *oop_maps = new OopMapSet();
       
   121   oop_maps->add_gc_map(pc_offset - start, new OopMap(framesize_in_slots, 0));
       
   122 
       
   123   __ reset_last_Java_frame(Rtemp);
       
   124 
       
   125   __ raw_pop(FP, LR);
       
   126 
       
   127   // Restore SP from its saved reg (FP) if the exception PC is a MethodHandle call site.
       
   128   __ ldr(Rtemp, Address(Rthread, JavaThread::is_method_handle_return_offset()));
       
   129 #ifdef AARCH64
       
   130   Label skip;
       
   131   __ cbz(Rtemp, skip);
       
   132   __ mov(SP, Rmh_SP_save);
       
   133   __ bind(skip);
       
   134 #else
       
   135   __ cmp(Rtemp, 0);
       
   136   __ mov(SP, Rmh_SP_save, ne);
       
   137 #endif
       
   138 
       
   139   // R0 contains handler address
       
   140   // Since this may be the deopt blob we must set R5 to look like we returned
       
   141   // from the original pc that threw the exception
       
   142 
       
   143   __ ldr(Rexception_pc,  Address(Rthread, JavaThread::exception_pc_offset()));  // R5/R20
       
   144 
       
   145   __ ldr(Rexception_obj, Address(Rthread, JavaThread::exception_oop_offset())); // R4/R19
       
   146   __ mov(Rtemp, 0);
       
   147 #ifdef ASSERT
       
   148   __ str(Rtemp, Address(Rthread, JavaThread::exception_handler_pc_offset()));
       
   149   __ str(Rtemp, Address(Rthread, JavaThread::exception_pc_offset()));
       
   150 #endif
       
   151   // Clear the exception oop so GC no longer processes it as a root.
       
   152   __ str(Rtemp, Address(Rthread, JavaThread::exception_oop_offset()));
       
   153   __ jump(R0);
       
   154 
       
   155   // -------------
       
   156   // make sure all code is generated
       
   157   masm->flush();
       
   158 
       
   159   _exception_blob = ExceptionBlob::create(&buffer, oop_maps, framesize_in_words);
       
   160 }