2007-12-01 00:00:00 +00:00
/*
2011-01-21 13:01:02 -08:00
* Copyright ( c ) 1999 , 2011 , Oracle and / or its affiliates . All rights reserved .
2007-12-01 00:00:00 +00:00
* 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 .
*
2010-05-27 19:08:38 -07:00
* 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 .
2007-12-01 00:00:00 +00:00
*
*/
2010-11-23 13:22:55 -08:00
# 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"
2007-12-01 00:00:00 +00:00
// Predefined classes
class ciField ;
class ValueStack ;
class InstructionPrinter ;
class IRScope ;
class LIR_OprDesc ;
typedef LIR_OprDesc * LIR_Opr ;
// 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 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 UnsafePrefetch ;
class UnsafePrefetchRead ;
class UnsafePrefetchWrite ;
class ProfileCall ;
2010-09-03 17:51:07 -07:00
class ProfileInvoke ;
2011-01-21 13:01:02 -08:00
class RuntimeCall ;
2007-12-01 00:00:00 +00:00
// A Value is a reference to the instruction creating the value
typedef Instruction * Value ;
define_array ( ValueArray , Value )
define_stack ( Values , ValueArray )
define_array ( ValueStackArray , ValueStack * )
define_stack ( ValueStackStack , ValueStackArray )
// BlockClosure is the base class for block traversal/iteration.
class BlockClosure : public CompilationResourceObj {
public :
virtual void block_do ( BlockBegin * block ) = 0 ;
} ;
2010-06-04 11:18:04 -07:00
// A simple closure class for visiting the values of an Instruction
class ValueVisitor : public StackObj {
public :
virtual void visit ( Value * v ) = 0 ;
} ;
2007-12-01 00:00:00 +00:00
// Some array and list classes
define_array ( BlockBeginArray , BlockBegin * )
define_stack ( _BlockList , BlockBeginArray )
class BlockList : public _BlockList {
public :
BlockList ( ) : _BlockList ( ) { }
BlockList ( const int size ) : _BlockList ( size ) { }
BlockList ( const int size , BlockBegin * init ) : _BlockList ( size , init ) { }
void iterate_forward ( BlockClosure * closure ) ;
void iterate_backward ( BlockClosure * closure ) ;
void blocks_do ( void f ( BlockBegin * ) ) ;
2010-06-04 11:18:04 -07:00
void values_do ( ValueVisitor * f ) ;
2007-12-01 00:00:00 +00:00
void print ( bool cfg_only = false , bool live_only = false ) PRODUCT_RETURN ;
} ;
// 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.
class InstructionVisitor : public StackObj {
public :
virtual void do_Phi ( Phi * x ) = 0 ;
virtual void do_Local ( Local * x ) = 0 ;
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_IfOp ( IfOp * x ) = 0 ;
virtual void do_Convert ( Convert * x ) = 0 ;
virtual void do_NullCheck ( NullCheck * x ) = 0 ;
virtual void do_Invoke ( Invoke * 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_Goto ( Goto * x ) = 0 ;
virtual void do_If ( If * 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_Return ( Return * x ) = 0 ;
virtual void do_Throw ( Throw * x ) = 0 ;
virtual void do_Base ( Base * 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_UnsafePrefetchRead ( UnsafePrefetchRead * x ) = 0 ;
virtual void do_UnsafePrefetchWrite ( UnsafePrefetchWrite * x ) = 0 ;
virtual void do_ProfileCall ( ProfileCall * x ) = 0 ;
2010-09-03 17:51:07 -07:00
virtual void do_ProfileInvoke ( ProfileInvoke * x ) = 0 ;
2011-01-21 13:01:02 -08:00
virtual void do_RuntimeCall ( RuntimeCall * x ) = 0 ;
2007-12-01 00:00:00 +00:00
} ;
// Hashing support
//
// Note: This hash functions affect the performance
// of ValueMap - make changes carefully!
# define HASH1(x1 ) ((intx)(x1))
# define HASH2(x1, x2 ) ((HASH1(x1 ) << 7) ^ HASH1(x2))
# define HASH3(x1, x2, x3 ) ((HASH2(x1, x2 ) << 7) ^ HASH1(x3))
# define HASH4(x1, x2, x3, x4) ((HASH3(x1, x2, x3) << 7) ^ HASH1(x4))
// The following macros are used to implement instruction-specific hashing.
// By default, each instruction implements hash() and is_equal(Value), used
// for value numbering/common subexpression elimination. The default imple-
// mentation disables value numbering. Each instruction which can be value-
// numbered, should define corresponding hash() and is_equal(Value) functions
// via the macros below. The f arguments specify all the values/op codes, etc.
// 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.
# define HASHING1(class_name, enabled, f1) \
virtual intx hash ( ) const { \
return ( enabled ) ? HASH2 ( name ( ) , f1 ) : 0 ; \
} \
virtual bool is_equal ( Value v ) const { \
if ( ! ( enabled ) ) return false ; \
class_name * _v = v - > as_ # # class_name ( ) ; \
if ( _v = = NULL ) return false ; \
if ( f1 ! = _v - > f1 ) return false ; \
return true ; \
} \
# define HASHING2(class_name, enabled, f1, f2) \
virtual intx hash ( ) const { \
return ( enabled ) ? HASH3 ( name ( ) , f1 , f2 ) : 0 ; \
} \
virtual bool is_equal ( Value v ) const { \
if ( ! ( enabled ) ) return false ; \
class_name * _v = v - > as_ # # class_name ( ) ; \
if ( _v = = NULL ) return false ; \
if ( f1 ! = _v - > f1 ) return false ; \
if ( f2 ! = _v - > f2 ) return false ; \
return true ; \
} \
# define HASHING3(class_name, enabled, f1, f2, f3) \
virtual intx hash ( ) const { \
return ( enabled ) ? HASH4 ( name ( ) , f1 , f2 , f3 ) : 0 ; \
} \
virtual bool is_equal ( Value v ) const { \
if ( ! ( enabled ) ) return false ; \
class_name * _v = v - > as_ # # class_name ( ) ; \
if ( _v = = NULL ) return false ; \
if ( f1 ! = _v - > f1 ) return false ; \
if ( f2 ! = _v - > f2 ) return false ; \
if ( f3 ! = _v - > f3 ) return false ; \
return true ; \
} \
// The mother of all instructions...
class Instruction : public CompilationResourceObj {
private :
int _id ; // the unique instruction id
2009-12-29 19:08:54 +01:00
# ifndef PRODUCT
int _printable_bci ; // the bci of the instruction for printing
# endif
2007-12-01 00:00:00 +00:00
int _use_count ; // the number of instructions refering to this value (w/o prev/next); only roots can have use count = 0 or > 1
int _pin_state ; // set of PinReason describing the reason for pinning
ValueType * _type ; // the instruction value type
Instruction * _next ; // the next instruction if any (NULL for BlockEnd instructions)
Instruction * _subst ; // the substitution instruction if any
LIR_Opr _operand ; // LIR specific information
unsigned int _flags ; // Flag bits
2009-12-29 19:08:54 +01:00
ValueStack * _state_before ; // Copy of state with input operands still on stack (or NULL)
ValueStack * _exception_state ; // Copy of state for exception handling
2007-12-01 00:00:00 +00:00
XHandlers * _exception_handlers ; // Flat list of exception handlers covering this instruction
friend class UseCountComputer ;
2010-06-04 11:18:04 -07:00
friend class BlockBegin ;
2007-12-01 00:00:00 +00:00
2009-12-29 19:08:54 +01:00
void update_exception_state ( ValueStack * state ) ;
bool has_printable_bci ( ) const { return NOT_PRODUCT ( _printable_bci ! = - 99 ) PRODUCT_ONLY ( false ) ; }
2007-12-01 00:00:00 +00:00
protected :
void set_type ( ValueType * type ) {
assert ( type ! = NULL , " type must exist " ) ;
_type = type ;
}
public :
2010-06-04 11:18:04 -07:00
void * operator new ( size_t size ) {
Compilation * c = Compilation : : current ( ) ;
void * res = c - > arena ( ) - > Amalloc ( size ) ;
( ( Instruction * ) res ) - > _id = c - > get_next_id ( ) ;
return res ;
}
2011-02-02 11:35:26 -05:00
static const int no_bci = - 99 ;
2007-12-01 00:00:00 +00:00
enum InstructionFlag {
NeedsNullCheckFlag = 0 ,
CanTrapFlag ,
DirectCompareFlag ,
IsEliminatedFlag ,
IsSafepointFlag ,
IsStaticFlag ,
IsStrictfpFlag ,
NeedsStoreCheckFlag ,
NeedsWriteBarrierFlag ,
PreservesStateFlag ,
TargetIsFinalFlag ,
TargetIsLoadedFlag ,
TargetIsStrictfpFlag ,
UnorderedIsTrueFlag ,
NeedsPatchingFlag ,
ThrowIncompatibleClassChangeErrorFlag ,
ProfileMDOFlag ,
2009-12-29 19:08:54 +01:00
IsLinkedInBlockFlag ,
2007-12-01 00:00:00 +00:00
InstructionLastFlag
} ;
public :
bool check_flag ( InstructionFlag id ) const { return ( _flags & ( 1 < < id ) ) ! = 0 ; }
void set_flag ( InstructionFlag id , bool f ) { _flags = f ? ( _flags | ( 1 < < id ) ) : ( _flags & ~ ( 1 < < id ) ) ; } ;
// 'globally' used condition values
enum Condition {
eql , neq , lss , leq , gtr , geq
} ;
// Instructions may be pinned for many reasons and under certain conditions
// with enough knowledge it's possible to safely unpin them.
enum PinReason {
PinUnknown = 1 < < 0
, PinExplicitNullCheck = 1 < < 3
, PinStackForStateSplit = 1 < < 12
, PinStateSplitConstructor = 1 < < 13
, PinGlobalValueNumbering = 1 < < 14
} ;
static Condition mirror ( Condition cond ) ;
static Condition negate ( Condition cond ) ;
// initialization
2010-06-04 11:18:04 -07:00
static int number_of_instructions ( ) {
return Compilation : : current ( ) - > number_of_instructions ( ) ;
}
2007-12-01 00:00:00 +00:00
// creation
2010-09-29 18:53:28 +02:00
Instruction ( ValueType * type , ValueStack * state_before = NULL , bool type_is_constant = false )
2009-12-29 19:08:54 +01:00
: _use_count ( 0 )
# ifndef PRODUCT
, _printable_bci ( - 99 )
# endif
2007-12-01 00:00:00 +00:00
, _pin_state ( 0 )
, _type ( type )
, _next ( NULL )
, _subst ( NULL )
, _flags ( 0 )
, _operand ( LIR_OprFact : : illegalOpr )
2009-12-29 19:08:54 +01:00
, _state_before ( state_before )
2007-12-01 00:00:00 +00:00
, _exception_handlers ( NULL )
{
2009-12-29 19:08:54 +01:00
check_state ( state_before ) ;
2007-12-01 00:00:00 +00:00
assert ( type ! = NULL & & ( ! type - > is_constant ( ) | | type_is_constant ) , " type must exist " ) ;
2009-12-29 19:08:54 +01:00
update_exception_state ( _state_before ) ;
2007-12-01 00:00:00 +00:00
}
// accessors
int id ( ) const { return _id ; }
2009-12-29 19:08:54 +01:00
# ifndef PRODUCT
int printable_bci ( ) const { assert ( has_printable_bci ( ) , " _printable_bci should have been set " ) ; return _printable_bci ; }
void set_printable_bci ( int bci ) { NOT_PRODUCT ( _printable_bci = bci ; ) }
# endif
2007-12-01 00:00:00 +00:00
int use_count ( ) const { return _use_count ; }
int pin_state ( ) const { return _pin_state ; }
bool is_pinned ( ) const { return _pin_state ! = 0 | | PinAllInstructions ; }
ValueType * type ( ) const { return _type ; }
Instruction * prev ( BlockBegin * block ) ; // use carefully, expensive operation
Instruction * next ( ) const { return _next ; }
bool has_subst ( ) const { return _subst ! = NULL ; }
Instruction * subst ( ) { return _subst = = NULL ? this : _subst - > subst ( ) ; }
LIR_Opr operand ( ) const { return _operand ; }
void set_needs_null_check ( bool f ) { set_flag ( NeedsNullCheckFlag , f ) ; }
bool needs_null_check ( ) const { return check_flag ( NeedsNullCheckFlag ) ; }
2009-12-29 19:08:54 +01:00
bool is_linked ( ) const { return check_flag ( IsLinkedInBlockFlag ) ; }
bool can_be_linked ( ) { return as_Local ( ) = = NULL & & as_Phi ( ) = = NULL ; }
2007-12-01 00:00:00 +00:00
bool has_uses ( ) const { return use_count ( ) > 0 ; }
2009-12-29 19:08:54 +01:00
ValueStack * state_before ( ) const { return _state_before ; }
ValueStack * exception_state ( ) const { return _exception_state ; }
virtual bool needs_exception_state ( ) const { return true ; }
2007-12-01 00:00:00 +00:00
XHandlers * exception_handlers ( ) const { return _exception_handlers ; }
// manipulation
void pin ( PinReason reason ) { _pin_state | = reason ; }
void pin ( ) { _pin_state | = PinUnknown ; }
// DANGEROUS: only used by EliminateStores
void unpin ( PinReason reason ) { assert ( ( reason & PinUnknown ) = = 0 , " can't unpin unknown state " ) ; _pin_state & = ~ reason ; }
2009-12-29 19:08:54 +01:00
Instruction * set_next ( Instruction * next ) {
assert ( next - > has_printable_bci ( ) , " _printable_bci should have been set " ) ;
assert ( next ! = NULL , " must not be NULL " ) ;
assert ( as_BlockEnd ( ) = = NULL , " BlockEnd instructions must have no next " ) ;
assert ( next - > can_be_linked ( ) , " shouldn't link these instructions into list " ) ;
next - > set_flag ( Instruction : : IsLinkedInBlockFlag , true ) ;
2007-12-01 00:00:00 +00:00
_next = next ;
return next ;
}
2009-12-29 19:08:54 +01:00
Instruction * set_next ( Instruction * next , int bci ) {
# ifndef PRODUCT
next - > set_printable_bci ( bci ) ;
# endif
return set_next ( next ) ;
}
2007-12-01 00:00:00 +00:00
void set_subst ( Instruction * subst ) {
assert ( subst = = NULL | |
type ( ) - > base ( ) = = subst - > type ( ) - > base ( ) | |
subst - > type ( ) - > base ( ) = = illegalType , " type can't change " ) ;
_subst = subst ;
}
void set_exception_handlers ( XHandlers * xhandlers ) { _exception_handlers = xhandlers ; }
2009-12-29 19:08:54 +01:00
void set_exception_state ( ValueStack * s ) { check_state ( s ) ; _exception_state = s ; }
2007-12-01 00:00:00 +00:00
// machine-specifics
void set_operand ( LIR_Opr operand ) { assert ( operand ! = LIR_OprFact : : illegalOpr , " operand must exist " ) ; _operand = operand ; }
void clear_operand ( ) { _operand = LIR_OprFact : : illegalOpr ; }
// generic
virtual Instruction * as_Instruction ( ) { return this ; } // to satisfy HASHING1 macro
2010-10-15 09:38:20 +02:00
virtual Phi * as_Phi ( ) { return NULL ; }
2007-12-01 00:00:00 +00:00
virtual Local * as_Local ( ) { return NULL ; }
virtual Constant * as_Constant ( ) { return NULL ; }
virtual AccessField * as_AccessField ( ) { return NULL ; }
virtual LoadField * as_LoadField ( ) { return NULL ; }
virtual StoreField * as_StoreField ( ) { return NULL ; }
virtual AccessArray * as_AccessArray ( ) { return NULL ; }
virtual ArrayLength * as_ArrayLength ( ) { return NULL ; }
virtual AccessIndexed * as_AccessIndexed ( ) { return NULL ; }
virtual LoadIndexed * as_LoadIndexed ( ) { return NULL ; }
virtual StoreIndexed * as_StoreIndexed ( ) { return NULL ; }
virtual NegateOp * as_NegateOp ( ) { return NULL ; }
virtual Op2 * as_Op2 ( ) { return NULL ; }
virtual ArithmeticOp * as_ArithmeticOp ( ) { return NULL ; }
virtual ShiftOp * as_ShiftOp ( ) { return NULL ; }
virtual LogicOp * as_LogicOp ( ) { return NULL ; }
virtual CompareOp * as_CompareOp ( ) { return NULL ; }
virtual IfOp * as_IfOp ( ) { return NULL ; }
virtual Convert * as_Convert ( ) { return NULL ; }
virtual NullCheck * as_NullCheck ( ) { return NULL ; }
virtual OsrEntry * as_OsrEntry ( ) { return NULL ; }
virtual StateSplit * as_StateSplit ( ) { return NULL ; }
virtual Invoke * as_Invoke ( ) { return NULL ; }
virtual NewInstance * as_NewInstance ( ) { return NULL ; }
virtual NewArray * as_NewArray ( ) { return NULL ; }
virtual NewTypeArray * as_NewTypeArray ( ) { return NULL ; }
virtual NewObjectArray * as_NewObjectArray ( ) { return NULL ; }
virtual NewMultiArray * as_NewMultiArray ( ) { return NULL ; }
virtual TypeCheck * as_TypeCheck ( ) { return NULL ; }
virtual CheckCast * as_CheckCast ( ) { return NULL ; }
virtual InstanceOf * as_InstanceOf ( ) { return NULL ; }
virtual AccessMonitor * as_AccessMonitor ( ) { return NULL ; }
virtual MonitorEnter * as_MonitorEnter ( ) { return NULL ; }
virtual MonitorExit * as_MonitorExit ( ) { return NULL ; }
virtual Intrinsic * as_Intrinsic ( ) { return NULL ; }
virtual BlockBegin * as_BlockBegin ( ) { return NULL ; }
virtual BlockEnd * as_BlockEnd ( ) { return NULL ; }
virtual Goto * as_Goto ( ) { return NULL ; }
virtual If * as_If ( ) { return NULL ; }
virtual IfInstanceOf * as_IfInstanceOf ( ) { return NULL ; }
virtual TableSwitch * as_TableSwitch ( ) { return NULL ; }
virtual LookupSwitch * as_LookupSwitch ( ) { return NULL ; }
virtual Return * as_Return ( ) { return NULL ; }
virtual Throw * as_Throw ( ) { return NULL ; }
virtual Base * as_Base ( ) { return NULL ; }
virtual RoundFP * as_RoundFP ( ) { return NULL ; }
virtual ExceptionObject * as_ExceptionObject ( ) { return NULL ; }
virtual UnsafeOp * as_UnsafeOp ( ) { return NULL ; }
virtual void visit ( InstructionVisitor * v ) = 0 ;
virtual bool can_trap ( ) const { return false ; }
2010-06-04 11:18:04 -07:00
virtual void input_values_do ( ValueVisitor * f ) = 0 ;
2009-12-29 19:08:54 +01:00
virtual void state_values_do ( ValueVisitor * f ) ;
2010-06-04 11:18:04 -07:00
virtual void other_values_do ( ValueVisitor * f ) { /* usually no other - override on demand */ }
void values_do ( ValueVisitor * f ) { input_values_do ( f ) ; state_values_do ( f ) ; other_values_do ( f ) ; }
2007-12-01 00:00:00 +00:00
virtual ciType * exact_type ( ) const { return NULL ; }
virtual ciType * declared_type ( ) const { return NULL ; }
// hashing
virtual const char * name ( ) const = 0 ;
HASHING1 ( Instruction , false , id ( ) ) // hashing disabled by default
// debugging
2009-12-29 19:08:54 +01:00
static void check_state ( ValueStack * state ) PRODUCT_RETURN ;
2007-12-01 00:00:00 +00:00
void print ( ) PRODUCT_RETURN ;
void print_line ( ) PRODUCT_RETURN ;
void print ( InstructionPrinter & ip ) PRODUCT_RETURN ;
} ;
// 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.
# define BASE(class_name, super_class_name) \
class class_name : public super_class_name { \
public : \
virtual class_name * as_ # # class_name ( ) { return this ; } \
# define LEAF(class_name, super_class_name) \
BASE ( class_name , super_class_name ) \
public : \
virtual const char * name ( ) const { return # class_name ; } \
virtual void visit ( InstructionVisitor * v ) { v - > do_ # # class_name ( this ) ; } \
// Debugging support
2010-06-04 11:18:04 -07:00
2007-12-01 00:00:00 +00:00
# ifdef ASSERT
2010-06-04 11:18:04 -07:00
class AssertValues : public ValueVisitor {
void visit ( Value * x ) { assert ( ( * x ) ! = NULL , " value must exist " ) ; }
} ;
# define ASSERT_VALUES { AssertValues assert_value; values_do(&assert_value); }
2007-12-01 00:00:00 +00:00
# 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.
LEAF ( Phi , Instruction )
private :
BlockBegin * _block ; // the block to which the phi function belongs
int _pf_flags ; // the flags of the phi function
int _index ; // to value on operand stack (index < 0) or to local
public :
// creation
Phi ( ValueType * type , BlockBegin * b , int index )
: Instruction ( type - > base ( ) )
, _pf_flags ( 0 )
, _block ( b )
, _index ( index )
{
if ( type - > is_illegal ( ) ) {
make_illegal ( ) ;
}
}
// flags
enum Flag {
no_flag = 0 ,
visited = 1 < < 0 ,
cannot_simplify = 1 < < 1
} ;
// accessors
bool is_local ( ) const { return _index > = 0 ; }
bool is_on_stack ( ) const { return ! is_local ( ) ; }
int local_index ( ) const { assert ( is_local ( ) , " " ) ; return _index ; }
int stack_index ( ) const { assert ( is_on_stack ( ) , " " ) ; return - ( _index + 1 ) ; }
Value operand_at ( int i ) const ;
int operand_count ( ) const ;
BlockBegin * block ( ) const { return _block ; }
void set ( Flag f ) { _pf_flags | = f ; }
void clear ( Flag f ) { _pf_flags & = ~ f ; }
bool is_set ( Flag f ) const { return ( _pf_flags & f ) ! = 0 ; }
// Invalidates phis corresponding to merges of locals of two different types
// (these should never be referenced, otherwise the bytecodes are illegal)
void make_illegal ( ) {
set ( cannot_simplify ) ;
set_type ( illegalType ) ;
}
bool is_illegal ( ) const {
return type ( ) - > is_illegal ( ) ;
}
// generic
2010-06-04 11:18:04 -07:00
virtual void input_values_do ( ValueVisitor * f ) {
2007-12-01 00:00:00 +00:00
}
} ;
// A local is a placeholder for an incoming argument to a function call.
LEAF ( Local , Instruction )
private :
int _java_index ; // the local index within the method to which the local belongs
2011-04-03 12:00:54 +02:00
ciType * _declared_type ;
2007-12-01 00:00:00 +00:00
public :
// creation
2011-04-03 12:00:54 +02:00
Local ( ciType * declared , ValueType * type , int index )
2007-12-01 00:00:00 +00:00
: Instruction ( type )
, _java_index ( index )
2011-04-03 12:00:54 +02:00
, _declared_type ( declared )
2007-12-01 00:00:00 +00:00
{ }
// accessors
int java_index ( ) const { return _java_index ; }
2011-04-03 12:00:54 +02:00
ciType * declared_type ( ) const { return _declared_type ; }
ciType * exact_type ( ) const ;
2007-12-01 00:00:00 +00:00
// generic
2010-06-04 11:18:04 -07:00
virtual void input_values_do ( ValueVisitor * f ) { /* no values */ }
2007-12-01 00:00:00 +00:00
} ;
LEAF ( Constant , Instruction )
public :
// creation
Constant ( ValueType * type ) :
2009-12-29 19:08:54 +01:00
Instruction ( type , NULL , true )
{
2007-12-01 00:00:00 +00:00
assert ( type - > is_constant ( ) , " must be a constant " ) ;
}
2009-12-29 19:08:54 +01:00
Constant ( ValueType * type , ValueStack * state_before ) :
Instruction ( type , state_before , true )
{
assert ( state_before ! = NULL , " only used for constants which need patching " ) ;
2007-12-01 00:00:00 +00:00
assert ( type - > is_constant ( ) , " must be a constant " ) ;
// since it's patching it needs to be pinned
pin ( ) ;
}
2009-12-29 19:08:54 +01:00
virtual bool can_trap ( ) const { return state_before ( ) ! = NULL ; }
2010-06-04 11:18:04 -07:00
virtual void input_values_do ( ValueVisitor * f ) { /* no values */ }
2007-12-01 00:00:00 +00:00
virtual intx hash ( ) const ;
virtual bool is_equal ( Value v ) const ;
2010-10-15 09:38:20 +02:00
enum CompareResult { not_comparable = - 1 , cond_false , cond_true } ;
virtual CompareResult compare ( Instruction : : Condition condition , Value right ) const ;
BlockBegin * compare ( Instruction : : Condition cond , Value right ,
BlockBegin * true_sux , BlockBegin * false_sux ) const {
switch ( compare ( cond , right ) ) {
case not_comparable :
return NULL ;
case cond_false :
return false_sux ;
case cond_true :
return true_sux ;
default :
ShouldNotReachHere ( ) ;
return NULL ;
}
}
2007-12-01 00:00:00 +00:00
} ;
BASE ( AccessField , Instruction )
private :
Value _obj ;
int _offset ;
ciField * _field ;
NullCheck * _explicit_null_check ; // For explicit null check elimination
public :
// creation
2009-12-29 19:08:54 +01:00
AccessField ( Value obj , int offset , ciField * field , bool is_static ,
2011-03-06 22:09:23 -08:00
ValueStack * state_before , bool needs_patching )
2009-12-29 19:08:54 +01:00
: Instruction ( as_ValueType ( field - > type ( ) - > basic_type ( ) ) , state_before )
2007-12-01 00:00:00 +00:00
, _obj ( obj )
, _offset ( offset )
, _field ( field )
, _explicit_null_check ( NULL )
{
set_needs_null_check ( ! is_static ) ;
set_flag ( IsStaticFlag , is_static ) ;
2011-03-06 22:09:23 -08:00
set_flag ( NeedsPatchingFlag , needs_patching ) ;
2007-12-01 00:00:00 +00:00
ASSERT_VALUES
// pin of all instructions with memory access
pin ( ) ;
}
// accessors
Value obj ( ) const { return _obj ; }
int offset ( ) const { return _offset ; }
ciField * field ( ) const { return _field ; }
BasicType field_type ( ) const { return _field - > type ( ) - > basic_type ( ) ; }
bool is_static ( ) const { return check_flag ( IsStaticFlag ) ; }
NullCheck * explicit_null_check ( ) const { return _explicit_null_check ; }
bool needs_patching ( ) const { return check_flag ( NeedsPatchingFlag ) ; }
2011-03-06 22:09:23 -08:00
// 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 ( ) ) ; }
2007-12-01 00:00:00 +00:00
// manipulation
2009-12-29 19:08:54 +01:00
2007-12-01 00:00:00 +00:00
// 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.
void set_explicit_null_check ( NullCheck * check ) { _explicit_null_check = check ; }
// generic
virtual bool can_trap ( ) const { return needs_null_check ( ) | | needs_patching ( ) ; }
2010-06-04 11:18:04 -07:00
virtual void input_values_do ( ValueVisitor * f ) { f - > visit ( & _obj ) ; }
2007-12-01 00:00:00 +00:00
} ;
LEAF ( LoadField , AccessField )
public :
// creation
2009-12-29 19:08:54 +01:00
LoadField ( Value obj , int offset , ciField * field , bool is_static ,
2011-03-06 22:09:23 -08:00
ValueStack * state_before , bool needs_patching )
: AccessField ( obj , offset , field , is_static , state_before , needs_patching )
2007-12-01 00:00:00 +00:00
{ }
ciType * declared_type ( ) const ;
ciType * exact_type ( ) const ;
// generic
2011-03-06 22:09:23 -08:00
HASHING2 ( LoadField , ! needs_patching ( ) & & ! field ( ) - > is_volatile ( ) , obj ( ) - > subst ( ) , offset ( ) ) // cannot be eliminated if needs patching or if volatile
2007-12-01 00:00:00 +00:00
} ;
LEAF ( StoreField , AccessField )
private :
Value _value ;
public :
// creation
2009-12-29 19:08:54 +01:00
StoreField ( Value obj , int offset , ciField * field , Value value , bool is_static ,
2011-03-06 22:09:23 -08:00
ValueStack * state_before , bool needs_patching )
: AccessField ( obj , offset , field , is_static , state_before , needs_patching )
2007-12-01 00:00:00 +00:00
, _value ( value )
{
set_flag ( NeedsWriteBarrierFlag , as_ValueType ( field_type ( ) ) - > is_object ( ) ) ;
ASSERT_VALUES
pin ( ) ;
}
// accessors
Value value ( ) const { return _value ; }
bool needs_write_barrier ( ) const { return check_flag ( NeedsWriteBarrierFlag ) ; }
// generic
2010-06-04 11:18:04 -07:00
virtual void input_values_do ( ValueVisitor * f ) { AccessField : : input_values_do ( f ) ; f - > visit ( & _value ) ; }
2007-12-01 00:00:00 +00:00
} ;
BASE ( AccessArray , Instruction )
private :
Value _array ;
public :
// creation
2009-12-29 19:08:54 +01:00
AccessArray ( ValueType * type , Value array , ValueStack * state_before )
: Instruction ( type , state_before )
2007-12-01 00:00:00 +00:00
, _array ( array )
2009-12-29 19:08:54 +01:00
{
2007-12-01 00:00:00 +00:00
set_needs_null_check ( true ) ;
ASSERT_VALUES
pin ( ) ; // instruction with side effect (null exception or range check throwing)
}
Value array ( ) const { return _array ; }
// generic
virtual bool can_trap ( ) const { return needs_null_check ( ) ; }
2010-06-04 11:18:04 -07:00
virtual void input_values_do ( ValueVisitor * f ) { f - > visit ( & _array ) ; }
2007-12-01 00:00:00 +00:00
} ;
LEAF ( ArrayLength , AccessArray )
private :
NullCheck * _explicit_null_check ; // For explicit null check elimination
public :
// creation
2009-12-29 19:08:54 +01:00
ArrayLength ( Value array , ValueStack * state_before )
: AccessArray ( intType , array , state_before )
2007-12-01 00:00:00 +00:00
, _explicit_null_check ( NULL ) { }
// accessors
NullCheck * explicit_null_check ( ) const { return _explicit_null_check ; }
// setters
// See LoadField::set_explicit_null_check for documentation
void set_explicit_null_check ( NullCheck * check ) { _explicit_null_check = check ; }
// generic
HASHING1 ( ArrayLength , true , array ( ) - > subst ( ) )
} ;
BASE ( AccessIndexed , AccessArray )
private :
Value _index ;
Value _length ;
BasicType _elt_type ;
public :
// creation
2009-12-29 19:08:54 +01:00
AccessIndexed ( Value array , Value index , Value length , BasicType elt_type , ValueStack * state_before )
: AccessArray ( as_ValueType ( elt_type ) , array , state_before )
2007-12-01 00:00:00 +00:00
, _index ( index )
, _length ( length )
, _elt_type ( elt_type )
{
ASSERT_VALUES
}
// accessors
Value index ( ) const { return _index ; }
Value length ( ) const { return _length ; }
BasicType elt_type ( ) const { return _elt_type ; }
// perform elimination of range checks involving constants
bool compute_needs_range_check ( ) ;
// generic
2010-06-04 11:18:04 -07:00
virtual void input_values_do ( ValueVisitor * f ) { AccessArray : : input_values_do ( f ) ; f - > visit ( & _index ) ; if ( _length ! = NULL ) f - > visit ( & _length ) ; }
2007-12-01 00:00:00 +00:00
} ;
LEAF ( LoadIndexed , AccessIndexed )
private :
NullCheck * _explicit_null_check ; // For explicit null check elimination
public :
// creation
2009-12-29 19:08:54 +01:00
LoadIndexed ( Value array , Value index , Value length , BasicType elt_type , ValueStack * state_before )
: AccessIndexed ( array , index , length , elt_type , state_before )
2007-12-01 00:00:00 +00:00
, _explicit_null_check ( NULL ) { }
// accessors
NullCheck * explicit_null_check ( ) const { return _explicit_null_check ; }
// setters
// See LoadField::set_explicit_null_check for documentation
void set_explicit_null_check ( NullCheck * check ) { _explicit_null_check = check ; }
ciType * exact_type ( ) const ;
ciType * declared_type ( ) const ;
// generic
HASHING2 ( LoadIndexed , true , array ( ) - > subst ( ) , index ( ) - > subst ( ) )
} ;
LEAF ( StoreIndexed , AccessIndexed )
private :
Value _value ;
2010-09-13 12:10:49 -07:00
ciMethod * _profiled_method ;
int _profiled_bci ;
2007-12-01 00:00:00 +00:00
public :
// creation
2009-12-29 19:08:54 +01:00
StoreIndexed ( Value array , Value index , Value length , BasicType elt_type , Value value , ValueStack * state_before )
: AccessIndexed ( array , index , length , elt_type , state_before )
2010-09-13 12:10:49 -07:00
, _value ( value ) , _profiled_method ( NULL ) , _profiled_bci ( 0 )
2007-12-01 00:00:00 +00:00
{
set_flag ( NeedsWriteBarrierFlag , ( as_ValueType ( elt_type ) - > is_object ( ) ) ) ;
set_flag ( NeedsStoreCheckFlag , ( as_ValueType ( elt_type ) - > is_object ( ) ) ) ;
ASSERT_VALUES
pin ( ) ;
}
// accessors
Value value ( ) const { return _value ; }
bool needs_write_barrier ( ) const { return check_flag ( NeedsWriteBarrierFlag ) ; }
bool needs_store_check ( ) const { return check_flag ( NeedsStoreCheckFlag ) ; }
2010-09-13 12:10:49 -07:00
// Helpers for methodDataOop profiling
void set_should_profile ( bool value ) { set_flag ( ProfileMDOFlag , value ) ; }
void set_profiled_method ( ciMethod * method ) { _profiled_method = method ; }
void set_profiled_bci ( int bci ) { _profiled_bci = bci ; }
bool should_profile ( ) const { return check_flag ( ProfileMDOFlag ) ; }
ciMethod * profiled_method ( ) const { return _profiled_method ; }
int profiled_bci ( ) const { return _profiled_bci ; }
2007-12-01 00:00:00 +00:00
// generic
2010-06-04 11:18:04 -07:00
virtual void input_values_do ( ValueVisitor * f ) { AccessIndexed : : input_values_do ( f ) ; f - > visit ( & _value ) ; }
2007-12-01 00:00:00 +00:00
} ;
LEAF ( NegateOp , Instruction )
private :
Value _x ;
public :
// creation
NegateOp ( Value x ) : Instruction ( x - > type ( ) - > base ( ) ) , _x ( x ) {
ASSERT_VALUES
}
// accessors
Value x ( ) const { return _x ; }
// generic
2010-06-04 11:18:04 -07:00
virtual void input_values_do ( ValueVisitor * f ) { f - > visit ( & _x ) ; }
2007-12-01 00:00:00 +00:00
} ;
BASE ( Op2 , Instruction )
private :
Bytecodes : : Code _op ;
Value _x ;
Value _y ;
public :
// creation
2009-12-29 19:08:54 +01:00
Op2 ( ValueType * type , Bytecodes : : Code op , Value x , Value y , ValueStack * state_before = NULL )
: Instruction ( type , state_before )
, _op ( op )
, _x ( x )
, _y ( y )
{
2007-12-01 00:00:00 +00:00
ASSERT_VALUES
}
// accessors
Bytecodes : : Code op ( ) const { return _op ; }
Value x ( ) const { return _x ; }
Value y ( ) const { return _y ; }
// manipulators
void swap_operands ( ) {
assert ( is_commutative ( ) , " operation must be commutative " ) ;
Value t = _x ; _x = _y ; _y = t ;
}
// generic
virtual bool is_commutative ( ) const { return false ; }
2010-06-04 11:18:04 -07:00
virtual void input_values_do ( ValueVisitor * f ) { f - > visit ( & _x ) ; f - > visit ( & _y ) ; }
2007-12-01 00:00:00 +00:00
} ;
LEAF ( ArithmeticOp , Op2 )
public :
// creation
2009-12-29 19:08:54 +01:00
ArithmeticOp ( Bytecodes : : Code op , Value x , Value y , bool is_strictfp , ValueStack * state_before )
: Op2 ( x - > type ( ) - > meet ( y - > type ( ) ) , op , x , y , state_before )
{
2007-12-01 00:00:00 +00:00
set_flag ( IsStrictfpFlag , is_strictfp ) ;
if ( can_trap ( ) ) pin ( ) ;
}
// accessors
bool is_strictfp ( ) const { return check_flag ( IsStrictfpFlag ) ; }
// generic
virtual bool is_commutative ( ) const ;
virtual bool can_trap ( ) const ;
HASHING3 ( Op2 , true , op ( ) , x ( ) - > subst ( ) , y ( ) - > subst ( ) )
} ;
LEAF ( ShiftOp , Op2 )
public :
// creation
ShiftOp ( Bytecodes : : Code op , Value x , Value s ) : Op2 ( x - > type ( ) - > base ( ) , op , x , s ) { }
// generic
HASHING3 ( Op2 , true , op ( ) , x ( ) - > subst ( ) , y ( ) - > subst ( ) )
} ;
LEAF ( LogicOp , Op2 )
public :
// creation
LogicOp ( Bytecodes : : Code op , Value x , Value y ) : Op2 ( x - > type ( ) - > meet ( y - > type ( ) ) , op , x , y ) { }
// generic
virtual bool is_commutative ( ) const ;
HASHING3 ( Op2 , true , op ( ) , x ( ) - > subst ( ) , y ( ) - > subst ( ) )
} ;
LEAF ( CompareOp , Op2 )
public :
// creation
CompareOp ( Bytecodes : : Code op , Value x , Value y , ValueStack * state_before )
2009-12-29 19:08:54 +01:00
: Op2 ( intType , op , x , y , state_before )
2007-12-01 00:00:00 +00:00
{ }
// generic
HASHING3 ( Op2 , true , op ( ) , x ( ) - > subst ( ) , y ( ) - > subst ( ) )
} ;
LEAF ( IfOp , Op2 )
private :
Value _tval ;
Value _fval ;
public :
// creation
IfOp ( Value x , Condition cond , Value y , Value tval , Value fval )
: Op2 ( tval - > type ( ) - > meet ( fval - > type ( ) ) , ( Bytecodes : : Code ) cond , x , y )
, _tval ( tval )
, _fval ( fval )
{
ASSERT_VALUES
assert ( tval - > type ( ) - > tag ( ) = = fval - > type ( ) - > tag ( ) , " types must match " ) ;
}
// accessors
virtual bool is_commutative ( ) const ;
Bytecodes : : Code op ( ) const { ShouldNotCallThis ( ) ; return Bytecodes : : _illegal ; }
Condition cond ( ) const { return ( Condition ) Op2 : : op ( ) ; }
Value tval ( ) const { return _tval ; }
Value fval ( ) const { return _fval ; }
// generic
2010-06-04 11:18:04 -07:00
virtual void input_values_do ( ValueVisitor * f ) { Op2 : : input_values_do ( f ) ; f - > visit ( & _tval ) ; f - > visit ( & _fval ) ; }
2007-12-01 00:00:00 +00:00
} ;
LEAF ( Convert , Instruction )
private :
Bytecodes : : Code _op ;
Value _value ;
public :
// creation
Convert ( Bytecodes : : Code op , Value value , ValueType * to_type ) : Instruction ( to_type ) , _op ( op ) , _value ( value ) {
ASSERT_VALUES
}
// accessors
Bytecodes : : Code op ( ) const { return _op ; }
Value value ( ) const { return _value ; }
// generic
2010-06-04 11:18:04 -07:00
virtual void input_values_do ( ValueVisitor * f ) { f - > visit ( & _value ) ; }
2007-12-01 00:00:00 +00:00
HASHING2 ( Convert , true , op ( ) , value ( ) - > subst ( ) )
} ;
LEAF ( NullCheck , Instruction )
private :
Value _obj ;
public :
// creation
2009-12-29 19:08:54 +01:00
NullCheck ( Value obj , ValueStack * state_before )
: Instruction ( obj - > type ( ) - > base ( ) , state_before )
, _obj ( obj )
{
2007-12-01 00:00:00 +00:00
ASSERT_VALUES
set_can_trap ( true ) ;
assert ( _obj - > type ( ) - > is_object ( ) , " null check must be applied to objects only " ) ;
pin ( Instruction : : PinExplicitNullCheck ) ;
}
// accessors
Value obj ( ) const { return _obj ; }
// setters
void set_can_trap ( bool can_trap ) { set_flag ( CanTrapFlag , can_trap ) ; }
// generic
virtual bool can_trap ( ) const { return check_flag ( CanTrapFlag ) ; /* null-check elimination sets to false */ }
2010-06-04 11:18:04 -07:00
virtual void input_values_do ( ValueVisitor * f ) { f - > visit ( & _obj ) ; }
2007-12-01 00:00:00 +00:00
HASHING1 ( NullCheck , true , obj ( ) - > subst ( ) )
} ;
BASE ( StateSplit , Instruction )
private :
ValueStack * _state ;
protected :
static void substitute ( BlockList & list , BlockBegin * old_block , BlockBegin * new_block ) ;
public :
// creation
2009-12-29 19:08:54 +01:00
StateSplit ( ValueType * type , ValueStack * state_before = NULL )
: Instruction ( type , state_before )
, _state ( NULL )
{
2007-12-01 00:00:00 +00:00
pin ( PinStateSplitConstructor ) ;
}
// accessors
ValueStack * state ( ) const { return _state ; }
IRScope * scope ( ) const ; // the state's scope
// manipulation
2009-12-29 19:08:54 +01:00
void set_state ( ValueStack * state ) { assert ( _state = = NULL , " overwriting existing state " ) ; check_state ( state ) ; _state = state ; }
2007-12-01 00:00:00 +00:00
// generic
2010-06-04 11:18:04 -07:00
virtual void input_values_do ( ValueVisitor * f ) { /* no values */ }
virtual void state_values_do ( ValueVisitor * f ) ;
2007-12-01 00:00:00 +00:00
} ;
LEAF ( Invoke , StateSplit )
private :
2010-03-09 20:16:19 +01:00
Bytecodes : : Code _code ;
Value _recv ;
Values * _args ;
BasicTypeList * _signature ;
int _vtable_index ;
ciMethod * _target ;
2007-12-01 00:00:00 +00:00
public :
// creation
Invoke ( Bytecodes : : Code code , ValueType * result_type , Value recv , Values * args ,
2010-03-09 20:16:19 +01:00
int vtable_index , ciMethod * target , ValueStack * state_before ) ;
2007-12-01 00:00:00 +00:00
// accessors
Bytecodes : : Code code ( ) const { return _code ; }
Value receiver ( ) const { return _recv ; }
bool has_receiver ( ) const { return receiver ( ) ! = NULL ; }
int number_of_arguments ( ) const { return _args - > length ( ) ; }
Value argument_at ( int i ) const { return _args - > at ( i ) ; }
int vtable_index ( ) const { return _vtable_index ; }
BasicTypeList * signature ( ) const { return _signature ; }
ciMethod * target ( ) const { return _target ; }
2011-04-03 12:00:54 +02:00
ciType * declared_type ( ) const ;
2007-12-01 00:00:00 +00:00
// Returns false if target is not loaded
bool target_is_final ( ) const { return check_flag ( TargetIsFinalFlag ) ; }
bool target_is_loaded ( ) const { return check_flag ( TargetIsLoadedFlag ) ; }
// Returns false if target is not loaded
bool target_is_strictfp ( ) const { return check_flag ( TargetIsStrictfpFlag ) ; }
2010-03-09 20:16:19 +01:00
// JSR 292 support
bool is_invokedynamic ( ) const { return code ( ) = = Bytecodes : : _invokedynamic ; }
2009-12-29 19:08:54 +01:00
virtual bool needs_exception_state ( ) const { return false ; }
2007-12-01 00:00:00 +00:00
// generic
virtual bool can_trap ( ) const { return true ; }
2010-06-04 11:18:04 -07:00
virtual void input_values_do ( ValueVisitor * f ) {
2007-12-01 00:00:00 +00:00
StateSplit : : input_values_do ( f ) ;
2010-06-04 11:18:04 -07:00
if ( has_receiver ( ) ) f - > visit ( & _recv ) ;
for ( int i = 0 ; i < _args - > length ( ) ; i + + ) f - > visit ( _args - > adr_at ( i ) ) ;
2007-12-01 00:00:00 +00:00
}
2010-06-04 11:18:04 -07:00
virtual void state_values_do ( ValueVisitor * f ) ;
2007-12-01 00:00:00 +00:00
} ;
LEAF ( NewInstance , StateSplit )
private :
ciInstanceKlass * _klass ;
public :
// creation
2009-12-29 19:08:54 +01:00
NewInstance ( ciInstanceKlass * klass , ValueStack * state_before )
: StateSplit ( instanceType , state_before )
, _klass ( klass )
{ }
2007-12-01 00:00:00 +00:00
// accessors
ciInstanceKlass * klass ( ) const { return _klass ; }
2009-12-29 19:08:54 +01:00
virtual bool needs_exception_state ( ) const { return false ; }
2007-12-01 00:00:00 +00:00
// generic
virtual bool can_trap ( ) const { return true ; }
ciType * exact_type ( ) const ;
2011-04-03 12:00:54 +02:00
ciType * declared_type ( ) const ;
2007-12-01 00:00:00 +00:00
} ;
BASE ( NewArray , StateSplit )
private :
Value _length ;
public :
// creation
2009-12-29 19:08:54 +01:00
NewArray ( Value length , ValueStack * state_before )
: StateSplit ( objectType , state_before )
, _length ( length )
{
2007-12-01 00:00:00 +00:00
// Do not ASSERT_VALUES since length is NULL for NewMultiArray
}
// accessors
Value length ( ) const { return _length ; }
2009-12-29 19:08:54 +01:00
virtual bool needs_exception_state ( ) const { return false ; }
2011-04-03 12:00:54 +02:00
ciType * declared_type ( ) const ;
2007-12-01 00:00:00 +00:00
// generic
virtual bool can_trap ( ) const { return true ; }
2010-06-04 11:18:04 -07:00
virtual void input_values_do ( ValueVisitor * f ) { StateSplit : : input_values_do ( f ) ; f - > visit ( & _length ) ; }
2007-12-01 00:00:00 +00:00
} ;
LEAF ( NewTypeArray , NewArray )
private :
BasicType _elt_type ;
public :
// creation
2009-12-29 19:08:54 +01:00
NewTypeArray ( Value length , BasicType elt_type , ValueStack * state_before )
: NewArray ( length , state_before )
, _elt_type ( elt_type )
{ }
2007-12-01 00:00:00 +00:00
// accessors
BasicType elt_type ( ) const { return _elt_type ; }
ciType * exact_type ( ) const ;
} ;
LEAF ( NewObjectArray , NewArray )
private :
ciKlass * _klass ;
public :
// creation
NewObjectArray ( ciKlass * klass , Value length , ValueStack * state_before ) : NewArray ( length , state_before ) , _klass ( klass ) { }
// accessors
ciKlass * klass ( ) const { return _klass ; }
ciType * exact_type ( ) const ;
} ;
LEAF ( NewMultiArray , NewArray )
private :
ciKlass * _klass ;
Values * _dims ;
public :
// creation
NewMultiArray ( ciKlass * klass , Values * dims , ValueStack * state_before ) : NewArray ( NULL , state_before ) , _klass ( klass ) , _dims ( dims ) {
ASSERT_VALUES
}
// accessors
ciKlass * klass ( ) const { return _klass ; }
Values * dims ( ) const { return _dims ; }
int rank ( ) const { return dims ( ) - > length ( ) ; }
// generic
2010-06-04 11:18:04 -07:00
virtual void input_values_do ( ValueVisitor * f ) {
2007-12-01 00:00:00 +00:00
// 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
StateSplit : : input_values_do ( f ) ;
2010-06-04 11:18:04 -07:00
for ( int i = 0 ; i < _dims - > length ( ) ; i + + ) f - > visit ( _dims - > adr_at ( i ) ) ;
2007-12-01 00:00:00 +00:00
}
} ;
BASE ( TypeCheck , StateSplit )
private :
ciKlass * _klass ;
Value _obj ;
2010-09-13 12:10:49 -07:00
ciMethod * _profiled_method ;
int _profiled_bci ;
2007-12-01 00:00:00 +00:00
public :
// creation
2010-09-13 12:10:49 -07:00
TypeCheck ( ciKlass * klass , Value obj , ValueType * type , ValueStack * state_before )
2009-12-29 19:08:54 +01:00
: StateSplit ( type , state_before ) , _klass ( klass ) , _obj ( obj ) ,
2010-09-13 12:10:49 -07:00
_profiled_method ( NULL ) , _profiled_bci ( 0 ) {
2007-12-01 00:00:00 +00:00
ASSERT_VALUES
set_direct_compare ( false ) ;
}
// accessors
ciKlass * klass ( ) const { return _klass ; }
Value obj ( ) const { return _obj ; }
bool is_loaded ( ) const { return klass ( ) ! = NULL ; }
bool direct_compare ( ) const { return check_flag ( DirectCompareFlag ) ; }
// manipulation
void set_direct_compare ( bool flag ) { set_flag ( DirectCompareFlag , flag ) ; }
// generic
virtual bool can_trap ( ) const { return true ; }
2010-06-04 11:18:04 -07:00
virtual void input_values_do ( ValueVisitor * f ) { StateSplit : : input_values_do ( f ) ; f - > visit ( & _obj ) ; }
2010-09-13 12:10:49 -07:00
// Helpers for methodDataOop profiling
void set_should_profile ( bool value ) { set_flag ( ProfileMDOFlag , value ) ; }
void set_profiled_method ( ciMethod * method ) { _profiled_method = method ; }
void set_profiled_bci ( int bci ) { _profiled_bci = bci ; }
bool should_profile ( ) const { return check_flag ( ProfileMDOFlag ) ; }
ciMethod * profiled_method ( ) const { return _profiled_method ; }
int profiled_bci ( ) const { return _profiled_bci ; }
2007-12-01 00:00:00 +00:00
} ;
LEAF ( CheckCast , TypeCheck )
public :
// creation
CheckCast ( ciKlass * klass , Value obj , ValueStack * state_before )
2010-09-13 12:10:49 -07:00
: TypeCheck ( klass , obj , objectType , state_before ) { }
2007-12-01 00:00:00 +00:00
void set_incompatible_class_change_check ( ) {
set_flag ( ThrowIncompatibleClassChangeErrorFlag , true ) ;
}
bool is_incompatible_class_change_check ( ) const {
return check_flag ( ThrowIncompatibleClassChangeErrorFlag ) ;
}
ciType * declared_type ( ) const ;
ciType * exact_type ( ) const ;
} ;
LEAF ( InstanceOf , TypeCheck )
public :
// creation
InstanceOf ( ciKlass * klass , Value obj , ValueStack * state_before ) : TypeCheck ( klass , obj , intType , state_before ) { }
2009-12-29 19:08:54 +01:00
virtual bool needs_exception_state ( ) const { return false ; }
2007-12-01 00:00:00 +00:00
} ;
BASE ( AccessMonitor , StateSplit )
private :
Value _obj ;
int _monitor_no ;
public :
// creation
2009-12-29 19:08:54 +01:00
AccessMonitor ( Value obj , int monitor_no , ValueStack * state_before = NULL )
: StateSplit ( illegalType , state_before )
2007-12-01 00:00:00 +00:00
, _obj ( obj )
, _monitor_no ( monitor_no )
{
set_needs_null_check ( true ) ;
ASSERT_VALUES
}
// accessors
Value obj ( ) const { return _obj ; }
int monitor_no ( ) const { return _monitor_no ; }
// generic
2010-06-04 11:18:04 -07:00
virtual void input_values_do ( ValueVisitor * f ) { StateSplit : : input_values_do ( f ) ; f - > visit ( & _obj ) ; }
2007-12-01 00:00:00 +00:00
} ;
LEAF ( MonitorEnter , AccessMonitor )
public :
// creation
2009-12-29 19:08:54 +01:00
MonitorEnter ( Value obj , int monitor_no , ValueStack * state_before )
: AccessMonitor ( obj , monitor_no , state_before )
2007-12-01 00:00:00 +00:00
{
ASSERT_VALUES
}
// generic
virtual bool can_trap ( ) const { return true ; }
} ;
LEAF ( MonitorExit , AccessMonitor )
public :
// creation
2009-12-29 19:08:54 +01:00
MonitorExit ( Value obj , int monitor_no )
: AccessMonitor ( obj , monitor_no , NULL )
{
ASSERT_VALUES
}
2007-12-01 00:00:00 +00:00
} ;
LEAF ( Intrinsic , StateSplit )
private :
vmIntrinsics : : ID _id ;
Values * _args ;
Value _recv ;
2011-04-03 12:00:54 +02:00
int _nonnull_state ; // mask identifying which args are nonnull
2007-12-01 00:00:00 +00:00
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.
Intrinsic ( ValueType * type ,
vmIntrinsics : : ID id ,
Values * args ,
bool has_receiver ,
2009-12-29 19:08:54 +01:00
ValueStack * state_before ,
2007-12-01 00:00:00 +00:00
bool preserves_state ,
bool cantrap = true )
2009-12-29 19:08:54 +01:00
: StateSplit ( type , state_before )
2007-12-01 00:00:00 +00:00
, _id ( id )
, _args ( args )
, _recv ( NULL )
2011-04-03 12:00:54 +02:00
, _nonnull_state ( AllBits )
2007-12-01 00:00:00 +00:00
{
assert ( args ! = NULL , " args must exist " ) ;
ASSERT_VALUES
set_flag ( PreservesStateFlag , preserves_state ) ;
set_flag ( CanTrapFlag , cantrap ) ;
if ( has_receiver ) {
_recv = argument_at ( 0 ) ;
}
set_needs_null_check ( has_receiver ) ;
// some intrinsics can't trap, so don't force them to be pinned
if ( ! can_trap ( ) ) {
unpin ( PinStateSplitConstructor ) ;
}
}
// accessors
vmIntrinsics : : ID id ( ) const { return _id ; }
int number_of_arguments ( ) const { return _args - > length ( ) ; }
Value argument_at ( int i ) const { return _args - > at ( i ) ; }
bool has_receiver ( ) const { return ( _recv ! = NULL ) ; }
Value receiver ( ) const { assert ( has_receiver ( ) , " must have receiver " ) ; return _recv ; }
bool preserves_state ( ) const { return check_flag ( PreservesStateFlag ) ; }
2011-04-03 12:00:54 +02:00
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 ) ) ;
}
}
}
2007-12-01 00:00:00 +00:00
// generic
virtual bool can_trap ( ) const { return check_flag ( CanTrapFlag ) ; }
2010-06-04 11:18:04 -07:00
virtual void input_values_do ( ValueVisitor * f ) {
2007-12-01 00:00:00 +00:00
StateSplit : : input_values_do ( f ) ;
2010-06-04 11:18:04 -07:00
for ( int i = 0 ; i < _args - > length ( ) ; i + + ) f - > visit ( _args - > adr_at ( i ) ) ;
2007-12-01 00:00:00 +00:00
}
} ;
class LIR_List ;
LEAF ( BlockBegin , StateSplit )
private :
int _block_id ; // the unique block id
2009-12-29 19:08:54 +01:00
int _bci ; // start-bci of block
2007-12-01 00:00:00 +00:00
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
BitMap _stores_to_locals ; // bit is set when a local variable is stored in the block
// SSA specific fields: (factor out later)
BlockList _successors ; // the successors of this block
BlockList _predecessors ; // the predecessors of this block
BlockBegin * _dominator ; // the dominator of this block
// SSA specific ends
BlockEnd * _end ; // the last instruction of this block
BlockList _exception_handlers ; // the exception handlers potentially invoked by this block
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
Label _label ; // the label associated with this block
LIR_List * _lir ; // the low level intermediate representation for this block
BitMap _live_in ; // set of live LIR_Opr registers at entry to this block
BitMap _live_out ; // set of live LIR_Opr registers at exit from this block
BitMap _live_gen ; // set of registers used before any redefinition in this block
BitMap _live_kill ; // set of registers defined in this block
BitMap _fpu_register_usage ;
intArray * _fpu_stack_state ; // For x86 FPU code generation with UseLinearScan
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
void iterate_preorder ( boolArray & mark , BlockClosure * closure ) ;
void iterate_postorder ( boolArray & mark , BlockClosure * closure ) ;
friend class SuxAndWeightAdjuster ;
public :
2010-06-04 11:18:04 -07:00
void * operator new ( size_t size ) {
Compilation * c = Compilation : : current ( ) ;
void * res = c - > arena ( ) - > Amalloc ( size ) ;
( ( BlockBegin * ) res ) - > _id = c - > get_next_id ( ) ;
( ( BlockBegin * ) res ) - > _block_id = c - > get_next_block_id ( ) ;
return res ;
}
2007-12-01 00:00:00 +00:00
// initialization/counting
2010-06-04 11:18:04 -07:00
static int number_of_blocks ( ) {
return Compilation : : current ( ) - > number_of_blocks ( ) ;
}
2007-12-01 00:00:00 +00:00
// creation
BlockBegin ( int bci )
: StateSplit ( illegalType )
2009-12-29 19:08:54 +01:00
, _bci ( bci )
2007-12-01 00:00:00 +00:00
, _depth_first_number ( - 1 )
, _linear_scan_number ( - 1 )
, _loop_depth ( 0 )
, _flags ( 0 )
, _dominator ( NULL )
, _end ( NULL )
, _predecessors ( 2 )
, _successors ( 2 )
, _exception_handlers ( 1 )
, _exception_states ( NULL )
, _exception_handler_pco ( - 1 )
, _lir ( NULL )
, _loop_index ( - 1 )
, _live_in ( )
, _live_out ( )
, _live_gen ( )
, _live_kill ( )
, _fpu_register_usage ( )
, _fpu_stack_state ( NULL )
, _first_lir_instruction_id ( - 1 )
, _last_lir_instruction_id ( - 1 )
, _total_preds ( 0 )
, _stores_to_locals ( )
{
2009-12-29 19:08:54 +01:00
# ifndef PRODUCT
set_printable_bci ( bci ) ;
# endif
2007-12-01 00:00:00 +00:00
}
// accessors
int block_id ( ) const { return _block_id ; }
2009-12-29 19:08:54 +01:00
int bci ( ) const { return _bci ; }
2007-12-01 00:00:00 +00:00
BlockList * successors ( ) { return & _successors ; }
BlockBegin * dominator ( ) const { return _dominator ; }
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 ; }
BlockEnd * end ( ) const { return _end ; }
Label * label ( ) { return & _label ; }
LIR_List * lir ( ) const { return _lir ; }
int exception_handler_pco ( ) const { return _exception_handler_pco ; }
BitMap & live_in ( ) { return _live_in ; }
BitMap & live_out ( ) { return _live_out ; }
BitMap & live_gen ( ) { return _live_gen ; }
BitMap & live_kill ( ) { return _live_kill ; }
BitMap & fpu_register_usage ( ) { return _fpu_register_usage ; }
intArray * fpu_stack_state ( ) const { return _fpu_stack_state ; }
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 ; }
BitMap & stores_to_locals ( ) { return _stores_to_locals ; }
// manipulation
void set_dominator ( BlockBegin * dom ) { _dominator = dom ; }
void set_loop_depth ( int d ) { _loop_depth = d ; }
void set_depth_first_number ( int dfn ) { _depth_first_number = dfn ; }
void set_linear_scan_number ( int lsn ) { _linear_scan_number = lsn ; }
void set_end ( BlockEnd * end ) ;
void disconnect_from_graph ( ) ;
static void disconnect_edge ( BlockBegin * from , BlockBegin * to ) ;
BlockBegin * insert_block_between ( BlockBegin * sux ) ;
void substitute_sux ( BlockBegin * old_sux , BlockBegin * new_sux ) ;
void set_lir ( LIR_List * lir ) { _lir = lir ; }
void set_exception_handler_pco ( int pco ) { _exception_handler_pco = pco ; }
void set_live_in ( BitMap map ) { _live_in = map ; }
void set_live_out ( BitMap map ) { _live_out = map ; }
void set_live_gen ( BitMap map ) { _live_gen = map ; }
void set_live_kill ( BitMap map ) { _live_kill = map ; }
void set_fpu_register_usage ( BitMap map ) { _fpu_register_usage = map ; }
void set_fpu_stack_state ( intArray * state ) { _fpu_stack_state = state ; }
void set_first_lir_instruction_id ( int id ) { _first_lir_instruction_id = id ; }
void set_last_lir_instruction_id ( int id ) { _last_lir_instruction_id = id ; }
void increment_total_preds ( int n = 1 ) { _total_preds + = n ; }
void init_stores_to_locals ( int locals_count ) { _stores_to_locals = BitMap ( locals_count ) ; _stores_to_locals . clear ( ) ; }
// generic
2010-06-04 11:18:04 -07:00
virtual void state_values_do ( ValueVisitor * f ) ;
2007-12-01 00:00:00 +00:00
// successors and predecessors
int number_of_sux ( ) const ;
BlockBegin * sux_at ( int i ) const ;
void add_successor ( BlockBegin * sux ) ;
void remove_successor ( BlockBegin * pred ) ;
bool is_successor ( BlockBegin * sux ) const { return _successors . contains ( sux ) ; }
void add_predecessor ( BlockBegin * pred ) ;
void remove_predecessor ( BlockBegin * pred ) ;
bool is_predecessor ( BlockBegin * pred ) const { return _predecessors . contains ( pred ) ; }
int number_of_preds ( ) const { return _predecessors . length ( ) ; }
BlockBegin * pred_at ( int i ) const { return _predecessors [ i ] ; }
// exception handlers potentially invoked by this block
void add_exception_handler ( BlockBegin * b ) ;
bool is_exception_handler ( BlockBegin * b ) const { return _exception_handlers . contains ( b ) ; }
int number_of_exception_handlers ( ) const { return _exception_handlers . length ( ) ; }
BlockBegin * exception_handler_at ( int i ) const { return _exception_handlers . at ( i ) ; }
// 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 ) ; }
int add_exception_state ( ValueStack * state ) ;
// flags
enum Flag {
no_flag = 0 ,
std_entry_flag = 1 < < 0 ,
osr_entry_flag = 1 < < 1 ,
exception_entry_flag = 1 < < 2 ,
subroutine_entry_flag = 1 < < 3 ,
backward_branch_target_flag = 1 < < 4 ,
is_on_work_list_flag = 1 < < 5 ,
was_visited_flag = 1 < < 6 ,
2010-04-15 18:14:49 -07:00
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
linear_scan_loop_header_flag = 1 < < 9 , // set during loop-detection for LinearScan
linear_scan_loop_end_flag = 1 < < 10 // set during loop-detection for LinearScan
2007-12-01 00:00:00 +00:00
} ;
void set ( Flag f ) { _flags | = f ; }
void clear ( Flag f ) { _flags & = ~ f ; }
bool is_set ( Flag f ) const { return ( _flags & f ) ! = 0 ; }
bool is_entry_block ( ) const {
const int entry_mask = std_entry_flag | osr_entry_flag | exception_entry_flag ;
return ( _flags & entry_mask ) ! = 0 ;
}
// iteration
void iterate_preorder ( BlockClosure * closure ) ;
void iterate_postorder ( BlockClosure * closure ) ;
2010-06-04 11:18:04 -07:00
void block_values_do ( ValueVisitor * f ) ;
2007-12-01 00:00:00 +00:00
// loops
void set_loop_index ( int ix ) { _loop_index = ix ; }
int loop_index ( ) const { return _loop_index ; }
// merging
bool try_merge ( ValueStack * state ) ; // try to merge states at block begin
void merge ( ValueStack * state ) { bool b = try_merge ( state ) ; assert ( b , " merge failed " ) ; }
// debugging
void print_block ( ) PRODUCT_RETURN ;
void print_block ( InstructionPrinter & ip , bool live_only = false ) PRODUCT_RETURN ;
} ;
BASE ( BlockEnd , StateSplit )
private :
BlockBegin * _begin ;
BlockList * _sux ;
protected :
BlockList * sux ( ) const { return _sux ; }
void set_sux ( BlockList * sux ) {
# ifdef ASSERT
assert ( sux ! = NULL , " sux must exist " ) ;
for ( int i = sux - > length ( ) - 1 ; i > = 0 ; i - - ) assert ( sux - > at ( i ) ! = NULL , " sux must exist " ) ;
# endif
_sux = sux ;
}
public :
// creation
BlockEnd ( ValueType * type , ValueStack * state_before , bool is_safepoint )
2009-12-29 19:08:54 +01:00
: StateSplit ( type , state_before )
2007-12-01 00:00:00 +00:00
, _begin ( NULL )
, _sux ( NULL )
2009-12-29 19:08:54 +01:00
{
2007-12-01 00:00:00 +00:00
set_flag ( IsSafepointFlag , is_safepoint ) ;
}
// accessors
bool is_safepoint ( ) const { return check_flag ( IsSafepointFlag ) ; }
BlockBegin * begin ( ) const { return _begin ; }
// manipulation
void set_begin ( BlockBegin * begin ) ;
// successors
int number_of_sux ( ) const { return _sux ! = NULL ? _sux - > length ( ) : 0 ; }
BlockBegin * sux_at ( int i ) const { return _sux - > at ( i ) ; }
BlockBegin * default_sux ( ) const { return sux_at ( number_of_sux ( ) - 1 ) ; }
BlockBegin * * addr_sux_at ( int i ) const { return _sux - > adr_at ( i ) ; }
int sux_index ( BlockBegin * sux ) const { return _sux - > find ( sux ) ; }
void substitute_sux ( BlockBegin * old_sux , BlockBegin * new_sux ) ;
} ;
LEAF ( Goto , BlockEnd )
2010-09-03 17:51:07 -07:00
public :
enum Direction {
none , // Just a regular goto
taken , not_taken // Goto produced from If
} ;
private :
ciMethod * _profiled_method ;
int _profiled_bci ;
Direction _direction ;
2007-12-01 00:00:00 +00:00
public :
// creation
2010-09-03 17:51:07 -07:00
Goto ( BlockBegin * sux , ValueStack * state_before , bool is_safepoint = false )
: BlockEnd ( illegalType , state_before , is_safepoint )
, _direction ( none )
, _profiled_method ( NULL )
, _profiled_bci ( 0 ) {
2007-12-01 00:00:00 +00:00
BlockList * s = new BlockList ( 1 ) ;
s - > append ( sux ) ;
set_sux ( s ) ;
}
2010-09-03 17:51:07 -07:00
Goto ( BlockBegin * sux , bool is_safepoint ) : BlockEnd ( illegalType , NULL , is_safepoint )
, _direction ( none )
, _profiled_method ( NULL )
, _profiled_bci ( 0 ) {
2007-12-01 00:00:00 +00:00
BlockList * s = new BlockList ( 1 ) ;
s - > append ( sux ) ;
set_sux ( s ) ;
}
2010-09-03 17:51:07 -07:00
bool should_profile ( ) const { return check_flag ( ProfileMDOFlag ) ; }
ciMethod * profiled_method ( ) const { return _profiled_method ; } // set only for profiled branches
int profiled_bci ( ) const { return _profiled_bci ; }
Direction direction ( ) const { return _direction ; }
void set_should_profile ( bool value ) { set_flag ( ProfileMDOFlag , value ) ; }
void set_profiled_method ( ciMethod * method ) { _profiled_method = method ; }
void set_profiled_bci ( int bci ) { _profiled_bci = bci ; }
void set_direction ( Direction d ) { _direction = d ; }
2007-12-01 00:00:00 +00:00
} ;
LEAF ( If , BlockEnd )
private :
Value _x ;
Condition _cond ;
Value _y ;
ciMethod * _profiled_method ;
int _profiled_bci ; // Canonicalizer may alter bci of If node
2010-09-03 17:51:07 -07:00
bool _swapped ; // Is the order reversed with respect to the original If in the
// bytecode stream?
2007-12-01 00:00:00 +00:00
public :
// creation
// unordered_is_true is valid for float/double compares only
If ( Value x , Condition cond , bool unordered_is_true , Value y , BlockBegin * tsux , BlockBegin * fsux , ValueStack * state_before , bool is_safepoint )
: BlockEnd ( illegalType , state_before , is_safepoint )
, _x ( x )
, _cond ( cond )
, _y ( y )
, _profiled_method ( NULL )
, _profiled_bci ( 0 )
2010-09-03 17:51:07 -07:00
, _swapped ( false )
2007-12-01 00:00:00 +00:00
{
ASSERT_VALUES
set_flag ( UnorderedIsTrueFlag , unordered_is_true ) ;
assert ( x - > type ( ) - > tag ( ) = = y - > type ( ) - > tag ( ) , " types must match " ) ;
BlockList * s = new BlockList ( 2 ) ;
s - > append ( tsux ) ;
s - > append ( fsux ) ;
set_sux ( s ) ;
}
// accessors
Value x ( ) const { return _x ; }
Condition cond ( ) const { return _cond ; }
bool unordered_is_true ( ) const { return check_flag ( UnorderedIsTrueFlag ) ; }
Value y ( ) const { return _y ; }
BlockBegin * sux_for ( bool is_true ) const { return sux_at ( is_true ? 0 : 1 ) ; }
BlockBegin * tsux ( ) const { return sux_for ( true ) ; }
BlockBegin * fsux ( ) const { return sux_for ( false ) ; }
BlockBegin * usux ( ) const { return sux_for ( unordered_is_true ( ) ) ; }
bool should_profile ( ) const { return check_flag ( ProfileMDOFlag ) ; }
ciMethod * profiled_method ( ) const { return _profiled_method ; } // set only for profiled branches
2010-09-03 17:51:07 -07:00
int profiled_bci ( ) const { return _profiled_bci ; } // set for profiled branches and tiered
bool is_swapped ( ) const { return _swapped ; }
2007-12-01 00:00:00 +00:00
// manipulation
void swap_operands ( ) {
Value t = _x ; _x = _y ; _y = t ;
_cond = mirror ( _cond ) ;
}
void swap_sux ( ) {
assert ( number_of_sux ( ) = = 2 , " wrong number of successors " ) ;
BlockList * s = sux ( ) ;
BlockBegin * t = s - > at ( 0 ) ; s - > at_put ( 0 , s - > at ( 1 ) ) ; s - > at_put ( 1 , t ) ;
_cond = negate ( _cond ) ;
set_flag ( UnorderedIsTrueFlag , ! check_flag ( UnorderedIsTrueFlag ) ) ;
}
void set_should_profile ( bool value ) { set_flag ( ProfileMDOFlag , value ) ; }
void set_profiled_method ( ciMethod * method ) { _profiled_method = method ; }
void set_profiled_bci ( int bci ) { _profiled_bci = bci ; }
2010-09-03 17:51:07 -07:00
void set_swapped ( bool value ) { _swapped = value ; }
2007-12-01 00:00:00 +00:00
// generic
2010-06-04 11:18:04 -07:00
virtual void input_values_do ( ValueVisitor * f ) { BlockEnd : : input_values_do ( f ) ; f - > visit ( & _x ) ; f - > visit ( & _y ) ; }
2007-12-01 00:00:00 +00:00
} ;
LEAF ( IfInstanceOf , BlockEnd )
private :
ciKlass * _klass ;
Value _obj ;
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 )
: BlockEnd ( illegalType , NULL , false ) // temporary set to false
, _klass ( klass )
, _obj ( obj )
, _test_is_instance ( test_is_instance )
, _instanceof_bci ( instanceof_bci )
{
ASSERT_VALUES
assert ( instanceof_bci > = 0 , " illegal bci " ) ;
BlockList * s = new BlockList ( 2 ) ;
s - > append ( tsux ) ;
s - > append ( 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.
ciKlass * klass ( ) const { return _klass ; }
Value obj ( ) const { return _obj ; }
int instanceof_bci ( ) const { return _instanceof_bci ; }
bool test_is_instance ( ) const { return _test_is_instance ; }
BlockBegin * sux_for ( bool is_true ) const { return sux_at ( is_true ? 0 : 1 ) ; }
BlockBegin * tsux ( ) const { return sux_for ( true ) ; }
BlockBegin * fsux ( ) const { return sux_for ( false ) ; }
// manipulation
void swap_sux ( ) {
assert ( number_of_sux ( ) = = 2 , " wrong number of successors " ) ;
BlockList * s = sux ( ) ;
BlockBegin * t = s - > at ( 0 ) ; s - > at_put ( 0 , s - > at ( 1 ) ) ; s - > at_put ( 1 , t ) ;
_test_is_instance = ! _test_is_instance ;
}
// generic
2010-06-04 11:18:04 -07:00
virtual void input_values_do ( ValueVisitor * f ) { BlockEnd : : input_values_do ( f ) ; f - > visit ( & _obj ) ; }
2007-12-01 00:00:00 +00:00
} ;
BASE ( Switch , BlockEnd )
private :
Value _tag ;
public :
// creation
Switch ( Value tag , BlockList * sux , ValueStack * state_before , bool is_safepoint )
: BlockEnd ( illegalType , state_before , is_safepoint )
, _tag ( tag ) {
ASSERT_VALUES
set_sux ( sux ) ;
}
// accessors
Value tag ( ) const { return _tag ; }
int length ( ) const { return number_of_sux ( ) - 1 ; }
2009-12-29 19:08:54 +01:00
virtual bool needs_exception_state ( ) const { return false ; }
2007-12-01 00:00:00 +00:00
// generic
2010-06-04 11:18:04 -07:00
virtual void input_values_do ( ValueVisitor * f ) { BlockEnd : : input_values_do ( f ) ; f - > visit ( & _tag ) ; }
2007-12-01 00:00:00 +00:00
} ;
LEAF ( TableSwitch , Switch )
private :
int _lo_key ;
public :
// creation
TableSwitch ( Value tag , BlockList * sux , int lo_key , ValueStack * state_before , bool is_safepoint )
: Switch ( tag , sux , state_before , is_safepoint )
, _lo_key ( lo_key ) { }
// accessors
int lo_key ( ) const { return _lo_key ; }
int hi_key ( ) const { return _lo_key + length ( ) - 1 ; }
} ;
LEAF ( LookupSwitch , Switch )
private :
intArray * _keys ;
public :
// creation
LookupSwitch ( Value tag , BlockList * sux , intArray * keys , ValueStack * state_before , bool is_safepoint )
: Switch ( tag , sux , state_before , is_safepoint )
, _keys ( keys ) {
assert ( keys ! = NULL , " keys must exist " ) ;
assert ( keys - > length ( ) = = length ( ) , " sux & keys have incompatible lengths " ) ;
}
// accessors
int key_at ( int i ) const { return _keys - > at ( i ) ; }
} ;
LEAF ( Return , BlockEnd )
private :
Value _result ;
public :
// creation
Return ( Value result ) :
BlockEnd ( result = = NULL ? voidType : result - > type ( ) - > base ( ) , NULL , true ) ,
_result ( result ) { }
// accessors
Value result ( ) const { return _result ; }
bool has_result ( ) const { return result ( ) ! = NULL ; }
// generic
2010-06-04 11:18:04 -07:00
virtual void input_values_do ( ValueVisitor * f ) {
2007-12-01 00:00:00 +00:00
BlockEnd : : input_values_do ( f ) ;
2010-06-04 11:18:04 -07:00
if ( has_result ( ) ) f - > visit ( & _result ) ;
2007-12-01 00:00:00 +00:00
}
} ;
LEAF ( Throw , BlockEnd )
private :
Value _exception ;
public :
// creation
Throw ( Value exception , ValueStack * state_before ) : BlockEnd ( illegalType , state_before , true ) , _exception ( exception ) {
ASSERT_VALUES
}
// accessors
Value exception ( ) const { return _exception ; }
// generic
virtual bool can_trap ( ) const { return true ; }
2010-06-04 11:18:04 -07:00
virtual void input_values_do ( ValueVisitor * f ) { BlockEnd : : input_values_do ( f ) ; f - > visit ( & _exception ) ; }
2007-12-01 00:00:00 +00:00
} ;
LEAF ( Base , BlockEnd )
public :
// creation
Base ( BlockBegin * std_entry , BlockBegin * osr_entry ) : BlockEnd ( illegalType , NULL , false ) {
assert ( std_entry - > is_set ( BlockBegin : : std_entry_flag ) , " std entry must be flagged " ) ;
assert ( osr_entry = = NULL | | osr_entry - > is_set ( BlockBegin : : osr_entry_flag ) , " osr entry must be flagged " ) ;
BlockList * s = new BlockList ( 2 ) ;
if ( osr_entry ! = NULL ) s - > append ( osr_entry ) ;
s - > append ( std_entry ) ; // must be default sux!
set_sux ( s ) ;
}
// accessors
BlockBegin * std_entry ( ) const { return default_sux ( ) ; }
BlockBegin * osr_entry ( ) const { return number_of_sux ( ) < 2 ? NULL : sux_at ( 0 ) ; }
} ;
LEAF ( OsrEntry , Instruction )
public :
// creation
# ifdef _LP64
2010-09-29 18:53:28 +02:00
OsrEntry ( ) : Instruction ( longType ) { pin ( ) ; }
2007-12-01 00:00:00 +00:00
# else
2010-09-29 18:53:28 +02:00
OsrEntry ( ) : Instruction ( intType ) { pin ( ) ; }
2007-12-01 00:00:00 +00:00
# endif
// generic
2010-06-04 11:18:04 -07:00
virtual void input_values_do ( ValueVisitor * f ) { }
2007-12-01 00:00:00 +00:00
} ;
// Models the incoming exception at a catch site
LEAF ( ExceptionObject , Instruction )
public :
// creation
2010-09-29 18:53:28 +02:00
ExceptionObject ( ) : Instruction ( objectType ) {
2007-12-01 00:00:00 +00:00
pin ( ) ;
}
// generic
2010-06-04 11:18:04 -07:00
virtual void input_values_do ( ValueVisitor * f ) { }
2007-12-01 00:00:00 +00:00
} ;
// 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.
LEAF ( RoundFP , Instruction )
private :
Value _input ; // floating-point value to be rounded
public :
RoundFP ( Value input )
: Instruction ( input - > type ( ) ) // Note: should not be used for constants
, _input ( input )
{
ASSERT_VALUES
}
// accessors
Value input ( ) const { return _input ; }
// generic
2010-06-04 11:18:04 -07:00
virtual void input_values_do ( ValueVisitor * f ) { f - > visit ( & _input ) ; }
2007-12-01 00:00:00 +00:00
} ;
BASE ( UnsafeOp , Instruction )
private :
BasicType _basic_type ; // ValueType can not express byte-sized integers
protected :
// creation
UnsafeOp ( BasicType basic_type , bool is_put )
: Instruction ( is_put ? voidType : as_ValueType ( basic_type ) )
, _basic_type ( basic_type )
{
//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
BasicType basic_type ( ) { return _basic_type ; }
// generic
2010-06-04 11:18:04 -07:00
virtual void input_values_do ( ValueVisitor * f ) { }
2007-12-01 00:00:00 +00:00
} ;
BASE ( UnsafeRawOp , UnsafeOp )
private :
Value _base ; // Base address (a Java long)
Value _index ; // Index if computed by optimizer; initialized to NULL
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 :
UnsafeRawOp ( BasicType basic_type , Value addr , bool is_put )
: UnsafeOp ( basic_type , is_put )
, _base ( addr )
, _index ( NULL )
, _log2_scale ( 0 )
{
// Can not use ASSERT_VALUES because index may be NULL
assert ( addr ! = NULL & & addr - > type ( ) - > is_long ( ) , " just checking " ) ;
}
UnsafeRawOp ( BasicType basic_type , Value base , Value index , int log2_scale , bool is_put )
: UnsafeOp ( basic_type , is_put )
, _base ( base )
, _index ( index )
, _log2_scale ( log2_scale )
{
}
public :
// accessors
Value base ( ) { return _base ; }
Value index ( ) { return _index ; }
bool has_index ( ) { return ( _index ! = NULL ) ; }
int log2_scale ( ) { return _log2_scale ; }
// setters
void set_base ( Value base ) { _base = base ; }
void set_index ( Value index ) { _index = index ; }
void set_log2_scale ( int log2_scale ) { _log2_scale = log2_scale ; }
// generic
2010-06-04 11:18:04 -07:00
virtual void input_values_do ( ValueVisitor * f ) { UnsafeOp : : input_values_do ( f ) ;
f - > visit ( & _base ) ;
if ( has_index ( ) ) f - > visit ( & _index ) ; }
2007-12-01 00:00:00 +00:00
} ;
LEAF ( UnsafeGetRaw , UnsafeRawOp )
private :
2010-11-30 23:23:40 -08:00
bool _may_be_unaligned , _is_wide ; // For OSREntry
2007-12-01 00:00:00 +00:00
public :
2010-11-30 23:23:40 -08:00
UnsafeGetRaw ( BasicType basic_type , Value addr , bool may_be_unaligned , bool is_wide = false )
2007-12-01 00:00:00 +00:00
: UnsafeRawOp ( basic_type , addr , false ) {
_may_be_unaligned = may_be_unaligned ;
2010-11-30 23:23:40 -08:00
_is_wide = is_wide ;
2007-12-01 00:00:00 +00:00
}
2010-11-30 23:23:40 -08:00
UnsafeGetRaw ( BasicType basic_type , Value base , Value index , int log2_scale , bool may_be_unaligned , bool is_wide = false )
2007-12-01 00:00:00 +00:00
: UnsafeRawOp ( basic_type , base , index , log2_scale , false ) {
_may_be_unaligned = may_be_unaligned ;
2010-11-30 23:23:40 -08:00
_is_wide = is_wide ;
2007-12-01 00:00:00 +00:00
}
2010-11-30 23:23:40 -08:00
bool may_be_unaligned ( ) { return _may_be_unaligned ; }
bool is_wide ( ) { return _is_wide ; }
2007-12-01 00:00:00 +00:00
} ;
LEAF ( UnsafePutRaw , UnsafeRawOp )
private :
Value _value ; // Value to be stored
public :
UnsafePutRaw ( BasicType basic_type , Value addr , Value value )
: UnsafeRawOp ( basic_type , addr , true )
, _value ( value )
{
assert ( value ! = NULL , " just checking " ) ;
ASSERT_VALUES
}
UnsafePutRaw ( BasicType basic_type , Value base , Value index , int log2_scale , Value value )
: UnsafeRawOp ( basic_type , base , index , log2_scale , true )
, _value ( value )
{
assert ( value ! = NULL , " just checking " ) ;
ASSERT_VALUES
}
// accessors
Value value ( ) { return _value ; }
// generic
2010-06-04 11:18:04 -07:00
virtual void input_values_do ( ValueVisitor * f ) { UnsafeRawOp : : input_values_do ( f ) ;
f - > visit ( & _value ) ; }
2007-12-01 00:00:00 +00:00
} ;
BASE ( UnsafeObjectOp , UnsafeOp )
private :
Value _object ; // Object to be fetched from or mutated
Value _offset ; // Offset within object
bool _is_volatile ; // true if volatile - dl/JSR166
public :
UnsafeObjectOp ( BasicType basic_type , Value object , Value offset , bool is_put , bool is_volatile )
: UnsafeOp ( basic_type , is_put ) , _object ( object ) , _offset ( offset ) , _is_volatile ( is_volatile )
{
}
// accessors
Value object ( ) { return _object ; }
Value offset ( ) { return _offset ; }
bool is_volatile ( ) { return _is_volatile ; }
// generic
2010-06-04 11:18:04 -07:00
virtual void input_values_do ( ValueVisitor * f ) { UnsafeOp : : input_values_do ( f ) ;
f - > visit ( & _object ) ;
f - > visit ( & _offset ) ; }
2007-12-01 00:00:00 +00:00
} ;
LEAF ( UnsafeGetObject , UnsafeObjectOp )
public :
UnsafeGetObject ( BasicType basic_type , Value object , Value offset , bool is_volatile )
: UnsafeObjectOp ( basic_type , object , offset , false , is_volatile )
{
ASSERT_VALUES
}
} ;
LEAF ( UnsafePutObject , UnsafeObjectOp )
private :
Value _value ; // Value to be stored
public :
UnsafePutObject ( BasicType basic_type , Value object , Value offset , Value value , bool is_volatile )
: UnsafeObjectOp ( basic_type , object , offset , true , is_volatile )
, _value ( value )
{
ASSERT_VALUES
}
// accessors
Value value ( ) { return _value ; }
// generic
2010-06-04 11:18:04 -07:00
virtual void input_values_do ( ValueVisitor * f ) { UnsafeObjectOp : : input_values_do ( f ) ;
f - > visit ( & _value ) ; }
2007-12-01 00:00:00 +00:00
} ;
BASE ( UnsafePrefetch , UnsafeObjectOp )
public :
UnsafePrefetch ( Value object , Value offset )
: UnsafeObjectOp ( T_VOID , object , offset , false , false )
{
}
} ;
LEAF ( UnsafePrefetchRead , UnsafePrefetch )
public :
UnsafePrefetchRead ( Value object , Value offset )
: UnsafePrefetch ( object , offset )
{
ASSERT_VALUES
}
} ;
LEAF ( UnsafePrefetchWrite , UnsafePrefetch )
public :
UnsafePrefetchWrite ( Value object , Value offset )
: UnsafePrefetch ( object , offset )
{
ASSERT_VALUES
}
} ;
LEAF ( ProfileCall , Instruction )
private :
ciMethod * _method ;
int _bci_of_invoke ;
Value _recv ;
ciKlass * _known_holder ;
public :
ProfileCall ( ciMethod * method , int bci , Value recv , ciKlass * known_holder )
: Instruction ( voidType )
, _method ( method )
, _bci_of_invoke ( bci )
, _recv ( recv )
, _known_holder ( known_holder )
{
// The ProfileCall has side-effects and must occur precisely where located
pin ( ) ;
}
ciMethod * method ( ) { return _method ; }
int bci_of_invoke ( ) { return _bci_of_invoke ; }
Value recv ( ) { return _recv ; }
ciKlass * known_holder ( ) { return _known_holder ; }
2010-06-04 11:18:04 -07:00
virtual void input_values_do ( ValueVisitor * f ) { if ( _recv ! = NULL ) f - > visit ( & _recv ) ; }
2007-12-01 00:00:00 +00:00
} ;
2011-01-21 13:01:02 -08:00
// Call some C runtime function that doesn't safepoint,
// optionally passing the current thread as the first argument.
LEAF ( RuntimeCall , Instruction )
private :
const char * _entry_name ;
address _entry ;
Values * _args ;
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 )
, _entry ( entry )
, _args ( args )
, _entry_name ( entry_name )
, _pass_thread ( pass_thread ) {
ASSERT_VALUES
pin ( ) ;
}
const char * entry_name ( ) const { return _entry_name ; }
address entry ( ) const { return _entry ; }
int number_of_arguments ( ) const { return _args - > length ( ) ; }
Value argument_at ( int i ) const { return _args - > at ( i ) ; }
bool pass_thread ( ) const { return _pass_thread ; }
virtual void input_values_do ( ValueVisitor * f ) {
for ( int i = 0 ; i < _args - > length ( ) ; i + + ) f - > visit ( _args - > adr_at ( i ) ) ;
}
} ;
2010-09-03 17:51:07 -07:00
// Use to trip invocation counter of an inlined method
2007-12-01 00:00:00 +00:00
2010-09-03 17:51:07 -07:00
LEAF ( ProfileInvoke , Instruction )
2007-12-01 00:00:00 +00:00
private :
2010-09-03 17:51:07 -07:00
ciMethod * _inlinee ;
ValueStack * _state ;
2007-12-01 00:00:00 +00:00
public :
2010-09-29 16:53:42 -07:00
ProfileInvoke ( ciMethod * inlinee , ValueStack * state )
2007-12-01 00:00:00 +00:00
: Instruction ( voidType )
2010-09-03 17:51:07 -07:00
, _inlinee ( inlinee )
, _state ( state )
2007-12-01 00:00:00 +00:00
{
2010-09-03 17:51:07 -07:00
// The ProfileInvoke has side-effects and must occur precisely where located QQQ???
2007-12-01 00:00:00 +00:00
pin ( ) ;
}
2010-09-03 17:51:07 -07:00
ciMethod * inlinee ( ) { return _inlinee ; }
ValueStack * state ( ) { return _state ; }
virtual void input_values_do ( ValueVisitor * ) { }
virtual void state_values_do ( ValueVisitor * ) ;
2007-12-01 00:00:00 +00:00
} ;
class BlockPair : public CompilationResourceObj {
private :
BlockBegin * _from ;
BlockBegin * _to ;
public :
BlockPair ( BlockBegin * from , BlockBegin * to ) : _from ( from ) , _to ( to ) { }
BlockBegin * from ( ) const { return _from ; }
BlockBegin * to ( ) const { return _to ; }
bool is_same ( BlockBegin * from , BlockBegin * to ) const { return _from = = from & & _to = = to ; }
bool is_same ( BlockPair * p ) const { return _from = = p - > from ( ) & & _to = = p - > to ( ) ; }
void set_to ( BlockBegin * b ) { _to = b ; }
void set_from ( BlockBegin * b ) { _from = b ; }
} ;
define_array ( BlockPairArray , BlockPair * )
define_stack ( BlockPairList , BlockPairArray )
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 ) ; }
# undef ASSERT_VALUES
2010-11-23 13:22:55 -08:00
# endif // SHARE_VM_C1_C1_INSTRUCTION_HPP