duke@435: /* duke@435: * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. duke@435: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. duke@435: * duke@435: * This code is free software; you can redistribute it and/or modify it duke@435: * under the terms of the GNU General Public License version 2 only, as duke@435: * published by the Free Software Foundation. duke@435: * duke@435: * This code is distributed in the hope that it will be useful, but WITHOUT duke@435: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or duke@435: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License duke@435: * version 2 for more details (a copy is included in the LICENSE file that duke@435: * accompanied this code). duke@435: * duke@435: * You should have received a copy of the GNU General Public License version duke@435: * 2 along with this work; if not, write to the Free Software Foundation, duke@435: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. duke@435: * duke@435: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, duke@435: * CA 95054 USA or visit www.sun.com if you need additional information or duke@435: * have any questions. duke@435: * duke@435: */ duke@435: duke@435: class BufferBlob; duke@435: class CodeBuffer; duke@435: class JVMState; duke@435: class MachCallDynamicJavaNode; duke@435: class MachCallJavaNode; duke@435: class MachCallLeafNode; duke@435: class MachCallNode; duke@435: class MachCallRuntimeNode; duke@435: class MachCallStaticJavaNode; duke@435: class MachEpilogNode; duke@435: class MachIfNode; duke@435: class MachNullCheckNode; duke@435: class MachOper; duke@435: class MachProjNode; duke@435: class MachPrologNode; duke@435: class MachReturnNode; duke@435: class MachSafePointNode; duke@435: class MachSpillCopyNode; duke@435: class Matcher; duke@435: class PhaseRegAlloc; duke@435: class RegMask; duke@435: class State; duke@435: duke@435: //---------------------------MachOper------------------------------------------ duke@435: class MachOper : public ResourceObj { duke@435: public: duke@435: // Allocate right next to the MachNodes in the same arena duke@435: void *operator new( size_t x, Compile* C ) { return C->node_arena()->Amalloc_D(x); } duke@435: duke@435: // Opcode duke@435: virtual uint opcode() const = 0; duke@435: duke@435: // Number of input edges. duke@435: // Generally at least 1 duke@435: virtual uint num_edges() const { return 1; } duke@435: // Array of Register masks duke@435: virtual const RegMask *in_RegMask(int index) const; duke@435: duke@435: // Methods to output the encoding of the operand duke@435: duke@435: // Negate conditional branches. Error for non-branch Nodes duke@435: virtual void negate(); duke@435: duke@435: // Return the value requested duke@435: // result register lookup, corresponding to int_format duke@435: virtual int reg(PhaseRegAlloc *ra_, const Node *node) const; duke@435: // input register lookup, corresponding to ext_format duke@435: virtual int reg(PhaseRegAlloc *ra_, const Node *node, int idx) const; duke@435: duke@435: // helpers for MacroAssembler generation from ADLC duke@435: Register as_Register(PhaseRegAlloc *ra_, const Node *node) const { duke@435: return ::as_Register(reg(ra_, node)); duke@435: } duke@435: Register as_Register(PhaseRegAlloc *ra_, const Node *node, int idx) const { duke@435: return ::as_Register(reg(ra_, node, idx)); duke@435: } duke@435: FloatRegister as_FloatRegister(PhaseRegAlloc *ra_, const Node *node) const { duke@435: return ::as_FloatRegister(reg(ra_, node)); duke@435: } duke@435: FloatRegister as_FloatRegister(PhaseRegAlloc *ra_, const Node *node, int idx) const { duke@435: return ::as_FloatRegister(reg(ra_, node, idx)); duke@435: } duke@435: duke@435: #if defined(IA32) || defined(AMD64) duke@435: XMMRegister as_XMMRegister(PhaseRegAlloc *ra_, const Node *node) const { duke@435: return ::as_XMMRegister(reg(ra_, node)); duke@435: } duke@435: XMMRegister as_XMMRegister(PhaseRegAlloc *ra_, const Node *node, int idx) const { duke@435: return ::as_XMMRegister(reg(ra_, node, idx)); duke@435: } duke@435: #endif duke@435: duke@435: virtual intptr_t constant() const; duke@435: virtual bool constant_is_oop() const; duke@435: virtual jdouble constantD() const; duke@435: virtual jfloat constantF() const; duke@435: virtual jlong constantL() const; duke@435: virtual TypeOopPtr *oop() const; duke@435: virtual int ccode() const; duke@435: // A zero, default, indicates this value is not needed. duke@435: // May need to lookup the base register, as done in int_ and ext_format duke@435: virtual int base (PhaseRegAlloc *ra_, const Node *node, int idx) const; duke@435: virtual int index(PhaseRegAlloc *ra_, const Node *node, int idx) const; duke@435: virtual int scale() const; duke@435: // Parameters needed to support MEMORY_INTERFACE access to stackSlot duke@435: virtual int disp (PhaseRegAlloc *ra_, const Node *node, int idx) const; duke@435: // Check for PC-Relative displacement duke@435: virtual bool disp_is_oop() const; duke@435: virtual int constant_disp() const; // usu. 0, may return Type::OffsetBot duke@435: virtual int base_position() const; // base edge position, or -1 duke@435: virtual int index_position() const; // index edge position, or -1 duke@435: duke@435: // Access the TypeKlassPtr of operands with a base==RegI and disp==RegP duke@435: // Only returns non-null value for i486.ad's indOffset32X duke@435: virtual const TypePtr *disp_as_type() const { return NULL; } duke@435: duke@435: // Return the label duke@435: virtual Label *label() const; duke@435: duke@435: // Return the method's address duke@435: virtual intptr_t method() const; duke@435: duke@435: // Hash and compare over operands are currently identical duke@435: virtual uint hash() const; duke@435: virtual uint cmp( const MachOper &oper ) const; duke@435: duke@435: // Virtual clone, since I do not know how big the MachOper is. duke@435: virtual MachOper *clone(Compile* C) const = 0; duke@435: duke@435: // Return ideal Type from simple operands. Fail for complex operands. duke@435: virtual const Type *type() const; duke@435: duke@435: // Set an integer offset if we have one, or error otherwise duke@435: virtual void set_con( jint c0 ) { ShouldNotReachHere(); } duke@435: duke@435: #ifndef PRODUCT duke@435: // Return name of operand duke@435: virtual const char *Name() const { return "???";} duke@435: duke@435: // Methods to output the text version of the operand duke@435: virtual void int_format(PhaseRegAlloc *,const MachNode *node, outputStream *st) const = 0; duke@435: virtual void ext_format(PhaseRegAlloc *,const MachNode *node,int idx, outputStream *st) const=0; duke@435: duke@435: virtual void dump_spec(outputStream *st) const; // Print per-operand info duke@435: #endif duke@435: }; duke@435: duke@435: //------------------------------MachNode--------------------------------------- duke@435: // Base type for all machine specific nodes. All node classes generated by the duke@435: // ADLC inherit from this class. duke@435: class MachNode : public Node { duke@435: public: duke@435: MachNode() : Node((uint)0), _num_opnds(0), _opnds(NULL) { duke@435: init_class_id(Class_Mach); duke@435: } duke@435: // Required boilerplate duke@435: virtual uint size_of() const { return sizeof(MachNode); } duke@435: virtual int Opcode() const; // Always equal to MachNode duke@435: virtual uint rule() const = 0; // Machine-specific opcode duke@435: // Number of inputs which come before the first operand. duke@435: // Generally at least 1, to skip the Control input duke@435: virtual uint oper_input_base() const { return 1; } duke@435: duke@435: // Copy inputs and operands to new node of instruction. duke@435: // Called from cisc_version() and short_branch_version(). duke@435: // !!!! The method's body is defined in ad_.cpp file. duke@435: void fill_new_machnode(MachNode *n, Compile* C) const; duke@435: duke@435: // Return an equivalent instruction using memory for cisc_operand position duke@435: virtual MachNode *cisc_version(int offset, Compile* C); duke@435: // Modify this instruction's register mask to use stack version for cisc_operand duke@435: virtual void use_cisc_RegMask(); duke@435: duke@435: // Support for short branches duke@435: virtual MachNode *short_branch_version(Compile* C) { return NULL; } duke@435: bool may_be_short_branch() const { return (flags() & Flag_may_be_short_branch) != 0; } duke@435: duke@435: // First index in _in[] corresponding to operand, or -1 if there is none duke@435: int operand_index(uint operand) const; duke@435: duke@435: // Register class input is expected in duke@435: virtual const RegMask &in_RegMask(uint) const; duke@435: duke@435: // cisc-spillable instructions redefine for use by in_RegMask duke@435: virtual const RegMask *cisc_RegMask() const { return NULL; } duke@435: duke@435: // If this instruction is a 2-address instruction, then return the duke@435: // index of the input which must match the output. Not nessecary duke@435: // for instructions which bind the input and output register to the duke@435: // same singleton regiser (e.g., Intel IDIV which binds AX to be duke@435: // both an input and an output). It is nessecary when the input and duke@435: // output have choices - but they must use the same choice. duke@435: virtual uint two_adr( ) const { return 0; } duke@435: duke@435: // Array of complex operand pointers. Each corresponds to zero or duke@435: // more leafs. Must be set by MachNode constructor to point to an duke@435: // internal array of MachOpers. The MachOper array is sized by duke@435: // specific MachNodes described in the ADL. duke@435: uint _num_opnds; duke@435: MachOper **_opnds; duke@435: uint num_opnds() const { return _num_opnds; } duke@435: duke@435: // Emit bytes into cbuf duke@435: virtual void emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const; duke@435: // Size of instruction in bytes duke@435: virtual uint size(PhaseRegAlloc *ra_) const; duke@435: // Helper function that computes size by emitting code duke@435: virtual uint emit_size(PhaseRegAlloc *ra_) const; duke@435: duke@435: // Return the alignment required (in units of relocInfo::addr_unit()) duke@435: // for this instruction (must be a power of 2) duke@435: virtual int alignment_required() const { return 1; } duke@435: duke@435: // Return the padding (in bytes) to be emitted before this duke@435: // instruction to properly align it. duke@435: virtual int compute_padding(int current_offset) const { return 0; } duke@435: duke@435: // Return number of relocatable values contained in this instruction duke@435: virtual int reloc() const { return 0; } duke@435: duke@435: // Return number of words used for double constants in this instruction duke@435: virtual int const_size() const { return 0; } duke@435: duke@435: // Hash and compare over operands. Used to do GVN on machine Nodes. duke@435: virtual uint hash() const; duke@435: virtual uint cmp( const Node &n ) const; duke@435: duke@435: // Expand method for MachNode, replaces nodes representing pseudo duke@435: // instructions with a set of nodes which represent real machine duke@435: // instructions and compute the same value. duke@435: virtual MachNode *Expand( State *, Node_List &proj_list ) { return this; } duke@435: duke@435: // Bottom_type call; value comes from operand0 duke@435: virtual const class Type *bottom_type() const { return _opnds[0]->type(); } duke@435: virtual uint ideal_reg() const { const Type *t = _opnds[0]->type(); return t == TypeInt::CC ? Op_RegFlags : Matcher::base2reg[t->base()]; } duke@435: duke@435: // If this is a memory op, return the base pointer and fixed offset. duke@435: // If there are no such, return NULL. If there are multiple addresses duke@435: // or the address is indeterminate (rare cases) then return (Node*)-1, duke@435: // which serves as node bottom. duke@435: // If the offset is not statically determined, set it to Type::OffsetBot. duke@435: // This method is free to ignore stack slots if that helps. duke@435: #define TYPE_PTR_SENTINAL ((const TypePtr*)-1) duke@435: // Passing TYPE_PTR_SENTINAL as adr_type asks for computation of the adr_type if possible duke@435: const Node* get_base_and_disp(intptr_t &offset, const TypePtr* &adr_type) const; duke@435: duke@435: // Helper for get_base_and_disp: find the base and index input nodes. duke@435: // Returns the MachOper as determined by memory_operand(), for use, if duke@435: // needed by the caller. If (MachOper *)-1 is returned, base and index duke@435: // are set to NodeSentinel. If (MachOper *) NULL is returned, base and duke@435: // index are set to NULL. duke@435: const MachOper* memory_inputs(Node* &base, Node* &index) const; duke@435: duke@435: // Helper for memory_inputs: Which operand carries the necessary info? duke@435: // By default, returns NULL, which means there is no such operand. duke@435: // If it returns (MachOper*)-1, this means there are multiple memories. duke@435: virtual const MachOper* memory_operand() const { return NULL; } duke@435: duke@435: // Call "get_base_and_disp" to decide which category of memory is used here. duke@435: virtual const class TypePtr *adr_type() const; duke@435: duke@435: // Negate conditional branches. Error for non-branch Nodes duke@435: virtual void negate(); duke@435: duke@435: // Apply peephole rule(s) to this instruction duke@435: virtual MachNode *peephole( Block *block, int block_index, PhaseRegAlloc *ra_, int &deleted, Compile* C ); duke@435: duke@435: // Check for PC-Relative addressing duke@435: bool is_pc_relative() const { return (flags() & Flag_is_pc_relative) != 0; } duke@435: duke@435: // Top-level ideal Opcode matched duke@435: virtual int ideal_Opcode() const { return Op_Node; } duke@435: duke@435: // Set the branch inside jump MachNodes. Error for non-branch Nodes. duke@435: virtual void label_set( Label& label, uint block_num ); duke@435: duke@435: // Adds the label for the case duke@435: virtual void add_case_label( int switch_val, Label* blockLabel); duke@435: duke@435: // Set the absolute address for methods duke@435: virtual void method_set( intptr_t addr ); duke@435: duke@435: // Should we clone rather than spill this instruction? duke@435: bool rematerialize() const; duke@435: duke@435: // Get the pipeline info duke@435: static const Pipeline *pipeline_class(); duke@435: virtual const Pipeline *pipeline() const; duke@435: duke@435: #ifndef PRODUCT duke@435: virtual const char *Name() const = 0; // Machine-specific name duke@435: virtual void dump_spec(outputStream *st) const; // Print per-node info duke@435: void dump_format(PhaseRegAlloc *ra, outputStream *st) const; // access to virtual duke@435: #endif duke@435: }; duke@435: duke@435: //------------------------------MachIdealNode---------------------------- duke@435: // Machine specific versions of nodes that must be defined by user. duke@435: // These are not converted by matcher from ideal nodes to machine nodes duke@435: // but are inserted into the code by the compiler. duke@435: class MachIdealNode : public MachNode { duke@435: public: duke@435: MachIdealNode( ) {} duke@435: duke@435: // Define the following defaults for non-matched machine nodes duke@435: virtual uint oper_input_base() const { return 0; } duke@435: virtual uint rule() const { return 9999999; } duke@435: virtual const class Type *bottom_type() const { return _opnds == NULL ? Type::CONTROL : MachNode::bottom_type(); } duke@435: }; duke@435: duke@435: //------------------------------MachTypeNode---------------------------- duke@435: // Machine Nodes that need to retain a known Type. duke@435: class MachTypeNode : public MachNode { duke@435: virtual uint size_of() const { return sizeof(*this); } // Size is bigger duke@435: public: duke@435: const Type *_bottom_type; duke@435: duke@435: virtual const class Type *bottom_type() const { return _bottom_type; } duke@435: #ifndef PRODUCT duke@435: virtual void dump_spec(outputStream *st) const; duke@435: #endif duke@435: }; duke@435: duke@435: //------------------------------MachBreakpointNode---------------------------- duke@435: // Machine breakpoint or interrupt Node duke@435: class MachBreakpointNode : public MachIdealNode { duke@435: public: duke@435: MachBreakpointNode( ) {} duke@435: virtual void emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const; duke@435: virtual uint size(PhaseRegAlloc *ra_) const; duke@435: duke@435: #ifndef PRODUCT duke@435: virtual const char *Name() const { return "Breakpoint"; } duke@435: virtual void format( PhaseRegAlloc *, outputStream *st ) const; duke@435: #endif duke@435: }; duke@435: duke@435: //------------------------------MachUEPNode----------------------------------- duke@435: // Machine Unvalidated Entry Point Node duke@435: class MachUEPNode : public MachIdealNode { duke@435: public: duke@435: MachUEPNode( ) {} duke@435: virtual void emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const; duke@435: virtual uint size(PhaseRegAlloc *ra_) const; duke@435: duke@435: #ifndef PRODUCT duke@435: virtual const char *Name() const { return "Unvalidated-Entry-Point"; } duke@435: virtual void format( PhaseRegAlloc *, outputStream *st ) const; duke@435: #endif duke@435: }; duke@435: duke@435: //------------------------------MachPrologNode-------------------------------- duke@435: // Machine function Prolog Node duke@435: class MachPrologNode : public MachIdealNode { duke@435: public: duke@435: MachPrologNode( ) {} duke@435: virtual void emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const; duke@435: virtual uint size(PhaseRegAlloc *ra_) const; duke@435: virtual int reloc() const; duke@435: duke@435: #ifndef PRODUCT duke@435: virtual const char *Name() const { return "Prolog"; } duke@435: virtual void format( PhaseRegAlloc *, outputStream *st ) const; duke@435: #endif duke@435: }; duke@435: duke@435: //------------------------------MachEpilogNode-------------------------------- duke@435: // Machine function Epilog Node duke@435: class MachEpilogNode : public MachIdealNode { duke@435: public: duke@435: MachEpilogNode(bool do_poll = false) : _do_polling(do_poll) {} duke@435: virtual void emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const; duke@435: virtual uint size(PhaseRegAlloc *ra_) const; duke@435: virtual int reloc() const; duke@435: virtual const Pipeline *pipeline() const; duke@435: duke@435: private: duke@435: bool _do_polling; duke@435: duke@435: public: duke@435: bool do_polling() const { return _do_polling; } duke@435: duke@435: // Offset of safepoint from the beginning of the node duke@435: int safepoint_offset() const; duke@435: duke@435: #ifndef PRODUCT duke@435: virtual const char *Name() const { return "Epilog"; } duke@435: virtual void format( PhaseRegAlloc *, outputStream *st ) const; duke@435: #endif duke@435: }; duke@435: duke@435: //------------------------------MachNopNode----------------------------------- duke@435: // Machine function Nop Node duke@435: class MachNopNode : public MachIdealNode { duke@435: private: duke@435: int _count; duke@435: public: duke@435: MachNopNode( ) : _count(1) {} duke@435: MachNopNode( int count ) : _count(count) {} duke@435: virtual void emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const; duke@435: virtual uint size(PhaseRegAlloc *ra_) const; duke@435: duke@435: virtual const class Type *bottom_type() const { return Type::CONTROL; } duke@435: duke@435: virtual int ideal_Opcode() const { return Op_Con; } // bogus; see output.cpp duke@435: virtual const Pipeline *pipeline() const; duke@435: #ifndef PRODUCT duke@435: virtual const char *Name() const { return "Nop"; } duke@435: virtual void format( PhaseRegAlloc *, outputStream *st ) const; duke@435: virtual void dump_spec(outputStream *st) const { } // No per-operand info duke@435: #endif duke@435: }; duke@435: duke@435: //------------------------------MachSpillCopyNode------------------------------ duke@435: // Machine SpillCopy Node. Copies 1 or 2 words from any location to any duke@435: // location (stack or register). duke@435: class MachSpillCopyNode : public MachIdealNode { duke@435: const RegMask *_in; // RegMask for input duke@435: const RegMask *_out; // RegMask for output duke@435: const Type *_type; duke@435: public: duke@435: MachSpillCopyNode( Node *n, const RegMask &in, const RegMask &out ) : duke@435: MachIdealNode(), _in(&in), _out(&out), _type(n->bottom_type()) { duke@435: init_class_id(Class_MachSpillCopy); duke@435: init_flags(Flag_is_Copy); duke@435: add_req(NULL); duke@435: add_req(n); duke@435: } duke@435: virtual uint size_of() const { return sizeof(*this); } duke@435: void set_out_RegMask(const RegMask &out) { _out = &out; } duke@435: void set_in_RegMask(const RegMask &in) { _in = ∈ } duke@435: virtual const RegMask &out_RegMask() const { return *_out; } duke@435: virtual const RegMask &in_RegMask(uint) const { return *_in; } duke@435: virtual const class Type *bottom_type() const { return _type; } duke@435: virtual uint ideal_reg() const { return Matcher::base2reg[_type->base()]; } duke@435: virtual uint oper_input_base() const { return 1; } duke@435: uint implementation( CodeBuffer *cbuf, PhaseRegAlloc *ra_, bool do_size, outputStream* st ) const; duke@435: duke@435: virtual void emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const; duke@435: virtual uint size(PhaseRegAlloc *ra_) const; duke@435: duke@435: #ifndef PRODUCT duke@435: virtual const char *Name() const { return "MachSpillCopy"; } duke@435: virtual void format( PhaseRegAlloc *, outputStream *st ) const; duke@435: #endif duke@435: }; duke@435: duke@435: //------------------------------MachNullChkNode-------------------------------- duke@435: // Machine-dependent null-pointer-check Node. Points a real MachNode that is duke@435: // also some kind of memory op. Turns the indicated MachNode into a duke@435: // conditional branch with good latency on the ptr-not-null path and awful duke@435: // latency on the pointer-is-null path. duke@435: duke@435: class MachNullCheckNode : public MachIdealNode { duke@435: public: duke@435: const uint _vidx; // Index of memop being tested duke@435: MachNullCheckNode( Node *ctrl, Node *memop, uint vidx ) : MachIdealNode(), _vidx(vidx) { duke@435: init_class_id(Class_MachNullCheck); duke@435: init_flags(Flag_is_Branch | Flag_is_pc_relative); duke@435: add_req(ctrl); duke@435: add_req(memop); duke@435: } duke@435: duke@435: virtual void emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const; duke@435: virtual bool pinned() const { return true; }; duke@435: virtual void negate() { } duke@435: virtual const class Type *bottom_type() const { return TypeTuple::IFBOTH; } duke@435: virtual uint ideal_reg() const { return NotAMachineReg; } duke@435: virtual const RegMask &in_RegMask(uint) const; duke@435: virtual const RegMask &out_RegMask() const { return RegMask::Empty; } duke@435: #ifndef PRODUCT duke@435: virtual const char *Name() const { return "NullCheck"; } duke@435: virtual void format( PhaseRegAlloc *, outputStream *st ) const; duke@435: #endif duke@435: }; duke@435: duke@435: //------------------------------MachProjNode---------------------------------- duke@435: // Machine-dependent Ideal projections (how is that for an oxymoron). Really duke@435: // just MachNodes made by the Ideal world that replicate simple projections duke@435: // but with machine-dependent input & output register masks. Generally duke@435: // produced as part of calling conventions. Normally I make MachNodes as part duke@435: // of the Matcher process, but the Matcher is ill suited to issues involving duke@435: // frame handling, so frame handling is all done in the Ideal world with duke@435: // occasional callbacks to the machine model for important info. duke@435: class MachProjNode : public ProjNode { duke@435: public: duke@435: MachProjNode( Node *multi, uint con, const RegMask &out, uint ideal_reg ) : ProjNode(multi,con), _rout(out), _ideal_reg(ideal_reg) {} duke@435: RegMask _rout; duke@435: const uint _ideal_reg; duke@435: enum projType { duke@435: unmatched_proj = 0, // Projs for Control, I/O, memory not matched duke@435: fat_proj = 999 // Projs killing many regs, defined by _rout duke@435: }; duke@435: virtual int Opcode() const; duke@435: virtual const Type *bottom_type() const; duke@435: virtual const TypePtr *adr_type() const; duke@435: virtual const RegMask &in_RegMask(uint) const { return RegMask::Empty; } duke@435: virtual const RegMask &out_RegMask() const { return _rout; } duke@435: virtual uint ideal_reg() const { return _ideal_reg; } duke@435: // Need size_of() for virtual ProjNode::clone() duke@435: virtual uint size_of() const { return sizeof(MachProjNode); } duke@435: #ifndef PRODUCT duke@435: virtual void dump_spec(outputStream *st) const; duke@435: #endif duke@435: }; duke@435: duke@435: //------------------------------MachIfNode------------------------------------- duke@435: // Machine-specific versions of IfNodes duke@435: class MachIfNode : public MachNode { duke@435: virtual uint size_of() const { return sizeof(*this); } // Size is bigger duke@435: public: duke@435: float _prob; // Probability branch goes either way duke@435: float _fcnt; // Frequency counter duke@435: MachIfNode() : MachNode() { duke@435: init_class_id(Class_MachIf); duke@435: } duke@435: #ifndef PRODUCT duke@435: virtual void dump_spec(outputStream *st) const; duke@435: #endif duke@435: }; duke@435: duke@435: //------------------------------MachFastLockNode------------------------------------- duke@435: // Machine-specific versions of FastLockNodes duke@435: class MachFastLockNode : public MachNode { duke@435: virtual uint size_of() const { return sizeof(*this); } // Size is bigger duke@435: public: duke@435: BiasedLockingCounters* _counters; duke@435: duke@435: MachFastLockNode() : MachNode() {} duke@435: }; duke@435: duke@435: //------------------------------MachReturnNode-------------------------------- duke@435: // Machine-specific versions of subroutine returns duke@435: class MachReturnNode : public MachNode { duke@435: virtual uint size_of() const; // Size is bigger duke@435: public: duke@435: RegMask *_in_rms; // Input register masks, set during allocation duke@435: ReallocMark _nesting; // assertion check for reallocations duke@435: const TypePtr* _adr_type; // memory effects of call or return duke@435: MachReturnNode() : MachNode() { duke@435: init_class_id(Class_MachReturn); duke@435: _adr_type = TypePtr::BOTTOM; // the default: all of memory duke@435: } duke@435: duke@435: void set_adr_type(const TypePtr* atp) { _adr_type = atp; } duke@435: duke@435: virtual const RegMask &in_RegMask(uint) const; duke@435: virtual bool pinned() const { return true; }; duke@435: virtual const TypePtr *adr_type() const; duke@435: }; duke@435: duke@435: //------------------------------MachSafePointNode----------------------------- duke@435: // Machine-specific versions of safepoints duke@435: class MachSafePointNode : public MachReturnNode { duke@435: public: duke@435: OopMap* _oop_map; // Array of OopMap info (8-bit char) for GC duke@435: JVMState* _jvms; // Pointer to list of JVM State Objects duke@435: uint _jvmadj; // Extra delta to jvms indexes (mach. args) duke@435: OopMap* oop_map() const { return _oop_map; } duke@435: void set_oop_map(OopMap* om) { _oop_map = om; } duke@435: duke@435: MachSafePointNode() : MachReturnNode(), _oop_map(NULL), _jvms(NULL), _jvmadj(0) { duke@435: init_class_id(Class_MachSafePoint); duke@435: init_flags(Flag_is_safepoint_node); duke@435: } duke@435: duke@435: virtual JVMState* jvms() const { return _jvms; } duke@435: void set_jvms(JVMState* s) { duke@435: _jvms = s; duke@435: } duke@435: bool is_safepoint_node() const { return (flags() & Flag_is_safepoint_node) != 0; } duke@435: virtual const Type *bottom_type() const; duke@435: duke@435: virtual const RegMask &in_RegMask(uint) const; duke@435: duke@435: // Functionality from old debug nodes duke@435: Node *returnadr() const { return in(TypeFunc::ReturnAdr); } duke@435: Node *frameptr () const { return in(TypeFunc::FramePtr); } duke@435: duke@435: Node *local(const JVMState* jvms, uint idx) const { duke@435: assert(verify_jvms(jvms), "jvms must match"); duke@435: return in(_jvmadj + jvms->locoff() + idx); duke@435: } duke@435: Node *stack(const JVMState* jvms, uint idx) const { duke@435: assert(verify_jvms(jvms), "jvms must match"); duke@435: return in(_jvmadj + jvms->stkoff() + idx); duke@435: } duke@435: Node *monitor_obj(const JVMState* jvms, uint idx) const { duke@435: assert(verify_jvms(jvms), "jvms must match"); duke@435: return in(_jvmadj + jvms->monitor_obj_offset(idx)); duke@435: } duke@435: Node *monitor_box(const JVMState* jvms, uint idx) const { duke@435: assert(verify_jvms(jvms), "jvms must match"); duke@435: return in(_jvmadj + jvms->monitor_box_offset(idx)); duke@435: } duke@435: void set_local(const JVMState* jvms, uint idx, Node *c) { duke@435: assert(verify_jvms(jvms), "jvms must match"); duke@435: set_req(_jvmadj + jvms->locoff() + idx, c); duke@435: } duke@435: void set_stack(const JVMState* jvms, uint idx, Node *c) { duke@435: assert(verify_jvms(jvms), "jvms must match"); duke@435: set_req(_jvmadj + jvms->stkoff() + idx, c); duke@435: } duke@435: void set_monitor(const JVMState* jvms, uint idx, Node *c) { duke@435: assert(verify_jvms(jvms), "jvms must match"); duke@435: set_req(_jvmadj + jvms->monoff() + idx, c); duke@435: } duke@435: }; duke@435: duke@435: //------------------------------MachCallNode---------------------------------- duke@435: // Machine-specific versions of subroutine calls duke@435: class MachCallNode : public MachSafePointNode { duke@435: protected: duke@435: virtual uint hash() const { return NO_HASH; } // CFG nodes do not hash duke@435: virtual uint cmp( const Node &n ) const; duke@435: virtual uint size_of() const = 0; // Size is bigger duke@435: public: duke@435: const TypeFunc *_tf; // Function type duke@435: address _entry_point; // Address of the method being called duke@435: float _cnt; // Estimate of number of times called duke@435: uint _argsize; // Size of argument block on stack duke@435: duke@435: const TypeFunc* tf() const { return _tf; } duke@435: const address entry_point() const { return _entry_point; } duke@435: const float cnt() const { return _cnt; } duke@435: uint argsize() const { return _argsize; } duke@435: duke@435: void set_tf(const TypeFunc* tf) { _tf = tf; } duke@435: void set_entry_point(address p) { _entry_point = p; } duke@435: void set_cnt(float c) { _cnt = c; } duke@435: void set_argsize(int s) { _argsize = s; } duke@435: duke@435: MachCallNode() : MachSafePointNode() { duke@435: init_class_id(Class_MachCall); duke@435: init_flags(Flag_is_Call); duke@435: } duke@435: duke@435: virtual const Type *bottom_type() const; duke@435: virtual bool pinned() const { return false; } duke@435: virtual const Type *Value( PhaseTransform *phase ) const; duke@435: virtual const RegMask &in_RegMask(uint) const; duke@435: virtual int ret_addr_offset() { return 0; } duke@435: duke@435: bool returns_long() const { return tf()->return_type() == T_LONG; } duke@435: bool return_value_is_used() const; duke@435: #ifndef PRODUCT duke@435: virtual void dump_spec(outputStream *st) const; duke@435: #endif duke@435: }; duke@435: duke@435: //------------------------------MachCallJavaNode------------------------------ duke@435: // "Base" class for machine-specific versions of subroutine calls duke@435: class MachCallJavaNode : public MachCallNode { duke@435: protected: duke@435: virtual uint cmp( const Node &n ) const; duke@435: virtual uint size_of() const; // Size is bigger duke@435: public: duke@435: ciMethod* _method; // Method being direct called duke@435: int _bci; // Byte Code index of call byte code duke@435: bool _optimized_virtual; // Tells if node is a static call or an optimized virtual duke@435: MachCallJavaNode() : MachCallNode() { duke@435: init_class_id(Class_MachCallJava); duke@435: } duke@435: #ifndef PRODUCT duke@435: virtual void dump_spec(outputStream *st) const; duke@435: #endif duke@435: }; duke@435: duke@435: //------------------------------MachCallStaticJavaNode------------------------ duke@435: // Machine-specific versions of monomorphic subroutine calls duke@435: class MachCallStaticJavaNode : public MachCallJavaNode { duke@435: virtual uint cmp( const Node &n ) const; duke@435: virtual uint size_of() const; // Size is bigger duke@435: public: duke@435: const char *_name; // Runtime wrapper name duke@435: MachCallStaticJavaNode() : MachCallJavaNode() { duke@435: init_class_id(Class_MachCallStaticJava); duke@435: } duke@435: duke@435: // If this is an uncommon trap, return the request code, else zero. duke@435: int uncommon_trap_request() const; duke@435: duke@435: virtual int ret_addr_offset(); duke@435: #ifndef PRODUCT duke@435: virtual void dump_spec(outputStream *st) const; duke@435: void dump_trap_args(outputStream *st) const; duke@435: #endif duke@435: }; duke@435: duke@435: //------------------------------MachCallDynamicJavaNode------------------------ duke@435: // Machine-specific versions of possibly megamorphic subroutine calls duke@435: class MachCallDynamicJavaNode : public MachCallJavaNode { duke@435: public: duke@435: int _vtable_index; duke@435: MachCallDynamicJavaNode() : MachCallJavaNode() { duke@435: init_class_id(Class_MachCallDynamicJava); duke@435: DEBUG_ONLY(_vtable_index = -99); // throw an assert if uninitialized duke@435: } duke@435: virtual int ret_addr_offset(); duke@435: #ifndef PRODUCT duke@435: virtual void dump_spec(outputStream *st) const; duke@435: #endif duke@435: }; duke@435: duke@435: //------------------------------MachCallRuntimeNode---------------------------- duke@435: // Machine-specific versions of subroutine calls duke@435: class MachCallRuntimeNode : public MachCallNode { duke@435: virtual uint cmp( const Node &n ) const; duke@435: virtual uint size_of() const; // Size is bigger duke@435: public: duke@435: const char *_name; // Printable name, if _method is NULL duke@435: MachCallRuntimeNode() : MachCallNode() { duke@435: init_class_id(Class_MachCallRuntime); duke@435: } duke@435: virtual int ret_addr_offset(); duke@435: #ifndef PRODUCT duke@435: virtual void dump_spec(outputStream *st) const; duke@435: #endif duke@435: }; duke@435: duke@435: class MachCallLeafNode: public MachCallRuntimeNode { duke@435: public: duke@435: MachCallLeafNode() : MachCallRuntimeNode() { duke@435: init_class_id(Class_MachCallLeaf); duke@435: } duke@435: }; duke@435: duke@435: //------------------------------MachHaltNode----------------------------------- duke@435: // Machine-specific versions of halt nodes duke@435: class MachHaltNode : public MachReturnNode { duke@435: public: duke@435: virtual JVMState* jvms() const; duke@435: }; duke@435: duke@435: duke@435: //------------------------------MachTempNode----------------------------------- duke@435: // Node used by the adlc to construct inputs to represent temporary registers duke@435: class MachTempNode : public MachNode { duke@435: private: duke@435: MachOper *_opnd_array[1]; duke@435: duke@435: public: duke@435: virtual const RegMask &out_RegMask() const { return *_opnds[0]->in_RegMask(0); } duke@435: virtual uint rule() const { return 9999999; } duke@435: virtual void emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {} duke@435: duke@435: MachTempNode(MachOper* oper) { duke@435: init_class_id(Class_MachTemp); duke@435: _num_opnds = 1; duke@435: _opnds = _opnd_array; duke@435: add_req(NULL); duke@435: _opnds[0] = oper; duke@435: } duke@435: virtual uint size_of() const { return sizeof(MachTempNode); } duke@435: duke@435: #ifndef PRODUCT duke@435: virtual void format(PhaseRegAlloc *, outputStream *st ) const {} duke@435: virtual const char *Name() const { return "MachTemp";} duke@435: #endif duke@435: }; duke@435: duke@435: duke@435: duke@435: //------------------------------labelOper-------------------------------------- duke@435: // Machine-independent version of label operand duke@435: class labelOper : public MachOper { duke@435: private: duke@435: virtual uint num_edges() const { return 0; } duke@435: public: duke@435: // Supported for fixed size branches duke@435: Label* _label; // Label for branch(es) duke@435: duke@435: uint _block_num; duke@435: duke@435: labelOper() : _block_num(0), _label(0) {} duke@435: duke@435: labelOper(Label* label, uint block_num) : _label(label), _block_num(block_num) {} duke@435: duke@435: labelOper(labelOper* l) : _label(l->_label) , _block_num(l->_block_num) {} duke@435: duke@435: virtual MachOper *clone(Compile* C) const; duke@435: duke@435: virtual Label *label() const { return _label; } duke@435: duke@435: virtual uint opcode() const; duke@435: duke@435: virtual uint hash() const; duke@435: virtual uint cmp( const MachOper &oper ) const; duke@435: #ifndef PRODUCT duke@435: virtual const char *Name() const { return "Label";} duke@435: duke@435: virtual void int_format(PhaseRegAlloc *ra, const MachNode *node, outputStream *st) const; duke@435: virtual void ext_format(PhaseRegAlloc *ra, const MachNode *node, int idx, outputStream *st) const { int_format( ra, node, st ); } duke@435: #endif duke@435: }; duke@435: duke@435: duke@435: //------------------------------methodOper-------------------------------------- duke@435: // Machine-independent version of method operand duke@435: class methodOper : public MachOper { duke@435: private: duke@435: virtual uint num_edges() const { return 0; } duke@435: public: duke@435: intptr_t _method; // Address of method duke@435: methodOper() : _method(0) {} duke@435: methodOper(intptr_t method) : _method(method) {} duke@435: duke@435: virtual MachOper *clone(Compile* C) const; duke@435: duke@435: virtual intptr_t method() const { return _method; } duke@435: duke@435: virtual uint opcode() const; duke@435: duke@435: virtual uint hash() const; duke@435: virtual uint cmp( const MachOper &oper ) const; duke@435: #ifndef PRODUCT duke@435: virtual const char *Name() const { return "Method";} duke@435: duke@435: virtual void int_format(PhaseRegAlloc *ra, const MachNode *node, outputStream *st) const; duke@435: virtual void ext_format(PhaseRegAlloc *ra, const MachNode *node, int idx, outputStream *st) const { int_format( ra, node, st ); } duke@435: #endif duke@435: };