Fri, 07 Nov 2008 09:29:38 -0800
6462850: generate biased locking code in C2 ideal graph
Summary: Inline biased locking code in C2 ideal graph during macro nodes expansion
Reviewed-by: never
duke@435 | 1 | // |
duke@435 | 2 | // Copyright 1999-2006 Sun Microsystems, Inc. All Rights Reserved. |
duke@435 | 3 | // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
duke@435 | 4 | // |
duke@435 | 5 | // This code is free software; you can redistribute it and/or modify it |
duke@435 | 6 | // under the terms of the GNU General Public License version 2 only, as |
duke@435 | 7 | // published by the Free Software Foundation. |
duke@435 | 8 | // |
duke@435 | 9 | // This code is distributed in the hope that it will be useful, but WITHOUT |
duke@435 | 10 | // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
duke@435 | 11 | // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
duke@435 | 12 | // version 2 for more details (a copy is included in the LICENSE file that |
duke@435 | 13 | // accompanied this code). |
duke@435 | 14 | // |
duke@435 | 15 | // You should have received a copy of the GNU General Public License version |
duke@435 | 16 | // 2 along with this work; if not, write to the Free Software Foundation, |
duke@435 | 17 | // Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
duke@435 | 18 | // |
duke@435 | 19 | // Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
duke@435 | 20 | // CA 95054 USA or visit www.sun.com if you need additional information or |
duke@435 | 21 | // have any questions. |
duke@435 | 22 | // |
duke@435 | 23 | // |
duke@435 | 24 | |
duke@435 | 25 | // X86 Linux Architecture Description File |
duke@435 | 26 | |
duke@435 | 27 | //----------OS-DEPENDENT ENCODING BLOCK----------------------------------------------------- |
duke@435 | 28 | // This block specifies the encoding classes used by the compiler to output |
duke@435 | 29 | // byte streams. Encoding classes generate functions which are called by |
duke@435 | 30 | // Machine Instruction Nodes in order to generate the bit encoding of the |
duke@435 | 31 | // instruction. Operands specify their base encoding interface with the |
duke@435 | 32 | // interface keyword. There are currently supported four interfaces, |
duke@435 | 33 | // REG_INTER, CONST_INTER, MEMORY_INTER, & COND_INTER. REG_INTER causes an |
duke@435 | 34 | // operand to generate a function which returns its register number when |
duke@435 | 35 | // queried. CONST_INTER causes an operand to generate a function which |
duke@435 | 36 | // returns the value of the constant when queried. MEMORY_INTER causes an |
duke@435 | 37 | // operand to generate four functions which return the Base Register, the |
duke@435 | 38 | // Index Register, the Scale Value, and the Offset Value of the operand when |
duke@435 | 39 | // queried. COND_INTER causes an operand to generate six functions which |
duke@435 | 40 | // return the encoding code (ie - encoding bits for the instruction) |
duke@435 | 41 | // associated with each basic boolean condition for a conditional instruction. |
duke@435 | 42 | // Instructions specify two basic values for encoding. They use the |
duke@435 | 43 | // ins_encode keyword to specify their encoding class (which must be one of |
duke@435 | 44 | // the class names specified in the encoding block), and they use the |
duke@435 | 45 | // opcode keyword to specify, in order, their primary, secondary, and |
duke@435 | 46 | // tertiary opcode. Only the opcode sections which a particular instruction |
duke@435 | 47 | // needs for encoding need to be specified. |
duke@435 | 48 | encode %{ |
duke@435 | 49 | // Build emit functions for each basic byte or larger field in the intel |
duke@435 | 50 | // encoding scheme (opcode, rm, sib, immediate), and call them from C++ |
duke@435 | 51 | // code in the enc_class source block. Emit functions will live in the |
duke@435 | 52 | // main source block for now. In future, we can generalize this by |
duke@435 | 53 | // adding a syntax that specifies the sizes of fields in an order, |
duke@435 | 54 | // so that the adlc can build the emit functions automagically |
duke@435 | 55 | |
duke@435 | 56 | enc_class linux_tlsencode (eRegP dst) %{ |
duke@435 | 57 | Register dstReg = as_Register($dst$$reg); |
duke@435 | 58 | MacroAssembler* masm = new MacroAssembler(&cbuf); |
duke@435 | 59 | masm->get_thread(dstReg); |
duke@435 | 60 | %} |
duke@435 | 61 | |
duke@435 | 62 | enc_class linux_breakpoint %{ |
duke@435 | 63 | MacroAssembler* masm = new MacroAssembler(&cbuf); |
duke@435 | 64 | masm->call(RuntimeAddress(CAST_FROM_FN_PTR(address, os::breakpoint))); |
duke@435 | 65 | %} |
duke@435 | 66 | |
duke@435 | 67 | enc_class call_epilog %{ |
duke@435 | 68 | if( VerifyStackAtCalls ) { |
duke@435 | 69 | // Check that stack depth is unchanged: find majik cookie on stack |
duke@435 | 70 | int framesize = ra_->reg2offset_unchecked(OptoReg::add(ra_->_matcher._old_SP,-3*VMRegImpl::slots_per_word)); |
duke@435 | 71 | if(framesize >= 128) { |
duke@435 | 72 | emit_opcode(cbuf, 0x81); // cmp [esp+0],0xbadb1ood |
duke@435 | 73 | emit_d8(cbuf,0xBC); |
duke@435 | 74 | emit_d8(cbuf,0x24); |
duke@435 | 75 | emit_d32(cbuf,framesize); // Find majik cookie from ESP |
duke@435 | 76 | emit_d32(cbuf, 0xbadb100d); |
duke@435 | 77 | } |
duke@435 | 78 | else { |
duke@435 | 79 | emit_opcode(cbuf, 0x81); // cmp [esp+0],0xbadb1ood |
duke@435 | 80 | emit_d8(cbuf,0x7C); |
duke@435 | 81 | emit_d8(cbuf,0x24); |
duke@435 | 82 | emit_d8(cbuf,framesize); // Find majik cookie from ESP |
duke@435 | 83 | emit_d32(cbuf, 0xbadb100d); |
duke@435 | 84 | } |
duke@435 | 85 | // jmp EQ around INT3 |
duke@435 | 86 | // QQQ TODO |
duke@435 | 87 | const int jump_around = 5; // size of call to breakpoint, 1 for CC |
duke@435 | 88 | emit_opcode(cbuf,0x74); |
duke@435 | 89 | emit_d8(cbuf, jump_around); |
duke@435 | 90 | // QQQ temporary |
duke@435 | 91 | emit_break(cbuf); |
duke@435 | 92 | // Die if stack mismatch |
duke@435 | 93 | // emit_opcode(cbuf,0xCC); |
duke@435 | 94 | } |
duke@435 | 95 | %} |
duke@435 | 96 | |
duke@435 | 97 | %} |
duke@435 | 98 | |
duke@435 | 99 | // INSTRUCTIONS -- Platform dependent |
duke@435 | 100 | |
duke@435 | 101 | //----------OS and Locking Instructions---------------------------------------- |
duke@435 | 102 | |
duke@435 | 103 | // This name is KNOWN by the ADLC and cannot be changed. |
duke@435 | 104 | // The ADLC forces a 'TypeRawPtr::BOTTOM' output type |
duke@435 | 105 | // for this guy. |
kvn@855 | 106 | instruct tlsLoadP(eRegP dst, eFlagsReg cr) %{ |
duke@435 | 107 | match(Set dst (ThreadLocal)); |
duke@435 | 108 | effect(DEF dst, KILL cr); |
duke@435 | 109 | |
kvn@855 | 110 | format %{ "MOV $dst, Thread::current()" %} |
duke@435 | 111 | ins_encode( linux_tlsencode(dst) ); |
duke@435 | 112 | ins_pipe( ialu_reg_fat ); |
duke@435 | 113 | %} |
duke@435 | 114 | |
kvn@855 | 115 | instruct TLS(eRegP dst) %{ |
duke@435 | 116 | match(Set dst (ThreadLocal)); |
duke@435 | 117 | |
duke@435 | 118 | expand %{ |
duke@435 | 119 | tlsLoadP(dst); |
duke@435 | 120 | %} |
duke@435 | 121 | %} |
duke@435 | 122 | |
duke@435 | 123 | // Die now |
duke@435 | 124 | instruct ShouldNotReachHere( ) |
duke@435 | 125 | %{ |
duke@435 | 126 | match(Halt); |
duke@435 | 127 | |
duke@435 | 128 | // Use the following format syntax |
duke@435 | 129 | format %{ "INT3 ; ShouldNotReachHere" %} |
duke@435 | 130 | // QQQ TODO for now call breakpoint |
duke@435 | 131 | // opcode(0xCC); |
duke@435 | 132 | // ins_encode(Opc); |
duke@435 | 133 | ins_encode(linux_breakpoint); |
duke@435 | 134 | ins_pipe( pipe_slow ); |
duke@435 | 135 | %} |
duke@435 | 136 | |
duke@435 | 137 | |
duke@435 | 138 | |
duke@435 | 139 | // Platform dependent source |
duke@435 | 140 | |
duke@435 | 141 | source %{ |
duke@435 | 142 | |
duke@435 | 143 | // emit an interrupt that is caught by the debugger |
duke@435 | 144 | void emit_break(CodeBuffer &cbuf) { |
duke@435 | 145 | |
duke@435 | 146 | // Debugger doesn't really catch this but best we can do so far QQQ |
duke@435 | 147 | MacroAssembler* masm = new MacroAssembler(&cbuf); |
duke@435 | 148 | masm->call(RuntimeAddress(CAST_FROM_FN_PTR(address, os::breakpoint))); |
duke@435 | 149 | } |
duke@435 | 150 | |
duke@435 | 151 | void MachBreakpointNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { |
duke@435 | 152 | emit_break(cbuf); |
duke@435 | 153 | } |
duke@435 | 154 | |
duke@435 | 155 | |
duke@435 | 156 | uint MachBreakpointNode::size(PhaseRegAlloc *ra_) const { |
duke@435 | 157 | return 5; |
duke@435 | 158 | } |
duke@435 | 159 | |
duke@435 | 160 | %} |