blob: d2d5a5ab36635f628d1ebb10741bd97c65604c3c [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.
*
*/
#ifndef SHARE_VM_RUNTIME_CONTINUATIONENTRY_HPP
#define SHARE_VM_RUNTIME_CONTINUATIONENTRY_HPP
#include "oops/oop.hpp"
#include "oops/oopsHierarchy.hpp"
#include "runtime/continuation.hpp"
#include "utilities/sizes.hpp"
#include CPU_HEADER(continuationEntry)
class CompiledMethod;
class JavaThread;
class OopMap;
class RegisterMap;
// Metadata stored in the continuation entry frame
class ContinuationEntry {
ContinuationEntryPD _pd;
#ifdef ASSERT
private:
static const int COOKIE_VALUE = 0x1234;
int cookie;
public:
static int cookie_value() { return COOKIE_VALUE; }
static ByteSize cookie_offset() { return byte_offset_of(ContinuationEntry, cookie); }
void verify_cookie() {
assert(cookie == COOKIE_VALUE, "Bad cookie: %#x, expected: %#x", cookie, COOKIE_VALUE);
}
#endif
public:
static int _return_pc_offset; // friend gen_continuation_enter
static void set_enter_code(CompiledMethod* cm, int interpreted_entry_offset);
static bool is_interpreted_call(address call_address);
private:
static address _return_pc;
static CompiledMethod* _enter_special;
static int _interpreted_entry_offset;
private:
ContinuationEntry* _parent;
oopDesc* _cont;
oopDesc* _chunk;
int _flags;
// Size in words of the stack arguments of the bottom frame on stack if compiled 0 otherwise.
// The caller (if there is one) is the still frozen top frame in the StackChunk.
int _argsize;
intptr_t* _parent_cont_fastpath;
#ifdef _LP64
int64_t _parent_held_monitor_count;
#else
int32_t _parent_held_monitor_count;
#endif
uint _pin_count;
public:
static ByteSize parent_offset() { return byte_offset_of(ContinuationEntry, _parent); }
static ByteSize cont_offset() { return byte_offset_of(ContinuationEntry, _cont); }
static ByteSize chunk_offset() { return byte_offset_of(ContinuationEntry, _chunk); }
static ByteSize flags_offset() { return byte_offset_of(ContinuationEntry, _flags); }
static ByteSize argsize_offset() { return byte_offset_of(ContinuationEntry, _argsize); }
static ByteSize pin_count_offset(){ return byte_offset_of(ContinuationEntry, _pin_count); }
static ByteSize parent_cont_fastpath_offset() { return byte_offset_of(ContinuationEntry, _parent_cont_fastpath); }
static ByteSize parent_held_monitor_count_offset() { return byte_offset_of(ContinuationEntry, _parent_held_monitor_count); }
public:
static size_t size() { return align_up((int)sizeof(ContinuationEntry), 2*wordSize); }
ContinuationEntry* parent() const { return _parent; }
int64_t parent_held_monitor_count() const { return (int64_t)_parent_held_monitor_count; }
static address entry_pc() { return _return_pc; }
intptr_t* entry_sp() const { return (intptr_t*)this; }
intptr_t* entry_fp() const;
static address compiled_entry();
static address interpreted_entry();
int argsize() const { return _argsize; }
void set_argsize(int value) { _argsize = value; }
bool is_pinned() { return _pin_count > 0; }
bool pin() {
if (_pin_count == UINT_MAX) return false;
_pin_count++;
return true;
}
bool unpin() {
if (_pin_count == 0) return false;
_pin_count--;
return true;
}
intptr_t* parent_cont_fastpath() const { return _parent_cont_fastpath; }
void set_parent_cont_fastpath(intptr_t* x) { _parent_cont_fastpath = x; }
static ContinuationEntry* from_frame(const frame& f);
frame to_frame() const;
void update_register_map(RegisterMap* map) const;
void flush_stack_processing(JavaThread* thread) const;
inline intptr_t* bottom_sender_sp() const;
inline oop cont_oop(const JavaThread* thread) const;
inline oop scope(const JavaThread* thread) const;
inline static oop cont_oop_or_null(const ContinuationEntry* ce, const JavaThread* thread);
oop* cont_addr() { return (oop*)&_cont; }
oop* chunk_addr() { return (oop*)&_chunk; }
bool is_virtual_thread() const { return _flags != 0; }
#ifndef PRODUCT
void describe(FrameValues& values, int frame_no) const;
#endif
#ifdef ASSERT
static bool assert_entry_frame_laid_out(JavaThread* thread);
#endif
};
#endif // SHARE_VM_RUNTIME_CONTINUATIONENTRY_HPP