jdk
1/*
2* Copyright (c) 1998, 2023, 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 COMPILER227#include "asm/macroAssembler.hpp"28#include "asm/macroAssembler.inline.hpp"29#include "code/vmreg.hpp"30#include "compiler/oopMap.hpp"31#include "interpreter/interpreter.hpp"32#include "memory/resourceArea.hpp"33#include "opto/runtime.hpp"34#include "runtime/sharedRuntime.hpp"35#include "runtime/stubRoutines.hpp"36#include "runtime/vframeArray.hpp"37#include "utilities/globalDefinitions.hpp"38#include "vmreg_x86.inline.hpp"39#endif40
41
42#define __ masm->43
44//------------------------------generate_exception_blob---------------------------
45// creates exception blob at the end
46// Using exception blob, this code is jumped from a compiled method.
47//
48// Given an exception pc at a call we call into the runtime for the
49// handler in this method. This handler might merely restore state
50// (i.e. callee save registers) unwind the frame and jump to the
51// exception handler for the nmethod if there is no Java level handler
52// for the nmethod.
53//
54// This code is entered with a jmp.
55//
56// Arguments:
57// rax: exception oop
58// rdx: exception pc
59//
60// Results:
61// rax: exception oop
62// rdx: exception pc in caller or ???
63// destination: exception handler of caller
64//
65// Note: the exception pc MUST be at a call (precise debug information)
66// Only register rax, rdx, rcx are not callee saved.
67//
68
69void OptoRuntime::generate_exception_blob() {70
71// Capture info about frame layout72enum layout {73thread_off, // last_java_sp74// The frame sender code expects that rbp will be in the "natural" place and75// will override any oopMap setting for it. We must therefore force the layout76// so that it agrees with the frame sender code.77rbp_off,78return_off, // slot for return address79framesize
80};81
82// allocate space for the code83ResourceMark rm;84// setup code generation tools85CodeBuffer buffer("exception_blob", 512, 512);86MacroAssembler* masm = new MacroAssembler(&buffer);87
88OopMapSet *oop_maps = new OopMapSet();89
90address start = __ pc();91
92__ push(rdx);93__ subptr(rsp, return_off * wordSize); // Prolog!94
95// rbp, location is implicitly known96__ movptr(Address(rsp,rbp_off *wordSize), rbp);97
98// Store exception in Thread object. We cannot pass any arguments to the99// handle_exception call, since we do not want to make any assumption100// about the size of the frame where the exception happened in.101__ get_thread(rcx);102__ movptr(Address(rcx, JavaThread::exception_oop_offset()), rax);103__ movptr(Address(rcx, JavaThread::exception_pc_offset()), rdx);104
105// This call does all the hard work. It checks if an exception handler106// exists in the method.107// If so, it returns the handler address.108// If not, it prepares for stack-unwinding, restoring the callee-save109// registers of the frame being removed.110//111__ movptr(Address(rsp, thread_off * wordSize), rcx); // Thread is first argument112__ set_last_Java_frame(rcx, noreg, noreg, nullptr, noreg);113
114__ call(RuntimeAddress(CAST_FROM_FN_PTR(address, OptoRuntime::handle_exception_C)));115
116// No registers to map, rbp is known implicitly117oop_maps->add_gc_map( __ pc() - start, new OopMap( framesize, 0 ));118__ get_thread(rcx);119__ reset_last_Java_frame(rcx, false);120
121// Restore callee-saved registers122__ movptr(rbp, Address(rsp, rbp_off * wordSize));123
124__ addptr(rsp, return_off * wordSize); // Epilog!125__ pop(rdx); // Exception pc126
127// rax: exception handler for given <exception oop/exception pc>128
129// We have a handler in rax, (could be deopt blob)130// rdx - throwing pc, deopt blob will need it.131
132__ push(rax);133
134// Get the exception135__ movptr(rax, Address(rcx, JavaThread::exception_oop_offset()));136// Get the exception pc in case we are deoptimized137__ movptr(rdx, Address(rcx, JavaThread::exception_pc_offset()));138#ifdef ASSERT139__ movptr(Address(rcx, JavaThread::exception_handler_pc_offset()), NULL_WORD);140__ movptr(Address(rcx, JavaThread::exception_pc_offset()), NULL_WORD);141#endif142// Clear the exception oop so GC no longer processes it as a root.143__ movptr(Address(rcx, JavaThread::exception_oop_offset()), NULL_WORD);144
145__ pop(rcx);146
147// rax: exception oop148// rcx: exception handler149// rdx: exception pc150__ jmp (rcx);151
152// -------------153// make sure all code is generated154masm->flush();155
156_exception_blob = ExceptionBlob::create(&buffer, oop_maps, framesize);157}
158