blob: 3df1e4b726d07d33f715dd57795d491c5b2ecfe7 [file] [log] [blame]
/*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "asm/assembler.hpp"
#include "asm/codeBuffer.hpp"
#include "memory/allocation.hpp"
#include "opto/c2_MacroAssembler.hpp"
#include "opto/compile.hpp"
#include "opto/output.hpp"
#include "utilities/growableArray.hpp"
#include "utilities/tuple.hpp"
#ifndef SHARE_OPTO_C2_CODESTUBS_HPP
#define SHARE_OPTO_C2_CODESTUBS_HPP
template <class... Ts>
class C2GeneralStub;
class C2CodeStub : public ArenaObj {
private:
Label _entry;
Label _continuation;
void add_to_stub_list();
protected:
C2CodeStub() :
_entry(),
_continuation() {}
public:
Label& entry() { return _entry; }
Label& continuation() { return _continuation; }
virtual void emit(C2_MacroAssembler& masm) = 0;
virtual int max_size() const = 0;
template <class... Ts>
static C2GeneralStub<Ts...>* make(const Ts&... data, int max_size,
void (*emit)(C2_MacroAssembler&, C2GeneralStub<Ts...>&));
};
class C2CodeStubList {
private:
GrowableArray<C2CodeStub*> _stubs;
public:
C2CodeStubList();
void add_stub(C2CodeStub* stub) { _stubs.append(stub); }
void emit(CodeBuffer& cb);
};
class C2SafepointPollStub : public C2CodeStub {
private:
uintptr_t _safepoint_offset;
public:
C2SafepointPollStub(uintptr_t safepoint_offset) :
_safepoint_offset(safepoint_offset) {}
int max_size() const;
void emit(C2_MacroAssembler& masm);
};
// We move non-hot code of the nmethod entry barrier to an out-of-line stub
class C2EntryBarrierStub: public C2CodeStub {
private:
Label _guard; // Used on AArch64 and RISCV
public:
C2EntryBarrierStub() : C2CodeStub(),
_guard() {}
Label& guard() { return _guard; }
int max_size() const;
void emit(C2_MacroAssembler& masm);
};
#ifdef _LP64
class C2HandleAnonOMOwnerStub : public C2CodeStub {
private:
Register _monitor;
Register _tmp;
public:
C2HandleAnonOMOwnerStub(Register monitor, Register tmp = noreg) : C2CodeStub(),
_monitor(monitor), _tmp(tmp) {}
Register monitor() { return _monitor; }
Register tmp() { return _tmp; }
int max_size() const;
void emit(C2_MacroAssembler& masm);
};
#endif
//-----------------------------C2GeneralStub-----------------------------------
// A generalized stub that can be used to implement an arbitrary stub in a
// type-safe manner. An example:
//
// Register dst; XMMRegister src;
// // The lambda defining how the code is emitted in the stub
// auto slowpath = [](C2_MacroAssembler& masm, C2GeneralStub<Register, XMMRegister>& stub) {
// // Access the saved data in a type safe manner
// Register dst = stub.get<0>();
// XMMRegister src = stub.get<1>();
// masm.bind(stub.entry());
// ...
// masm.jump(stub.continuation());
// }
// // Create a stub with 2 data fields being dst and src, a max size of 4 bytes
// // and predefined emission function
// auto stub = C2CodeStub::make<Register, XMMRegister>(dst, src, 4, slowpath);
// __ jump_conditional(stub->entry());
// ...
// __ bind(stub->continuation());
//
template <class... Ts>
class C2GeneralStub : public C2CodeStub {
private:
Tuple<Ts...> _data;
int _max_size;
void (*_emit)(C2_MacroAssembler&, C2GeneralStub&);
constexpr C2GeneralStub(const Ts&... data, int max_size,
void (*emit)(C2_MacroAssembler&, C2GeneralStub<Ts...>&))
: _data(data...), _max_size(max_size), _emit(emit) {}
friend C2CodeStub;
public:
template <std::size_t I>
constexpr const auto& data() const { return _data.template get<I>(); }
int max_size() const { return _max_size; }
void emit(C2_MacroAssembler& masm) { _emit(masm, *this); }
};
template <class... Ts>
C2GeneralStub<Ts...>* C2CodeStub::make(const Ts&... data, int max_size,
void (*emit)(C2_MacroAssembler&, C2GeneralStub<Ts...>&)) {
auto stub = new (Compile::current()->comp_arena()) C2GeneralStub<Ts...>(data..., max_size, emit);
stub->add_to_stub_list();
return stub;
}
#endif // SHARE_OPTO_C2_CODESTUBS_HPP