/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* 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_C1_C1_INSTRUCTION_HPP
#define SHARE_VM_C1_C1_INSTRUCTION_HPP
#include "c1/c1_Compilation.hpp"
#include "c1/c1_LIR.hpp"
#include "c1/c1_ValueType.hpp"
#include "ci/ciField.hpp"
// Predefined classes
class ciField;
class ValueStack;
class InstructionPrinter;
class IRScope;
class LIR_OprDesc;
// Instruction class hierarchy
//
// All leaf classes in the class hierarchy are concrete classes
// (i.e., are instantiated). All other classes are abstract and
// serve factoring.
class Instruction;
class Phi;
class Local;
class Constant;
class AccessField;
class LoadField;
class StoreField;
class AccessArray;
class ArrayLength;
class AccessIndexed;
class LoadIndexed;
class StoreIndexed;
class NegateOp;
class Op2;
class ArithmeticOp;
class ShiftOp;
class LogicOp;
class CompareOp;
class IfOp;
class Convert;
class NullCheck;
class TypeCast;
class OsrEntry;
class ExceptionObject;
class StateSplit;
class Invoke;
class NewInstance;
class NewArray;
class NewTypeArray;
class NewObjectArray;
class NewMultiArray;
class TypeCheck;
class CheckCast;
class InstanceOf;
class AccessMonitor;
class MonitorEnter;
class MonitorExit;
class Intrinsic;
class BlockBegin;
class BlockEnd;
class Goto;
class If;
class IfInstanceOf;
class Switch;
class TableSwitch;
class LookupSwitch;
class Return;
class Throw;
class Base;
class RoundFP;
class UnsafeOp;
class UnsafeRawOp;
class UnsafeGetRaw;
class UnsafePutRaw;
class UnsafeObjectOp;
class UnsafeGetObject;
class UnsafePutObject;
class UnsafeGetAndSetObject;
class UnsafePrefetch;
class UnsafePrefetchRead;
class UnsafePrefetchWrite;
class ProfileCall;
class ProfileInvoke;
class RuntimeCall;
class MemBar;
// A Value is a reference to the instruction creating the value
public:
};
// A simple closure class for visiting the values of an Instruction
public:
};
// Some array and list classes
public:
void blocks_do(void f(BlockBegin*));
void values_do(ValueVisitor* f);
};
// InstructionVisitors provide type-based dispatch for instructions.
// For each concrete Instruction class X, a virtual function do_X is
// provided. Functionality that needs to be implemented for all classes
// (e.g., printing, code generation) is factored out into a specialised
// visitor instead of added to the Instruction classes itself.
public:
virtual void do_Constant (Constant* x) = 0;
virtual void do_LoadField (LoadField* x) = 0;
virtual void do_StoreField (StoreField* x) = 0;
virtual void do_ArrayLength (ArrayLength* x) = 0;
virtual void do_LoadIndexed (LoadIndexed* x) = 0;
virtual void do_StoreIndexed (StoreIndexed* x) = 0;
virtual void do_NegateOp (NegateOp* x) = 0;
virtual void do_ArithmeticOp (ArithmeticOp* x) = 0;
virtual void do_ShiftOp (ShiftOp* x) = 0;
virtual void do_LogicOp (LogicOp* x) = 0;
virtual void do_CompareOp (CompareOp* x) = 0;
virtual void do_Convert (Convert* x) = 0;
virtual void do_NullCheck (NullCheck* x) = 0;
virtual void do_TypeCast (TypeCast* x) = 0;
virtual void do_NewInstance (NewInstance* x) = 0;
virtual void do_NewTypeArray (NewTypeArray* x) = 0;
virtual void do_NewObjectArray (NewObjectArray* x) = 0;
virtual void do_NewMultiArray (NewMultiArray* x) = 0;
virtual void do_CheckCast (CheckCast* x) = 0;
virtual void do_InstanceOf (InstanceOf* x) = 0;
virtual void do_MonitorEnter (MonitorEnter* x) = 0;
virtual void do_MonitorExit (MonitorExit* x) = 0;
virtual void do_Intrinsic (Intrinsic* x) = 0;
virtual void do_BlockBegin (BlockBegin* x) = 0;
virtual void do_IfInstanceOf (IfInstanceOf* x) = 0;
virtual void do_TableSwitch (TableSwitch* x) = 0;
virtual void do_LookupSwitch (LookupSwitch* x) = 0;
virtual void do_OsrEntry (OsrEntry* x) = 0;
virtual void do_ExceptionObject(ExceptionObject* x) = 0;
virtual void do_RoundFP (RoundFP* x) = 0;
virtual void do_UnsafeGetRaw (UnsafeGetRaw* x) = 0;
virtual void do_UnsafePutRaw (UnsafePutRaw* x) = 0;
virtual void do_UnsafeGetObject(UnsafeGetObject* x) = 0;
virtual void do_UnsafePutObject(UnsafePutObject* x) = 0;
virtual void do_UnsafeGetAndSetObject(UnsafeGetAndSetObject* x) = 0;
virtual void do_UnsafePrefetchRead (UnsafePrefetchRead* x) = 0;
virtual void do_UnsafePrefetchWrite(UnsafePrefetchWrite* x) = 0;
virtual void do_ProfileCall (ProfileCall* x) = 0;
virtual void do_ProfileInvoke (ProfileInvoke* x) = 0;
virtual void do_RuntimeCall (RuntimeCall* x) = 0;
};
// Hashing support
//
// Note: This hash functions affect the performance
// of ValueMap - make changes carefully!
// The following macros are used to implement instruction-specific hashing.
// By default, each instruction implements hash() and is_equal(Value), used
// mentation disables value numbering. Each instruction which can be value-
// numbered, should define corresponding hash() and is_equal(Value) functions
// that need to be identical for two instructions to be identical.
//
// Note: The default implementation of hash() returns 0 in order to indicate
// that the instruction should not be considered for value numbering.
// The currently used hash functions do not guarantee that never a 0
// is produced. While this is still correct, it may be a performance
// bug (no value numbering for that node). However, this situation is
// so unlikely, that we are not going to handle it specially.
} \
if (!(enabled) ) return false; \
return true; \
} \
} \
if (!(enabled) ) return false; \
return true; \
} \
} \
if (!(enabled) ) return false; \
return true; \
} \
// The mother of all instructions...
private:
#ifndef PRODUCT
#endif
int _use_count; // the number of instructions refering to this value (w/o prev/next); only roots can have use count = 0 or > 1
friend class UseCountComputer;
friend class BlockBegin;
//protected:
public:
}
public:
return res;
}
enum InstructionFlag {
NeedsNullCheckFlag = 0,
};
public:
void set_flag(InstructionFlag id, bool f) { _flags = f ? (_flags | (1 << id)) : (_flags & ~(1 << id)); };
// 'globally' used condition values
enum Condition {
};
// Instructions may be pinned for many reasons and under certain conditions
// with enough knowledge it's possible to safely unpin them.
enum PinReason {
};
// initialization
static int number_of_instructions() {
}
// creation
: _use_count(0)
#ifndef PRODUCT
, _printable_bci(-99)
#endif
, _pin_state(0)
, _flags(0)
{
}
// accessors
#ifndef PRODUCT
int printable_bci() const { assert(has_printable_bci(), "_printable_bci should have been set"); return _printable_bci; }
#endif
virtual bool needs_exception_state() const { return true; }
// manipulation
// DANGEROUS: only used by EliminateStores
void unpin(PinReason reason) { assert((reason & PinUnknown) == 0, "can't unpin unknown state"); _pin_state &= ~reason; }
return next;
}
#ifndef PRODUCT
#endif
}
}
// machine-specifics
void set_operand(LIR_Opr operand) { assert(operand != LIR_OprFact::illegalOpr, "operand must exist"); _operand = operand; }
// generic
virtual void visit(InstructionVisitor* v) = 0;
virtual bool can_trap() const { return false; }
virtual void input_values_do(ValueVisitor* f) = 0;
virtual void state_values_do(ValueVisitor* f);
// hashing
virtual const char* name() const = 0;
// debugging
};
// The following macros are used to define base (i.e., non-leaf)
// and leaf instruction classes. They define class-name related
// generic functionality in one place.
class class_name: public super_class_name { \
public: \
public: \
virtual const char* name() const { return #class_name; } \
// Debugging support
#ifdef ASSERT
};
#else
#define ASSERT_VALUES
#endif // ASSERT
// A Phi is a phi function in the sense of SSA form. It stands for
// the value of a local variable at the beginning of a join block.
// A Phi consists of n operands, one for every incoming branch.
private:
public:
// creation
, _pf_flags(0)
, _block(b)
{
if (type->is_illegal()) {
make_illegal();
}
}
// flags
enum Flag {
no_flag = 0,
};
// accessors
Value operand_at(int i) const;
int operand_count() const;
// Invalidates phis corresponding to merges of locals of two different types
// (these should never be referenced, otherwise the bytecodes are illegal)
void make_illegal() {
}
bool is_illegal() const {
return type()->is_illegal();
}
// generic
}
};
// A local is a placeholder for an incoming argument to a function call.
private:
int _java_index; // the local index within the method to which the local belongs
public:
// creation
: Instruction(type)
, _java_index(index)
{
}
// accessors
int java_index() const { return _java_index; }
virtual ciType* exact_type() const;
// generic
};
public:
// creation
{
}
{
// since it's patching it needs to be pinned
pin();
}
virtual ciType* exact_type() const;
case not_comparable:
return NULL;
case cond_false:
return false_sux;
case cond_true:
return true_sux;
default:
return NULL;
}
}
};
private:
int _offset;
public:
// creation
{
// pin of all instructions with memory access
pin();
}
// accessors
// Unresolved getstatic and putstatic can cause initialization.
// Technically it occurs at the Constant that materializes the base
// of the static fields but it's simpler to model it here.
bool is_init_point() const { return is_static() && (needs_patching() || !_field->holder()->is_initialized()); }
// manipulation
// Under certain circumstances, if a previous NullCheck instruction
// proved the target object non-null, we can eliminate the explicit
// null check and do an implicit one, simply specifying the debug
// information from the NullCheck. This field should only be consulted
// if needs_null_check() is true.
// generic
};
public:
// creation
{}
ciType* declared_type() const;
ciType* exact_type() const;
// generic
HASHING2(LoadField, !needs_patching() && !field()->is_volatile(), obj()->subst(), offset()) // cannot be eliminated if needs patching or if volatile
};
private:
public:
// creation
{
pin();
}
// accessors
// generic
virtual void input_values_do(ValueVisitor* f) { AccessField::input_values_do(f); f->visit(&_value); }
};
private:
public:
// creation
{
set_needs_null_check(true);
pin(); // instruction with side effect (null exception or range check throwing)
}
// generic
virtual bool can_trap() const { return needs_null_check(); }
};
private:
public:
// creation
, _explicit_null_check(NULL) {}
// accessors
// setters
// See LoadField::set_explicit_null_check for documentation
// generic
};
private:
public:
// creation
{
}
// accessors
// perform elimination of range checks involving constants
bool compute_needs_range_check();
// generic
virtual void input_values_do(ValueVisitor* f) { AccessArray::input_values_do(f); f->visit(&_index); if (_length != NULL) f->visit(&_length); }
};
private:
public:
// creation
, _explicit_null_check(NULL) {}
// accessors
// setters
// See LoadField::set_explicit_null_check for documentation
ciType* exact_type() const;
ciType* declared_type() const;
// generic
};
private:
int _profiled_bci;
public:
// creation
StoreIndexed(Value array, Value index, Value length, BasicType elt_type, Value value, ValueStack* state_before)
{
pin();
}
// accessors
// Helpers for methodDataOop profiling
int profiled_bci() const { return _profiled_bci; }
// generic
virtual void input_values_do(ValueVisitor* f) { AccessIndexed::input_values_do(f); f->visit(&_value); }
};
private:
public:
// creation
}
// accessors
// generic
};
private:
public:
// creation
, _x(x)
, _y(y)
{
}
// accessors
// manipulators
void swap_operands() {
}
// generic
virtual bool is_commutative() const { return false; }
};
public:
// creation
{
}
// accessors
// generic
virtual bool is_commutative() const;
virtual bool can_trap() const;
};
public:
// creation
// generic
};
public:
// creation
// generic
virtual bool is_commutative() const;
};
public:
// creation
{}
// generic
};
private:
public:
// creation
{
}
// accessors
virtual bool is_commutative() const;
// generic
virtual void input_values_do(ValueVisitor* f) { Op2::input_values_do(f); f->visit(&_tval); f->visit(&_fval); }
};
private:
public:
// creation
Convert(Bytecodes::Code op, Value value, ValueType* to_type) : Instruction(to_type), _op(op), _value(value) {
}
// accessors
// generic
};
private:
public:
// creation
{
set_can_trap(true);
}
// accessors
// setters
// generic
virtual bool can_trap() const { return check_flag(CanTrapFlag); /* null-check elimination sets to false */ }
};
// This node is supposed to cast the type of another node to a more precise
// declared type.
private:
public:
// The type of this node is the same type as the object type (and it might be constant).
// accessors
// generic
};
private:
protected:
public:
// creation
{
}
// accessors
// manipulation
void set_state(ValueStack* state) { assert(_state == NULL, "overwriting existing state"); check_state(state); _state = state; }
// generic
virtual void state_values_do(ValueVisitor* f);
};
private:
int _vtable_index;
public:
// creation
// accessors
int vtable_index() const { return _vtable_index; }
ciType* declared_type() const;
// Returns false if target is not loaded
// Returns false if target is not loaded
// JSR 292 support
virtual bool needs_exception_state() const { return false; }
// generic
virtual bool can_trap() const { return true; }
virtual void input_values_do(ValueVisitor* f) {
}
virtual void state_values_do(ValueVisitor *f);
};
private:
public:
// creation
{}
// accessors
virtual bool needs_exception_state() const { return false; }
// generic
virtual bool can_trap() const { return true; }
ciType* exact_type() const;
ciType* declared_type() const;
};
private:
public:
// creation
{
// Do not ASSERT_VALUES since length is NULL for NewMultiArray
}
// accessors
virtual bool needs_exception_state() const { return false; }
ciType* declared_type() const;
// generic
virtual bool can_trap() const { return true; }
virtual void input_values_do(ValueVisitor* f) { StateSplit::input_values_do(f); f->visit(&_length); }
};
private:
public:
// creation
{}
// accessors
ciType* exact_type() const;
};
private:
public:
// creation
NewObjectArray(ciKlass* klass, Value length, ValueStack* state_before) : NewArray(length, state_before), _klass(klass) {}
// accessors
ciType* exact_type() const;
};
private:
public:
// creation
NewMultiArray(ciKlass* klass, Values* dims, ValueStack* state_before) : NewArray(NULL, state_before), _klass(klass), _dims(dims) {
}
// accessors
// generic
virtual void input_values_do(ValueVisitor* f) {
// NOTE: we do not call NewArray::input_values_do since "length"
// is meaningless for a multi-dimensional array; passing the
// zeroth element down to NewArray as its length is a bad idea
// since there will be a copy in the "dims" array which doesn't
// get updated, and the value must not be traversed twice. Was bug
// - kbr 4/10/2001
}
};
private:
int _profiled_bci;
public:
// creation
set_direct_compare(false);
}
// accessors
// manipulation
// generic
virtual bool can_trap() const { return true; }
// Helpers for methodDataOop profiling
int profiled_bci() const { return _profiled_bci; }
};
public:
// creation
void set_incompatible_class_change_check() {
}
bool is_incompatible_class_change_check() const {
}
ciType* declared_type() const;
ciType* exact_type() const;
};
public:
// creation
InstanceOf(ciKlass* klass, Value obj, ValueStack* state_before) : TypeCheck(klass, obj, intType, state_before) {}
virtual bool needs_exception_state() const { return false; }
};
private:
int _monitor_no;
public:
// creation
{
set_needs_null_check(true);
}
// accessors
int monitor_no() const { return _monitor_no; }
// generic
};
public:
// creation
{
}
// generic
virtual bool can_trap() const { return true; }
};
public:
// creation
{
}
};
private:
int _nonnull_state; // mask identifying which args are nonnull
public:
// preserves_state can be set to true for Intrinsics
// which are guaranteed to preserve register state across any slow
// cases; setting it to true does not mean that the Intrinsic can
// not trap, only that if we continue execution in the same basic
// block after the Intrinsic, all of the registers are intact. This
// allows load elimination and common expression elimination to be
// performed across the Intrinsic. The default value is false.
bool has_receiver,
bool preserves_state,
bool cantrap = true)
{
if (has_receiver) {
_recv = argument_at(0);
}
// some intrinsics can't trap, so don't force them to be pinned
if (!can_trap()) {
}
}
// accessors
bool arg_needs_null_check(int i) {
if (i >= 0 && i < (int)sizeof(_nonnull_state) * BitsPerByte) {
return is_set_nth_bit(_nonnull_state, i);
}
return true;
}
void set_arg_needs_null_check(int i, bool check) {
if (i >= 0 && i < (int)sizeof(_nonnull_state) * BitsPerByte) {
if (check) {
_nonnull_state |= nth_bit(i);
} else {
_nonnull_state &= ~(nth_bit(i));
}
}
}
// generic
virtual void input_values_do(ValueVisitor* f) {
}
};
class LIR_List;
private:
int _block_id; // the unique block id
int _bci; // start-bci of block
int _depth_first_number; // number of this block in a depth-first ordering
int _linear_scan_number; // number of this block in linear-scan ordering
int _loop_depth; // the loop nesting level of this block
int _loop_index; // number of the innermost loop of this block
int _flags; // the flags associated with this block
// fields used by BlockListBuilder
int _total_preds; // number of predecessors found by BlockListBuilder
// SSA specific fields: (factor out later)
// SSA specific ends
ValueStackStack* _exception_states; // only for xhandler entries: states of all instructions that have an edge to this xhandler
int _exception_handler_pco; // if this block is the start of an exception handler,
// this records the PC offset in the assembly code of the
// first instruction in this block
int _first_lir_instruction_id; // ID of first LIR instruction in this block
int _last_lir_instruction_id; // ID of last LIR instruction in this block
friend class SuxAndWeightAdjuster;
public:
return res;
}
static int number_of_blocks() {
}
// creation
BlockBegin(int bci)
, _depth_first_number(-1)
, _linear_scan_number(-1)
, _loop_depth(0)
, _flags(0)
, _dominator(NULL)
, _predecessors(2)
, _successors(2)
, _exception_handlers(1)
, _exception_handler_pco(-1)
, _loop_index(-1)
, _live_in()
, _live_out()
, _live_gen()
, _live_kill()
, _last_lir_instruction_id(-1)
, _total_preds(0)
{
#ifndef PRODUCT
#endif
}
// accessors
int loop_depth() const { return _loop_depth; }
int depth_first_number() const { return _depth_first_number; }
int linear_scan_number() const { return _linear_scan_number; }
int exception_handler_pco() const { return _exception_handler_pco; }
int first_lir_instruction_id() const { return _first_lir_instruction_id; }
int last_lir_instruction_id() const { return _last_lir_instruction_id; }
int total_preds() const { return _total_preds; }
// manipulation
void set_loop_depth(int d) { _loop_depth = d; }
void clear_end();
void disconnect_from_graph();
void init_stores_to_locals(int locals_count) { _stores_to_locals = BitMap(locals_count); _stores_to_locals.clear(); }
// generic
virtual void state_values_do(ValueVisitor* f);
// successors and predecessors
int number_of_sux() const;
BlockBegin* sux_at(int i) const;
// exception handlers potentially invoked by this block
void add_exception_handler(BlockBegin* b);
// states of the instructions that have an edge to this exception handler
int number_of_exception_states() { assert(is_set(exception_entry_flag), "only for xhandlers"); return _exception_states == NULL ? 0 : _exception_states->length(); }
ValueStack* exception_state_at(int idx) const { assert(is_set(exception_entry_flag), "only for xhandlers"); return _exception_states->at(idx); }
// flags
enum Flag {
no_flag = 0,
std_entry_flag = 1 << 0,
parser_loop_header_flag = 1 << 7, // set by parser to identify blocks where phi functions can not be created on demand
critical_edge_split_flag = 1 << 8, // set for all blocks that are introduced when critical edges are split
};
bool is_entry_block() const {
return (_flags & entry_mask) != 0;
}
// iteration
void block_values_do(ValueVisitor* f);
// loops
int loop_index() const { return _loop_index; }
// merging
// debugging
void print_block() PRODUCT_RETURN;
};
private:
protected:
#ifdef ASSERT
#endif
}
public:
// creation
{
}
// accessors
// manipulation
// successors
};
public:
enum Direction {
none, // Just a regular goto
};
private:
int _profiled_bci;
public:
// creation
, _direction(none)
, _profiled_bci(0) {
set_sux(s);
}
, _direction(none)
, _profiled_bci(0) {
set_sux(s);
}
int profiled_bci() const { return _profiled_bci; }
};
private:
int _profiled_bci; // Canonicalizer may alter bci of If node
bool _swapped; // Is the order reversed with respect to the original If in the
// bytecode stream?
public:
// creation
If(Value x, Condition cond, bool unordered_is_true, Value y, BlockBegin* tsux, BlockBegin* fsux, ValueStack* state_before, bool is_safepoint)
, _x(x)
, _y(y)
, _profiled_bci(0)
, _swapped(false)
{
set_sux(s);
}
// accessors
bool is_swapped() const { return _swapped; }
// manipulation
void swap_operands() {
}
void swap_sux() {
}
// generic
virtual void input_values_do(ValueVisitor* f) { BlockEnd::input_values_do(f); f->visit(&_x); f->visit(&_y); }
};
private:
bool _test_is_instance; // jump if instance
int _instanceof_bci;
public:
IfInstanceOf(ciKlass* klass, Value obj, bool test_is_instance, int instanceof_bci, BlockBegin* tsux, BlockBegin* fsux)
{
set_sux(s);
}
// accessors
//
// Note 1: If test_is_instance() is true, IfInstanceOf tests if obj *is* an
// instance of klass; otherwise it tests if it is *not* and instance
// of klass.
//
// Note 2: IfInstanceOf instructions are created by combining an InstanceOf
// and an If instruction. The IfInstanceOf bci() corresponds to the
// bci that the If would have had; the (this->) instanceof_bci() is
// the bci of the original InstanceOf instruction.
int instanceof_bci() const { return _instanceof_bci; }
bool test_is_instance() const { return _test_is_instance; }
// manipulation
void swap_sux() {
}
// generic
};
private:
public:
// creation
}
// accessors
virtual bool needs_exception_state() const { return false; }
// generic
};
private:
int _lo_key;
public:
// creation
// accessors
};
private:
public:
// creation
LookupSwitch(Value tag, BlockList* sux, intArray* keys, ValueStack* state_before, bool is_safepoint)
}
// accessors
};
private:
public:
// creation
// accessors
// generic
virtual void input_values_do(ValueVisitor* f) {
BlockEnd::input_values_do(f);
}
};
private:
public:
// creation
Throw(Value exception, ValueStack* state_before) : BlockEnd(illegalType, state_before, true), _exception(exception) {
}
// accessors
// generic
virtual bool can_trap() const { return true; }
virtual void input_values_do(ValueVisitor* f) { BlockEnd::input_values_do(f); f->visit(&_exception); }
};
public:
// creation
assert(osr_entry == NULL || osr_entry->is_set(BlockBegin::osr_entry_flag), "osr entry must be flagged");
set_sux(s);
}
// accessors
};
public:
// creation
#ifdef _LP64
#else
#endif
// generic
virtual void input_values_do(ValueVisitor* f) { }
};
// Models the incoming exception at a catch site
public:
// creation
pin();
}
// generic
virtual void input_values_do(ValueVisitor* f) { }
};
// Models needed rounding for floating-point values on Intel.
// Currently only used to represent rounding of double-precision
// values stored into local variables, but could be used to model
// intermediate rounding of single-precision values as well.
private:
public:
{
}
// accessors
// generic
};
private:
protected:
// creation
{
//Note: Unsafe ops are not not guaranteed to throw NPE.
// Convservatively, Unsafe operations must be pinned though we could be
// looser about this if we wanted to..
pin();
}
public:
// accessors
// generic
virtual void input_values_do(ValueVisitor* f) { }
};
private:
int _log2_scale; // Scale factor: 0, 1, 2, or 3.
// Indicates log2 of number of bytes (1, 2, 4, or 8)
// to scale index by.
protected:
, _log2_scale(0)
{
// Can not use ASSERT_VALUES because index may be NULL
}
{
}
public:
// accessors
int log2_scale() { return _log2_scale; }
// setters
// generic
};
private:
public:
}
UnsafeGetRaw(BasicType basic_type, Value base, Value index, int log2_scale, bool may_be_unaligned, bool is_wide = false)
}
bool may_be_unaligned() { return _may_be_unaligned; }
};
private:
public:
{
}
{
}
// accessors
// generic
};
private:
bool _is_volatile; // true if volatile - dl/JSR166
public:
{
}
// accessors
bool is_volatile() { return _is_volatile; }
// generic
};
public:
{
}
};
private:
public:
{
}
// accessors
// generic
};
private:
bool _is_add;
public:
{
}
// accessors
// generic
};
public:
{
}
};
public:
{
}
};
public:
{
}
};
private:
int _bci_of_invoke;
public:
{
// The ProfileCall has side-effects and must occur precisely where located
pin();
}
int bci_of_invoke() { return _bci_of_invoke; }
};
// Call some C runtime function that doesn't safepoint,
// optionally passing the current thread as the first argument.
private:
const char* _entry_name;
bool _pass_thread; // Pass the JavaThread* as an implicit first argument
public:
RuntimeCall(ValueType* type, const char* entry_name, address entry, Values* args, bool pass_thread = true)
: Instruction(type)
, _pass_thread(pass_thread) {
pin();
}
const char* entry_name() const { return _entry_name; }
bool pass_thread() const { return _pass_thread; }
virtual void input_values_do(ValueVisitor* f) {
}
};
// Use to trip invocation counter of an inlined method
private:
public:
{
// The ProfileInvoke has side-effects and must occur precisely where located QQQ???
pin();
}
virtual void input_values_do(ValueVisitor*) {}
virtual void state_values_do(ValueVisitor*);
};
private:
public:
{
pin();
}
virtual void input_values_do(ValueVisitor*) {}
};
class BlockPair: public CompilationResourceObj {
private:
public:
};
inline int BlockBegin::number_of_sux() const { assert(_end == NULL || _end->number_of_sux() == _successors.length(), "mismatch"); return _successors.length(); }
inline BlockBegin* BlockBegin::sux_at(int i) const { assert(_end == NULL || _end->sux_at(i) == _successors.at(i), "mismatch"); return _successors.at(i); }
inline void BlockBegin::add_successor(BlockBegin* sux) { assert(_end == NULL, "Would create mismatch with successors of BlockEnd"); _successors.append(sux); }
#endif // SHARE_VM_C1_C1_INSTRUCTION_HPP