--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPool.java Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPool.java Wed Dec 08 17:50:49 2010 -0800
@@ -60,10 +60,7 @@
headerSize = type.getSize();
elementSize = 0;
// fetch constants:
- MULTI_OPERAND_COUNT_OFFSET = db.lookupIntConstant("constantPoolOopDesc::_multi_operand_count_offset").intValue();
- MULTI_OPERAND_BASE_OFFSET = db.lookupIntConstant("constantPoolOopDesc::_multi_operand_base_offset").intValue();
INDY_BSM_OFFSET = db.lookupIntConstant("constantPoolOopDesc::_indy_bsm_offset").intValue();
- INDY_NT_OFFSET = db.lookupIntConstant("constantPoolOopDesc::_indy_nt_offset").intValue();
INDY_ARGC_OFFSET = db.lookupIntConstant("constantPoolOopDesc::_indy_argc_offset").intValue();
INDY_ARGV_OFFSET = db.lookupIntConstant("constantPoolOopDesc::_indy_argv_offset").intValue();
}
@@ -83,10 +80,7 @@
private static long headerSize;
private static long elementSize;
- private static int MULTI_OPERAND_COUNT_OFFSET;
- private static int MULTI_OPERAND_BASE_OFFSET;
private static int INDY_BSM_OFFSET;
- private static int INDY_NT_OFFSET;
private static int INDY_ARGC_OFFSET;
private static int INDY_ARGV_OFFSET;
@@ -296,20 +290,23 @@
}
/** Lookup for multi-operand (InvokeDynamic) entries. */
- public int[] getMultiOperandsAt(int i) {
+ public short[] getBootstrapSpecifierAt(int i) {
if (Assert.ASSERTS_ENABLED) {
Assert.that(getTagAt(i).isInvokeDynamic(), "Corrupted constant pool");
}
- int pos = this.getIntAt(i);
- int countPos = pos + MULTI_OPERAND_COUNT_OFFSET; // == pos-1
- int basePos = pos + MULTI_OPERAND_BASE_OFFSET; // == pos
- if (countPos < 0) return null; // safety first
+ if (getTagAt(i).value() == JVM_CONSTANT_InvokeDynamicTrans)
+ return null;
+ int bsmSpec = extractLowShortFromInt(this.getIntAt(i));
TypeArray operands = getOperands();
if (operands == null) return null; // safety first
- int length = operands.getIntAt(countPos);
- int[] values = new int[length];
- for (int j = 0; j < length; j++) {
- values[j] = operands.getIntAt(basePos+j);
+ int basePos = VM.getVM().buildIntFromShorts(operands.getShortAt(bsmSpec * 2 + 0),
+ operands.getShortAt(bsmSpec * 2 + 1));
+ int argv = basePos + INDY_ARGV_OFFSET;
+ int argc = operands.getShortAt(basePos + INDY_ARGC_OFFSET);
+ int endPos = argv + argc;
+ short[] values = new short[endPos - basePos];
+ for (int j = 0; j < values.length; j++) {
+ values[j] = operands.getShortAt(basePos+j);
}
return values;
}
@@ -334,6 +331,7 @@
case JVM_CONSTANT_MethodHandle: return "JVM_CONSTANT_MethodHandle";
case JVM_CONSTANT_MethodType: return "JVM_CONSTANT_MethodType";
case JVM_CONSTANT_InvokeDynamic: return "JVM_CONSTANT_InvokeDynamic";
+ case JVM_CONSTANT_InvokeDynamicTrans: return "JVM_CONSTANT_InvokeDynamic/transitional";
case JVM_CONSTANT_Invalid: return "JVM_CONSTANT_Invalid";
case JVM_CONSTANT_UnresolvedClass: return "JVM_CONSTANT_UnresolvedClass";
case JVM_CONSTANT_UnresolvedClassInError: return "JVM_CONSTANT_UnresolvedClassInError";
@@ -393,6 +391,7 @@
case JVM_CONSTANT_MethodHandle:
case JVM_CONSTANT_MethodType:
case JVM_CONSTANT_InvokeDynamic:
+ case JVM_CONSTANT_InvokeDynamicTrans:
visitor.doInt(new IntField(new NamedFieldIdentifier(nameForTag(ctag)), indexOffset(index), true), true);
break;
}
@@ -556,19 +555,16 @@
break;
}
+ case JVM_CONSTANT_InvokeDynamicTrans:
case JVM_CONSTANT_InvokeDynamic: {
dos.writeByte(cpConstType);
- int[] values = getMultiOperandsAt(ci);
- for (int vn = 0; vn < values.length; vn++) {
- dos.writeShort(values[vn]);
- }
- int bootstrapMethodIndex = values[INDY_BSM_OFFSET];
- int nameAndTypeIndex = values[INDY_NT_OFFSET];
- int argumentCount = values[INDY_ARGC_OFFSET];
- assert(INDY_ARGV_OFFSET + argumentCount == values.length);
- if (DEBUG) debugMessage("CP[" + ci + "] = indy BSM = " + bootstrapMethodIndex
- + ", N&T = " + nameAndTypeIndex
- + ", argc = " + argumentCount);
+ int value = getIntAt(ci);
+ short bsmIndex = (short) extractLowShortFromInt(value);
+ short nameAndTypeIndex = (short) extractHighShortFromInt(value);
+ dos.writeShort(bsmIndex);
+ dos.writeShort(nameAndTypeIndex);
+ if (DEBUG) debugMessage("CP[" + ci + "] = indy BSM = " + bsmIndex
+ + ", N&T = " + nameAndTypeIndex);
break;
}
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/jcore/ClassWriter.java Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/jcore/ClassWriter.java Wed Dec 08 17:50:49 2010 -0800
@@ -321,13 +321,16 @@
break;
}
+ case JVM_CONSTANT_InvokeDynamicTrans:
case JVM_CONSTANT_InvokeDynamic: {
dos.writeByte(cpConstType);
- int[] values = cpool.getMultiOperandsAt(ci);
- for (int vn = 0; vn < values.length; vn++) {
- dos.writeShort(values[vn]);
- }
- if (DEBUG) debugMessage("CP[" + ci + "] = INDY indexes = " + Arrays.toString(values));
+ int value = cpool.getIntAt(ci);
+ short bsmIndex = (short) extractLowShortFromInt(value);
+ short nameAndTypeIndex = (short) extractHighShortFromInt(value);
+ dos.writeShort(bsmIndex);
+ dos.writeShort(nameAndTypeIndex);
+ if (DEBUG) debugMessage("CP[" + ci + "] = INDY bsm = " +
+ bsmIndex + ", N&T = " + nameAndTypeIndex);
break;
}
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java Wed Dec 08 17:50:49 2010 -0800
@@ -460,7 +460,8 @@
return buf.toString();
}
- private String genListOfShort(int[] values) {
+ private String genListOfShort(short[] values) {
+ if (values == null || values.length == 0) return "";
Formatter buf = new Formatter(genHTML);
buf.append('[');
for (int i = 0; i < values.length; i++) {
@@ -594,9 +595,11 @@
buf.cell(Integer.toString(cpool.getIntAt(index)));
break;
+ case JVM_CONSTANT_InvokeDynamicTrans:
case JVM_CONSTANT_InvokeDynamic:
buf.cell("JVM_CONSTANT_InvokeDynamic");
- buf.cell(genListOfShort(cpool.getMultiOperandsAt(index)));
+ buf.cell(genLowHighShort(cpool.getIntAt(index)) +
+ genListOfShort(cpool.getBootstrapSpecifierAt(index)));
break;
default:
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/ConstantTag.java Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/ConstantTag.java Wed Dec 08 17:50:49 2010 -0800
@@ -40,7 +40,7 @@
private static int JVM_CONSTANT_NameAndType = 12;
private static int JVM_CONSTANT_MethodHandle = 15; // JSR 292
private static int JVM_CONSTANT_MethodType = 16; // JSR 292
- // static int JVM_CONSTANT_InvokeDynamicTrans = 17; // JSR 292, only occurs in old class files
+ private static int JVM_CONSTANT_InvokeDynamicTrans = 17; // JSR 292, only occurs in old class files
private static int JVM_CONSTANT_InvokeDynamic = 18; // JSR 292
private static int JVM_CONSTANT_Invalid = 0; // For bad value initialization
private static int JVM_CONSTANT_UnresolvedClass = 100; // Temporary tag until actual use
@@ -67,6 +67,8 @@
this.tag = tag;
}
+ public int value() { return tag; }
+
public boolean isKlass() { return tag == JVM_CONSTANT_Class; }
public boolean isField () { return tag == JVM_CONSTANT_Fieldref; }
public boolean isMethod() { return tag == JVM_CONSTANT_Methodref; }
@@ -81,6 +83,7 @@
public boolean isMethodHandle() { return tag == JVM_CONSTANT_MethodHandle; }
public boolean isMethodType() { return tag == JVM_CONSTANT_MethodType; }
public boolean isInvokeDynamic() { return tag == JVM_CONSTANT_InvokeDynamic; }
+ public boolean isInvokeDynamicTrans() { return tag == JVM_CONSTANT_InvokeDynamicTrans; }
public boolean isInvalid() { return tag == JVM_CONSTANT_Invalid; }
--- a/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp Wed Dec 08 17:50:49 2010 -0800
@@ -909,10 +909,10 @@
#if defined(COMPILER2) && !defined(_LP64)
// Save & restore possible 64-bit Long arguments in G-regs
sllx(L0,32,G2); // Move old high G1 bits high in G2
- sllx(G1, 0,G1); // Clear current high G1 bits
+ srl(G1, 0,G1); // Clear current high G1 bits
or3 (G1,G2,G1); // Recover 64-bit G1
sllx(L6,32,G2); // Move old high G4 bits high in G2
- sllx(G4, 0,G4); // Clear current high G4 bits
+ srl(G4, 0,G4); // Clear current high G4 bits
or3 (G4,G2,G4); // Recover 64-bit G4
#endif
restore(O0, 0, G2_thread);
@@ -1443,6 +1443,45 @@
}
}
+int MacroAssembler::size_of_set64(jlong value) {
+ v9_dep();
+
+ int hi = (int)(value >> 32);
+ int lo = (int)(value & ~0);
+ int count = 0;
+
+ // (Matcher::isSimpleConstant64 knows about the following optimizations.)
+ if (Assembler::is_simm13(lo) && value == lo) {
+ count++;
+ } else if (hi == 0) {
+ count++;
+ if (low10(lo) != 0)
+ count++;
+ }
+ else if (hi == -1) {
+ count += 2;
+ }
+ else if (lo == 0) {
+ if (Assembler::is_simm13(hi)) {
+ count++;
+ } else {
+ count++;
+ if (low10(hi) != 0)
+ count++;
+ }
+ count++;
+ }
+ else {
+ count += 2;
+ if (low10(hi) != 0)
+ count++;
+ if (low10(lo) != 0)
+ count++;
+ count += 2;
+ }
+ return count;
+}
+
// compute size in bytes of sparc frame, given
// number of extraWords
int MacroAssembler::total_frame_size_in_bytes(int extraWords) {
--- a/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp Wed Dec 08 17:50:49 2010 -0800
@@ -1621,6 +1621,10 @@
void sub( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(sub_op3 ) | rs1(s1) | rs2(s2) ); }
void sub( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(sub_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
+
+ // Note: offset is added to s2.
+ inline void sub(Register s1, RegisterOrConstant s2, Register d, int offset = 0);
+
void subcc( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(sub_op3 | cc_bit_op3 ) | rs1(s1) | rs2(s2) ); }
void subcc( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(sub_op3 | cc_bit_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
void subc( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(subc_op3 ) | rs1(s1) | rs2(s2) ); }
@@ -1798,6 +1802,7 @@
// branches that use right instruction for v8 vs. v9
inline void br( Condition c, bool a, Predict p, address d, relocInfo::relocType rt = relocInfo::none );
inline void br( Condition c, bool a, Predict p, Label& L );
+
inline void fb( Condition c, bool a, Predict p, address d, relocInfo::relocType rt = relocInfo::none );
inline void fb( Condition c, bool a, Predict p, Label& L );
@@ -1894,6 +1899,9 @@
void patchable_set(intptr_t value, Register d);
void set64(jlong value, Register d, Register tmp);
+ // Compute size of set64.
+ static int size_of_set64(jlong value);
+
// sign-extend 32 to 64
inline void signx( Register s, Register d ) { sra( s, G0, d); }
inline void signx( Register d ) { sra( d, G0, d); }
--- a/hotspot/src/cpu/sparc/vm/assembler_sparc.inline.hpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.inline.hpp Wed Dec 08 17:50:49 2010 -0800
@@ -328,6 +328,11 @@
inline void Assembler::stdcq( int crd, Register s1, Register s2) { v8_only(); emit_long( op(ldst_op) | fcn(crd) | op3(stdcq_op3) | rs1(s1) | rs2(s2) ); }
inline void Assembler::stdcq( int crd, Register s1, int simm13a) { v8_only(); emit_data( op(ldst_op) | fcn(crd) | op3(stdcq_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); }
+inline void Assembler::sub(Register s1, RegisterOrConstant s2, Register d, int offset) {
+ if (s2.is_register()) sub(s1, s2.as_register(), d);
+ else { sub(s1, s2.as_constant() + offset, d); offset = 0; }
+ if (offset != 0) sub(d, offset, d);
+}
// pp 231
--- a/hotspot/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp Wed Dec 08 17:50:49 2010 -0800
@@ -434,7 +434,7 @@
Register pre_val_reg = pre_val()->as_register();
- ce->mem2reg(addr(), pre_val(), T_OBJECT, patch_code(), info(), false);
+ ce->mem2reg(addr(), pre_val(), T_OBJECT, patch_code(), info(), false /*wide*/, false /*unaligned*/);
if (__ is_in_wdisp16_range(_continuation)) {
__ br_on_reg_cond(Assembler::rc_z, /*annul*/false, Assembler::pt,
pre_val_reg, _continuation);
--- a/hotspot/src/cpu/sparc/vm/c1_FrameMap_sparc.hpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/cpu/sparc/vm/c1_FrameMap_sparc.hpp Wed Dec 08 17:50:49 2010 -0800
@@ -155,4 +155,7 @@
static bool is_caller_save_register (LIR_Opr reg);
static bool is_caller_save_register (Register r);
+ static int nof_caller_save_cpu_regs() { return pd_nof_caller_save_cpu_regs_frame_map; }
+ static int last_cpu_reg() { return pd_last_cpu_reg; }
+
#endif // CPU_SPARC_VM_C1_FRAMEMAP_SPARC_HPP
--- a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp Wed Dec 08 17:50:49 2010 -0800
@@ -100,6 +100,11 @@
return false;
}
+ if (UseCompressedOops) {
+ if (dst->is_address() && !dst->is_stack() && (dst->type() == T_OBJECT || dst->type() == T_ARRAY)) return false;
+ if (src->is_address() && !src->is_stack() && (src->type() == T_OBJECT || src->type() == T_ARRAY)) return false;
+ }
+
if (dst->is_register()) {
if (src->is_address() && Assembler::is_simm13(src->as_address_ptr()->disp())) {
return !PatchALot;
@@ -253,7 +258,7 @@
int offset_offset = java_lang_String::offset_offset_in_bytes(); // first character position
int count_offset = java_lang_String:: count_offset_in_bytes();
- __ ld_ptr(str0, value_offset, tmp0);
+ __ load_heap_oop(str0, value_offset, tmp0);
__ ld(str0, offset_offset, tmp2);
__ add(tmp0, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp0);
__ ld(str0, count_offset, str0);
@@ -262,7 +267,7 @@
// str1 may be null
add_debug_info_for_null_check_here(info);
- __ ld_ptr(str1, value_offset, tmp1);
+ __ load_heap_oop(str1, value_offset, tmp1);
__ add(tmp0, tmp2, tmp0);
__ ld(str1, offset_offset, tmp2);
@@ -766,7 +771,7 @@
void LIR_Assembler::vtable_call(LIR_OpJavaCall* op) {
add_debug_info_for_null_check_here(op->info());
- __ ld_ptr(O0, oopDesc::klass_offset_in_bytes(), G3_scratch);
+ __ load_klass(O0, G3_scratch);
if (__ is_simm13(op->vtable_offset())) {
__ ld_ptr(G3_scratch, op->vtable_offset(), G5_method);
} else {
@@ -780,138 +785,17 @@
// the peephole pass fills the delay slot
}
-
-// load with 32-bit displacement
-int LIR_Assembler::load(Register s, int disp, Register d, BasicType ld_type, CodeEmitInfo *info) {
- int load_offset = code_offset();
- if (Assembler::is_simm13(disp)) {
- if (info != NULL) add_debug_info_for_null_check_here(info);
- switch(ld_type) {
- case T_BOOLEAN: // fall through
- case T_BYTE : __ ldsb(s, disp, d); break;
- case T_CHAR : __ lduh(s, disp, d); break;
- case T_SHORT : __ ldsh(s, disp, d); break;
- case T_INT : __ ld(s, disp, d); break;
- case T_ADDRESS:// fall through
- case T_ARRAY : // fall through
- case T_OBJECT: __ ld_ptr(s, disp, d); break;
- default : ShouldNotReachHere();
- }
- } else {
- __ set(disp, O7);
- if (info != NULL) add_debug_info_for_null_check_here(info);
- load_offset = code_offset();
- switch(ld_type) {
- case T_BOOLEAN: // fall through
- case T_BYTE : __ ldsb(s, O7, d); break;
- case T_CHAR : __ lduh(s, O7, d); break;
- case T_SHORT : __ ldsh(s, O7, d); break;
- case T_INT : __ ld(s, O7, d); break;
- case T_ADDRESS:// fall through
- case T_ARRAY : // fall through
- case T_OBJECT: __ ld_ptr(s, O7, d); break;
- default : ShouldNotReachHere();
- }
- }
- if (ld_type == T_ARRAY || ld_type == T_OBJECT) __ verify_oop(d);
- return load_offset;
-}
-
-
-// store with 32-bit displacement
-void LIR_Assembler::store(Register value, Register base, int offset, BasicType type, CodeEmitInfo *info) {
- if (Assembler::is_simm13(offset)) {
- if (info != NULL) add_debug_info_for_null_check_here(info);
- switch (type) {
- case T_BOOLEAN: // fall through
- case T_BYTE : __ stb(value, base, offset); break;
- case T_CHAR : __ sth(value, base, offset); break;
- case T_SHORT : __ sth(value, base, offset); break;
- case T_INT : __ stw(value, base, offset); break;
- case T_ADDRESS:// fall through
- case T_ARRAY : // fall through
- case T_OBJECT: __ st_ptr(value, base, offset); break;
- default : ShouldNotReachHere();
- }
- } else {
- __ set(offset, O7);
- if (info != NULL) add_debug_info_for_null_check_here(info);
- switch (type) {
- case T_BOOLEAN: // fall through
- case T_BYTE : __ stb(value, base, O7); break;
- case T_CHAR : __ sth(value, base, O7); break;
- case T_SHORT : __ sth(value, base, O7); break;
- case T_INT : __ stw(value, base, O7); break;
- case T_ADDRESS:// fall through
- case T_ARRAY : //fall through
- case T_OBJECT: __ st_ptr(value, base, O7); break;
- default : ShouldNotReachHere();
- }
- }
- // Note: Do the store before verification as the code might be patched!
- if (type == T_ARRAY || type == T_OBJECT) __ verify_oop(value);
-}
-
-
-// load float with 32-bit displacement
-void LIR_Assembler::load(Register s, int disp, FloatRegister d, BasicType ld_type, CodeEmitInfo *info) {
- FloatRegisterImpl::Width w;
- switch(ld_type) {
- case T_FLOAT : w = FloatRegisterImpl::S; break;
- case T_DOUBLE: w = FloatRegisterImpl::D; break;
- default : ShouldNotReachHere();
- }
-
- if (Assembler::is_simm13(disp)) {
- if (info != NULL) add_debug_info_for_null_check_here(info);
- if (disp % BytesPerLong != 0 && w == FloatRegisterImpl::D) {
- __ ldf(FloatRegisterImpl::S, s, disp + BytesPerWord, d->successor());
- __ ldf(FloatRegisterImpl::S, s, disp , d);
- } else {
- __ ldf(w, s, disp, d);
- }
- } else {
- __ set(disp, O7);
- if (info != NULL) add_debug_info_for_null_check_here(info);
- __ ldf(w, s, O7, d);
- }
-}
-
-
-// store float with 32-bit displacement
-void LIR_Assembler::store(FloatRegister value, Register base, int offset, BasicType type, CodeEmitInfo *info) {
- FloatRegisterImpl::Width w;
- switch(type) {
- case T_FLOAT : w = FloatRegisterImpl::S; break;
- case T_DOUBLE: w = FloatRegisterImpl::D; break;
- default : ShouldNotReachHere();
- }
-
- if (Assembler::is_simm13(offset)) {
- if (info != NULL) add_debug_info_for_null_check_here(info);
- if (w == FloatRegisterImpl::D && offset % BytesPerLong != 0) {
- __ stf(FloatRegisterImpl::S, value->successor(), base, offset + BytesPerWord);
- __ stf(FloatRegisterImpl::S, value , base, offset);
- } else {
- __ stf(w, value, base, offset);
- }
- } else {
- __ set(offset, O7);
- if (info != NULL) add_debug_info_for_null_check_here(info);
- __ stf(w, value, O7, base);
- }
-}
-
-
-int LIR_Assembler::store(LIR_Opr from_reg, Register base, int offset, BasicType type, bool unaligned) {
+int LIR_Assembler::store(LIR_Opr from_reg, Register base, int offset, BasicType type, bool wide, bool unaligned) {
int store_offset;
if (!Assembler::is_simm13(offset + (type == T_LONG) ? wordSize : 0)) {
assert(!unaligned, "can't handle this");
// for offsets larger than a simm13 we setup the offset in O7
__ set(offset, O7);
- store_offset = store(from_reg, base, O7, type);
+ store_offset = store(from_reg, base, O7, type, wide);
} else {
- if (type == T_ARRAY || type == T_OBJECT) __ verify_oop(from_reg->as_register());
+ if (type == T_ARRAY || type == T_OBJECT) {
+ __ verify_oop(from_reg->as_register());
+ }
store_offset = code_offset();
switch (type) {
case T_BOOLEAN: // fall through
@@ -934,9 +818,22 @@
__ stw(from_reg->as_register_hi(), base, offset + hi_word_offset_in_bytes);
#endif
break;
- case T_ADDRESS:// fall through
+ case T_ADDRESS:
+ __ st_ptr(from_reg->as_register(), base, offset);
+ break;
case T_ARRAY : // fall through
- case T_OBJECT: __ st_ptr(from_reg->as_register(), base, offset); break;
+ case T_OBJECT:
+ {
+ if (UseCompressedOops && !wide) {
+ __ encode_heap_oop(from_reg->as_register(), G3_scratch);
+ store_offset = code_offset();
+ __ stw(G3_scratch, base, offset);
+ } else {
+ __ st_ptr(from_reg->as_register(), base, offset);
+ }
+ break;
+ }
+
case T_FLOAT : __ stf(FloatRegisterImpl::S, from_reg->as_float_reg(), base, offset); break;
case T_DOUBLE:
{
@@ -958,8 +855,10 @@
}
-int LIR_Assembler::store(LIR_Opr from_reg, Register base, Register disp, BasicType type) {
- if (type == T_ARRAY || type == T_OBJECT) __ verify_oop(from_reg->as_register());
+int LIR_Assembler::store(LIR_Opr from_reg, Register base, Register disp, BasicType type, bool wide) {
+ if (type == T_ARRAY || type == T_OBJECT) {
+ __ verify_oop(from_reg->as_register());
+ }
int store_offset = code_offset();
switch (type) {
case T_BOOLEAN: // fall through
@@ -975,9 +874,21 @@
__ std(from_reg->as_register_hi(), base, disp);
#endif
break;
- case T_ADDRESS:// fall through
+ case T_ADDRESS:
+ __ st_ptr(from_reg->as_register(), base, disp);
+ break;
case T_ARRAY : // fall through
- case T_OBJECT: __ st_ptr(from_reg->as_register(), base, disp); break;
+ case T_OBJECT:
+ {
+ if (UseCompressedOops && !wide) {
+ __ encode_heap_oop(from_reg->as_register(), G3_scratch);
+ store_offset = code_offset();
+ __ stw(G3_scratch, base, disp);
+ } else {
+ __ st_ptr(from_reg->as_register(), base, disp);
+ }
+ break;
+ }
case T_FLOAT : __ stf(FloatRegisterImpl::S, from_reg->as_float_reg(), base, disp); break;
case T_DOUBLE: __ stf(FloatRegisterImpl::D, from_reg->as_double_reg(), base, disp); break;
default : ShouldNotReachHere();
@@ -986,14 +897,14 @@
}
-int LIR_Assembler::load(Register base, int offset, LIR_Opr to_reg, BasicType type, bool unaligned) {
+int LIR_Assembler::load(Register base, int offset, LIR_Opr to_reg, BasicType type, bool wide, bool unaligned) {
int load_offset;
if (!Assembler::is_simm13(offset + (type == T_LONG) ? wordSize : 0)) {
assert(base != O7, "destroying register");
assert(!unaligned, "can't handle this");
// for offsets larger than a simm13 we setup the offset in O7
__ set(offset, O7);
- load_offset = load(base, O7, to_reg, type);
+ load_offset = load(base, O7, to_reg, type, wide);
} else {
load_offset = code_offset();
switch(type) {
@@ -1030,9 +941,18 @@
#endif
}
break;
- case T_ADDRESS:// fall through
+ case T_ADDRESS: __ ld_ptr(base, offset, to_reg->as_register()); break;
case T_ARRAY : // fall through
- case T_OBJECT: __ ld_ptr(base, offset, to_reg->as_register()); break;
+ case T_OBJECT:
+ {
+ if (UseCompressedOops && !wide) {
+ __ lduw(base, offset, to_reg->as_register());
+ __ decode_heap_oop(to_reg->as_register());
+ } else {
+ __ ld_ptr(base, offset, to_reg->as_register());
+ }
+ break;
+ }
case T_FLOAT: __ ldf(FloatRegisterImpl::S, base, offset, to_reg->as_float_reg()); break;
case T_DOUBLE:
{
@@ -1048,23 +968,34 @@
}
default : ShouldNotReachHere();
}
- if (type == T_ARRAY || type == T_OBJECT) __ verify_oop(to_reg->as_register());
+ if (type == T_ARRAY || type == T_OBJECT) {
+ __ verify_oop(to_reg->as_register());
+ }
}
return load_offset;
}
-int LIR_Assembler::load(Register base, Register disp, LIR_Opr to_reg, BasicType type) {
+int LIR_Assembler::load(Register base, Register disp, LIR_Opr to_reg, BasicType type, bool wide) {
int load_offset = code_offset();
switch(type) {
case T_BOOLEAN: // fall through
- case T_BYTE : __ ldsb(base, disp, to_reg->as_register()); break;
- case T_CHAR : __ lduh(base, disp, to_reg->as_register()); break;
- case T_SHORT : __ ldsh(base, disp, to_reg->as_register()); break;
- case T_INT : __ ld(base, disp, to_reg->as_register()); break;
- case T_ADDRESS:// fall through
+ case T_BYTE : __ ldsb(base, disp, to_reg->as_register()); break;
+ case T_CHAR : __ lduh(base, disp, to_reg->as_register()); break;
+ case T_SHORT : __ ldsh(base, disp, to_reg->as_register()); break;
+ case T_INT : __ ld(base, disp, to_reg->as_register()); break;
+ case T_ADDRESS: __ ld_ptr(base, disp, to_reg->as_register()); break;
case T_ARRAY : // fall through
- case T_OBJECT: __ ld_ptr(base, disp, to_reg->as_register()); break;
+ case T_OBJECT:
+ {
+ if (UseCompressedOops && !wide) {
+ __ lduw(base, disp, to_reg->as_register());
+ __ decode_heap_oop(to_reg->as_register());
+ } else {
+ __ ld_ptr(base, disp, to_reg->as_register());
+ }
+ break;
+ }
case T_FLOAT: __ ldf(FloatRegisterImpl::S, base, disp, to_reg->as_float_reg()); break;
case T_DOUBLE: __ ldf(FloatRegisterImpl::D, base, disp, to_reg->as_double_reg()); break;
case T_LONG :
@@ -1078,60 +1009,28 @@
break;
default : ShouldNotReachHere();
}
- if (type == T_ARRAY || type == T_OBJECT) __ verify_oop(to_reg->as_register());
+ if (type == T_ARRAY || type == T_OBJECT) {
+ __ verify_oop(to_reg->as_register());
+ }
return load_offset;
}
-
-// load/store with an Address
-void LIR_Assembler::load(const Address& a, Register d, BasicType ld_type, CodeEmitInfo *info, int offset) {
- load(a.base(), a.disp() + offset, d, ld_type, info);
-}
-
-
-void LIR_Assembler::store(Register value, const Address& dest, BasicType type, CodeEmitInfo *info, int offset) {
- store(value, dest.base(), dest.disp() + offset, type, info);
-}
-
-
-// loadf/storef with an Address
-void LIR_Assembler::load(const Address& a, FloatRegister d, BasicType ld_type, CodeEmitInfo *info, int offset) {
- load(a.base(), a.disp() + offset, d, ld_type, info);
-}
-
-
-void LIR_Assembler::store(FloatRegister value, const Address& dest, BasicType type, CodeEmitInfo *info, int offset) {
- store(value, dest.base(), dest.disp() + offset, type, info);
-}
-
-
-// load/store with an Address
-void LIR_Assembler::load(LIR_Address* a, Register d, BasicType ld_type, CodeEmitInfo *info) {
- load(as_Address(a), d, ld_type, info);
-}
-
-
-void LIR_Assembler::store(Register value, LIR_Address* dest, BasicType type, CodeEmitInfo *info) {
- store(value, as_Address(dest), type, info);
-}
-
-
-// loadf/storef with an Address
-void LIR_Assembler::load(LIR_Address* a, FloatRegister d, BasicType ld_type, CodeEmitInfo *info) {
- load(as_Address(a), d, ld_type, info);
-}
-
-
-void LIR_Assembler::store(FloatRegister value, LIR_Address* dest, BasicType type, CodeEmitInfo *info) {
- store(value, as_Address(dest), type, info);
-}
-
-
void LIR_Assembler::const2stack(LIR_Opr src, LIR_Opr dest) {
LIR_Const* c = src->as_constant_ptr();
switch (c->type()) {
case T_INT:
- case T_FLOAT:
+ case T_FLOAT: {
+ Register src_reg = O7;
+ int value = c->as_jint_bits();
+ if (value == 0) {
+ src_reg = G0;
+ } else {
+ __ set(value, O7);
+ }
+ Address addr = frame_map()->address_for_slot(dest->single_stack_ix());
+ __ stw(src_reg, addr.base(), addr.disp());
+ break;
+ }
case T_ADDRESS: {
Register src_reg = O7;
int value = c->as_jint_bits();
@@ -1141,7 +1040,7 @@
__ set(value, O7);
}
Address addr = frame_map()->address_for_slot(dest->single_stack_ix());
- __ stw(src_reg, addr.base(), addr.disp());
+ __ st_ptr(src_reg, addr.base(), addr.disp());
break;
}
case T_OBJECT: {
@@ -1178,14 +1077,12 @@
}
-void LIR_Assembler::const2mem(LIR_Opr src, LIR_Opr dest, BasicType type, CodeEmitInfo* info ) {
+void LIR_Assembler::const2mem(LIR_Opr src, LIR_Opr dest, BasicType type, CodeEmitInfo* info, bool wide) {
LIR_Const* c = src->as_constant_ptr();
LIR_Address* addr = dest->as_address_ptr();
Register base = addr->base()->as_pointer_register();
-
- if (info != NULL) {
- add_debug_info_for_null_check_here(info);
- }
+ int offset = -1;
+
switch (c->type()) {
case T_INT:
case T_FLOAT:
@@ -1199,10 +1096,10 @@
}
if (addr->index()->is_valid()) {
assert(addr->disp() == 0, "must be zero");
- store(tmp, base, addr->index()->as_pointer_register(), type);
+ offset = store(tmp, base, addr->index()->as_pointer_register(), type, wide);
} else {
assert(Assembler::is_simm13(addr->disp()), "can't handle larger addresses");
- store(tmp, base, addr->disp(), type);
+ offset = store(tmp, base, addr->disp(), type, wide, false);
}
break;
}
@@ -1212,21 +1109,21 @@
assert(Assembler::is_simm13(addr->disp()) &&
Assembler::is_simm13(addr->disp() + 4), "can't handle larger addresses");
- Register tmp = O7;
+ LIR_Opr tmp = FrameMap::O7_opr;
int value_lo = c->as_jint_lo_bits();
if (value_lo == 0) {
- tmp = G0;
+ tmp = FrameMap::G0_opr;
} else {
__ set(value_lo, O7);
}
- store(tmp, base, addr->disp() + lo_word_offset_in_bytes, T_INT);
+ offset = store(tmp, base, addr->disp() + lo_word_offset_in_bytes, T_INT, wide, false);
int value_hi = c->as_jint_hi_bits();
if (value_hi == 0) {
- tmp = G0;
+ tmp = FrameMap::G0_opr;
} else {
__ set(value_hi, O7);
}
- store(tmp, base, addr->disp() + hi_word_offset_in_bytes, T_INT);
+ offset = store(tmp, base, addr->disp() + hi_word_offset_in_bytes, T_INT, wide, false);
break;
}
case T_OBJECT: {
@@ -1241,10 +1138,10 @@
// handle either reg+reg or reg+disp address
if (addr->index()->is_valid()) {
assert(addr->disp() == 0, "must be zero");
- store(tmp, base, addr->index()->as_pointer_register(), type);
+ offset = store(tmp, base, addr->index()->as_pointer_register(), type, wide);
} else {
assert(Assembler::is_simm13(addr->disp()), "can't handle larger addresses");
- store(tmp, base, addr->disp(), type);
+ offset = store(tmp, base, addr->disp(), type, wide, false);
}
break;
@@ -1252,6 +1149,10 @@
default:
Unimplemented();
}
+ if (info != NULL) {
+ assert(offset != -1, "offset should've been set");
+ add_debug_info_for_null_check(offset, info);
+ }
}
@@ -1336,7 +1237,7 @@
assert(to_reg->is_single_cpu(), "Must be a cpu register.");
__ set(const_addrlit, O7);
- load(O7, 0, to_reg->as_register(), T_INT);
+ __ ld(O7, 0, to_reg->as_register());
}
}
break;
@@ -1429,7 +1330,7 @@
void LIR_Assembler::mem2reg(LIR_Opr src_opr, LIR_Opr dest, BasicType type,
- LIR_PatchCode patch_code, CodeEmitInfo* info, bool unaligned) {
+ LIR_PatchCode patch_code, CodeEmitInfo* info, bool wide, bool unaligned) {
LIR_Address* addr = src_opr->as_address_ptr();
LIR_Opr to_reg = dest;
@@ -1475,16 +1376,15 @@
assert(disp_reg != noreg || Assembler::is_simm13(disp_value), "should have set this up");
if (disp_reg == noreg) {
- offset = load(src, disp_value, to_reg, type, unaligned);
+ offset = load(src, disp_value, to_reg, type, wide, unaligned);
} else {
assert(!unaligned, "can't handle this");
- offset = load(src, disp_reg, to_reg, type);
+ offset = load(src, disp_reg, to_reg, type, wide);
}
if (patch != NULL) {
patching_epilog(patch, patch_code, src, info);
}
-
if (info != NULL) add_debug_info_for_null_check(offset, info);
}
@@ -1518,7 +1418,7 @@
}
bool unaligned = (addr.disp() - STACK_BIAS) % 8 != 0;
- load(addr.base(), addr.disp(), dest, dest->type(), unaligned);
+ load(addr.base(), addr.disp(), dest, dest->type(), true /*wide*/, unaligned);
}
@@ -1530,7 +1430,7 @@
addr = frame_map()->address_for_slot(dest->double_stack_ix());
}
bool unaligned = (addr.disp() - STACK_BIAS) % 8 != 0;
- store(from_reg, addr.base(), addr.disp(), from_reg->type(), unaligned);
+ store(from_reg, addr.base(), addr.disp(), from_reg->type(), true /*wide*/, unaligned);
}
@@ -1578,7 +1478,7 @@
void LIR_Assembler::reg2mem(LIR_Opr from_reg, LIR_Opr dest, BasicType type,
LIR_PatchCode patch_code, CodeEmitInfo* info, bool pop_fpu_stack,
- bool unaligned) {
+ bool wide, bool unaligned) {
LIR_Address* addr = dest->as_address_ptr();
Register src = addr->base()->as_pointer_register();
@@ -1622,10 +1522,10 @@
assert(disp_reg != noreg || Assembler::is_simm13(disp_value), "should have set this up");
if (disp_reg == noreg) {
- offset = store(from_reg, src, disp_value, type, unaligned);
+ offset = store(from_reg, src, disp_value, type, wide, unaligned);
} else {
assert(!unaligned, "can't handle this");
- offset = store(from_reg, src, disp_reg, type);
+ offset = store(from_reg, src, disp_reg, type, wide);
}
if (patch != NULL) {
@@ -2184,13 +2084,13 @@
// make sure src and dst are non-null and load array length
if (flags & LIR_OpArrayCopy::src_null_check) {
__ tst(src);
- __ br(Assembler::equal, false, Assembler::pn, *stub->entry());
+ __ brx(Assembler::equal, false, Assembler::pn, *stub->entry());
__ delayed()->nop();
}
if (flags & LIR_OpArrayCopy::dst_null_check) {
__ tst(dst);
- __ br(Assembler::equal, false, Assembler::pn, *stub->entry());
+ __ brx(Assembler::equal, false, Assembler::pn, *stub->entry());
__ delayed()->nop();
}
@@ -2232,10 +2132,18 @@
}
if (flags & LIR_OpArrayCopy::type_check) {
- __ ld_ptr(src, oopDesc::klass_offset_in_bytes(), tmp);
- __ ld_ptr(dst, oopDesc::klass_offset_in_bytes(), tmp2);
- __ cmp(tmp, tmp2);
- __ br(Assembler::notEqual, false, Assembler::pt, *stub->entry());
+ if (UseCompressedOops) {
+ // We don't need decode because we just need to compare
+ __ lduw(src, oopDesc::klass_offset_in_bytes(), tmp);
+ __ lduw(dst, oopDesc::klass_offset_in_bytes(), tmp2);
+ __ cmp(tmp, tmp2);
+ __ br(Assembler::notEqual, false, Assembler::pt, *stub->entry());
+ } else {
+ __ ld_ptr(src, oopDesc::klass_offset_in_bytes(), tmp);
+ __ ld_ptr(dst, oopDesc::klass_offset_in_bytes(), tmp2);
+ __ cmp(tmp, tmp2);
+ __ brx(Assembler::notEqual, false, Assembler::pt, *stub->entry());
+ }
__ delayed()->nop();
}
@@ -2250,20 +2158,44 @@
// but not necessarily exactly of type default_type.
Label known_ok, halt;
jobject2reg(op->expected_type()->constant_encoding(), tmp);
- __ ld_ptr(dst, oopDesc::klass_offset_in_bytes(), tmp2);
- if (basic_type != T_OBJECT) {
- __ cmp(tmp, tmp2);
- __ br(Assembler::notEqual, false, Assembler::pn, halt);
- __ delayed()->ld_ptr(src, oopDesc::klass_offset_in_bytes(), tmp2);
- __ cmp(tmp, tmp2);
- __ br(Assembler::equal, false, Assembler::pn, known_ok);
- __ delayed()->nop();
+ if (UseCompressedOops) {
+ // tmp holds the default type. It currently comes uncompressed after the
+ // load of a constant, so encode it.
+ __ encode_heap_oop(tmp);
+ // load the raw value of the dst klass, since we will be comparing
+ // uncompressed values directly.
+ __ lduw(dst, oopDesc::klass_offset_in_bytes(), tmp2);
+ if (basic_type != T_OBJECT) {
+ __ cmp(tmp, tmp2);
+ __ br(Assembler::notEqual, false, Assembler::pn, halt);
+ // load the raw value of the src klass.
+ __ delayed()->lduw(src, oopDesc::klass_offset_in_bytes(), tmp2);
+ __ cmp(tmp, tmp2);
+ __ br(Assembler::equal, false, Assembler::pn, known_ok);
+ __ delayed()->nop();
+ } else {
+ __ cmp(tmp, tmp2);
+ __ br(Assembler::equal, false, Assembler::pn, known_ok);
+ __ delayed()->cmp(src, dst);
+ __ brx(Assembler::equal, false, Assembler::pn, known_ok);
+ __ delayed()->nop();
+ }
} else {
- __ cmp(tmp, tmp2);
- __ br(Assembler::equal, false, Assembler::pn, known_ok);
- __ delayed()->cmp(src, dst);
- __ br(Assembler::equal, false, Assembler::pn, known_ok);
- __ delayed()->nop();
+ __ ld_ptr(dst, oopDesc::klass_offset_in_bytes(), tmp2);
+ if (basic_type != T_OBJECT) {
+ __ cmp(tmp, tmp2);
+ __ brx(Assembler::notEqual, false, Assembler::pn, halt);
+ __ delayed()->ld_ptr(src, oopDesc::klass_offset_in_bytes(), tmp2);
+ __ cmp(tmp, tmp2);
+ __ brx(Assembler::equal, false, Assembler::pn, known_ok);
+ __ delayed()->nop();
+ } else {
+ __ cmp(tmp, tmp2);
+ __ brx(Assembler::equal, false, Assembler::pn, known_ok);
+ __ delayed()->cmp(src, dst);
+ __ brx(Assembler::equal, false, Assembler::pn, known_ok);
+ __ delayed()->nop();
+ }
}
__ bind(halt);
__ stop("incorrect type information in arraycopy");
@@ -2471,7 +2403,7 @@
Label next_test;
Address recv_addr(mdo, md->byte_offset_of_slot(data, ReceiverTypeData::receiver_offset(i)) -
mdo_offset_bias);
- load(recv_addr, tmp1, T_OBJECT);
+ __ ld_ptr(recv_addr, tmp1);
__ br_notnull(tmp1, false, Assembler::pt, next_test);
__ delayed()->nop();
__ st_ptr(recv, recv_addr);
@@ -2487,11 +2419,8 @@
void LIR_Assembler::setup_md_access(ciMethod* method, int bci,
ciMethodData*& md, ciProfileData*& data, int& mdo_offset_bias) {
- md = method->method_data();
- if (md == NULL) {
- bailout("out of memory building methodDataOop");
- return;
- }
+ md = method->method_data_or_null();
+ assert(md != NULL, "Sanity");
data = md->bci_to_data(bci);
assert(data != NULL, "need data for checkcast");
assert(data->is_ReceiverTypeData(), "need ReceiverTypeData for type check");
@@ -2563,7 +2492,7 @@
// get object class
// not a safepoint as obj null check happens earlier
- load(obj, oopDesc::klass_offset_in_bytes(), klass_RInfo, T_OBJECT, NULL);
+ __ load_klass(obj, klass_RInfo);
if (op->fast_check()) {
assert_different_registers(klass_RInfo, k_RInfo);
__ cmp(k_RInfo, klass_RInfo);
@@ -2605,7 +2534,7 @@
__ set(mdo_offset_bias, tmp1);
__ add(mdo, tmp1, mdo);
}
- load(Address(obj, oopDesc::klass_offset_in_bytes()), recv, T_OBJECT);
+ __ load_klass(obj, recv);
type_profile_helper(mdo, mdo_offset_bias, md, data, recv, tmp1, success);
// Jump over the failure case
__ ba(false, *success);
@@ -2674,11 +2603,12 @@
__ br_null(value, false, Assembler::pn, done);
__ delayed()->nop();
}
- load(array, oopDesc::klass_offset_in_bytes(), k_RInfo, T_OBJECT, op->info_for_exception());
- load(value, oopDesc::klass_offset_in_bytes(), klass_RInfo, T_OBJECT, NULL);
+ add_debug_info_for_null_check_here(op->info_for_exception());
+ __ load_klass(array, k_RInfo);
+ __ load_klass(value, klass_RInfo);
// get instance klass
- load(k_RInfo, objArrayKlass::element_klass_offset_in_bytes() + sizeof(oopDesc), k_RInfo, T_OBJECT, NULL);
+ __ ld_ptr(Address(k_RInfo, objArrayKlass::element_klass_offset_in_bytes() + sizeof(oopDesc)), k_RInfo);
// perform the fast part of the checking logic
__ check_klass_subtype_fast_path(klass_RInfo, k_RInfo, Rtmp1, O7, success_target, failure_target, NULL);
@@ -2700,7 +2630,7 @@
__ set(mdo_offset_bias, tmp1);
__ add(mdo, tmp1, mdo);
}
- load(Address(value, oopDesc::klass_offset_in_bytes()), recv, T_OBJECT);
+ __ load_klass(value, recv);
type_profile_helper(mdo, mdo_offset_bias, md, data, recv, tmp1, &done);
__ ba(false, done);
__ delayed()->nop();
@@ -2781,14 +2711,17 @@
Register t2 = op->tmp2()->as_register();
__ mov(cmp_value, t1);
__ mov(new_value, t2);
-#ifdef _LP64
if (op->code() == lir_cas_obj) {
- __ casx(addr, t1, t2);
- } else
-#endif
- {
+ if (UseCompressedOops) {
+ __ encode_heap_oop(t1);
+ __ encode_heap_oop(t2);
__ cas(addr, t1, t2);
+ } else {
+ __ cas_ptr(addr, t1, t2);
}
+ } else {
+ __ cas(addr, t1, t2);
+ }
__ cmp(t1, t2);
} else {
Unimplemented();
@@ -2885,11 +2818,8 @@
int bci = op->profiled_bci();
// Update counter for all call types
- ciMethodData* md = method->method_data();
- if (md == NULL) {
- bailout("out of memory building methodDataOop");
- return;
- }
+ ciMethodData* md = method->method_data_or_null();
+ assert(md != NULL, "Sanity");
ciProfileData* data = md->bci_to_data(bci);
assert(data->is_CounterData(), "need CounterData for calls");
assert(op->mdo()->is_single_cpu(), "mdo must be allocated");
@@ -2966,7 +2896,7 @@
}
}
} else {
- load(Address(recv, oopDesc::klass_offset_in_bytes()), recv, T_OBJECT);
+ __ load_klass(recv, recv);
Label update_done;
type_profile_helper(mdo, mdo_offset_bias, md, data, recv, tmp1, &update_done);
// Receiver did not match any saved receiver and there is no empty row for it.
@@ -3160,7 +3090,7 @@
} else {
// use normal move for all other volatiles since they don't need
// special handling to remain atomic.
- move_op(src, dest, type, lir_patch_none, info, false, false);
+ move_op(src, dest, type, lir_patch_none, info, false, false, false);
}
}
--- a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.hpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.hpp Wed Dec 08 17:50:49 2010 -0800
@@ -40,33 +40,11 @@
// and then a load or store is emitted with ([O7] + [d]).
//
- // some load/store variants return the code_offset for proper positioning of debug info for null checks
-
- // load/store with 32 bit displacement
- int load(Register s, int disp, Register d, BasicType ld_type, CodeEmitInfo* info = NULL);
- void store(Register value, Register base, int offset, BasicType type, CodeEmitInfo *info = NULL);
-
- // loadf/storef with 32 bit displacement
- void load(Register s, int disp, FloatRegister d, BasicType ld_type, CodeEmitInfo* info = NULL);
- void store(FloatRegister d, Register s1, int disp, BasicType st_type, CodeEmitInfo* info = NULL);
+ int store(LIR_Opr from_reg, Register base, int offset, BasicType type, bool wide, bool unaligned);
+ int store(LIR_Opr from_reg, Register base, Register disp, BasicType type, bool wide);
- // convienence methods for calling load/store with an Address
- void load(const Address& a, Register d, BasicType ld_type, CodeEmitInfo* info = NULL, int offset = 0);
- void store(Register d, const Address& a, BasicType st_type, CodeEmitInfo* info = NULL, int offset = 0);
- void load(const Address& a, FloatRegister d, BasicType ld_type, CodeEmitInfo* info = NULL, int offset = 0);
- void store(FloatRegister d, const Address& a, BasicType st_type, CodeEmitInfo* info = NULL, int offset = 0);
-
- // convienence methods for calling load/store with an LIR_Address
- void load(LIR_Address* a, Register d, BasicType ld_type, CodeEmitInfo* info = NULL);
- void store(Register d, LIR_Address* a, BasicType st_type, CodeEmitInfo* info = NULL);
- void load(LIR_Address* a, FloatRegister d, BasicType ld_type, CodeEmitInfo* info = NULL);
- void store(FloatRegister d, LIR_Address* a, BasicType st_type, CodeEmitInfo* info = NULL);
-
- int store(LIR_Opr from_reg, Register base, int offset, BasicType type, bool unaligned = false);
- int store(LIR_Opr from_reg, Register base, Register disp, BasicType type);
-
- int load(Register base, int offset, LIR_Opr to_reg, BasicType type, bool unaligned = false);
- int load(Register base, Register disp, LIR_Opr to_reg, BasicType type);
+ int load(Register base, int offset, LIR_Opr to_reg, BasicType type, bool wide, bool unaligned);
+ int load(Register base, Register disp, LIR_Opr to_reg, BasicType type, bool wide);
void monitorexit(LIR_Opr obj_opr, LIR_Opr lock_opr, Register hdr, int monitor_no);
--- a/hotspot/src/cpu/sparc/vm/c1_MacroAssembler_sparc.cpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/cpu/sparc/vm/c1_MacroAssembler_sparc.cpp Wed Dec 08 17:50:49 2010 -0800
@@ -40,7 +40,7 @@
const Register temp_reg = G3_scratch;
// Note: needs more testing of out-of-line vs. inline slow case
verify_oop(receiver);
- ld_ptr(receiver, oopDesc::klass_offset_in_bytes(), temp_reg);
+ load_klass(receiver, temp_reg);
cmp(temp_reg, iCache);
brx(Assembler::equal, true, Assembler::pt, L);
delayed()->nop();
@@ -185,9 +185,19 @@
} else {
set((intx)markOopDesc::prototype(), t1);
}
- st_ptr(t1 , obj, oopDesc::mark_offset_in_bytes ());
- st_ptr(klass, obj, oopDesc::klass_offset_in_bytes ());
- if (len->is_valid()) st(len , obj, arrayOopDesc::length_offset_in_bytes());
+ st_ptr(t1, obj, oopDesc::mark_offset_in_bytes());
+ if (UseCompressedOops) {
+ // Save klass
+ mov(klass, t1);
+ encode_heap_oop_not_null(t1);
+ stw(t1, obj, oopDesc::klass_offset_in_bytes());
+ } else {
+ st_ptr(klass, obj, oopDesc::klass_offset_in_bytes());
+ }
+ if (len->is_valid()) st(len, obj, arrayOopDesc::length_offset_in_bytes());
+ else if (UseCompressedOops) {
+ store_klass_gap(G0, obj);
+ }
}
@@ -235,7 +245,7 @@
Register t1, // temp register
Register t2 // temp register
) {
- const int hdr_size_in_bytes = instanceOopDesc::base_offset_in_bytes();
+ const int hdr_size_in_bytes = instanceOopDesc::header_size() * HeapWordSize;
initialize_header(obj, klass, noreg, t1, t2);
--- a/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp Wed Dec 08 17:50:49 2010 -0800
@@ -612,7 +612,7 @@
// load the klass and check the has finalizer flag
Label register_finalizer;
Register t = O1;
- __ ld_ptr(O0, oopDesc::klass_offset_in_bytes(), t);
+ __ load_klass(O0, t);
__ ld(t, Klass::access_flags_offset_in_bytes() + sizeof(oopDesc), t);
__ set(JVM_ACC_HAS_FINALIZER, G3);
__ andcc(G3, t, G0);
--- a/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp Wed Dec 08 17:50:49 2010 -0800
@@ -689,8 +689,8 @@
{
// Perform an in-place conversion to int or an int subword.
__ ldsw(G3_amh_vmargslot, O0_argslot);
+ Address value;
Address vmarg = __ argument_address(O0_argslot);
- Address value;
bool value_left_justified = false;
switch (ek) {
@@ -700,9 +700,21 @@
case _adapter_opt_l2i:
{
// just delete the extra slot
+#ifdef _LP64
+ // In V9, longs are given 2 64-bit slots in the interpreter, but the
+ // data is passed in only 1 slot.
+ // Keep the second slot.
+ __ add(Gargs, __ argument_offset(O0_argslot, -1), O0_argslot);
+ remove_arg_slots(_masm, -stack_move_unit(), O0_argslot, O1_scratch, O2_scratch, O3_scratch);
+ value = Address(O0_argslot, 4); // Get least-significant 32-bit of 64-bit value.
+ vmarg = Address(O0_argslot, Interpreter::stackElementSize);
+#else
+ // Keep the first slot.
__ add(Gargs, __ argument_offset(O0_argslot), O0_argslot);
remove_arg_slots(_masm, -stack_move_unit(), O0_argslot, O1_scratch, O2_scratch, O3_scratch);
- value = vmarg = Address(O0_argslot, 0);
+ value = Address(O0_argslot, 0);
+ vmarg = value;
+#endif
}
break;
case _adapter_opt_unboxi:
--- a/hotspot/src/cpu/sparc/vm/sparc.ad Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/cpu/sparc/vm/sparc.ad Wed Dec 08 17:50:49 2010 -0800
@@ -667,6 +667,20 @@
return offset;
}
+static inline jdouble replicate_immI(int con, int count, int width) {
+ // Load a constant replicated "count" times with width "width"
+ int bit_width = width * 8;
+ jlong elt_val = con;
+ elt_val &= (((jlong) 1) << bit_width) - 1; // mask off sign bits
+ jlong val = elt_val;
+ for (int i = 0; i < count - 1; i++) {
+ val <<= bit_width;
+ val |= elt_val;
+ }
+ jdouble dval = *((jdouble*) &val); // coerce to double type
+ return dval;
+}
+
// Standard Sparc opcode form2 field breakdown
static inline void emit2_19(CodeBuffer &cbuf, int f30, int f29, int f25, int f22, int f20, int f19, int f0 ) {
f0 &= (1<<19)-1; // Mask displacement to 19 bits
@@ -1008,6 +1022,90 @@
//=============================================================================
+const bool Matcher::constant_table_absolute_addressing = false;
+const RegMask& MachConstantBaseNode::_out_RegMask = PTR_REG_mask;
+
+void MachConstantBaseNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const {
+ Compile* C = ra_->C;
+ Compile::ConstantTable& constant_table = C->constant_table();
+ MacroAssembler _masm(&cbuf);
+
+ Register r = as_Register(ra_->get_encode(this));
+ CodeSection* cs = __ code()->consts();
+ int consts_size = cs->align_at_start(cs->size());
+
+ if (UseRDPCForConstantTableBase) {
+ // For the following RDPC logic to work correctly the consts
+ // section must be allocated right before the insts section. This
+ // assert checks for that. The layout and the SECT_* constants
+ // are defined in src/share/vm/asm/codeBuffer.hpp.
+ assert(CodeBuffer::SECT_CONSTS + 1 == CodeBuffer::SECT_INSTS, "must be");
+ int offset = __ offset();
+ int disp;
+
+ // If the displacement from the current PC to the constant table
+ // base fits into simm13 we set the constant table base to the
+ // current PC.
+ if (__ is_simm13(-(consts_size + offset))) {
+ constant_table.set_table_base_offset(-(consts_size + offset));
+ disp = 0;
+ } else {
+ // If the offset of the top constant (last entry in the table)
+ // fits into simm13 we set the constant table base to the actual
+ // table base.
+ if (__ is_simm13(constant_table.top_offset())) {
+ constant_table.set_table_base_offset(0);
+ disp = consts_size + offset;
+ } else {
+ // Otherwise we set the constant table base in the middle of the
+ // constant table.
+ int half_consts_size = consts_size / 2;
+ assert(half_consts_size * 2 == consts_size, "sanity");
+ constant_table.set_table_base_offset(-half_consts_size); // table base offset gets added to the load displacement.
+ disp = half_consts_size + offset;
+ }
+ }
+
+ __ rdpc(r);
+
+ if (disp != 0) {
+ assert(r != O7, "need temporary");
+ __ sub(r, __ ensure_simm13_or_reg(disp, O7), r);
+ }
+ }
+ else {
+ // Materialize the constant table base.
+ assert(constant_table.size() == consts_size, err_msg("must be: %d == %d", constant_table.size(), consts_size));
+ address baseaddr = cs->start() + -(constant_table.table_base_offset());
+ RelocationHolder rspec = internal_word_Relocation::spec(baseaddr);
+ AddressLiteral base(baseaddr, rspec);
+ __ set(base, r);
+ }
+}
+
+uint MachConstantBaseNode::size(PhaseRegAlloc*) const {
+ if (UseRDPCForConstantTableBase) {
+ // This is really the worst case but generally it's only 1 instruction.
+ return 4 /*rdpc*/ + 4 /*sub*/ + MacroAssembler::worst_case_size_of_set();
+ } else {
+ return MacroAssembler::worst_case_size_of_set();
+ }
+}
+
+#ifndef PRODUCT
+void MachConstantBaseNode::format(PhaseRegAlloc* ra_, outputStream* st) const {
+ char reg[128];
+ ra_->dump_register(this, reg);
+ if (UseRDPCForConstantTableBase) {
+ st->print("RDPC %s\t! constant table base", reg);
+ } else {
+ st->print("SET &constanttable,%s\t! constant table base", reg);
+ }
+}
+#endif
+
+
+//=============================================================================
#ifndef PRODUCT
void MachPrologNode::format( PhaseRegAlloc *ra_, outputStream *st ) const {
@@ -2247,25 +2345,6 @@
__ delayed()->nop();
%}
- enc_class jump_enc( iRegX switch_val, o7RegI table) %{
- MacroAssembler _masm(&cbuf);
-
- Register switch_reg = as_Register($switch_val$$reg);
- Register table_reg = O7;
-
- address table_base = __ address_table_constant(_index2label);
- RelocationHolder rspec = internal_word_Relocation::spec(table_base);
-
- // Move table address into a register.
- __ set(table_base, table_reg, rspec);
-
- // Jump to base address + switch value
- __ ld_ptr(table_reg, switch_reg, table_reg);
- __ jmp(table_reg, G0);
- __ delayed()->nop();
-
- %}
-
enc_class enc_ba( Label labl ) %{
MacroAssembler _masm(&cbuf);
Label &L = *($labl$$label);
@@ -2384,20 +2463,6 @@
cbuf.insts()->emit_int32(op);
%}
- // Utility encoding for loading a 64 bit Pointer into a register
- // The 64 bit pointer is stored in the generated code stream
- enc_class SetPtr( immP src, iRegP rd ) %{
- Register dest = reg_to_register_object($rd$$reg);
- MacroAssembler _masm(&cbuf);
- // [RGV] This next line should be generated from ADLC
- if ( _opnds[1]->constant_is_oop() ) {
- intptr_t val = $src$$constant;
- __ set_oop_constant((jobject)val, dest);
- } else { // non-oop pointers, e.g. card mark base, heap top
- __ set($src$$constant, dest);
- }
- %}
-
enc_class Set13( immI13 src, iRegI rd ) %{
emit3_simm13( cbuf, Assembler::arith_op, $rd$$reg, Assembler::or_op3, 0, $src$$constant );
%}
@@ -2411,10 +2476,6 @@
__ set($src$$constant, reg_to_register_object($rd$$reg));
%}
- enc_class SetNull( iRegI rd ) %{
- emit3_simm13( cbuf, Assembler::arith_op, $rd$$reg, Assembler::or_op3, 0, 0 );
- %}
-
enc_class call_epilog %{
if( VerifyStackAtCalls ) {
MacroAssembler _masm(&cbuf);
@@ -2778,35 +2839,6 @@
__ float_cmp( $primary, -1, Fsrc1, Fsrc2, Rdst);
%}
- enc_class LdImmL (immL src, iRegL dst, o7RegL tmp) %{ // Load Immediate
- MacroAssembler _masm(&cbuf);
- Register dest = reg_to_register_object($dst$$reg);
- Register temp = reg_to_register_object($tmp$$reg);
- __ set64( $src$$constant, dest, temp );
- %}
-
- enc_class LdReplImmI(immI src, regD dst, o7RegP tmp, int count, int width) %{
- // Load a constant replicated "count" times with width "width"
- int bit_width = $width$$constant * 8;
- jlong elt_val = $src$$constant;
- elt_val &= (((jlong)1) << bit_width) - 1; // mask off sign bits
- jlong val = elt_val;
- for (int i = 0; i < $count$$constant - 1; i++) {
- val <<= bit_width;
- val |= elt_val;
- }
- jdouble dval = *(jdouble*)&val; // coerce to double type
- MacroAssembler _masm(&cbuf);
- address double_address = __ double_constant(dval);
- RelocationHolder rspec = internal_word_Relocation::spec(double_address);
- AddressLiteral addrlit(double_address, rspec);
-
- __ sethi(addrlit, $tmp$$Register);
- // XXX This is a quick fix for 6833573.
- //__ ldf(FloatRegisterImpl::D, $tmp$$Register, addrlit.low10(), $dst$$FloatRegister, rspec);
- __ ldf(FloatRegisterImpl::D, $tmp$$Register, addrlit.low10(), as_DoubleFloatRegister($dst$$reg), rspec);
- %}
-
// Compiler ensures base is doubleword aligned and cnt is count of doublewords
enc_class enc_Clear_Array(iRegX cnt, iRegP base, iRegX temp) %{
MacroAssembler _masm(&cbuf);
@@ -3521,6 +3553,29 @@
interface(CONST_INTER);
%}
+// Pointer Immediate: 32 or 64-bit
+operand immP_set() %{
+ predicate(!VM_Version::is_niagara1_plus());
+ match(ConP);
+
+ op_cost(5);
+ // formats are generated automatically for constants and base registers
+ format %{ %}
+ interface(CONST_INTER);
+%}
+
+// Pointer Immediate: 32 or 64-bit
+// From Niagara2 processors on a load should be better than materializing.
+operand immP_load() %{
+ predicate(VM_Version::is_niagara1_plus());
+ match(ConP);
+
+ op_cost(5);
+ // formats are generated automatically for constants and base registers
+ format %{ %}
+ interface(CONST_INTER);
+%}
+
operand immP13() %{
predicate((-4096 < n->get_ptr()) && (n->get_ptr() <= 4095));
match(ConP);
@@ -3616,6 +3671,26 @@
interface(CONST_INTER);
%}
+// Long Immediate: cheap (materialize in <= 3 instructions)
+operand immL_cheap() %{
+ predicate(!VM_Version::is_niagara1_plus() || MacroAssembler::size_of_set64(n->get_long()) <= 3);
+ match(ConL);
+ op_cost(0);
+
+ format %{ %}
+ interface(CONST_INTER);
+%}
+
+// Long Immediate: expensive (materialize in > 3 instructions)
+operand immL_expensive() %{
+ predicate(VM_Version::is_niagara1_plus() && MacroAssembler::size_of_set64(n->get_long()) > 3);
+ match(ConL);
+ op_cost(0);
+
+ format %{ %}
+ interface(CONST_INTER);
+%}
+
// Double Immediate
operand immD() %{
match(ConD);
@@ -5981,25 +6056,59 @@
ins_pipe(ialu_imm);
%}
-instruct loadConP(iRegP dst, immP src) %{
- match(Set dst src);
+#ifndef _LP64
+instruct loadConP(iRegP dst, immP con) %{
+ match(Set dst con);
+ ins_cost(DEFAULT_COST * 3/2);
+ format %{ "SET $con,$dst\t!ptr" %}
+ ins_encode %{
+ // [RGV] This next line should be generated from ADLC
+ if (_opnds[1]->constant_is_oop()) {
+ intptr_t val = $con$$constant;
+ __ set_oop_constant((jobject) val, $dst$$Register);
+ } else { // non-oop pointers, e.g. card mark base, heap top
+ __ set($con$$constant, $dst$$Register);
+ }
+ %}
+ ins_pipe(loadConP);
+%}
+#else
+instruct loadConP_set(iRegP dst, immP_set con) %{
+ match(Set dst con);
ins_cost(DEFAULT_COST * 3/2);
- format %{ "SET $src,$dst\t!ptr" %}
- // This rule does not use "expand" unlike loadConI because then
- // the result type is not known to be an Oop. An ADLC
- // enhancement will be needed to make that work - not worth it!
-
- ins_encode( SetPtr( src, dst ) );
+ format %{ "SET $con,$dst\t! ptr" %}
+ ins_encode %{
+ // [RGV] This next line should be generated from ADLC
+ if (_opnds[1]->constant_is_oop()) {
+ intptr_t val = $con$$constant;
+ __ set_oop_constant((jobject) val, $dst$$Register);
+ } else { // non-oop pointers, e.g. card mark base, heap top
+ __ set($con$$constant, $dst$$Register);
+ }
+ %}
ins_pipe(loadConP);
-
-%}
+%}
+
+instruct loadConP_load(iRegP dst, immP_load con) %{
+ match(Set dst con);
+ ins_cost(MEMORY_REF_COST);
+ format %{ "LD [$constanttablebase + $constantoffset],$dst\t! load from constant table: ptr=$con" %}
+ ins_encode %{
+ RegisterOrConstant con_offset = __ ensure_simm13_or_reg($constantoffset($con), $dst$$Register);
+ __ ld_ptr($constanttablebase, con_offset, $dst$$Register);
+ %}
+ ins_pipe(loadConP);
+%}
+#endif // _LP64
instruct loadConP0(iRegP dst, immP0 src) %{
match(Set dst src);
size(4);
format %{ "CLR $dst\t!ptr" %}
- ins_encode( SetNull( dst ) );
+ ins_encode %{
+ __ clr($dst$$Register);
+ %}
ins_pipe(ialu_imm);
%}
@@ -6019,7 +6128,9 @@
size(4);
format %{ "CLR $dst\t! compressed NULL ptr" %}
- ins_encode( SetNull( dst ) );
+ ins_encode %{
+ __ clr($dst$$Register);
+ %}
ins_pipe(ialu_imm);
%}
@@ -6034,13 +6145,27 @@
ins_pipe(ialu_hi_lo_reg);
%}
-instruct loadConL(iRegL dst, immL src, o7RegL tmp) %{
- // %%% maybe this should work like loadConD
- match(Set dst src);
+// Materialize long value (predicated by immL_cheap).
+instruct loadConL_set64(iRegL dst, immL_cheap con, o7RegL tmp) %{
+ match(Set dst con);
effect(KILL tmp);
- ins_cost(DEFAULT_COST * 4);
- format %{ "SET64 $src,$dst KILL $tmp\t! long" %}
- ins_encode( LdImmL(src, dst, tmp) );
+ ins_cost(DEFAULT_COST * 3);
+ format %{ "SET64 $con,$dst KILL $tmp\t! cheap long" %}
+ ins_encode %{
+ __ set64($con$$constant, $dst$$Register, $tmp$$Register);
+ %}
+ ins_pipe(loadConL);
+%}
+
+// Load long value from constant table (predicated by immL_expensive).
+instruct loadConL_ldx(iRegL dst, immL_expensive con) %{
+ match(Set dst con);
+ ins_cost(MEMORY_REF_COST);
+ format %{ "LDX [$constanttablebase + $constantoffset],$dst\t! load from constant table: long=$con" %}
+ ins_encode %{
+ RegisterOrConstant con_offset = __ ensure_simm13_or_reg($constantoffset($con), $dst$$Register);
+ __ ldx($constanttablebase, con_offset, $dst$$Register);
+ %}
ins_pipe(loadConL);
%}
@@ -6063,50 +6188,26 @@
ins_pipe(ialu_imm);
%}
-instruct loadConF(regF dst, immF src, o7RegP tmp) %{
- match(Set dst src);
+instruct loadConF(regF dst, immF con, o7RegI tmp) %{
+ match(Set dst con);
effect(KILL tmp);
-
-#ifdef _LP64
- size(8*4);
-#else
- size(2*4);
-#endif
-
- format %{ "SETHI hi(&$src),$tmp\t!get float $src from table\n\t"
- "LDF [$tmp+lo(&$src)],$dst" %}
+ format %{ "LDF [$constanttablebase + $constantoffset],$dst\t! load from constant table: float=$con" %}
ins_encode %{
- address float_address = __ float_constant($src$$constant);
- RelocationHolder rspec = internal_word_Relocation::spec(float_address);
- AddressLiteral addrlit(float_address, rspec);
-
- __ sethi(addrlit, $tmp$$Register);
- __ ldf(FloatRegisterImpl::S, $tmp$$Register, addrlit.low10(), $dst$$FloatRegister, rspec);
+ RegisterOrConstant con_offset = __ ensure_simm13_or_reg($constantoffset($con), $tmp$$Register);
+ __ ldf(FloatRegisterImpl::S, $constanttablebase, con_offset, $dst$$FloatRegister);
%}
ins_pipe(loadConFD);
%}
-instruct loadConD(regD dst, immD src, o7RegP tmp) %{
- match(Set dst src);
+instruct loadConD(regD dst, immD con, o7RegI tmp) %{
+ match(Set dst con);
effect(KILL tmp);
-
-#ifdef _LP64
- size(8*4);
-#else
- size(2*4);
-#endif
-
- format %{ "SETHI hi(&$src),$tmp\t!get double $src from table\n\t"
- "LDDF [$tmp+lo(&$src)],$dst" %}
+ format %{ "LDDF [$constanttablebase + $constantoffset],$dst\t! load from constant table: double=$con" %}
ins_encode %{
- address double_address = __ double_constant($src$$constant);
- RelocationHolder rspec = internal_word_Relocation::spec(double_address);
- AddressLiteral addrlit(double_address, rspec);
-
- __ sethi(addrlit, $tmp$$Register);
// XXX This is a quick fix for 6833573.
- //__ ldf(FloatRegisterImpl::D, $tmp$$Register, addrlit.low10(), $dst$$FloatRegister, rspec);
- __ ldf(FloatRegisterImpl::D, $tmp$$Register, addrlit.low10(), as_DoubleFloatRegister($dst$$reg), rspec);
+ //__ ldf(FloatRegisterImpl::D, $constanttablebase, $constantoffset($con), $dst$$FloatRegister);
+ RegisterOrConstant con_offset = __ ensure_simm13_or_reg($constantoffset($con), $tmp$$Register);
+ __ ldf(FloatRegisterImpl::D, $constanttablebase, con_offset, as_DoubleFloatRegister($dst$$reg));
%}
ins_pipe(loadConFD);
%}
@@ -8558,16 +8659,16 @@
%}
// Replicate scalar constant to packed byte values in Double register
-instruct Repl8B_immI(regD dst, immI13 src, o7RegP tmp) %{
- match(Set dst (Replicate8B src));
-#ifdef _LP64
- size(36);
-#else
- size(8);
-#endif
- format %{ "SETHI hi(&Repl8($src)),$tmp\t!get Repl8B($src) from table\n\t"
- "LDDF [$tmp+lo(&Repl8($src))],$dst" %}
- ins_encode( LdReplImmI(src, dst, tmp, (8), (1)) );
+instruct Repl8B_immI(regD dst, immI13 con, o7RegI tmp) %{
+ match(Set dst (Replicate8B con));
+ effect(KILL tmp);
+ format %{ "LDDF [$constanttablebase + $constantoffset],$dst\t! load from constant table: Repl8B($con)" %}
+ ins_encode %{
+ // XXX This is a quick fix for 6833573.
+ //__ ldf(FloatRegisterImpl::D, $constanttablebase, $constantoffset(replicate_immI($con$$constant, 8, 1)), $dst$$FloatRegister);
+ RegisterOrConstant con_offset = __ ensure_simm13_or_reg($constantoffset(replicate_immI($con$$constant, 8, 1)), $tmp$$Register);
+ __ ldf(FloatRegisterImpl::D, $constanttablebase, con_offset, as_DoubleFloatRegister($dst$$reg));
+ %}
ins_pipe(loadConFD);
%}
@@ -8594,16 +8695,16 @@
%}
// Replicate scalar constant to packed char values in Double register
-instruct Repl4C_immI(regD dst, immI src, o7RegP tmp) %{
- match(Set dst (Replicate4C src));
-#ifdef _LP64
- size(36);
-#else
- size(8);
-#endif
- format %{ "SETHI hi(&Repl4($src)),$tmp\t!get Repl4C($src) from table\n\t"
- "LDDF [$tmp+lo(&Repl4($src))],$dst" %}
- ins_encode( LdReplImmI(src, dst, tmp, (4), (2)) );
+instruct Repl4C_immI(regD dst, immI con, o7RegI tmp) %{
+ match(Set dst (Replicate4C con));
+ effect(KILL tmp);
+ format %{ "LDDF [$constanttablebase + $constantoffset],$dst\t! load from constant table: Repl4C($con)" %}
+ ins_encode %{
+ // XXX This is a quick fix for 6833573.
+ //__ ldf(FloatRegisterImpl::D, $constanttablebase, $constantoffset(replicate_immI($con$$constant, 4, 2)), $dst$$FloatRegister);
+ RegisterOrConstant con_offset = __ ensure_simm13_or_reg($constantoffset(replicate_immI($con$$constant, 4, 2)), $tmp$$Register);
+ __ ldf(FloatRegisterImpl::D, $constanttablebase, con_offset, as_DoubleFloatRegister($dst$$reg));
+ %}
ins_pipe(loadConFD);
%}
@@ -8630,16 +8731,16 @@
%}
// Replicate scalar constant to packed short values in Double register
-instruct Repl4S_immI(regD dst, immI src, o7RegP tmp) %{
- match(Set dst (Replicate4S src));
-#ifdef _LP64
- size(36);
-#else
- size(8);
-#endif
- format %{ "SETHI hi(&Repl4($src)),$tmp\t!get Repl4S($src) from table\n\t"
- "LDDF [$tmp+lo(&Repl4($src))],$dst" %}
- ins_encode( LdReplImmI(src, dst, tmp, (4), (2)) );
+instruct Repl4S_immI(regD dst, immI con, o7RegI tmp) %{
+ match(Set dst (Replicate4S con));
+ effect(KILL tmp);
+ format %{ "LDDF [$constanttablebase + $constantoffset],$dst\t! load from constant table: Repl4S($con)" %}
+ ins_encode %{
+ // XXX This is a quick fix for 6833573.
+ //__ ldf(FloatRegisterImpl::D, $constanttablebase, $constantoffset(replicate_immI($con$$constant, 4, 2)), $dst$$FloatRegister);
+ RegisterOrConstant con_offset = __ ensure_simm13_or_reg($constantoffset(replicate_immI($con$$constant, 4, 2)), $tmp$$Register);
+ __ ldf(FloatRegisterImpl::D, $constanttablebase, con_offset, as_DoubleFloatRegister($dst$$reg));
+ %}
ins_pipe(loadConFD);
%}
@@ -8664,16 +8765,16 @@
%}
// Replicate scalar zero constant to packed int values in Double register
-instruct Repl2I_immI(regD dst, immI src, o7RegP tmp) %{
- match(Set dst (Replicate2I src));
-#ifdef _LP64
- size(36);
-#else
- size(8);
-#endif
- format %{ "SETHI hi(&Repl2($src)),$tmp\t!get Repl2I($src) from table\n\t"
- "LDDF [$tmp+lo(&Repl2($src))],$dst" %}
- ins_encode( LdReplImmI(src, dst, tmp, (2), (4)) );
+instruct Repl2I_immI(regD dst, immI con, o7RegI tmp) %{
+ match(Set dst (Replicate2I con));
+ effect(KILL tmp);
+ format %{ "LDDF [$constanttablebase + $constantoffset],$dst\t! load from constant table: Repl2I($con)" %}
+ ins_encode %{
+ // XXX This is a quick fix for 6833573.
+ //__ ldf(FloatRegisterImpl::D, $constanttablebase, $constantoffset(replicate_immI($con$$constant, 2, 4)), $dst$$FloatRegister);
+ RegisterOrConstant con_offset = __ ensure_simm13_or_reg($constantoffset(replicate_immI($con$$constant, 2, 4)), $tmp$$Register);
+ __ ldf(FloatRegisterImpl::D, $constanttablebase, con_offset, as_DoubleFloatRegister($dst$$reg));
+ %}
ins_pipe(loadConFD);
%}
@@ -8929,12 +9030,27 @@
ins_cost(350);
- format %{ "SETHI [hi(table_base)],O7\n\t"
- "ADD O7, lo(table_base), O7\n\t"
- "LD [O7+$switch_val], O7\n\t"
+ format %{ "ADD $constanttablebase, $constantoffset, O7\n\t"
+ "LD [O7 + $switch_val], O7\n\t"
"JUMP O7"
%}
- ins_encode( jump_enc( switch_val, table) );
+ ins_encode %{
+ // Calculate table address into a register.
+ Register table_reg;
+ Register label_reg = O7;
+ if (constant_offset() == 0) {
+ table_reg = $constanttablebase;
+ } else {
+ table_reg = O7;
+ RegisterOrConstant con_offset = __ ensure_simm13_or_reg($constantoffset, O7);
+ __ add($constanttablebase, con_offset, table_reg);
+ }
+
+ // Jump to base address + switch value
+ __ ld_ptr(table_reg, $switch_val$$Register, label_reg);
+ __ jmp(label_reg, G0);
+ __ delayed()->nop();
+ %}
ins_pc_relative(1);
ins_pipe(ialu_reg_reg);
%}
--- a/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp Wed Dec 08 17:50:49 2010 -0800
@@ -80,9 +80,6 @@
static bool is_sparc64(int features) { return (features & fmaf_instructions_m) != 0; }
static int maximum_niagara1_processor_count() { return 32; }
- // Returns true if the platform is in the niagara line and
- // newer than the niagara1.
- static bool is_niagara1_plus();
public:
// Initialization
@@ -105,6 +102,9 @@
static bool is_ultra3() { return (_features & ultra3_m) == ultra3_m; }
static bool is_sun4v() { return (_features & sun4v_m) != 0; }
static bool is_niagara1() { return is_niagara1(_features); }
+ // Returns true if the platform is in the niagara line and
+ // newer than the niagara1.
+ static bool is_niagara1_plus();
static bool is_sparc64() { return is_sparc64(_features); }
static bool has_fast_fxtof() { return has_v9() && !is_ultra3(); }
--- a/hotspot/src/cpu/x86/vm/assembler_x86.cpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp Wed Dec 08 17:50:49 2010 -0800
@@ -2649,6 +2649,37 @@
emit_byte(0xC0 | encode);
}
+void Assembler::sqrtsd(XMMRegister dst, Address src) {
+ NOT_LP64(assert(VM_Version::supports_sse2(), ""));
+ InstructionMark im(this);
+ emit_byte(0xF2);
+ prefix(src, dst);
+ emit_byte(0x0F);
+ emit_byte(0x51);
+ emit_operand(dst, src);
+}
+
+void Assembler::sqrtss(XMMRegister dst, XMMRegister src) {
+ // HMM Table D-1 says sse2
+ // NOT_LP64(assert(VM_Version::supports_sse(), ""));
+ NOT_LP64(assert(VM_Version::supports_sse2(), ""));
+ emit_byte(0xF3);
+ int encode = prefix_and_encode(dst->encoding(), src->encoding());
+ emit_byte(0x0F);
+ emit_byte(0x51);
+ emit_byte(0xC0 | encode);
+}
+
+void Assembler::sqrtss(XMMRegister dst, Address src) {
+ NOT_LP64(assert(VM_Version::supports_sse2(), ""));
+ InstructionMark im(this);
+ emit_byte(0xF3);
+ prefix(src, dst);
+ emit_byte(0x0F);
+ emit_byte(0x51);
+ emit_operand(dst, src);
+}
+
void Assembler::stmxcsr( Address dst) {
NOT_LP64(assert(VM_Version::supports_sse(), ""));
InstructionMark im(this);
@@ -4358,16 +4389,6 @@
emit_byte(0xE8 | encode);
}
-void Assembler::sqrtsd(XMMRegister dst, Address src) {
- NOT_LP64(assert(VM_Version::supports_sse2(), ""));
- InstructionMark im(this);
- emit_byte(0xF2);
- prefix(src, dst);
- emit_byte(0x0F);
- emit_byte(0x51);
- emit_operand(dst, src);
-}
-
void Assembler::subq(Address dst, int32_t imm32) {
InstructionMark im(this);
prefixq(dst);
@@ -4929,10 +4950,6 @@
}
-void MacroAssembler::movsd(XMMRegister dst, AddressLiteral src) {
- movsd(dst, as_Address(src));
-}
-
void MacroAssembler::pop_callee_saved_registers() {
pop(rcx);
pop(rdx);
--- a/hotspot/src/cpu/x86/vm/assembler_x86.hpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.hpp Wed Dec 08 17:50:49 2010 -0800
@@ -135,6 +135,7 @@
// Using noreg ensures if the dead code is incorrectly live and executed it
// will cause an assertion failure
#define rscratch1 noreg
+#define rscratch2 noreg
#endif // _LP64
@@ -1352,6 +1353,10 @@
void sqrtsd(XMMRegister dst, Address src);
void sqrtsd(XMMRegister dst, XMMRegister src);
+ // Compute Square Root of Scalar Single-Precision Floating-Point Value
+ void sqrtss(XMMRegister dst, Address src);
+ void sqrtss(XMMRegister dst, XMMRegister src);
+
void std() { emit_byte(0xfd); }
void stmxcsr( Address dst );
@@ -2124,6 +2129,9 @@
void comisd(XMMRegister dst, Address src) { Assembler::comisd(dst, src); }
void comisd(XMMRegister dst, AddressLiteral src);
+ void fadd_s(Address src) { Assembler::fadd_s(src); }
+ void fadd_s(AddressLiteral src) { Assembler::fadd_s(as_Address(src)); }
+
void fldcw(Address src) { Assembler::fldcw(src); }
void fldcw(AddressLiteral src);
@@ -2137,6 +2145,9 @@
void fld_x(Address src) { Assembler::fld_x(src); }
void fld_x(AddressLiteral src);
+ void fmul_s(Address src) { Assembler::fmul_s(src); }
+ void fmul_s(AddressLiteral src) { Assembler::fmul_s(as_Address(src)); }
+
void ldmxcsr(Address src) { Assembler::ldmxcsr(src); }
void ldmxcsr(AddressLiteral src);
@@ -2153,10 +2164,50 @@
public:
- void movsd(XMMRegister dst, XMMRegister src) { Assembler::movsd(dst, src); }
- void movsd(Address dst, XMMRegister src) { Assembler::movsd(dst, src); }
- void movsd(XMMRegister dst, Address src) { Assembler::movsd(dst, src); }
- void movsd(XMMRegister dst, AddressLiteral src);
+ void addsd(XMMRegister dst, XMMRegister src) { Assembler::addsd(dst, src); }
+ void addsd(XMMRegister dst, Address src) { Assembler::addsd(dst, src); }
+ void addsd(XMMRegister dst, AddressLiteral src) { Assembler::addsd(dst, as_Address(src)); }
+
+ void addss(XMMRegister dst, XMMRegister src) { Assembler::addss(dst, src); }
+ void addss(XMMRegister dst, Address src) { Assembler::addss(dst, src); }
+ void addss(XMMRegister dst, AddressLiteral src) { Assembler::addss(dst, as_Address(src)); }
+
+ void divsd(XMMRegister dst, XMMRegister src) { Assembler::divsd(dst, src); }
+ void divsd(XMMRegister dst, Address src) { Assembler::divsd(dst, src); }
+ void divsd(XMMRegister dst, AddressLiteral src) { Assembler::divsd(dst, as_Address(src)); }
+
+ void divss(XMMRegister dst, XMMRegister src) { Assembler::divss(dst, src); }
+ void divss(XMMRegister dst, Address src) { Assembler::divss(dst, src); }
+ void divss(XMMRegister dst, AddressLiteral src) { Assembler::divss(dst, as_Address(src)); }
+
+ void movsd(XMMRegister dst, XMMRegister src) { Assembler::movsd(dst, src); }
+ void movsd(Address dst, XMMRegister src) { Assembler::movsd(dst, src); }
+ void movsd(XMMRegister dst, Address src) { Assembler::movsd(dst, src); }
+ void movsd(XMMRegister dst, AddressLiteral src) { Assembler::movsd(dst, as_Address(src)); }
+
+ void mulsd(XMMRegister dst, XMMRegister src) { Assembler::mulsd(dst, src); }
+ void mulsd(XMMRegister dst, Address src) { Assembler::mulsd(dst, src); }
+ void mulsd(XMMRegister dst, AddressLiteral src) { Assembler::mulsd(dst, as_Address(src)); }
+
+ void mulss(XMMRegister dst, XMMRegister src) { Assembler::mulss(dst, src); }
+ void mulss(XMMRegister dst, Address src) { Assembler::mulss(dst, src); }
+ void mulss(XMMRegister dst, AddressLiteral src) { Assembler::mulss(dst, as_Address(src)); }
+
+ void sqrtsd(XMMRegister dst, XMMRegister src) { Assembler::sqrtsd(dst, src); }
+ void sqrtsd(XMMRegister dst, Address src) { Assembler::sqrtsd(dst, src); }
+ void sqrtsd(XMMRegister dst, AddressLiteral src) { Assembler::sqrtsd(dst, as_Address(src)); }
+
+ void sqrtss(XMMRegister dst, XMMRegister src) { Assembler::sqrtss(dst, src); }
+ void sqrtss(XMMRegister dst, Address src) { Assembler::sqrtss(dst, src); }
+ void sqrtss(XMMRegister dst, AddressLiteral src) { Assembler::sqrtss(dst, as_Address(src)); }
+
+ void subsd(XMMRegister dst, XMMRegister src) { Assembler::subsd(dst, src); }
+ void subsd(XMMRegister dst, Address src) { Assembler::subsd(dst, src); }
+ void subsd(XMMRegister dst, AddressLiteral src) { Assembler::subsd(dst, as_Address(src)); }
+
+ void subss(XMMRegister dst, XMMRegister src) { Assembler::subss(dst, src); }
+ void subss(XMMRegister dst, Address src) { Assembler::subss(dst, src); }
+ void subss(XMMRegister dst, AddressLiteral src) { Assembler::subss(dst, as_Address(src)); }
void ucomiss(XMMRegister dst, XMMRegister src) { Assembler::ucomiss(dst, src); }
void ucomiss(XMMRegister dst, Address src) { Assembler::ucomiss(dst, src); }
--- a/hotspot/src/cpu/x86/vm/c1_CodeStubs_x86.cpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/cpu/x86/vm/c1_CodeStubs_x86.cpp Wed Dec 08 17:50:49 2010 -0800
@@ -483,7 +483,7 @@
Register pre_val_reg = pre_val()->as_register();
- ce->mem2reg(addr(), pre_val(), T_OBJECT, patch_code(), info(), false);
+ ce->mem2reg(addr(), pre_val(), T_OBJECT, patch_code(), info(), false /*wide*/, false /*unaligned*/);
__ cmpptr(pre_val_reg, (int32_t) NULL_WORD);
__ jcc(Assembler::equal, _continuation);
--- a/hotspot/src/cpu/x86/vm/c1_Defs_x86.hpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/cpu/x86/vm/c1_Defs_x86.hpp Wed Dec 08 17:50:49 2010 -0800
@@ -61,8 +61,8 @@
pd_nof_xmm_regs_linearscan = pd_nof_xmm_regs_frame_map, // number of registers visible to linear scan
pd_first_cpu_reg = 0,
pd_last_cpu_reg = NOT_LP64(5) LP64_ONLY(11),
- pd_first_byte_reg = 2,
- pd_last_byte_reg = 5,
+ pd_first_byte_reg = NOT_LP64(2) LP64_ONLY(0),
+ pd_last_byte_reg = NOT_LP64(5) LP64_ONLY(11),
pd_first_fpu_reg = pd_nof_cpu_regs_frame_map,
pd_last_fpu_reg = pd_first_fpu_reg + 7,
pd_first_xmm_reg = pd_nof_cpu_regs_frame_map + pd_nof_fpu_regs_frame_map,
--- a/hotspot/src/cpu/x86/vm/c1_FrameMap_x86.cpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/cpu/x86/vm/c1_FrameMap_x86.cpp Wed Dec 08 17:50:49 2010 -0800
@@ -158,9 +158,11 @@
map_register( 6, r8); r8_opr = LIR_OprFact::single_cpu(6);
map_register( 7, r9); r9_opr = LIR_OprFact::single_cpu(7);
map_register( 8, r11); r11_opr = LIR_OprFact::single_cpu(8);
- map_register( 9, r12); r12_opr = LIR_OprFact::single_cpu(9);
- map_register(10, r13); r13_opr = LIR_OprFact::single_cpu(10);
- map_register(11, r14); r14_opr = LIR_OprFact::single_cpu(11);
+ map_register( 9, r13); r13_opr = LIR_OprFact::single_cpu(9);
+ map_register(10, r14); r14_opr = LIR_OprFact::single_cpu(10);
+ // r12 is allocated conditionally. With compressed oops it holds
+ // the heapbase value and is not visible to the allocator.
+ map_register(11, r12); r12_opr = LIR_OprFact::single_cpu(11);
// The unallocatable registers are at the end
map_register(12, r10); r10_opr = LIR_OprFact::single_cpu(12);
map_register(13, r15); r15_opr = LIR_OprFact::single_cpu(13);
@@ -191,9 +193,9 @@
_caller_save_cpu_regs[6] = r8_opr;
_caller_save_cpu_regs[7] = r9_opr;
_caller_save_cpu_regs[8] = r11_opr;
- _caller_save_cpu_regs[9] = r12_opr;
- _caller_save_cpu_regs[10] = r13_opr;
- _caller_save_cpu_regs[11] = r14_opr;
+ _caller_save_cpu_regs[9] = r13_opr;
+ _caller_save_cpu_regs[10] = r14_opr;
+ _caller_save_cpu_regs[11] = r12_opr;
#endif // _LP64
--- a/hotspot/src/cpu/x86/vm/c1_FrameMap_x86.hpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/cpu/x86/vm/c1_FrameMap_x86.hpp Wed Dec 08 17:50:49 2010 -0800
@@ -130,4 +130,15 @@
return _caller_save_xmm_regs[i];
}
+ static int adjust_reg_range(int range) {
+ // Reduce the number of available regs (to free r12) in case of compressed oops
+ if (UseCompressedOops) return range - 1;
+ return range;
+ }
+
+ static int nof_caller_save_cpu_regs() { return adjust_reg_range(pd_nof_caller_save_cpu_regs_frame_map); }
+ static int last_cpu_reg() { return adjust_reg_range(pd_last_cpu_reg); }
+ static int last_byte_reg() { return adjust_reg_range(pd_last_byte_reg); }
+
#endif // CPU_X86_VM_C1_FRAMEMAP_X86_HPP
+
--- a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Wed Dec 08 17:50:49 2010 -0800
@@ -343,8 +343,8 @@
Register receiver = FrameMap::receiver_opr->as_register();
Register ic_klass = IC_Klass;
const int ic_cmp_size = LP64_ONLY(10) NOT_LP64(9);
-
- if (!VerifyOops) {
+ const bool do_post_padding = VerifyOops || UseCompressedOops;
+ if (!do_post_padding) {
// insert some nops so that the verified entry point is aligned on CodeEntryAlignment
while ((__ offset() + ic_cmp_size) % CodeEntryAlignment != 0) {
__ nop();
@@ -352,8 +352,8 @@
}
int offset = __ offset();
__ inline_cache_check(receiver, IC_Klass);
- assert(__ offset() % CodeEntryAlignment == 0 || VerifyOops, "alignment must be correct");
- if (VerifyOops) {
+ assert(__ offset() % CodeEntryAlignment == 0 || do_post_padding, "alignment must be correct");
+ if (do_post_padding) {
// force alignment after the cache check.
// It's been verified to be aligned if !VerifyOops
__ align(CodeEntryAlignment);
@@ -559,16 +559,16 @@
__ movptr (rax, arg1->as_register());
// Get addresses of first characters from both Strings
- __ movptr (rsi, Address(rax, java_lang_String::value_offset_in_bytes()));
- __ movptr (rcx, Address(rax, java_lang_String::offset_offset_in_bytes()));
- __ lea (rsi, Address(rsi, rcx, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR)));
+ __ load_heap_oop(rsi, Address(rax, java_lang_String::value_offset_in_bytes()));
+ __ movptr (rcx, Address(rax, java_lang_String::offset_offset_in_bytes()));
+ __ lea (rsi, Address(rsi, rcx, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR)));
// rbx, may be NULL
add_debug_info_for_null_check_here(info);
- __ movptr (rdi, Address(rbx, java_lang_String::value_offset_in_bytes()));
- __ movptr (rcx, Address(rbx, java_lang_String::offset_offset_in_bytes()));
- __ lea (rdi, Address(rdi, rcx, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR)));
+ __ load_heap_oop(rdi, Address(rbx, java_lang_String::value_offset_in_bytes()));
+ __ movptr (rcx, Address(rbx, java_lang_String::offset_offset_in_bytes()));
+ __ lea (rdi, Address(rdi, rcx, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR)));
// compute minimum length (in rax) and difference of lengths (on top of stack)
if (VM_Version::supports_cmov()) {
@@ -696,10 +696,15 @@
LIR_Const* c = src->as_constant_ptr();
switch (c->type()) {
- case T_INT:
+ case T_INT: {
+ assert(patch_code == lir_patch_none, "no patching handled here");
+ __ movl(dest->as_register(), c->as_jint());
+ break;
+ }
+
case T_ADDRESS: {
assert(patch_code == lir_patch_none, "no patching handled here");
- __ movl(dest->as_register(), c->as_jint());
+ __ movptr(dest->as_register(), c->as_jint());
break;
}
@@ -780,8 +785,11 @@
switch (c->type()) {
case T_INT: // fall through
case T_FLOAT:
+ __ movl(frame_map()->address_for_slot(dest->single_stack_ix()), c->as_jint_bits());
+ break;
+
case T_ADDRESS:
- __ movl(frame_map()->address_for_slot(dest->single_stack_ix()), c->as_jint_bits());
+ __ movptr(frame_map()->address_for_slot(dest->single_stack_ix()), c->as_jint_bits());
break;
case T_OBJECT:
@@ -806,7 +814,7 @@
}
}
-void LIR_Assembler::const2mem(LIR_Opr src, LIR_Opr dest, BasicType type, CodeEmitInfo* info ) {
+void LIR_Assembler::const2mem(LIR_Opr src, LIR_Opr dest, BasicType type, CodeEmitInfo* info, bool wide) {
assert(src->is_constant(), "should not call otherwise");
assert(dest->is_address(), "should not call otherwise");
LIR_Const* c = src->as_constant_ptr();
@@ -816,14 +824,21 @@
switch (type) {
case T_INT: // fall through
case T_FLOAT:
+ __ movl(as_Address(addr), c->as_jint_bits());
+ break;
+
case T_ADDRESS:
- __ movl(as_Address(addr), c->as_jint_bits());
+ __ movptr(as_Address(addr), c->as_jint_bits());
break;
case T_OBJECT: // fall through
case T_ARRAY:
if (c->as_jobject() == NULL) {
- __ movptr(as_Address(addr), NULL_WORD);
+ if (UseCompressedOops && !wide) {
+ __ movl(as_Address(addr), (int32_t)NULL_WORD);
+ } else {
+ __ movptr(as_Address(addr), NULL_WORD);
+ }
} else {
if (is_literal_address(addr)) {
ShouldNotReachHere();
@@ -831,8 +846,14 @@
} else {
#ifdef _LP64
__ movoop(rscratch1, c->as_jobject());
- null_check_here = code_offset();
- __ movptr(as_Address_lo(addr), rscratch1);
+ if (UseCompressedOops && !wide) {
+ __ encode_heap_oop(rscratch1);
+ null_check_here = code_offset();
+ __ movl(as_Address_lo(addr), rscratch1);
+ } else {
+ null_check_here = code_offset();
+ __ movptr(as_Address_lo(addr), rscratch1);
+ }
#else
__ movoop(as_Address(addr), c->as_jobject());
#endif
@@ -1009,22 +1030,28 @@
}
-void LIR_Assembler::reg2mem(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_PatchCode patch_code, CodeEmitInfo* info, bool pop_fpu_stack, bool /* unaligned */) {
+void LIR_Assembler::reg2mem(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_PatchCode patch_code, CodeEmitInfo* info, bool pop_fpu_stack, bool wide, bool /* unaligned */) {
LIR_Address* to_addr = dest->as_address_ptr();
PatchingStub* patch = NULL;
+ Register compressed_src = rscratch1;
if (type == T_ARRAY || type == T_OBJECT) {
__ verify_oop(src->as_register());
+#ifdef _LP64
+ if (UseCompressedOops && !wide) {
+ __ movptr(compressed_src, src->as_register());
+ __ encode_heap_oop(compressed_src);
+ }
+#endif
}
+
if (patch_code != lir_patch_none) {
patch = new PatchingStub(_masm, PatchingStub::access_field_id);
Address toa = as_Address(to_addr);
assert(toa.disp() != 0, "must have");
}
- if (info != NULL) {
- add_debug_info_for_null_check_here(info);
- }
-
+
+ int null_check_here = code_offset();
switch (type) {
case T_FLOAT: {
if (src->is_single_xmm()) {
@@ -1050,13 +1077,17 @@
break;
}
- case T_ADDRESS: // fall through
case T_ARRAY: // fall through
case T_OBJECT: // fall through
-#ifdef _LP64
+ if (UseCompressedOops && !wide) {
+ __ movl(as_Address(to_addr), compressed_src);
+ } else {
+ __ movptr(as_Address(to_addr), src->as_register());
+ }
+ break;
+ case T_ADDRESS:
__ movptr(as_Address(to_addr), src->as_register());
break;
-#endif // _LP64
case T_INT:
__ movl(as_Address(to_addr), src->as_register());
break;
@@ -1113,6 +1144,9 @@
default:
ShouldNotReachHere();
}
+ if (info != NULL) {
+ add_debug_info_for_null_check(null_check_here, info);
+ }
if (patch_code != lir_patch_none) {
patching_epilog(patch, patch_code, to_addr->base()->as_register(), info);
@@ -1196,7 +1230,7 @@
}
-void LIR_Assembler::mem2reg(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_PatchCode patch_code, CodeEmitInfo* info, bool /* unaligned */) {
+void LIR_Assembler::mem2reg(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_PatchCode patch_code, CodeEmitInfo* info, bool wide, bool /* unaligned */) {
assert(src->is_address(), "should not call otherwise");
assert(dest->is_register(), "should not call otherwise");
@@ -1250,13 +1284,18 @@
break;
}
- case T_ADDRESS: // fall through
case T_OBJECT: // fall through
case T_ARRAY: // fall through
-#ifdef _LP64
+ if (UseCompressedOops && !wide) {
+ __ movl(dest->as_register(), from_addr);
+ } else {
+ __ movptr(dest->as_register(), from_addr);
+ }
+ break;
+
+ case T_ADDRESS:
__ movptr(dest->as_register(), from_addr);
break;
-#endif // _L64
case T_INT:
__ movl(dest->as_register(), from_addr);
break;
@@ -1351,6 +1390,11 @@
}
if (type == T_ARRAY || type == T_OBJECT) {
+#ifdef _LP64
+ if (UseCompressedOops && !wide) {
+ __ decode_heap_oop(dest->as_register());
+ }
+#endif
__ verify_oop(dest->as_register());
}
}
@@ -1672,11 +1716,8 @@
ciMethod* method = op->profiled_method();
assert(method != NULL, "Should have method");
int bci = op->profiled_bci();
- md = method->method_data();
- if (md == NULL) {
- bailout("out of memory building methodDataOop");
- return;
- }
+ md = method->method_data_or_null();
+ assert(md != NULL, "Sanity");
data = md->bci_to_data(bci);
assert(data != NULL, "need data for type check");
assert(data->is_ReceiverTypeData(), "need ReceiverTypeData for type check");
@@ -1690,7 +1731,7 @@
} else if (obj == klass_RInfo) {
klass_RInfo = dst;
}
- if (k->is_loaded()) {
+ if (k->is_loaded() && !UseCompressedOops) {
select_different_registers(obj, dst, k_RInfo, klass_RInfo);
} else {
Rtmp1 = op->tmp3()->as_register();
@@ -1727,21 +1768,26 @@
if (op->fast_check()) {
// get object class
// not a safepoint as obj null check happens earlier
- if (k->is_loaded()) {
#ifdef _LP64
- __ cmpptr(k_RInfo, Address(obj, oopDesc::klass_offset_in_bytes()));
-#else
- __ cmpoop(Address(obj, oopDesc::klass_offset_in_bytes()), k->constant_encoding());
-#endif // _LP64
+ if (UseCompressedOops) {
+ __ load_klass(Rtmp1, obj);
+ __ cmpptr(k_RInfo, Rtmp1);
} else {
__ cmpptr(k_RInfo, Address(obj, oopDesc::klass_offset_in_bytes()));
}
+#else
+ if (k->is_loaded()) {
+ __ cmpoop(Address(obj, oopDesc::klass_offset_in_bytes()), k->constant_encoding());
+ } else {
+ __ cmpptr(k_RInfo, Address(obj, oopDesc::klass_offset_in_bytes()));
+ }
+#endif
__ jcc(Assembler::notEqual, *failure_target);
// successful cast, fall through to profile or jump
} else {
// get object class
// not a safepoint as obj null check happens earlier
- __ movptr(klass_RInfo, Address(obj, oopDesc::klass_offset_in_bytes()));
+ __ load_klass(klass_RInfo, obj);
if (k->is_loaded()) {
// See if we get an immediate positive hit
#ifdef _LP64
@@ -1796,7 +1842,7 @@
Register mdo = klass_RInfo, recv = k_RInfo;
__ bind(profile_cast_success);
__ movoop(mdo, md->constant_encoding());
- __ movptr(recv, Address(obj, oopDesc::klass_offset_in_bytes()));
+ __ load_klass(recv, obj);
Label update_done;
type_profile_helper(mdo, md, data, recv, success);
__ jmp(*success);
@@ -1830,11 +1876,8 @@
ciMethod* method = op->profiled_method();
assert(method != NULL, "Should have method");
int bci = op->profiled_bci();
- md = method->method_data();
- if (md == NULL) {
- bailout("out of memory building methodDataOop");
- return;
- }
+ md = method->method_data_or_null();
+ assert(md != NULL, "Sanity");
data = md->bci_to_data(bci);
assert(data != NULL, "need data for type check");
assert(data->is_ReceiverTypeData(), "need ReceiverTypeData for type check");
@@ -1860,10 +1903,10 @@
}
add_debug_info_for_null_check_here(op->info_for_exception());
- __ movptr(k_RInfo, Address(array, oopDesc::klass_offset_in_bytes()));
- __ movptr(klass_RInfo, Address(value, oopDesc::klass_offset_in_bytes()));
-
- // get instance klass
+ __ load_klass(k_RInfo, array);
+ __ load_klass(klass_RInfo, value);
+
+ // get instance klass (it's already uncompressed)
__ movptr(k_RInfo, Address(k_RInfo, objArrayKlass::element_klass_offset_in_bytes() + sizeof(oopDesc)));
// perform the fast part of the checking logic
__ check_klass_subtype_fast_path(klass_RInfo, k_RInfo, Rtmp1, success_target, failure_target, NULL);
@@ -1882,7 +1925,7 @@
Register mdo = klass_RInfo, recv = k_RInfo;
__ bind(profile_cast_success);
__ movoop(mdo, md->constant_encoding());
- __ movptr(recv, Address(value, oopDesc::klass_offset_in_bytes()));
+ __ load_klass(recv, value);
Label update_done;
type_profile_helper(mdo, md, data, recv, &done);
__ jmpb(done);
@@ -1946,12 +1989,31 @@
assert(cmpval != newval, "cmp and new values must be in different registers");
assert(cmpval != addr, "cmp and addr must be in different registers");
assert(newval != addr, "new value and addr must be in different registers");
- if (os::is_MP()) {
- __ lock();
- }
+
if ( op->code() == lir_cas_obj) {
- __ cmpxchgptr(newval, Address(addr, 0));
- } else if (op->code() == lir_cas_int) {
+#ifdef _LP64
+ if (UseCompressedOops) {
+ __ encode_heap_oop(cmpval);
+ __ mov(rscratch1, newval);
+ __ encode_heap_oop(rscratch1);
+ if (os::is_MP()) {
+ __ lock();
+ }
+ // cmpval (rax) is implicitly used by this instruction
+ __ cmpxchgl(rscratch1, Address(addr, 0));
+ } else
+#endif
+ {
+ if (os::is_MP()) {
+ __ lock();
+ }
+ __ cmpxchgptr(newval, Address(addr, 0));
+ }
+ } else {
+ assert(op->code() == lir_cas_int, "lir_cas_int expected");
+ if (os::is_MP()) {
+ __ lock();
+ }
__ cmpxchgl(newval, Address(addr, 0));
}
#ifdef _LP64
@@ -3193,8 +3255,13 @@
}
if (flags & LIR_OpArrayCopy::type_check) {
- __ movptr(tmp, src_klass_addr);
- __ cmpptr(tmp, dst_klass_addr);
+ if (UseCompressedOops) {
+ __ movl(tmp, src_klass_addr);
+ __ cmpl(tmp, dst_klass_addr);
+ } else {
+ __ movptr(tmp, src_klass_addr);
+ __ cmpptr(tmp, dst_klass_addr);
+ }
__ jcc(Assembler::notEqual, *stub->entry());
}
@@ -3209,13 +3276,23 @@
// but not necessarily exactly of type default_type.
Label known_ok, halt;
__ movoop(tmp, default_type->constant_encoding());
+#ifdef _LP64
+ if (UseCompressedOops) {
+ __ encode_heap_oop(tmp);
+ }
+#endif
+
if (basic_type != T_OBJECT) {
- __ cmpptr(tmp, dst_klass_addr);
+
+ if (UseCompressedOops) __ cmpl(tmp, dst_klass_addr);
+ else __ cmpptr(tmp, dst_klass_addr);
__ jcc(Assembler::notEqual, halt);
- __ cmpptr(tmp, src_klass_addr);
+ if (UseCompressedOops) __ cmpl(tmp, src_klass_addr);
+ else __ cmpptr(tmp, src_klass_addr);
__ jcc(Assembler::equal, known_ok);
} else {
- __ cmpptr(tmp, dst_klass_addr);
+ if (UseCompressedOops) __ cmpl(tmp, dst_klass_addr);
+ else __ cmpptr(tmp, dst_klass_addr);
__ jcc(Assembler::equal, known_ok);
__ cmpptr(src, dst);
__ jcc(Assembler::equal, known_ok);
@@ -3289,11 +3366,8 @@
int bci = op->profiled_bci();
// Update counter for all call types
- ciMethodData* md = method->method_data();
- if (md == NULL) {
- bailout("out of memory building methodDataOop");
- return;
- }
+ ciMethodData* md = method->method_data_or_null();
+ assert(md != NULL, "Sanity");
ciProfileData* data = md->bci_to_data(bci);
assert(data->is_CounterData(), "need CounterData for calls");
assert(op->mdo()->is_single_cpu(), "mdo must be allocated");
@@ -3344,7 +3418,7 @@
}
}
} else {
- __ movptr(recv, Address(recv, oopDesc::klass_offset_in_bytes()));
+ __ load_klass(recv, recv);
Label update_done;
type_profile_helper(mdo, md, data, recv, &update_done);
// Receiver did not match any saved receiver and there is no empty row for it.
--- a/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp Wed Dec 08 17:50:49 2010 -0800
@@ -874,6 +874,10 @@
void LIRGenerator::do_ArrayCopy(Intrinsic* x) {
assert(x->number_of_arguments() == 5, "wrong type");
+
+ // Make all state_for calls early since they can emit code
+ CodeEmitInfo* info = state_for(x, x->state());
+
LIRItem src(x->argument_at(0), this);
LIRItem src_pos(x->argument_at(1), this);
LIRItem dst(x->argument_at(2), this);
@@ -916,7 +920,6 @@
ciArrayKlass* expected_type;
arraycopy_helper(x, &flags, &expected_type);
- CodeEmitInfo* info = state_for(x, x->state()); // we may want to have stack (deoptimization?)
__ arraycopy(src.result(), src_pos.result(), dst.result(), dst_pos.result(), length.result(), tmp, expected_type, flags, info); // does add_safepoint
}
@@ -1151,9 +1154,12 @@
stub = new SimpleExceptionStub(Runtime1::throw_class_cast_exception_id, obj.result(), info_for_exception);
}
LIR_Opr reg = rlock_result(x);
+ LIR_Opr tmp3 = LIR_OprFact::illegalOpr;
+ if (!x->klass()->is_loaded() || UseCompressedOops) {
+ tmp3 = new_register(objectType);
+ }
__ checkcast(reg, obj.result(), x->klass(),
- new_register(objectType), new_register(objectType),
- !x->klass()->is_loaded() ? new_register(objectType) : LIR_OprFact::illegalOpr,
+ new_register(objectType), new_register(objectType), tmp3,
x->direct_compare(), info_for_exception, patching_info, stub,
x->profiled_method(), x->profiled_bci());
}
@@ -1170,9 +1176,12 @@
patching_info = state_for(x, x->state_before());
}
obj.load_item();
+ LIR_Opr tmp3 = LIR_OprFact::illegalOpr;
+ if (!x->klass()->is_loaded() || UseCompressedOops) {
+ tmp3 = new_register(objectType);
+ }
__ instanceof(reg, obj.result(), x->klass(),
- new_register(objectType), new_register(objectType),
- !x->klass()->is_loaded() ? new_register(objectType) : LIR_OprFact::illegalOpr,
+ new_register(objectType), new_register(objectType), tmp3,
x->direct_compare(), patching_info, x->profiled_method(), x->profiled_bci());
}
--- a/hotspot/src/cpu/x86/vm/c1_LinearScan_x86.hpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/cpu/x86/vm/c1_LinearScan_x86.hpp Wed Dec 08 17:50:49 2010 -0800
@@ -31,18 +31,17 @@
assert(FrameMap::rsp_opr->cpu_regnr() == 6, "wrong assumption below");
assert(FrameMap::rbp_opr->cpu_regnr() == 7, "wrong assumption below");
assert(reg_num >= 0, "invalid reg_num");
-
- return reg_num < 6 || reg_num > 7;
#else
- // rsp and rbp, r10, r15 (numbers 6 ancd 7) are ignored
+ // rsp and rbp, r10, r15 (numbers [12,15]) are ignored
+ // r12 (number 11) is conditional on compressed oops.
+ assert(FrameMap::r12_opr->cpu_regnr() == 11, "wrong assumption below");
assert(FrameMap::r10_opr->cpu_regnr() == 12, "wrong assumption below");
assert(FrameMap::r15_opr->cpu_regnr() == 13, "wrong assumption below");
assert(FrameMap::rsp_opr->cpu_regnrLo() == 14, "wrong assumption below");
assert(FrameMap::rbp_opr->cpu_regnrLo() == 15, "wrong assumption below");
assert(reg_num >= 0, "invalid reg_num");
-
- return reg_num < 12 || reg_num > 15;
#endif // _LP64
+ return reg_num <= FrameMap::last_cpu_reg() || reg_num >= pd_nof_cpu_regs_frame_map;
}
inline int LinearScan::num_physical_regs(BasicType type) {
@@ -104,7 +103,7 @@
if (allocator()->gen()->is_vreg_flag_set(cur->reg_num(), LIRGenerator::byte_reg)) {
assert(cur->type() != T_FLOAT && cur->type() != T_DOUBLE, "cpu regs only");
_first_reg = pd_first_byte_reg;
- _last_reg = pd_last_byte_reg;
+ _last_reg = FrameMap::last_byte_reg();
return true;
} else if ((UseSSE >= 1 && cur->type() == T_FLOAT) || (UseSSE >= 2 && cur->type() == T_DOUBLE)) {
_first_reg = pd_first_xmm_reg;
--- a/hotspot/src/cpu/x86/vm/c1_MacroAssembler_x86.cpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/cpu/x86/vm/c1_MacroAssembler_x86.cpp Wed Dec 08 17:50:49 2010 -0800
@@ -155,11 +155,26 @@
// This assumes that all prototype bits fit in an int32_t
movptr(Address(obj, oopDesc::mark_offset_in_bytes ()), (int32_t)(intptr_t)markOopDesc::prototype());
}
+#ifdef _LP64
+ if (UseCompressedOops) { // Take care not to kill klass
+ movptr(t1, klass);
+ encode_heap_oop_not_null(t1);
+ movl(Address(obj, oopDesc::klass_offset_in_bytes()), t1);
+ } else
+#endif
+ {
+ movptr(Address(obj, oopDesc::klass_offset_in_bytes()), klass);
+ }
- movptr(Address(obj, oopDesc::klass_offset_in_bytes()), klass);
if (len->is_valid()) {
movl(Address(obj, arrayOopDesc::length_offset_in_bytes()), len);
}
+#ifdef _LP64
+ else if (UseCompressedOops) {
+ xorptr(t1, t1);
+ store_klass_gap(obj, t1);
+ }
+#endif
}
@@ -230,7 +245,7 @@
void C1_MacroAssembler::initialize_object(Register obj, Register klass, Register var_size_in_bytes, int con_size_in_bytes, Register t1, Register t2) {
assert((con_size_in_bytes & MinObjAlignmentInBytesMask) == 0,
"con_size_in_bytes is not multiple of alignment");
- const int hdr_size_in_bytes = instanceOopDesc::base_offset_in_bytes();
+ const int hdr_size_in_bytes = instanceOopDesc::header_size() * HeapWordSize;
initialize_header(obj, klass, noreg, t1, t2);
@@ -317,13 +332,19 @@
// check against inline cache
assert(!MacroAssembler::needs_explicit_null_check(oopDesc::klass_offset_in_bytes()), "must add explicit null check");
int start_offset = offset();
- cmpptr(iCache, Address(receiver, oopDesc::klass_offset_in_bytes()));
+
+ if (UseCompressedOops) {
+ load_klass(rscratch1, receiver);
+ cmpptr(rscratch1, iCache);
+ } else {
+ cmpptr(iCache, Address(receiver, oopDesc::klass_offset_in_bytes()));
+ }
// if icache check fails, then jump to runtime routine
// Note: RECEIVER must still contain the receiver!
jump_cc(Assembler::notEqual,
RuntimeAddress(SharedRuntime::get_ic_miss_stub()));
const int ic_cmp_size = LP64_ONLY(10) NOT_LP64(9);
- assert(offset() - start_offset == ic_cmp_size, "check alignment in emit_method_entry");
+ assert(UseCompressedOops || offset() - start_offset == ic_cmp_size, "check alignment in emit_method_entry");
}
--- a/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp Wed Dec 08 17:50:49 2010 -0800
@@ -1261,7 +1261,7 @@
// load the klass and check the has finalizer flag
Label register_finalizer;
Register t = rsi;
- __ movptr(t, Address(rax, oopDesc::klass_offset_in_bytes()));
+ __ load_klass(t, rax);
__ movl(t, Address(t, Klass::access_flags_offset_in_bytes() + sizeof(oopDesc)));
__ testl(t, JVM_ACC_HAS_FINALIZER);
__ jcc(Assembler::notZero, register_finalizer);
--- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp Wed Dec 08 17:50:49 2010 -0800
@@ -2197,9 +2197,6 @@
__ enter(); // required for proper stackwalking of RuntimeStub frame
- checkcast_copy_entry = __ pc();
- BLOCK_COMMENT("Entry:");
-
#ifdef ASSERT
// caller guarantees that the arrays really are different
// otherwise, we would have to make conjoint checks
@@ -2210,26 +2207,28 @@
}
#endif //ASSERT
- // allocate spill slots for r13, r14
- enum {
- saved_r13_offset,
- saved_r14_offset,
- saved_rbp_offset,
- saved_rip_offset,
- saved_rarg0_offset
- };
- __ subptr(rsp, saved_rbp_offset * wordSize);
- __ movptr(Address(rsp, saved_r13_offset * wordSize), r13);
- __ movptr(Address(rsp, saved_r14_offset * wordSize), r14);
setup_arg_regs(4); // from => rdi, to => rsi, length => rdx
// ckoff => rcx, ckval => r8
// r9 and r10 may be used to save non-volatile registers
#ifdef _WIN64
// last argument (#4) is on stack on Win64
- const int ckval_offset = saved_rarg0_offset + 4;
- __ movptr(ckval, Address(rsp, ckval_offset * wordSize));
+ __ movptr(ckval, Address(rsp, 6 * wordSize));
#endif
+ // Caller of this entry point must set up the argument registers.
+ checkcast_copy_entry = __ pc();
+ BLOCK_COMMENT("Entry:");
+
+ // allocate spill slots for r13, r14
+ enum {
+ saved_r13_offset,
+ saved_r14_offset,
+ saved_rbp_offset
+ };
+ __ subptr(rsp, saved_rbp_offset * wordSize);
+ __ movptr(Address(rsp, saved_r13_offset * wordSize), r13);
+ __ movptr(Address(rsp, saved_r14_offset * wordSize), r14);
+
// check that int operands are properly extended to size_t
assert_clean_int(length, rax);
assert_clean_int(ckoff, rax);
@@ -2443,11 +2442,10 @@
const Register src_pos = c_rarg1; // source position
const Register dst = c_rarg2; // destination array oop
const Register dst_pos = c_rarg3; // destination position
- // elements count is on stack on Win64
-#ifdef _WIN64
-#define C_RARG4 Address(rsp, 6 * wordSize)
+#ifndef _WIN64
+ const Register length = c_rarg4;
#else
-#define C_RARG4 c_rarg4
+ const Address length(rsp, 6 * wordSize); // elements count is on stack on Win64
#endif
{ int modulus = CodeEntryAlignment;
@@ -2514,27 +2512,27 @@
// registers used as temp
const Register r11_length = r11; // elements count to copy
const Register r10_src_klass = r10; // array klass
- const Register r9_dst_klass = r9; // dest array klass
// if (length < 0) return -1;
- __ movl(r11_length, C_RARG4); // length (elements count, 32-bits value)
+ __ movl(r11_length, length); // length (elements count, 32-bits value)
__ testl(r11_length, r11_length);
__ jccb(Assembler::negative, L_failed_0);
__ load_klass(r10_src_klass, src);
#ifdef ASSERT
// assert(src->klass() != NULL);
- BLOCK_COMMENT("assert klasses not null");
- { Label L1, L2;
+ {
+ BLOCK_COMMENT("assert klasses not null {");
+ Label L1, L2;
__ testptr(r10_src_klass, r10_src_klass);
__ jcc(Assembler::notZero, L2); // it is broken if klass is NULL
__ bind(L1);
__ stop("broken null klass");
__ bind(L2);
- __ load_klass(r9_dst_klass, dst);
- __ cmpq(r9_dst_klass, 0);
+ __ load_klass(rax, dst);
+ __ cmpq(rax, 0);
__ jcc(Assembler::equal, L1); // this would be broken also
- BLOCK_COMMENT("assert done");
+ BLOCK_COMMENT("} assert klasses not null done");
}
#endif
@@ -2546,34 +2544,36 @@
// array_tag: typeArray = 0x3, objArray = 0x2, non-array = 0x0
//
- int lh_offset = klassOopDesc::header_size() * HeapWordSize +
- Klass::layout_helper_offset_in_bytes();
-
- const Register rax_lh = rax; // layout helper
-
- __ movl(rax_lh, Address(r10_src_klass, lh_offset));
+ const int lh_offset = klassOopDesc::header_size() * HeapWordSize +
+ Klass::layout_helper_offset_in_bytes();
// Handle objArrays completely differently...
- jint objArray_lh = Klass::array_layout_helper(T_OBJECT);
- __ cmpl(rax_lh, objArray_lh);
+ const jint objArray_lh = Klass::array_layout_helper(T_OBJECT);
+ __ cmpl(Address(r10_src_klass, lh_offset), objArray_lh);
__ jcc(Assembler::equal, L_objArray);
// if (src->klass() != dst->klass()) return -1;
- __ load_klass(r9_dst_klass, dst);
- __ cmpq(r10_src_klass, r9_dst_klass);
+ __ load_klass(rax, dst);
+ __ cmpq(r10_src_klass, rax);
__ jcc(Assembler::notEqual, L_failed);
+ const Register rax_lh = rax; // layout helper
+ __ movl(rax_lh, Address(r10_src_klass, lh_offset));
+
// if (!src->is_Array()) return -1;
__ cmpl(rax_lh, Klass::_lh_neutral_value);
__ jcc(Assembler::greaterEqual, L_failed);
// At this point, it is known to be a typeArray (array_tag 0x3).
#ifdef ASSERT
- { Label L;
+ {
+ BLOCK_COMMENT("assert primitive array {");
+ Label L;
__ cmpl(rax_lh, (Klass::_lh_array_tag_type_value << Klass::_lh_array_tag_shift));
__ jcc(Assembler::greaterEqual, L);
__ stop("must be a primitive array");
__ bind(L);
+ BLOCK_COMMENT("} assert primitive array done");
}
#endif
@@ -2631,11 +2631,14 @@
__ BIND(L_copy_longs);
#ifdef ASSERT
- { Label L;
+ {
+ BLOCK_COMMENT("assert long copy {");
+ Label L;
__ cmpl(rax_elsize, LogBytesPerLong);
__ jcc(Assembler::equal, L);
__ stop("must be long copy, but elsize is wrong");
__ bind(L);
+ BLOCK_COMMENT("} assert long copy done");
}
#endif
__ lea(from, Address(src, src_pos, Address::times_8, 0));// src_addr
@@ -2645,12 +2648,12 @@
// objArrayKlass
__ BIND(L_objArray);
- // live at this point: r10_src_klass, src[_pos], dst[_pos]
+ // live at this point: r10_src_klass, r11_length, src[_pos], dst[_pos]
Label L_plain_copy, L_checkcast_copy;
// test array classes for subtyping
- __ load_klass(r9_dst_klass, dst);
- __ cmpq(r10_src_klass, r9_dst_klass); // usual case is exact equality
+ __ load_klass(rax, dst);
+ __ cmpq(r10_src_klass, rax); // usual case is exact equality
__ jcc(Assembler::notEqual, L_checkcast_copy);
// Identically typed arrays can be copied without element-wise checks.
@@ -2666,41 +2669,33 @@
__ jump(RuntimeAddress(oop_copy_entry));
__ BIND(L_checkcast_copy);
- // live at this point: r10_src_klass, !r11_length
+ // live at this point: r10_src_klass, r11_length, rax (dst_klass)
{
- // assert(r11_length == C_RARG4); // will reload from here
- Register r11_dst_klass = r11;
- __ load_klass(r11_dst_klass, dst);
-
// Before looking at dst.length, make sure dst is also an objArray.
- __ cmpl(Address(r11_dst_klass, lh_offset), objArray_lh);
+ __ cmpl(Address(rax, lh_offset), objArray_lh);
__ jcc(Assembler::notEqual, L_failed);
// It is safe to examine both src.length and dst.length.
-#ifndef _WIN64
- arraycopy_range_checks(src, src_pos, dst, dst_pos, C_RARG4,
- rax, L_failed);
-#else
- __ movl(r11_length, C_RARG4); // reload
arraycopy_range_checks(src, src_pos, dst, dst_pos, r11_length,
rax, L_failed);
+
+ const Register r11_dst_klass = r11;
__ load_klass(r11_dst_klass, dst); // reload
-#endif
// Marshal the base address arguments now, freeing registers.
__ lea(from, Address(src, src_pos, TIMES_OOP,
arrayOopDesc::base_offset_in_bytes(T_OBJECT)));
__ lea(to, Address(dst, dst_pos, TIMES_OOP,
arrayOopDesc::base_offset_in_bytes(T_OBJECT)));
- __ movl(count, C_RARG4); // length (reloaded)
+ __ movl(count, length); // length (reloaded)
Register sco_temp = c_rarg3; // this register is free now
assert_different_registers(from, to, count, sco_temp,
r11_dst_klass, r10_src_klass);
assert_clean_int(count, sco_temp);
// Generate the type check.
- int sco_offset = (klassOopDesc::header_size() * HeapWordSize +
- Klass::super_check_offset_offset_in_bytes());
+ const int sco_offset = (klassOopDesc::header_size() * HeapWordSize +
+ Klass::super_check_offset_offset_in_bytes());
__ movl(sco_temp, Address(r11_dst_klass, sco_offset));
assert_clean_int(sco_temp, rax);
generate_type_check(r10_src_klass, sco_temp, r11_dst_klass, L_plain_copy);
@@ -2709,12 +2704,14 @@
int ek_offset = (klassOopDesc::header_size() * HeapWordSize +
objArrayKlass::element_klass_offset_in_bytes());
__ movptr(r11_dst_klass, Address(r11_dst_klass, ek_offset));
- __ movl(sco_temp, Address(r11_dst_klass, sco_offset));
+ __ movl( sco_temp, Address(r11_dst_klass, sco_offset));
assert_clean_int(sco_temp, rax);
// the checkcast_copy loop needs two extra arguments:
assert(c_rarg3 == sco_temp, "#3 already in place");
- __ movptr(C_RARG4, r11_dst_klass); // dst.klass.element_klass
+ // Set up arguments for checkcast_copy_entry.
+ setup_arg_regs(4);
+ __ movptr(r8, r11_dst_klass); // dst.klass.element_klass, r8 is c_rarg4 on Linux/Solaris
__ jump(RuntimeAddress(checkcast_copy_entry));
}
@@ -2727,8 +2724,6 @@
return start;
}
-#undef length_arg
-
void generate_arraycopy_stubs() {
// Call the conjoint generation methods immediately after
// the disjoint ones so that short branches from the former
--- a/hotspot/src/cpu/x86/vm/x86_32.ad Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/cpu/x86/vm/x86_32.ad Wed Dec 08 17:50:49 2010 -0800
@@ -507,6 +507,25 @@
//=============================================================================
+const bool Matcher::constant_table_absolute_addressing = true;
+const RegMask& MachConstantBaseNode::_out_RegMask = RegMask::Empty;
+
+void MachConstantBaseNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const {
+ // Empty encoding
+}
+
+uint MachConstantBaseNode::size(PhaseRegAlloc* ra_) const {
+ return 0;
+}
+
+#ifndef PRODUCT
+void MachConstantBaseNode::format(PhaseRegAlloc* ra_, outputStream* st) const {
+ st->print("# MachConstantBaseNode (empty encoding)");
+}
+#endif
+
+
+//=============================================================================
#ifndef PRODUCT
void MachPrologNode::format( PhaseRegAlloc *ra_, outputStream* st ) const {
Compile* C = ra_->C;
@@ -1320,29 +1339,6 @@
}
-static void emit_double_constant(CodeBuffer& cbuf, double x) {
- int mark = cbuf.insts()->mark_off();
- MacroAssembler _masm(&cbuf);
- address double_address = __ double_constant(x);
- cbuf.insts()->set_mark_off(mark); // preserve mark across masm shift
- emit_d32_reloc(cbuf,
- (int)double_address,
- internal_word_Relocation::spec(double_address),
- RELOC_DISP32);
-}
-
-static void emit_float_constant(CodeBuffer& cbuf, float x) {
- int mark = cbuf.insts()->mark_off();
- MacroAssembler _masm(&cbuf);
- address float_address = __ float_constant(x);
- cbuf.insts()->set_mark_off(mark); // preserve mark across masm shift
- emit_d32_reloc(cbuf,
- (int)float_address,
- internal_word_Relocation::spec(float_address),
- RELOC_DISP32);
-}
-
-
const bool Matcher::match_rule_supported(int opcode) {
if (!has_match_rule(opcode))
return false;
@@ -1354,22 +1350,6 @@
return regnum - 32; // The FP registers are in the second chunk
}
-bool is_positive_zero_float(jfloat f) {
- return jint_cast(f) == jint_cast(0.0F);
-}
-
-bool is_positive_one_float(jfloat f) {
- return jint_cast(f) == jint_cast(1.0F);
-}
-
-bool is_positive_zero_double(jdouble d) {
- return jlong_cast(d) == jlong_cast(0.0);
-}
-
-bool is_positive_one_double(jdouble d) {
- return jlong_cast(d) == jlong_cast(1.0);
-}
-
// This is UltraSparc specific, true just means we have fast l2f conversion
const bool Matcher::convL2FSupported(void) {
return true;
@@ -2036,67 +2016,6 @@
%}
- enc_class LdImmD (immD src) %{ // Load Immediate
- if( is_positive_zero_double($src$$constant)) {
- // FLDZ
- emit_opcode(cbuf,0xD9);
- emit_opcode(cbuf,0xEE);
- } else if( is_positive_one_double($src$$constant)) {
- // FLD1
- emit_opcode(cbuf,0xD9);
- emit_opcode(cbuf,0xE8);
- } else {
- emit_opcode(cbuf,0xDD);
- emit_rm(cbuf, 0x0, 0x0, 0x5);
- emit_double_constant(cbuf, $src$$constant);
- }
- %}
-
-
- enc_class LdImmF (immF src) %{ // Load Immediate
- if( is_positive_zero_float($src$$constant)) {
- emit_opcode(cbuf,0xD9);
- emit_opcode(cbuf,0xEE);
- } else if( is_positive_one_float($src$$constant)) {
- emit_opcode(cbuf,0xD9);
- emit_opcode(cbuf,0xE8);
- } else {
- $$$emit8$primary;
- // Load immediate does not have a zero or sign extended version
- // for 8-bit immediates
- // First load to TOS, then move to dst
- emit_rm(cbuf, 0x0, 0x0, 0x5);
- emit_float_constant(cbuf, $src$$constant);
- }
- %}
-
- enc_class LdImmX (regX dst, immXF con) %{ // Load Immediate
- emit_rm(cbuf, 0x0, $dst$$reg, 0x5);
- emit_float_constant(cbuf, $con$$constant);
- %}
-
- enc_class LdImmXD (regXD dst, immXD con) %{ // Load Immediate
- emit_rm(cbuf, 0x0, $dst$$reg, 0x5);
- emit_double_constant(cbuf, $con$$constant);
- %}
-
- enc_class load_conXD (regXD dst, immXD con) %{ // Load double constant
- // UseXmmLoadAndClearUpper ? movsd(dst, con) : movlpd(dst, con)
- emit_opcode(cbuf, UseXmmLoadAndClearUpper ? 0xF2 : 0x66);
- emit_opcode(cbuf, 0x0F);
- emit_opcode(cbuf, UseXmmLoadAndClearUpper ? 0x10 : 0x12);
- emit_rm(cbuf, 0x0, $dst$$reg, 0x5);
- emit_double_constant(cbuf, $con$$constant);
- %}
-
- enc_class Opc_MemImm_F(immF src) %{
- cbuf.set_insts_mark();
- $$$emit8$primary;
- emit_rm(cbuf, 0x0, $secondary, 0x5);
- emit_float_constant(cbuf, $src$$constant);
- %}
-
-
enc_class MovI2X_reg(regX dst, eRegI src) %{
emit_opcode(cbuf, 0x66 ); // MOVD dst,src
emit_opcode(cbuf, 0x0F );
@@ -4801,7 +4720,7 @@
interface(CONST_INTER);
%}
-// Double Immediate
+// Double Immediate one
operand immD1() %{
predicate( UseSSE<=1 && n->getd() == 1.0 );
match(ConD);
@@ -4844,7 +4763,17 @@
// Float Immediate zero
operand immF0() %{
- predicate( UseSSE == 0 && n->getf() == 0.0 );
+ predicate(UseSSE == 0 && n->getf() == 0.0F);
+ match(ConF);
+
+ op_cost(5);
+ format %{ %}
+ interface(CONST_INTER);
+%}
+
+// Float Immediate one
+operand immF1() %{
+ predicate(UseSSE == 0 && n->getf() == 1.0F);
match(ConF);
op_cost(5);
@@ -7215,24 +7144,53 @@
%}
// The instruction usage is guarded by predicate in operand immF().
-instruct loadConF(regF dst, immF src) %{
- match(Set dst src);
+instruct loadConF(regF dst, immF con) %{
+ match(Set dst con);
+ ins_cost(125);
+ format %{ "FLD_S ST,[$constantaddress]\t# load from constant table: float=$con\n\t"
+ "FSTP $dst" %}
+ ins_encode %{
+ __ fld_s($constantaddress($con));
+ __ fstp_d($dst$$reg);
+ %}
+ ins_pipe(fpu_reg_con);
+%}
+
+// The instruction usage is guarded by predicate in operand immF0().
+instruct loadConF0(regF dst, immF0 con) %{
+ match(Set dst con);
ins_cost(125);
-
- format %{ "FLD_S ST,$src\n\t"
+ format %{ "FLDZ ST\n\t"
"FSTP $dst" %}
- opcode(0xD9, 0x00); /* D9 /0 */
- ins_encode(LdImmF(src), Pop_Reg_F(dst) );
- ins_pipe( fpu_reg_con );
+ ins_encode %{
+ __ fldz();
+ __ fstp_d($dst$$reg);
+ %}
+ ins_pipe(fpu_reg_con);
+%}
+
+// The instruction usage is guarded by predicate in operand immF1().
+instruct loadConF1(regF dst, immF1 con) %{
+ match(Set dst con);
+ ins_cost(125);
+ format %{ "FLD1 ST\n\t"
+ "FSTP $dst" %}
+ ins_encode %{
+ __ fld1();
+ __ fstp_d($dst$$reg);
+ %}
+ ins_pipe(fpu_reg_con);
%}
// The instruction usage is guarded by predicate in operand immXF().
instruct loadConX(regX dst, immXF con) %{
match(Set dst con);
ins_cost(125);
- format %{ "MOVSS $dst,[$con]" %}
- ins_encode( Opcode(0xF3), Opcode(0x0F), Opcode(0x10), LdImmX(dst, con));
- ins_pipe( pipe_slow );
+ format %{ "MOVSS $dst,[$constantaddress]\t# load from constant table: float=$con" %}
+ ins_encode %{
+ __ movflt($dst$$XMMRegister, $constantaddress($con));
+ %}
+ ins_pipe(pipe_slow);
%}
// The instruction usage is guarded by predicate in operand immXF0().
@@ -7240,28 +7198,63 @@
match(Set dst src);
ins_cost(100);
format %{ "XORPS $dst,$dst\t# float 0.0" %}
- ins_encode( Opcode(0x0F), Opcode(0x57), RegReg(dst,dst));
- ins_pipe( pipe_slow );
+ ins_encode %{
+ __ xorps($dst$$XMMRegister, $dst$$XMMRegister);
+ %}
+ ins_pipe(pipe_slow);
%}
// The instruction usage is guarded by predicate in operand immD().
-instruct loadConD(regD dst, immD src) %{
- match(Set dst src);
+instruct loadConD(regD dst, immD con) %{
+ match(Set dst con);
+ ins_cost(125);
+
+ format %{ "FLD_D ST,[$constantaddress]\t# load from constant table: double=$con\n\t"
+ "FSTP $dst" %}
+ ins_encode %{
+ __ fld_d($constantaddress($con));
+ __ fstp_d($dst$$reg);
+ %}
+ ins_pipe(fpu_reg_con);
+%}
+
+// The instruction usage is guarded by predicate in operand immD0().
+instruct loadConD0(regD dst, immD0 con) %{
+ match(Set dst con);
ins_cost(125);
- format %{ "FLD_D ST,$src\n\t"
+ format %{ "FLDZ ST\n\t"
"FSTP $dst" %}
- ins_encode(LdImmD(src), Pop_Reg_D(dst) );
- ins_pipe( fpu_reg_con );
+ ins_encode %{
+ __ fldz();
+ __ fstp_d($dst$$reg);
+ %}
+ ins_pipe(fpu_reg_con);
+%}
+
+// The instruction usage is guarded by predicate in operand immD1().
+instruct loadConD1(regD dst, immD1 con) %{
+ match(Set dst con);
+ ins_cost(125);
+
+ format %{ "FLD1 ST\n\t"
+ "FSTP $dst" %}
+ ins_encode %{
+ __ fld1();
+ __ fstp_d($dst$$reg);
+ %}
+ ins_pipe(fpu_reg_con);
%}
// The instruction usage is guarded by predicate in operand immXD().
instruct loadConXD(regXD dst, immXD con) %{
match(Set dst con);
ins_cost(125);
- format %{ "MOVSD $dst,[$con]" %}
- ins_encode(load_conXD(dst, con));
- ins_pipe( pipe_slow );
+ format %{ "MOVSD $dst,[$constantaddress]\t# load from constant table: double=$con" %}
+ ins_encode %{
+ __ movdbl($dst$$XMMRegister, $constantaddress($con));
+ %}
+ ins_pipe(pipe_slow);
%}
// The instruction usage is guarded by predicate in operand immXD0().
@@ -10303,41 +10296,45 @@
ins_pipe( fpu_reg_mem );
%}
-instruct addD_reg_imm1(regD dst, immD1 src) %{
+instruct addD_reg_imm1(regD dst, immD1 con) %{
predicate(UseSSE<=1);
- match(Set dst (AddD dst src));
+ match(Set dst (AddD dst con));
ins_cost(125);
format %{ "FLD1\n\t"
"DADDp $dst,ST" %}
- opcode(0xDE, 0x00);
- ins_encode( LdImmD(src),
- OpcP, RegOpc(dst) );
- ins_pipe( fpu_reg );
-%}
-
-instruct addD_reg_imm(regD dst, immD src) %{
+ ins_encode %{
+ __ fld1();
+ __ faddp($dst$$reg);
+ %}
+ ins_pipe(fpu_reg);
+%}
+
+instruct addD_reg_imm(regD dst, immD con) %{
predicate(UseSSE<=1 && _kids[1]->_leaf->getd() != 0.0 && _kids[1]->_leaf->getd() != 1.0 );
- match(Set dst (AddD dst src));
+ match(Set dst (AddD dst con));
ins_cost(200);
- format %{ "FLD_D [$src]\n\t"
+ format %{ "FLD_D [$constantaddress]\t# load from constant table: double=$con\n\t"
"DADDp $dst,ST" %}
- opcode(0xDE, 0x00); /* DE /0 */
- ins_encode( LdImmD(src),
- OpcP, RegOpc(dst));
- ins_pipe( fpu_reg_mem );
+ ins_encode %{
+ __ fld_d($constantaddress($con));
+ __ faddp($dst$$reg);
+ %}
+ ins_pipe(fpu_reg_mem);
%}
instruct addD_reg_imm_round(stackSlotD dst, regD src, immD con) %{
predicate(UseSSE<=1 && _kids[0]->_kids[1]->_leaf->getd() != 0.0 && _kids[0]->_kids[1]->_leaf->getd() != 1.0 );
match(Set dst (RoundDouble (AddD src con)));
ins_cost(200);
- format %{ "FLD_D [$con]\n\t"
+ format %{ "FLD_D [$constantaddress]\t# load from constant table: double=$con\n\t"
"DADD ST,$src\n\t"
"FSTP_D $dst\t# D-round" %}
- opcode(0xD8, 0x00); /* D8 /0 */
- ins_encode( LdImmD(con),
- OpcP, RegOpc(src), Pop_Mem_D(dst));
- ins_pipe( fpu_mem_reg_con );
+ ins_encode %{
+ __ fld_d($constantaddress($con));
+ __ fadd($src$$reg);
+ __ fstp_d(Address(rsp, $dst$$disp));
+ %}
+ ins_pipe(fpu_mem_reg_con);
%}
// Add two double precision floating point values in xmm
@@ -10352,9 +10349,11 @@
instruct addXD_imm(regXD dst, immXD con) %{
predicate(UseSSE>=2);
match(Set dst (AddD dst con));
- format %{ "ADDSD $dst,[$con]" %}
- ins_encode( Opcode(0xF2), Opcode(0x0F), Opcode(0x58), LdImmXD(dst, con) );
- ins_pipe( pipe_slow );
+ format %{ "ADDSD $dst,[$constantaddress]\t# load from constant table: double=$con" %}
+ ins_encode %{
+ __ addsd($dst$$XMMRegister, $constantaddress($con));
+ %}
+ ins_pipe(pipe_slow);
%}
instruct addXD_mem(regXD dst, memory mem) %{
@@ -10377,9 +10376,11 @@
instruct subXD_imm(regXD dst, immXD con) %{
predicate(UseSSE>=2);
match(Set dst (SubD dst con));
- format %{ "SUBSD $dst,[$con]" %}
- ins_encode( Opcode(0xF2), Opcode(0x0F), Opcode(0x5C), LdImmXD(dst, con) );
- ins_pipe( pipe_slow );
+ format %{ "SUBSD $dst,[$constantaddress]\t# load from constant table: double=$con" %}
+ ins_encode %{
+ __ subsd($dst$$XMMRegister, $constantaddress($con));
+ %}
+ ins_pipe(pipe_slow);
%}
instruct subXD_mem(regXD dst, memory mem) %{
@@ -10402,9 +10403,11 @@
instruct mulXD_imm(regXD dst, immXD con) %{
predicate(UseSSE>=2);
match(Set dst (MulD dst con));
- format %{ "MULSD $dst,[$con]" %}
- ins_encode( Opcode(0xF2), Opcode(0x0F), Opcode(0x59), LdImmXD(dst, con) );
- ins_pipe( pipe_slow );
+ format %{ "MULSD $dst,[$constantaddress]\t# load from constant table: double=$con" %}
+ ins_encode %{
+ __ mulsd($dst$$XMMRegister, $constantaddress($con));
+ %}
+ ins_pipe(pipe_slow);
%}
instruct mulXD_mem(regXD dst, memory mem) %{
@@ -10428,9 +10431,11 @@
instruct divXD_imm(regXD dst, immXD con) %{
predicate(UseSSE>=2);
match(Set dst (DivD dst con));
- format %{ "DIVSD $dst,[$con]" %}
- ins_encode( Opcode(0xF2), Opcode(0x0F), Opcode(0x5E), LdImmXD(dst, con));
- ins_pipe( pipe_slow );
+ format %{ "DIVSD $dst,[$constantaddress]\t# load from constant table: double=$con" %}
+ ins_encode %{
+ __ divsd($dst$$XMMRegister, $constantaddress($con));
+ %}
+ ins_pipe(pipe_slow);
%}
instruct divXD_mem(regXD dst, memory mem) %{
@@ -10481,16 +10486,17 @@
ins_pipe( fpu_reg_reg );
%}
-instruct mulD_reg_imm(regD dst, immD src) %{
+instruct mulD_reg_imm(regD dst, immD con) %{
predicate( UseSSE<=1 && _kids[1]->_leaf->getd() != 0.0 && _kids[1]->_leaf->getd() != 1.0 );
- match(Set dst (MulD dst src));
+ match(Set dst (MulD dst con));
ins_cost(200);
- format %{ "FLD_D [$src]\n\t"
+ format %{ "FLD_D [$constantaddress]\t# load from constant table: double=$con\n\t"
"DMULp $dst,ST" %}
- opcode(0xDE, 0x1); /* DE /1 */
- ins_encode( LdImmD(src),
- OpcP, RegOpc(dst) );
- ins_pipe( fpu_reg_mem );
+ ins_encode %{
+ __ fld_d($constantaddress($con));
+ __ fmulp($dst$$reg);
+ %}
+ ins_pipe(fpu_reg_mem);
%}
@@ -11224,9 +11230,11 @@
instruct addX_imm(regX dst, immXF con) %{
predicate(UseSSE>=1);
match(Set dst (AddF dst con));
- format %{ "ADDSS $dst,[$con]" %}
- ins_encode( Opcode(0xF3), Opcode(0x0F), Opcode(0x58), LdImmX(dst, con) );
- ins_pipe( pipe_slow );
+ format %{ "ADDSS $dst,[$constantaddress]\t# load from constant table: float=$con" %}
+ ins_encode %{
+ __ addss($dst$$XMMRegister, $constantaddress($con));
+ %}
+ ins_pipe(pipe_slow);
%}
instruct addX_mem(regX dst, memory mem) %{
@@ -11249,9 +11257,11 @@
instruct subX_imm(regX dst, immXF con) %{
predicate(UseSSE>=1);
match(Set dst (SubF dst con));
- format %{ "SUBSS $dst,[$con]" %}
- ins_encode( Opcode(0xF3), Opcode(0x0F), Opcode(0x5C), LdImmX(dst, con) );
- ins_pipe( pipe_slow );
+ format %{ "SUBSS $dst,[$constantaddress]\t# load from constant table: float=$con" %}
+ ins_encode %{
+ __ subss($dst$$XMMRegister, $constantaddress($con));
+ %}
+ ins_pipe(pipe_slow);
%}
instruct subX_mem(regX dst, memory mem) %{
@@ -11274,9 +11284,11 @@
instruct mulX_imm(regX dst, immXF con) %{
predicate(UseSSE>=1);
match(Set dst (MulF dst con));
- format %{ "MULSS $dst,[$con]" %}
- ins_encode( Opcode(0xF3), Opcode(0x0F), Opcode(0x59), LdImmX(dst, con) );
- ins_pipe( pipe_slow );
+ format %{ "MULSS $dst,[$constantaddress]\t# load from constant table: float=$con" %}
+ ins_encode %{
+ __ mulss($dst$$XMMRegister, $constantaddress($con));
+ %}
+ ins_pipe(pipe_slow);
%}
instruct mulX_mem(regX dst, memory mem) %{
@@ -11299,9 +11311,11 @@
instruct divX_imm(regX dst, immXF con) %{
predicate(UseSSE>=1);
match(Set dst (DivF dst con));
- format %{ "DIVSS $dst,[$con]" %}
- ins_encode( Opcode(0xF3), Opcode(0x0F), Opcode(0x5E), LdImmX(dst, con) );
- ins_pipe( pipe_slow );
+ format %{ "DIVSS $dst,[$constantaddress]\t# load from constant table: float=$con" %}
+ ins_encode %{
+ __ divss($dst$$XMMRegister, $constantaddress($con));
+ %}
+ ins_pipe(pipe_slow);
%}
instruct divX_mem(regX dst, memory mem) %{
@@ -11456,31 +11470,33 @@
// Spill to obtain 24-bit precision
-instruct addF24_reg_imm(stackSlotF dst, regF src1, immF src2) %{
+instruct addF24_reg_imm(stackSlotF dst, regF src, immF con) %{
predicate(UseSSE==0 && Compile::current()->select_24_bit_instr());
- match(Set dst (AddF src1 src2));
- format %{ "FLD $src1\n\t"
- "FADD $src2\n\t"
+ match(Set dst (AddF src con));
+ format %{ "FLD $src\n\t"
+ "FADD_S [$constantaddress]\t# load from constant table: float=$con\n\t"
"FSTP_S $dst" %}
- opcode(0xD8, 0x00); /* D8 /0 */
- ins_encode( Push_Reg_F(src1),
- Opc_MemImm_F(src2),
- Pop_Mem_F(dst));
- ins_pipe( fpu_mem_reg_con );
+ ins_encode %{
+ __ fld_s($src$$reg - 1); // FLD ST(i-1)
+ __ fadd_s($constantaddress($con));
+ __ fstp_s(Address(rsp, $dst$$disp));
+ %}
+ ins_pipe(fpu_mem_reg_con);
%}
//
// This instruction does not round to 24-bits
-instruct addF_reg_imm(regF dst, regF src1, immF src2) %{
+instruct addF_reg_imm(regF dst, regF src, immF con) %{
predicate(UseSSE==0 && !Compile::current()->select_24_bit_instr());
- match(Set dst (AddF src1 src2));
- format %{ "FLD $src1\n\t"
- "FADD $src2\n\t"
- "FSTP_S $dst" %}
- opcode(0xD8, 0x00); /* D8 /0 */
- ins_encode( Push_Reg_F(src1),
- Opc_MemImm_F(src2),
- Pop_Reg_F(dst));
- ins_pipe( fpu_reg_reg_con );
+ match(Set dst (AddF src con));
+ format %{ "FLD $src\n\t"
+ "FADD_S [$constantaddress]\t# load from constant table: float=$con\n\t"
+ "FSTP $dst" %}
+ ins_encode %{
+ __ fld_s($src$$reg - 1); // FLD ST(i-1)
+ __ fadd_s($constantaddress($con));
+ __ fstp_d($dst$$reg);
+ %}
+ ins_pipe(fpu_reg_reg_con);
%}
// Spill to obtain 24-bit precision
@@ -11559,29 +11575,35 @@
%}
// Spill to obtain 24-bit precision
-instruct mulF24_reg_imm(stackSlotF dst, regF src1, immF src2) %{
+instruct mulF24_reg_imm(stackSlotF dst, regF src, immF con) %{
predicate(UseSSE==0 && Compile::current()->select_24_bit_instr());
- match(Set dst (MulF src1 src2));
-
- format %{ "FMULc $dst,$src1,$src2" %}
- opcode(0xD8, 0x1); /* D8 /1*/
- ins_encode( Push_Reg_F(src1),
- Opc_MemImm_F(src2),
- Pop_Mem_F(dst));
- ins_pipe( fpu_mem_reg_con );
+ match(Set dst (MulF src con));
+
+ format %{ "FLD $src\n\t"
+ "FMUL_S [$constantaddress]\t# load from constant table: float=$con\n\t"
+ "FSTP_S $dst" %}
+ ins_encode %{
+ __ fld_s($src$$reg - 1); // FLD ST(i-1)
+ __ fmul_s($constantaddress($con));
+ __ fstp_s(Address(rsp, $dst$$disp));
+ %}
+ ins_pipe(fpu_mem_reg_con);
%}
//
// This instruction does not round to 24-bits
-instruct mulF_reg_imm(regF dst, regF src1, immF src2) %{
+instruct mulF_reg_imm(regF dst, regF src, immF con) %{
predicate(UseSSE==0 && !Compile::current()->select_24_bit_instr());
- match(Set dst (MulF src1 src2));
-
- format %{ "FMULc $dst. $src1, $src2" %}
- opcode(0xD8, 0x1); /* D8 /1*/
- ins_encode( Push_Reg_F(src1),
- Opc_MemImm_F(src2),
- Pop_Reg_F(dst));
- ins_pipe( fpu_reg_reg_con );
+ match(Set dst (MulF src con));
+
+ format %{ "FLD $src\n\t"
+ "FMUL_S [$constantaddress]\t# load from constant table: float=$con\n\t"
+ "FSTP $dst" %}
+ ins_encode %{
+ __ fld_s($src$$reg - 1); // FLD ST(i-1)
+ __ fmul_s($constantaddress($con));
+ __ fstp_d($dst$$reg);
+ %}
+ ins_pipe(fpu_reg_reg_con);
%}
@@ -12939,16 +12961,11 @@
instruct jumpXtnd(eRegI switch_val) %{
match(Jump switch_val);
ins_cost(350);
-
- format %{ "JMP [table_base](,$switch_val,1)\n\t" %}
-
- ins_encode %{
- address table_base = __ address_table_constant(_index2label);
-
+ format %{ "JMP [$constantaddress](,$switch_val,1)\n\t" %}
+ ins_encode %{
// Jump to Address(table_base + switch_reg)
- InternalAddress table(table_base);
Address index(noreg, $switch_val$$Register, Address::times_1);
- __ jump(ArrayAddress(table, index));
+ __ jump(ArrayAddress($constantaddress, index));
%}
ins_pc_relative(1);
ins_pipe(pipe_jmp);
--- a/hotspot/src/cpu/x86/vm/x86_64.ad Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/cpu/x86/vm/x86_64.ad Wed Dec 08 17:50:49 2010 -0800
@@ -833,6 +833,25 @@
//=============================================================================
+const bool Matcher::constant_table_absolute_addressing = true;
+const RegMask& MachConstantBaseNode::_out_RegMask = RegMask::Empty;
+
+void MachConstantBaseNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const {
+ // Empty encoding
+}
+
+uint MachConstantBaseNode::size(PhaseRegAlloc* ra_) const {
+ return 0;
+}
+
+#ifndef PRODUCT
+void MachConstantBaseNode::format(PhaseRegAlloc* ra_, outputStream* st) const {
+ st->print("# MachConstantBaseNode (empty encoding)");
+}
+#endif
+
+
+//=============================================================================
#ifndef PRODUCT
void MachPrologNode::format(PhaseRegAlloc* ra_, outputStream* st) const
{
@@ -1922,28 +1941,6 @@
return offset;
}
-static void emit_double_constant(CodeBuffer& cbuf, double x) {
- int mark = cbuf.insts()->mark_off();
- MacroAssembler _masm(&cbuf);
- address double_address = __ double_constant(x);
- cbuf.insts()->set_mark_off(mark); // preserve mark across masm shift
- emit_d32_reloc(cbuf,
- (int) (double_address - cbuf.insts_end() - 4),
- internal_word_Relocation::spec(double_address),
- RELOC_DISP32);
-}
-
-static void emit_float_constant(CodeBuffer& cbuf, float x) {
- int mark = cbuf.insts()->mark_off();
- MacroAssembler _masm(&cbuf);
- address float_address = __ float_constant(x);
- cbuf.insts()->set_mark_off(mark); // preserve mark across masm shift
- emit_d32_reloc(cbuf,
- (int) (float_address - cbuf.insts_end() - 4),
- internal_word_Relocation::spec(float_address),
- RELOC_DISP32);
-}
-
const bool Matcher::match_rule_supported(int opcode) {
if (!has_match_rule(opcode))
@@ -2789,43 +2786,6 @@
}
%}
- enc_class load_immF(regF dst, immF con)
- %{
- // XXX reg_mem doesn't support RIP-relative addressing yet
- emit_rm(cbuf, 0x0, $dst$$reg & 7, 0x5); // 00 reg 101
- emit_float_constant(cbuf, $con$$constant);
- %}
-
- enc_class load_immD(regD dst, immD con)
- %{
- // XXX reg_mem doesn't support RIP-relative addressing yet
- emit_rm(cbuf, 0x0, $dst$$reg & 7, 0x5); // 00 reg 101
- emit_double_constant(cbuf, $con$$constant);
- %}
-
- enc_class load_conF (regF dst, immF con) %{ // Load float constant
- emit_opcode(cbuf, 0xF3);
- if ($dst$$reg >= 8) {
- emit_opcode(cbuf, Assembler::REX_R);
- }
- emit_opcode(cbuf, 0x0F);
- emit_opcode(cbuf, 0x10);
- emit_rm(cbuf, 0x0, $dst$$reg & 7, 0x5); // 00 reg 101
- emit_float_constant(cbuf, $con$$constant);
- %}
-
- enc_class load_conD (regD dst, immD con) %{ // Load double constant
- // UseXmmLoadAndClearUpper ? movsd(dst, con) : movlpd(dst, con)
- emit_opcode(cbuf, UseXmmLoadAndClearUpper ? 0xF2 : 0x66);
- if ($dst$$reg >= 8) {
- emit_opcode(cbuf, Assembler::REX_R);
- }
- emit_opcode(cbuf, 0x0F);
- emit_opcode(cbuf, UseXmmLoadAndClearUpper ? 0x10 : 0x12);
- emit_rm(cbuf, 0x0, $dst$$reg & 7, 0x5); // 00 reg 101
- emit_double_constant(cbuf, $con$$constant);
- %}
-
// Encode a reg-reg copy. If it is useless, then empty encoding.
enc_class enc_copy(rRegI dst, rRegI src)
%{
@@ -2926,63 +2886,6 @@
emit_d32(cbuf, 0x00);
%}
- enc_class jump_enc(rRegL switch_val, rRegI dest) %{
- MacroAssembler masm(&cbuf);
-
- Register switch_reg = as_Register($switch_val$$reg);
- Register dest_reg = as_Register($dest$$reg);
- address table_base = masm.address_table_constant(_index2label);
-
- // We could use jump(ArrayAddress) except that the macro assembler needs to use r10
- // to do that and the compiler is using that register as one it can allocate.
- // So we build it all by hand.
- // Address index(noreg, switch_reg, Address::times_1);
- // ArrayAddress dispatch(table, index);
-
- Address dispatch(dest_reg, switch_reg, Address::times_1);
-
- masm.lea(dest_reg, InternalAddress(table_base));
- masm.jmp(dispatch);
- %}
-
- enc_class jump_enc_addr(rRegL switch_val, immI2 shift, immL32 offset, rRegI dest) %{
- MacroAssembler masm(&cbuf);
-
- Register switch_reg = as_Register($switch_val$$reg);
- Register dest_reg = as_Register($dest$$reg);
- address table_base = masm.address_table_constant(_index2label);
-
- // We could use jump(ArrayAddress) except that the macro assembler needs to use r10
- // to do that and the compiler is using that register as one it can allocate.
- // So we build it all by hand.
- // Address index(noreg, switch_reg, (Address::ScaleFactor)$shift$$constant, (int)$offset$$constant);
- // ArrayAddress dispatch(table, index);
-
- Address dispatch(dest_reg, switch_reg, (Address::ScaleFactor)$shift$$constant, (int)$offset$$constant);
-
- masm.lea(dest_reg, InternalAddress(table_base));
- masm.jmp(dispatch);
- %}
-
- enc_class jump_enc_offset(rRegL switch_val, immI2 shift, rRegI dest) %{
- MacroAssembler masm(&cbuf);
-
- Register switch_reg = as_Register($switch_val$$reg);
- Register dest_reg = as_Register($dest$$reg);
- address table_base = masm.address_table_constant(_index2label);
-
- // We could use jump(ArrayAddress) except that the macro assembler needs to use r10
- // to do that and the compiler is using that register as one it can allocate.
- // So we build it all by hand.
- // Address index(noreg, switch_reg, (Address::ScaleFactor)$shift$$constant);
- // ArrayAddress dispatch(table, index);
-
- Address dispatch(dest_reg, switch_reg, (Address::ScaleFactor)$shift$$constant);
- masm.lea(dest_reg, InternalAddress(table_base));
- masm.jmp(dispatch);
-
- %}
-
enc_class lock_prefix()
%{
if (os::is_MP()) {
@@ -6641,12 +6544,11 @@
ins_pipe(ialu_reg);
%}
-instruct loadConP(rRegP dst, immP src)
-%{
- match(Set dst src);
-
- format %{ "movq $dst, $src\t# ptr" %}
- ins_encode(load_immP(dst, src));
+instruct loadConP(rRegP dst, immP con) %{
+ match(Set dst con);
+
+ format %{ "movq $dst, $con\t# ptr" %}
+ ins_encode(load_immP(dst, con));
ins_pipe(ialu_reg_fat); // XXX
%}
@@ -6673,13 +6575,13 @@
ins_pipe(ialu_reg);
%}
-instruct loadConF(regF dst, immF src)
-%{
- match(Set dst src);
+instruct loadConF(regF dst, immF con) %{
+ match(Set dst con);
ins_cost(125);
-
- format %{ "movss $dst, [$src]" %}
- ins_encode(load_conF(dst, src));
+ format %{ "movss $dst, [$constantaddress]\t# load from constant table: float=$con" %}
+ ins_encode %{
+ __ movflt($dst$$XMMRegister, $constantaddress($con));
+ %}
ins_pipe(pipe_slow);
%}
@@ -6721,13 +6623,13 @@
%}
// Use the same format since predicate() can not be used here.
-instruct loadConD(regD dst, immD src)
-%{
- match(Set dst src);
+instruct loadConD(regD dst, immD con) %{
+ match(Set dst con);
ins_cost(125);
-
- format %{ "movsd $dst, [$src]" %}
- ins_encode(load_conD(dst, src));
+ format %{ "movsd $dst, [$constantaddress]\t# load from constant table: double=$con" %}
+ ins_encode %{
+ __ movdbl($dst$$XMMRegister, $constantaddress($con));
+ %}
ins_pipe(pipe_slow);
%}
@@ -7694,9 +7596,18 @@
predicate(false);
effect(TEMP dest);
- format %{ "leaq $dest, table_base\n\t"
+ format %{ "leaq $dest, [$constantaddress]\n\t"
"jmp [$dest + $switch_val << $shift]\n\t" %}
- ins_encode(jump_enc_offset(switch_val, shift, dest));
+ ins_encode %{
+ // We could use jump(ArrayAddress) except that the macro assembler needs to use r10
+ // to do that and the compiler is using that register as one it can allocate.
+ // So we build it all by hand.
+ // Address index(noreg, switch_reg, (Address::ScaleFactor)$shift$$constant);
+ // ArrayAddress dispatch(table, index);
+ Address dispatch($dest$$Register, $switch_val$$Register, (Address::ScaleFactor) $shift$$constant);
+ __ lea($dest$$Register, $constantaddress);
+ __ jmp(dispatch);
+ %}
ins_pipe(pipe_jmp);
ins_pc_relative(1);
%}
@@ -7706,9 +7617,18 @@
ins_cost(350);
effect(TEMP dest);
- format %{ "leaq $dest, table_base\n\t"
+ format %{ "leaq $dest, [$constantaddress]\n\t"
"jmp [$dest + $switch_val << $shift + $offset]\n\t" %}
- ins_encode(jump_enc_addr(switch_val, shift, offset, dest));
+ ins_encode %{
+ // We could use jump(ArrayAddress) except that the macro assembler needs to use r10
+ // to do that and the compiler is using that register as one it can allocate.
+ // So we build it all by hand.
+ // Address index(noreg, switch_reg, (Address::ScaleFactor) $shift$$constant, (int) $offset$$constant);
+ // ArrayAddress dispatch(table, index);
+ Address dispatch($dest$$Register, $switch_val$$Register, (Address::ScaleFactor) $shift$$constant, (int) $offset$$constant);
+ __ lea($dest$$Register, $constantaddress);
+ __ jmp(dispatch);
+ %}
ins_pipe(pipe_jmp);
ins_pc_relative(1);
%}
@@ -7718,9 +7638,18 @@
ins_cost(350);
effect(TEMP dest);
- format %{ "leaq $dest, table_base\n\t"
+ format %{ "leaq $dest, [$constantaddress]\n\t"
"jmp [$dest + $switch_val]\n\t" %}
- ins_encode(jump_enc(switch_val, dest));
+ ins_encode %{
+ // We could use jump(ArrayAddress) except that the macro assembler needs to use r10
+ // to do that and the compiler is using that register as one it can allocate.
+ // So we build it all by hand.
+ // Address index(noreg, switch_reg, Address::times_1);
+ // ArrayAddress dispatch(table, index);
+ Address dispatch($dest$$Register, $switch_val$$Register, Address::times_1);
+ __ lea($dest$$Register, $constantaddress);
+ __ jmp(dispatch);
+ %}
ins_pipe(pipe_jmp);
ins_pc_relative(1);
%}
@@ -10376,30 +10305,36 @@
ins_pipe(pipe_slow);
%}
-instruct cmpF_cc_imm(rFlagsRegU cr, regF src1, immF src2)
-%{
- match(Set cr (CmpF src1 src2));
+instruct cmpF_cc_imm(rFlagsRegU cr, regF src, immF con) %{
+ match(Set cr (CmpF src con));
ins_cost(145);
- format %{ "ucomiss $src1, $src2\n\t"
+ format %{ "ucomiss $src, [$constantaddress]\t# load from constant table: float=$con\n\t"
"jnp,s exit\n\t"
"pushfq\t# saw NaN, set CF\n\t"
"andq [rsp], #0xffffff2b\n\t"
"popfq\n"
"exit: nop\t# avoid branch to branch" %}
- opcode(0x0F, 0x2E);
- ins_encode(REX_reg_mem(src1, src2), OpcP, OpcS, load_immF(src1, src2),
- cmpfp_fixup);
- ins_pipe(pipe_slow);
-%}
-
-instruct cmpF_cc_immCF(rFlagsRegUCF cr, regF src1, immF src2) %{
- match(Set cr (CmpF src1 src2));
-
+ ins_encode %{
+ Label L_exit;
+ __ ucomiss($src$$XMMRegister, $constantaddress($con));
+ __ jcc(Assembler::noParity, L_exit);
+ __ pushf();
+ __ andq(rsp, 0xffffff2b);
+ __ popf();
+ __ bind(L_exit);
+ __ nop();
+ %}
+ ins_pipe(pipe_slow);
+%}
+
+instruct cmpF_cc_immCF(rFlagsRegUCF cr, regF src, immF con) %{
+ match(Set cr (CmpF src con));
ins_cost(100);
- format %{ "ucomiss $src1, $src2" %}
- opcode(0x0F, 0x2E);
- ins_encode(REX_reg_mem(src1, src2), OpcP, OpcS, load_immF(src1, src2));
+ format %{ "ucomiss $src, [$constantaddress]\t# load from constant table: float=$con" %}
+ ins_encode %{
+ __ ucomiss($src$$XMMRegister, $constantaddress($con));
+ %}
ins_pipe(pipe_slow);
%}
@@ -10458,30 +10393,36 @@
ins_pipe(pipe_slow);
%}
-instruct cmpD_cc_imm(rFlagsRegU cr, regD src1, immD src2)
-%{
- match(Set cr (CmpD src1 src2));
+instruct cmpD_cc_imm(rFlagsRegU cr, regD src, immD con) %{
+ match(Set cr (CmpD src con));
ins_cost(145);
- format %{ "ucomisd $src1, [$src2]\n\t"
+ format %{ "ucomisd $src, [$constantaddress]\t# load from constant table: double=$con\n\t"
"jnp,s exit\n\t"
"pushfq\t# saw NaN, set CF\n\t"
"andq [rsp], #0xffffff2b\n\t"
"popfq\n"
"exit: nop\t# avoid branch to branch" %}
- opcode(0x66, 0x0F, 0x2E);
- ins_encode(OpcP, REX_reg_mem(src1, src2), OpcS, OpcT, load_immD(src1, src2),
- cmpfp_fixup);
- ins_pipe(pipe_slow);
-%}
-
-instruct cmpD_cc_immCF(rFlagsRegUCF cr, regD src1, immD src2) %{
- match(Set cr (CmpD src1 src2));
-
+ ins_encode %{
+ Label L_exit;
+ __ ucomisd($src$$XMMRegister, $constantaddress($con));
+ __ jcc(Assembler::noParity, L_exit);
+ __ pushf();
+ __ andq(rsp, 0xffffff2b);
+ __ popf();
+ __ bind(L_exit);
+ __ nop();
+ %}
+ ins_pipe(pipe_slow);
+%}
+
+instruct cmpD_cc_immCF(rFlagsRegUCF cr, regD src, immD con) %{
+ match(Set cr (CmpD src con));
ins_cost(100);
- format %{ "ucomisd $src1, [$src2]" %}
- opcode(0x66, 0x0F, 0x2E);
- ins_encode(OpcP, REX_reg_mem(src1, src2), OpcS, OpcT, load_immD(src1, src2));
+ format %{ "ucomisd $src, [$constantaddress]\t# load from constant table: double=$con" %}
+ ins_encode %{
+ __ ucomisd($src$$XMMRegister, $constantaddress($con));
+ %}
ins_pipe(pipe_slow);
%}
@@ -10528,23 +10469,29 @@
%}
// Compare into -1,0,1
-instruct cmpF_imm(rRegI dst, regF src1, immF src2, rFlagsReg cr)
-%{
- match(Set dst (CmpF3 src1 src2));
+instruct cmpF_imm(rRegI dst, regF src, immF con, rFlagsReg cr) %{
+ match(Set dst (CmpF3 src con));
effect(KILL cr);
ins_cost(275);
- format %{ "ucomiss $src1, [$src2]\n\t"
+ format %{ "ucomiss $src, [$constantaddress]\t# load from constant table: float=$con\n\t"
"movl $dst, #-1\n\t"
"jp,s done\n\t"
"jb,s done\n\t"
"setne $dst\n\t"
"movzbl $dst, $dst\n"
"done:" %}
-
- opcode(0x0F, 0x2E);
- ins_encode(REX_reg_mem(src1, src2), OpcP, OpcS, load_immF(src1, src2),
- cmpfp3(dst));
+ ins_encode %{
+ Label L_done;
+ Register Rdst = $dst$$Register;
+ __ ucomiss($src$$XMMRegister, $constantaddress($con));
+ __ movl(Rdst, -1);
+ __ jcc(Assembler::parity, L_done);
+ __ jcc(Assembler::below, L_done);
+ __ setb(Assembler::notEqual, Rdst);
+ __ movzbl(Rdst, Rdst);
+ __ bind(L_done);
+ %}
ins_pipe(pipe_slow);
%}
@@ -10591,23 +10538,29 @@
%}
// Compare into -1,0,1
-instruct cmpD_imm(rRegI dst, regD src1, immD src2, rFlagsReg cr)
-%{
- match(Set dst (CmpD3 src1 src2));
+instruct cmpD_imm(rRegI dst, regD src, immD con, rFlagsReg cr) %{
+ match(Set dst (CmpD3 src con));
effect(KILL cr);
ins_cost(275);
- format %{ "ucomisd $src1, [$src2]\n\t"
+ format %{ "ucomisd $src, [$constantaddress]\t# load from constant table: double=$con\n\t"
"movl $dst, #-1\n\t"
"jp,s done\n\t"
"jb,s done\n\t"
"setne $dst\n\t"
"movzbl $dst, $dst\n"
"done:" %}
-
- opcode(0x66, 0x0F, 0x2E);
- ins_encode(OpcP, REX_reg_mem(src1, src2), OpcS, OpcT, load_immD(src1, src2),
- cmpfp3(dst));
+ ins_encode %{
+ Register Rdst = $dst$$Register;
+ Label L_done;
+ __ ucomisd($src$$XMMRegister, $constantaddress($con));
+ __ movl(Rdst, -1);
+ __ jcc(Assembler::parity, L_done);
+ __ jcc(Assembler::below, L_done);
+ __ setb(Assembler::notEqual, Rdst);
+ __ movzbl(Rdst, Rdst);
+ __ bind(L_done);
+ %}
ins_pipe(pipe_slow);
%}
@@ -10633,14 +10586,13 @@
ins_pipe(pipe_slow);
%}
-instruct addF_imm(regF dst, immF src)
-%{
- match(Set dst (AddF dst src));
-
- format %{ "addss $dst, [$src]" %}
+instruct addF_imm(regF dst, immF con) %{
+ match(Set dst (AddF dst con));
+ format %{ "addss $dst, [$constantaddress]\t# load from constant table: float=$con" %}
ins_cost(150); // XXX
- opcode(0xF3, 0x0F, 0x58);
- ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, load_immF(dst, src));
+ ins_encode %{
+ __ addss($dst$$XMMRegister, $constantaddress($con));
+ %}
ins_pipe(pipe_slow);
%}
@@ -10666,14 +10618,13 @@
ins_pipe(pipe_slow);
%}
-instruct addD_imm(regD dst, immD src)
-%{
- match(Set dst (AddD dst src));
-
- format %{ "addsd $dst, [$src]" %}
+instruct addD_imm(regD dst, immD con) %{
+ match(Set dst (AddD dst con));
+ format %{ "addsd $dst, [$constantaddress]\t# load from constant table: double=$con" %}
ins_cost(150); // XXX
- opcode(0xF2, 0x0F, 0x58);
- ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, load_immD(dst, src));
+ ins_encode %{
+ __ addsd($dst$$XMMRegister, $constantaddress($con));
+ %}
ins_pipe(pipe_slow);
%}
@@ -10699,14 +10650,13 @@
ins_pipe(pipe_slow);
%}
-instruct subF_imm(regF dst, immF src)
-%{
- match(Set dst (SubF dst src));
-
- format %{ "subss $dst, [$src]" %}
+instruct subF_imm(regF dst, immF con) %{
+ match(Set dst (SubF dst con));
+ format %{ "subss $dst, [$constantaddress]\t# load from constant table: float=$con" %}
ins_cost(150); // XXX
- opcode(0xF3, 0x0F, 0x5C);
- ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, load_immF(dst, src));
+ ins_encode %{
+ __ subss($dst$$XMMRegister, $constantaddress($con));
+ %}
ins_pipe(pipe_slow);
%}
@@ -10732,14 +10682,13 @@
ins_pipe(pipe_slow);
%}
-instruct subD_imm(regD dst, immD src)
-%{
- match(Set dst (SubD dst src));
-
- format %{ "subsd $dst, [$src]" %}
+instruct subD_imm(regD dst, immD con) %{
+ match(Set dst (SubD dst con));
+ format %{ "subsd $dst, [$constantaddress]\t# load from constant table: double=$con" %}
ins_cost(150); // XXX
- opcode(0xF2, 0x0F, 0x5C);
- ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, load_immD(dst, src));
+ ins_encode %{
+ __ subsd($dst$$XMMRegister, $constantaddress($con));
+ %}
ins_pipe(pipe_slow);
%}
@@ -10765,14 +10714,13 @@
ins_pipe(pipe_slow);
%}
-instruct mulF_imm(regF dst, immF src)
-%{
- match(Set dst (MulF dst src));
-
- format %{ "mulss $dst, [$src]" %}
+instruct mulF_imm(regF dst, immF con) %{
+ match(Set dst (MulF dst con));
+ format %{ "mulss $dst, [$constantaddress]\t# load from constant table: float=$con" %}
ins_cost(150); // XXX
- opcode(0xF3, 0x0F, 0x59);
- ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, load_immF(dst, src));
+ ins_encode %{
+ __ mulss($dst$$XMMRegister, $constantaddress($con));
+ %}
ins_pipe(pipe_slow);
%}
@@ -10798,14 +10746,13 @@
ins_pipe(pipe_slow);
%}
-instruct mulD_imm(regD dst, immD src)
-%{
- match(Set dst (MulD dst src));
-
- format %{ "mulsd $dst, [$src]" %}
+instruct mulD_imm(regD dst, immD con) %{
+ match(Set dst (MulD dst con));
+ format %{ "mulsd $dst, [$constantaddress]\t# load from constant table: double=$con" %}
ins_cost(150); // XXX
- opcode(0xF2, 0x0F, 0x59);
- ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, load_immD(dst, src));
+ ins_encode %{
+ __ mulsd($dst$$XMMRegister, $constantaddress($con));
+ %}
ins_pipe(pipe_slow);
%}
@@ -10831,14 +10778,13 @@
ins_pipe(pipe_slow);
%}
-instruct divF_imm(regF dst, immF src)
-%{
- match(Set dst (DivF dst src));
-
- format %{ "divss $dst, [$src]" %}
+instruct divF_imm(regF dst, immF con) %{
+ match(Set dst (DivF dst con));
+ format %{ "divss $dst, [$constantaddress]\t# load from constant table: float=$con" %}
ins_cost(150); // XXX
- opcode(0xF3, 0x0F, 0x5E);
- ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, load_immF(dst, src));
+ ins_encode %{
+ __ divss($dst$$XMMRegister, $constantaddress($con));
+ %}
ins_pipe(pipe_slow);
%}
@@ -10864,14 +10810,13 @@
ins_pipe(pipe_slow);
%}
-instruct divD_imm(regD dst, immD src)
-%{
- match(Set dst (DivD dst src));
-
- format %{ "divsd $dst, [$src]" %}
+instruct divD_imm(regD dst, immD con) %{
+ match(Set dst (DivD dst con));
+ format %{ "divsd $dst, [$constantaddress]\t# load from constant table: double=$con" %}
ins_cost(150); // XXX
- opcode(0xF2, 0x0F, 0x5E);
- ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, load_immD(dst, src));
+ ins_encode %{
+ __ divsd($dst$$XMMRegister, $constantaddress($con));
+ %}
ins_pipe(pipe_slow);
%}
@@ -10897,14 +10842,13 @@
ins_pipe(pipe_slow);
%}
-instruct sqrtF_imm(regF dst, immF src)
-%{
- match(Set dst (ConvD2F (SqrtD (ConvF2D src))));
-
- format %{ "sqrtss $dst, [$src]" %}
+instruct sqrtF_imm(regF dst, immF con) %{
+ match(Set dst (ConvD2F (SqrtD (ConvF2D con))));
+ format %{ "sqrtss $dst, [$constantaddress]\t# load from constant table: float=$con" %}
ins_cost(150); // XXX
- opcode(0xF3, 0x0F, 0x51);
- ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, load_immF(dst, src));
+ ins_encode %{
+ __ sqrtss($dst$$XMMRegister, $constantaddress($con));
+ %}
ins_pipe(pipe_slow);
%}
@@ -10930,14 +10874,13 @@
ins_pipe(pipe_slow);
%}
-instruct sqrtD_imm(regD dst, immD src)
-%{
- match(Set dst (SqrtD src));
-
- format %{ "sqrtsd $dst, [$src]" %}
+instruct sqrtD_imm(regD dst, immD con) %{
+ match(Set dst (SqrtD con));
+ format %{ "sqrtsd $dst, [$constantaddress]\t# load from constant table: double=$con" %}
ins_cost(150); // XXX
- opcode(0xF2, 0x0F, 0x51);
- ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, load_immD(dst, src));
+ ins_encode %{
+ __ sqrtsd($dst$$XMMRegister, $constantaddress($con));
+ %}
ins_pipe(pipe_slow);
%}
--- a/hotspot/src/os/linux/vm/vmError_linux.cpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/os/linux/vm/vmError_linux.cpp Wed Dec 08 17:50:49 2010 -0800
@@ -44,11 +44,11 @@
jio_snprintf(p, buflen - len,
"\n\n"
"Do you want to debug the problem?\n\n"
- "To debug, run 'gdb /proc/%d/exe %d'; then switch to thread " INTX_FORMAT "\n"
+ "To debug, run 'gdb /proc/%d/exe %d'; then switch to thread " INTX_FORMAT " (" INTPTR_FORMAT ")\n"
"Enter 'yes' to launch gdb automatically (PATH must include gdb)\n"
"Otherwise, press RETURN to abort...",
os::current_process_id(), os::current_process_id(),
- os::current_thread_id());
+ os::current_thread_id(), os::current_thread_id());
yes = os::message_box("Unexpected Error", buf);
--- a/hotspot/src/share/vm/adlc/adlparse.cpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/share/vm/adlc/adlparse.cpp Wed Dec 08 17:50:49 2010 -0800
@@ -95,7 +95,7 @@
if (ident == NULL) { // Empty line
continue; // Get the next line
}
- if (!strcmp(ident, "instruct")) instr_parse();
+ if (!strcmp(ident, "instruct")) instr_parse();
else if (!strcmp(ident, "operand")) oper_parse();
else if (!strcmp(ident, "opclass")) opclass_parse();
else if (!strcmp(ident, "ins_attrib")) ins_attr_parse();
@@ -216,24 +216,23 @@
else if (!strcmp(ident, "encode")) {
parse_err(SYNERR, "Instructions specify ins_encode, not encode\n");
}
- else if (!strcmp(ident, "ins_encode"))
- instr->_insencode = ins_encode_parse(*instr);
- else if (!strcmp(ident, "opcode")) instr->_opcode = opcode_parse(instr);
- else if (!strcmp(ident, "size")) instr->_size = size_parse(instr);
- else if (!strcmp(ident, "effect")) effect_parse(instr);
- else if (!strcmp(ident, "expand")) instr->_exprule = expand_parse(instr);
- else if (!strcmp(ident, "rewrite")) instr->_rewrule = rewrite_parse();
+ else if (!strcmp(ident, "ins_encode")) ins_encode_parse(*instr);
+ else if (!strcmp(ident, "opcode")) instr->_opcode = opcode_parse(instr);
+ else if (!strcmp(ident, "size")) instr->_size = size_parse(instr);
+ else if (!strcmp(ident, "effect")) effect_parse(instr);
+ else if (!strcmp(ident, "expand")) instr->_exprule = expand_parse(instr);
+ else if (!strcmp(ident, "rewrite")) instr->_rewrule = rewrite_parse();
else if (!strcmp(ident, "constraint")) {
parse_err(SYNERR, "Instructions do not specify a constraint\n");
}
else if (!strcmp(ident, "construct")) {
parse_err(SYNERR, "Instructions do not specify a construct\n");
}
- else if (!strcmp(ident, "format")) instr->_format = format_parse();
+ else if (!strcmp(ident, "format")) instr->_format = format_parse();
else if (!strcmp(ident, "interface")) {
parse_err(SYNERR, "Instructions do not specify an interface\n");
}
- else if (!strcmp(ident, "ins_pipe")) ins_pipe_parse(*instr);
+ else if (!strcmp(ident, "ins_pipe")) ins_pipe_parse(*instr);
else { // Done with staticly defined parts of instruction definition
// Check identifier to see if it is the name of an attribute
const Form *form = _globalNames[ident];
@@ -323,7 +322,8 @@
const char *optype2 = NULL;
// Can not have additional base operands in right side of match!
if ( ! right->base_operand( position, _globalNames, result2, name2, optype2) ) {
- assert( instr->_predicate == NULL, "ADLC does not support instruction chain rules with predicates");
+ if (instr->_predicate != NULL)
+ parse_err(SYNERR, "ADLC does not support instruction chain rules with predicates");
// Chain from input _ideal_operand_type_,
// Needed for shared roots of match-trees
ChainList *lst = (ChainList *)_AD._chainRules[optype];
@@ -935,9 +935,9 @@
// (2)
// If we are at a replacement variable,
// copy it and record in EncClass
- if ( _curchar == '$' ) {
+ if (_curchar == '$') {
// Found replacement Variable
- char *rep_var = get_rep_var_ident_dup();
+ char* rep_var = get_rep_var_ident_dup();
// Add flag to _strings list indicating we should check _rep_vars
encoding->add_rep_var(rep_var);
}
@@ -2774,47 +2774,122 @@
//------------------------------ins_encode_parse_block-------------------------
// Parse the block form of ins_encode. See ins_encode_parse for more details
-InsEncode *ADLParser::ins_encode_parse_block(InstructForm &inst) {
+void ADLParser::ins_encode_parse_block(InstructForm& inst) {
// Create a new encoding name based on the name of the instruction
// definition, which should be unique.
- const char * prefix = "__enc_";
- char* ec_name = (char*)malloc(strlen(inst._ident) + strlen(prefix) + 1);
+ const char* prefix = "__ins_encode_";
+ char* ec_name = (char*) malloc(strlen(inst._ident) + strlen(prefix) + 1);
sprintf(ec_name, "%s%s", prefix, inst._ident);
assert(_AD._encode->encClass(ec_name) == NULL, "shouldn't already exist");
- EncClass *encoding = _AD._encode->add_EncClass(ec_name);
+ EncClass* encoding = _AD._encode->add_EncClass(ec_name);
encoding->_linenum = linenum();
// synthesize the arguments list for the enc_class from the
// arguments to the instruct definition.
- const char * param = NULL;
+ const char* param = NULL;
inst._parameters.reset();
while ((param = inst._parameters.iter()) != NULL) {
- OperandForm *opForm = (OperandForm*)inst._localNames[param];
+ OperandForm* opForm = (OperandForm*) inst._localNames[param];
encoding->add_parameter(opForm->_ident, param);
}
- // Add the prologue to create the MacroAssembler
- encoding->add_code("\n"
- " // Define a MacroAssembler instance for use by the encoding. The\n"
- " // name is chosen to match the __ idiom used for assembly in other\n"
- " // parts of hotspot and assumes the existence of the standard\n"
- " // #define __ _masm.\n"
- " MacroAssembler _masm(&cbuf);\n");
+ // Define a MacroAssembler instance for use by the encoding. The
+ // name is chosen to match the __ idiom used for assembly in other
+ // parts of hotspot and assumes the existence of the standard
+ // #define __ _masm.
+ encoding->add_code(" MacroAssembler _masm(&cbuf);\n");
// Parse the following %{ }% block
- enc_class_parse_block(encoding, ec_name);
+ ins_encode_parse_block_impl(inst, encoding, ec_name);
// Build an encoding rule which invokes the encoding rule we just
// created, passing all arguments that we received.
- InsEncode *encrule = new InsEncode(); // Encode class for instruction
- NameAndList *params = encrule->add_encode(ec_name);
+ InsEncode* encrule = new InsEncode(); // Encode class for instruction
+ NameAndList* params = encrule->add_encode(ec_name);
inst._parameters.reset();
while ((param = inst._parameters.iter()) != NULL) {
params->add_entry(param);
}
- return encrule;
+ // Set encode class of this instruction.
+ inst._insencode = encrule;
+}
+
+
+void ADLParser::ins_encode_parse_block_impl(InstructForm& inst, EncClass* encoding, char* ec_name) {
+ skipws_no_preproc(); // Skip leading whitespace
+ // Prepend location descriptor, for debugging; cf. ADLParser::find_cpp_block
+ if (_AD._adlocation_debug) {
+ encoding->add_code(get_line_string());
+ }
+
+ // Collect the parts of the encode description
+ // (1) strings that are passed through to output
+ // (2) replacement/substitution variable, preceeded by a '$'
+ while ((_curchar != '%') && (*(_ptr+1) != '}')) {
+
+ // (1)
+ // Check if there is a string to pass through to output
+ char *start = _ptr; // Record start of the next string
+ while ((_curchar != '$') && ((_curchar != '%') || (*(_ptr+1) != '}')) ) {
+ // If at the start of a comment, skip past it
+ if( (_curchar == '/') && ((*(_ptr+1) == '/') || (*(_ptr+1) == '*')) ) {
+ skipws_no_preproc();
+ } else {
+ // ELSE advance to the next character, or start of the next line
+ next_char_or_line();
+ }
+ }
+ // If a string was found, terminate it and record in EncClass
+ if (start != _ptr) {
+ *_ptr = '\0'; // Terminate the string
+ encoding->add_code(start);
+ }
+
+ // (2)
+ // If we are at a replacement variable,
+ // copy it and record in EncClass
+ if (_curchar == '$') {
+ // Found replacement Variable
+ char* rep_var = get_rep_var_ident_dup();
+
+ // Add flag to _strings list indicating we should check _rep_vars
+ encoding->add_rep_var(rep_var);
+
+ skipws();
+
+ // Check if this instruct is a MachConstantNode.
+ if (strcmp(rep_var, "constanttablebase") == 0) {
+ // This instruct is a MachConstantNode.
+ inst.set_is_mach_constant(true);
+
+ if (_curchar == '(') {
+ parse_err(SYNERR, "constanttablebase in instruct %s cannot have an argument (only constantaddress and constantoffset)", ec_name);
+ return;
+ }
+ }
+ else if ((strcmp(rep_var, "constantaddress") == 0) ||
+ (strcmp(rep_var, "constantoffset") == 0)) {
+ // This instruct is a MachConstantNode.
+ inst.set_is_mach_constant(true);
+
+ // If the constant keyword has an argument, parse it.
+ if (_curchar == '(') constant_parse(inst);
+ }
+ }
+ } // end while part of format description
+ next_char(); // Skip '%'
+ next_char(); // Skip '}'
+
+ skipws();
+
+ if (_AD._adlocation_debug) {
+ encoding->add_code(end_line_marker());
+ }
+
+ // Debug Stuff
+ if (_AD._adl_debug > 1) fprintf(stderr, "EncodingClass Form: %s\n", ec_name);
}
@@ -2838,7 +2913,7 @@
//
// making it more compact to take advantage of the MacroAssembler and
// placing the assembly closer to it's use by instructions.
-InsEncode *ADLParser::ins_encode_parse(InstructForm &inst) {
+void ADLParser::ins_encode_parse(InstructForm& inst) {
// Parse encode class name
skipws(); // Skip whitespace
@@ -2849,11 +2924,12 @@
next_char(); // Skip '{'
// Parse the block form of ins_encode
- return ins_encode_parse_block(inst);
+ ins_encode_parse_block(inst);
+ return;
}
parse_err(SYNERR, "missing '%%{' or '(' in ins_encode definition\n");
- return NULL;
+ return;
}
next_char(); // move past '('
skipws();
@@ -2866,7 +2942,7 @@
ec_name = get_ident();
if (ec_name == NULL) {
parse_err(SYNERR, "Invalid encode class name after 'ins_encode('.\n");
- return NULL;
+ return;
}
// Check that encoding is defined in the encode section
EncClass *encode_class = _AD._encode->encClass(ec_name);
@@ -2898,7 +2974,7 @@
(Opcode::as_opcode_type(param) == Opcode::NOT_AN_OPCODE) &&
((_AD._register == NULL ) || (_AD._register->getRegDef(param) == NULL)) ) {
parse_err(SYNERR, "Using non-locally defined parameter %s for encoding %s.\n", param, ec_name);
- return NULL;
+ return;
}
params->add_entry(param);
@@ -2915,7 +2991,7 @@
// Only ',' or ')' are valid after a parameter name
parse_err(SYNERR, "expected ',' or ')' after parameter %s.\n",
ec_name);
- return NULL;
+ return;
}
} else {
@@ -2923,11 +2999,11 @@
// Did not find a parameter
if (_curchar == ',') {
parse_err(SYNERR, "Expected encode parameter before ',' in encoding %s.\n", ec_name);
- return NULL;
+ return;
}
if (_curchar != ')') {
parse_err(SYNERR, "Expected ')' after encode parameters.\n");
- return NULL;
+ return;
}
}
} // WHILE loop collecting parameters
@@ -2944,7 +3020,7 @@
else if ( _curchar != ')' ) {
// If not a ',' then only a ')' is allowed
parse_err(SYNERR, "Expected ')' after encoding %s.\n", ec_name);
- return NULL;
+ return;
}
// Check for ',' separating parameters
@@ -2956,14 +3032,14 @@
} // done parsing ins_encode methods and their parameters
if (_curchar != ')') {
parse_err(SYNERR, "Missing ')' at end of ins_encode description.\n");
- return NULL;
+ return;
}
next_char(); // move past ')'
skipws(); // Skip leading whitespace
if ( _curchar != ';' ) {
parse_err(SYNERR, "Missing ';' at end of ins_encode.\n");
- return NULL;
+ return;
}
next_char(); // move past ';'
skipws(); // be friendly to oper_parse()
@@ -2971,7 +3047,113 @@
// Debug Stuff
if (_AD._adl_debug > 1) fprintf(stderr,"Instruction Encode: %s\n", ec_name);
- return encrule;
+ // Set encode class of this instruction.
+ inst._insencode = encrule;
+}
+
+
+//------------------------------constant_parse---------------------------------
+// Parse a constant expression.
+void ADLParser::constant_parse(InstructForm& inst) {
+ // Create a new encoding name based on the name of the instruction
+ // definition, which should be unique.
+ const char* prefix = "__constant_";
+ char* ec_name = (char*) malloc(strlen(inst._ident) + strlen(prefix) + 1);
+ sprintf(ec_name, "%s%s", prefix, inst._ident);
+
+ assert(_AD._encode->encClass(ec_name) == NULL, "shouldn't already exist");
+ EncClass* encoding = _AD._encode->add_EncClass(ec_name);
+ encoding->_linenum = linenum();
+
+ // synthesize the arguments list for the enc_class from the
+ // arguments to the instruct definition.
+ const char* param = NULL;
+ inst._parameters.reset();
+ while ((param = inst._parameters.iter()) != NULL) {
+ OperandForm* opForm = (OperandForm*) inst._localNames[param];
+ encoding->add_parameter(opForm->_ident, param);
+ }
+
+ // Parse the following ( ) expression.
+ constant_parse_expression(encoding, ec_name);
+
+ // Build an encoding rule which invokes the encoding rule we just
+ // created, passing all arguments that we received.
+ InsEncode* encrule = new InsEncode(); // Encode class for instruction
+ NameAndList* params = encrule->add_encode(ec_name);
+ inst._parameters.reset();
+ while ((param = inst._parameters.iter()) != NULL) {
+ params->add_entry(param);
+ }
+
+ // Set encode class of this instruction.
+ inst._constant = encrule;
+}
+
+
+//------------------------------constant_parse_expression----------------------
+void ADLParser::constant_parse_expression(EncClass* encoding, char* ec_name) {
+ skipws();
+
+ // Prepend location descriptor, for debugging; cf. ADLParser::find_cpp_block
+ if (_AD._adlocation_debug) {
+ encoding->add_code(get_line_string());
+ }
+
+ // Start code line.
+ encoding->add_code(" _constant = C->constant_table().add");
+
+ // Parse everything in ( ) expression.
+ encoding->add_code("(");
+ next_char(); // Skip '('
+ int parens_depth = 1;
+
+ // Collect the parts of the constant expression.
+ // (1) strings that are passed through to output
+ // (2) replacement/substitution variable, preceeded by a '$'
+ while (parens_depth > 0) {
+ if (_curchar == '(') {
+ parens_depth++;
+ encoding->add_code("(");
+ next_char();
+ }
+ else if (_curchar == ')') {
+ parens_depth--;
+ encoding->add_code(")");
+ next_char();
+ }
+ else {
+ // (1)
+ // Check if there is a string to pass through to output
+ char *start = _ptr; // Record start of the next string
+ while ((_curchar != '$') && (_curchar != '(') && (_curchar != ')')) {
+ next_char();
+ }
+ // If a string was found, terminate it and record in EncClass
+ if (start != _ptr) {
+ *_ptr = '\0'; // Terminate the string
+ encoding->add_code(start);
+ }
+
+ // (2)
+ // If we are at a replacement variable, copy it and record in EncClass.
+ if (_curchar == '$') {
+ // Found replacement Variable
+ char* rep_var = get_rep_var_ident_dup();
+ encoding->add_rep_var(rep_var);
+ }
+ }
+ }
+
+ // Finish code line.
+ encoding->add_code(";");
+
+ if (_AD._adlocation_debug) {
+ encoding->add_code(end_line_marker());
+ }
+
+ // Debug Stuff
+ if (_AD._adl_debug > 1) fprintf(stderr, "EncodingClass Form: %s\n", ec_name);
}
--- a/hotspot/src/share/vm/adlc/adlparse.hpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/share/vm/adlc/adlparse.hpp Wed Dec 08 17:50:49 2010 -0800
@@ -156,8 +156,13 @@
Attribute *attr_parse(char *ident);// Parse instr/operand attribute rule
// Parse instruction encode rule
- InsEncode *ins_encode_parse(InstructForm &inst);
- InsEncode *ins_encode_parse_block(InstructForm &inst);
+ void ins_encode_parse(InstructForm &inst);
+ void ins_encode_parse_block(InstructForm &inst);
+ void ins_encode_parse_block_impl(InstructForm& inst, EncClass* encoding, char* ec_name);
+
+ void constant_parse(InstructForm& inst);
+ void constant_parse_expression(EncClass* encoding, char* ec_name);
+
Opcode *opcode_parse(InstructForm *insr); // Parse instruction opcode
char *size_parse(InstructForm *insr); // Parse instruction size
Interface *interface_parse(); // Parse operand interface rule
--- a/hotspot/src/share/vm/adlc/archDesc.hpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/share/vm/adlc/archDesc.hpp Wed Dec 08 17:50:49 2010 -0800
@@ -126,7 +126,6 @@
void chain_rule(FILE *fp, const char *indent, const char *ideal,
const Expr *icost, const char *irule,
Dict &operands_chained_from, ProductionState &status);
- void chain_rule_c(FILE *fp, char *indent, char *ideal, char *irule); // %%%%% TODO: remove this
void expand_opclass(FILE *fp, const char *indent, const Expr *cost,
const char *result_type, ProductionState &status);
Expr *calc_cost(FILE *fp, const char *spaces, MatchList &mList, ProductionState &status);
@@ -301,13 +300,18 @@
void buildMachNodeGenerator(FILE *fp_cpp);
// Generator for Expand methods for instructions with expand rules
- void defineExpand(FILE *fp, InstructForm *node);
+ void defineExpand (FILE *fp, InstructForm *node);
// Generator for Peephole methods for instructions with peephole rules
- void definePeephole(FILE *fp, InstructForm *node);
+ void definePeephole (FILE *fp, InstructForm *node);
// Generator for Size methods for instructions
- void defineSize(FILE *fp, InstructForm &node);
+ void defineSize (FILE *fp, InstructForm &node);
+
+public:
+ // Generator for EvalConstantValue methods for instructions
+ void defineEvalConstant(FILE *fp, InstructForm &node);
// Generator for Emit methods for instructions
- void defineEmit(FILE *fp, InstructForm &node);
+ void defineEmit (FILE *fp, InstructForm &node);
+
// Define a MachOper encode method
void define_oper_interface(FILE *fp, OperandForm &oper, FormDict &globals,
const char *name, const char *encoding);
--- a/hotspot/src/share/vm/adlc/formssel.cpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/share/vm/adlc/formssel.cpp Wed Dec 08 17:50:49 2010 -0800
@@ -30,11 +30,14 @@
InstructForm::InstructForm(const char *id, bool ideal_only)
: _ident(id), _ideal_only(ideal_only),
_localNames(cmpstr, hashstr, Form::arena),
- _effects(cmpstr, hashstr, Form::arena) {
+ _effects(cmpstr, hashstr, Form::arena),
+ _is_mach_constant(false)
+{
_ftype = Form::INS;
_matrule = NULL;
_insencode = NULL;
+ _constant = NULL;
_opcode = NULL;
_size = NULL;
_attribs = NULL;
@@ -58,11 +61,14 @@
InstructForm::InstructForm(const char *id, InstructForm *instr, MatchRule *rule)
: _ident(id), _ideal_only(false),
_localNames(instr->_localNames),
- _effects(instr->_effects) {
+ _effects(instr->_effects),
+ _is_mach_constant(false)
+{
_ftype = Form::INS;
_matrule = rule;
_insencode = instr->_insencode;
+ _constant = instr->_constant;
_opcode = instr->_opcode;
_size = instr->_size;
_attribs = instr->_attribs;
@@ -1094,6 +1100,9 @@
else if (is_ideal_nop()) {
return "MachNopNode";
}
+ else if (is_mach_constant()) {
+ return "MachConstantNode";
+ }
else if (captures_bottom_type(globals)) {
return "MachTypeNode";
} else {
@@ -1190,6 +1199,21 @@
//
// Generate the format call for the replacement variable
void InstructForm::rep_var_format(FILE *fp, const char *rep_var) {
+ // Handle special constant table variables.
+ if (strcmp(rep_var, "constanttablebase") == 0) {
+ fprintf(fp, "char reg[128]; ra->dump_register(in(mach_constant_base_node_input()), reg);\n");
+ fprintf(fp, "st->print(\"%%s\");\n");
+ return;
+ }
+ if (strcmp(rep_var, "constantoffset") == 0) {
+ fprintf(fp, "st->print(\"#%%d\", constant_offset());\n");
+ return;
+ }
+ if (strcmp(rep_var, "constantaddress") == 0) {
+ fprintf(fp, "st->print(\"constant table base + #%%d\", constant_offset());\n");
+ return;
+ }
+
// Find replacement variable's type
const Form *form = _localNames[rep_var];
if (form == NULL) {
@@ -1348,6 +1372,7 @@
fprintf(fp,"\nInstruction: %s\n", (_ident?_ident:""));
if (_matrule) _matrule->output(fp);
if (_insencode) _insencode->output(fp);
+ if (_constant) _constant->output(fp);
if (_opcode) _opcode->output(fp);
if (_attribs) _attribs->output(fp);
if (_predicate) _predicate->output(fp);
--- a/hotspot/src/share/vm/adlc/formssel.hpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/share/vm/adlc/formssel.hpp Wed Dec 08 17:50:49 2010 -0800
@@ -74,15 +74,16 @@
//------------------------------InstructForm-----------------------------------
class InstructForm : public Form {
private:
- bool _ideal_only; // Not a user-defined instruction
+ bool _ideal_only; // Not a user-defined instruction
// Members used for tracking CISC-spilling
- uint _cisc_spill_operand;// Which operand may cisc-spill
+ uint _cisc_spill_operand;// Which operand may cisc-spill
void set_cisc_spill_operand(uint op_index) { _cisc_spill_operand = op_index; }
- bool _is_cisc_alternate;
+ bool _is_cisc_alternate;
InstructForm *_cisc_spill_alternate;// cisc possible replacement
const char *_cisc_reg_mask_name;
InstructForm *_short_branch_form;
bool _is_short_branch;
+ bool _is_mach_constant; // true if Node is a MachConstantNode
uint _alignment;
public:
@@ -94,6 +95,7 @@
Opcode *_opcode; // Encoding of the opcode for instruction
char *_size; // Size of instruction
InsEncode *_insencode; // Encoding class instruction belongs to
+ InsEncode *_constant; // Encoding class constant value belongs to
Attribute *_attribs; // List of Attribute rules
Predicate *_predicate; // Predicate test for this instruction
FormDict _effects; // Dictionary of effect rules
@@ -251,6 +253,9 @@
bool is_short_branch() { return _is_short_branch; }
void set_short_branch(bool val) { _is_short_branch = val; }
+ bool is_mach_constant() const { return _is_mach_constant; }
+ void set_is_mach_constant(bool x) { _is_mach_constant = x; }
+
InstructForm *short_branch_form() { return _short_branch_form; }
bool has_short_branch_form() { return _short_branch_form != NULL; }
// Output short branch prototypes and method bodies
--- a/hotspot/src/share/vm/adlc/output_c.cpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/share/vm/adlc/output_c.cpp Wed Dec 08 17:50:49 2010 -0800
@@ -1496,8 +1496,8 @@
unsigned i;
// Generate Expand function header
- fprintf(fp,"MachNode *%sNode::Expand(State *state, Node_List &proj_list, Node* mem) {\n", node->_ident);
- fprintf(fp,"Compile* C = Compile::current();\n");
+ fprintf(fp, "MachNode* %sNode::Expand(State* state, Node_List& proj_list, Node* mem) {\n", node->_ident);
+ fprintf(fp, " Compile* C = Compile::current();\n");
// Generate expand code
if( node->expands() ) {
const char *opid;
@@ -1818,6 +1818,12 @@
}
}
+ // If the node is a MachConstantNode, insert the MachConstantBaseNode edge.
+ // NOTE: this edge must be the last input (see MachConstantNode::mach_constant_base_node_input).
+ if (node->is_mach_constant()) {
+ fprintf(fp," add_req(C->mach_constant_base_node());\n");
+ }
+
fprintf(fp,"\n");
if( node->expands() ) {
fprintf(fp," return result;\n");
@@ -1924,7 +1930,17 @@
// No state needed.
assert( _opclass == NULL,
"'primary', 'secondary' and 'tertiary' don't follow operand.");
- } else {
+ }
+ else if ((strcmp(rep_var, "constanttablebase") == 0) ||
+ (strcmp(rep_var, "constantoffset") == 0) ||
+ (strcmp(rep_var, "constantaddress") == 0)) {
+ if (!_inst.is_mach_constant()) {
+ _AD.syntax_err(_encoding._linenum,
+ "Replacement variable %s not allowed in instruct %s (only in MachConstantNode).\n",
+ rep_var, _encoding._name);
+ }
+ }
+ else {
// Lookup its position in parameter list
int param_no = _encoding.rep_var_index(rep_var);
if ( param_no == -1 ) {
@@ -2380,6 +2396,15 @@
rep_var, _inst._ident, _encoding._name);
}
}
+ else if (strcmp(rep_var, "constanttablebase") == 0) {
+ fprintf(_fp, "as_Register(ra_->get_encode(in(mach_constant_base_node_input())))");
+ }
+ else if (strcmp(rep_var, "constantoffset") == 0) {
+ fprintf(_fp, "constant_offset()");
+ }
+ else if (strcmp(rep_var, "constantaddress") == 0) {
+ fprintf(_fp, "InternalAddress(__ code()->consts()->start() + constant_offset())");
+ }
else {
// Lookup its position in parameter list
int param_no = _encoding.rep_var_index(rep_var);
@@ -2465,37 +2490,39 @@
fprintf(fp,"}\n");
}
-void ArchDesc::defineEmit(FILE *fp, InstructForm &inst) {
- InsEncode *ins_encode = inst._insencode;
+// defineEmit -----------------------------------------------------------------
+void ArchDesc::defineEmit(FILE* fp, InstructForm& inst) {
+ InsEncode* encode = inst._insencode;
// (1)
// Output instruction's emit prototype
- fprintf(fp,"void %sNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {\n",
- inst._ident);
+ fprintf(fp, "void %sNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const {\n", inst._ident);
// If user did not define an encode section,
// provide stub that does not generate any machine code.
- if( (_encode == NULL) || (ins_encode == NULL) ) {
+ if( (_encode == NULL) || (encode == NULL) ) {
fprintf(fp, " // User did not define an encode section.\n");
- fprintf(fp,"}\n");
+ fprintf(fp, "}\n");
return;
}
// Save current instruction's starting address (helps with relocation).
- fprintf(fp, " cbuf.set_insts_mark();\n");
-
- // // // idx0 is only needed for syntactic purposes and only by "storeSSI"
- // fprintf( fp, " unsigned idx0 = 0;\n");
+ fprintf(fp, " cbuf.set_insts_mark();\n");
+
+ // For MachConstantNodes which are ideal jump nodes, fill the jump table.
+ if (inst.is_mach_constant() && inst.is_ideal_jump()) {
+ fprintf(fp, " ra_->C->constant_table().fill_jump_table(cbuf, (MachConstantNode*) this, _index2label);\n");
+ }
// Output each operand's offset into the array of registers.
- inst.index_temps( fp, _globalNames );
+ inst.index_temps(fp, _globalNames);
// Output this instruction's encodings
const char *ec_name;
bool user_defined = false;
- ins_encode->reset();
- while ( (ec_name = ins_encode->encode_class_iter()) != NULL ) {
- fprintf(fp, " {");
+ encode->reset();
+ while ((ec_name = encode->encode_class_iter()) != NULL) {
+ fprintf(fp, " {\n");
// Output user-defined encoding
user_defined = true;
@@ -2507,25 +2534,25 @@
abort();
}
- if (ins_encode->current_encoding_num_args() != encoding->num_args()) {
- globalAD->syntax_err(ins_encode->_linenum, "In %s: passing %d arguments to %s but expecting %d",
- inst._ident, ins_encode->current_encoding_num_args(),
+ if (encode->current_encoding_num_args() != encoding->num_args()) {
+ globalAD->syntax_err(encode->_linenum, "In %s: passing %d arguments to %s but expecting %d",
+ inst._ident, encode->current_encoding_num_args(),
ec_name, encoding->num_args());
}
- DefineEmitState pending(fp, *this, *encoding, *ins_encode, inst );
+ DefineEmitState pending(fp, *this, *encoding, *encode, inst);
encoding->_code.reset();
encoding->_rep_vars.reset();
// Process list of user-defined strings,
// and occurrences of replacement variables.
// Replacement Vars are pushed into a list and then output
- while ( (ec_code = encoding->_code.iter()) != NULL ) {
- if ( ! encoding->_code.is_signal( ec_code ) ) {
+ while ((ec_code = encoding->_code.iter()) != NULL) {
+ if (!encoding->_code.is_signal(ec_code)) {
// Emit pending code
pending.emit();
pending.clear();
// Emit this code section
- fprintf(fp,"%s", ec_code);
+ fprintf(fp, "%s", ec_code);
} else {
// A replacement variable or one of its subfields
// Obtain replacement variable from list
@@ -2536,7 +2563,7 @@
// Emit pending code
pending.emit();
pending.clear();
- fprintf(fp, "}\n");
+ fprintf(fp, " }\n");
} // end while instruction's encodings
// Check if user stated which encoding to user
@@ -2545,7 +2572,86 @@
}
// (3) and (4)
- fprintf(fp,"}\n");
+ fprintf(fp, "}\n");
+}
+
+// defineEvalConstant ---------------------------------------------------------
+void ArchDesc::defineEvalConstant(FILE* fp, InstructForm& inst) {
+ InsEncode* encode = inst._constant;
+
+ // (1)
+ // Output instruction's emit prototype
+ fprintf(fp, "void %sNode::eval_constant(Compile* C) {\n", inst._ident);
+
+ // For ideal jump nodes, allocate a jump table.
+ if (inst.is_ideal_jump()) {
+ fprintf(fp, " _constant = C->constant_table().allocate_jump_table(this);\n");
+ }
+
+ // If user did not define an encode section,
+ // provide stub that does not generate any machine code.
+ if ((_encode == NULL) || (encode == NULL)) {
+ fprintf(fp, " // User did not define an encode section.\n");
+ fprintf(fp, "}\n");
+ return;
+ }
+
+ // Output this instruction's encodings
+ const char *ec_name;
+ bool user_defined = false;
+ encode->reset();
+ while ((ec_name = encode->encode_class_iter()) != NULL) {
+ fprintf(fp, " {\n");
+ // Output user-defined encoding
+ user_defined = true;
+
+ const char *ec_code = NULL;
+ const char *ec_rep_var = NULL;
+ EncClass *encoding = _encode->encClass(ec_name);
+ if (encoding == NULL) {
+ fprintf(stderr, "User did not define contents of this encode_class: %s\n", ec_name);
+ abort();
+ }
+
+ if (encode->current_encoding_num_args() != encoding->num_args()) {
+ globalAD->syntax_err(encode->_linenum, "In %s: passing %d arguments to %s but expecting %d",
+ inst._ident, encode->current_encoding_num_args(),
+ ec_name, encoding->num_args());
+ }
+
+ DefineEmitState pending(fp, *this, *encoding, *encode, inst);
+ encoding->_code.reset();
+ encoding->_rep_vars.reset();
+ // Process list of user-defined strings,
+ // and occurrences of replacement variables.
+ // Replacement Vars are pushed into a list and then output
+ while ((ec_code = encoding->_code.iter()) != NULL) {
+ if (!encoding->_code.is_signal(ec_code)) {
+ // Emit pending code
+ pending.emit();
+ pending.clear();
+ // Emit this code section
+ fprintf(fp, "%s", ec_code);
+ } else {
+ // A replacement variable or one of its subfields
+ // Obtain replacement variable from list
+ ec_rep_var = encoding->_rep_vars.iter();
+ pending.add_rep_var(ec_rep_var);
+ }
+ }
+ // Emit pending code
+ pending.emit();
+ pending.clear();
+ fprintf(fp, " }\n");
+ } // end while instruction's encodings
+
+ // Check if user stated which encoding to user
+ if (user_defined == false) {
+ fprintf(fp, " // User did not define which encode class to use.\n");
+ }
+
+ // (3) and (4)
+ fprintf(fp, "}\n");
}
// ---------------------------------------------------------------------------
@@ -2952,6 +3058,7 @@
// If there are multiple defs/kills, or an explicit expand rule, build rule
if( instr->expands() || instr->needs_projections() ||
instr->has_temps() ||
+ instr->is_mach_constant() ||
instr->_matrule != NULL &&
instr->num_opnds() != instr->num_unique_opnds() )
defineExpand(_CPP_EXPAND_file._fp, instr);
@@ -3032,8 +3139,9 @@
// Ensure this is a machine-world instruction
if ( instr->ideal_only() ) continue;
- if (instr->_insencode) defineEmit(fp, *instr);
- if (instr->_size) defineSize(fp, *instr);
+ if (instr->_insencode) defineEmit (fp, *instr);
+ if (instr->is_mach_constant()) defineEvalConstant(fp, *instr);
+ if (instr->_size) defineSize (fp, *instr);
// side-call to generate output that used to be in the header file:
extern void gen_inst_format(FILE *fp, FormDict &globals, InstructForm &oper, bool for_c_file);
--- a/hotspot/src/share/vm/adlc/output_h.cpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/share/vm/adlc/output_h.cpp Wed Dec 08 17:50:49 2010 -0800
@@ -1550,7 +1550,12 @@
}
// virtual functions for encode and format
- //
+
+ // Virtual function for evaluating the constant.
+ if (instr->is_mach_constant()) {
+ fprintf(fp," virtual void eval_constant(Compile* C);\n");
+ }
+
// Output the opcode function and the encode function here using the
// encoding class information in the _insencode slot.
if ( instr->_insencode ) {
@@ -1559,7 +1564,7 @@
// virtual function for getting the size of an instruction
if ( instr->_size ) {
- fprintf(fp," virtual uint size(PhaseRegAlloc *ra_) const;\n");
+ fprintf(fp," virtual uint size(PhaseRegAlloc *ra_) const;\n");
}
// Return the top-level ideal opcode.
@@ -1752,6 +1757,7 @@
// Virtual methods which are only generated to override base class
if( instr->expands() || instr->needs_projections() ||
instr->has_temps() ||
+ instr->is_mach_constant() ||
instr->_matrule != NULL &&
instr->num_opnds() != instr->num_unique_opnds() ) {
fprintf(fp," virtual MachNode *Expand(State *state, Node_List &proj_list, Node* mem);\n");
@@ -1780,24 +1786,6 @@
// Declare short branch methods, if applicable
instr->declare_short_branch_methods(fp);
- // Instructions containing a constant that will be entered into the
- // float/double table redefine the base virtual function
-#ifdef SPARC
- // Sparc doubles entries in the constant table require more space for
- // alignment. (expires 9/98)
- int table_entries = (3 * instr->num_consts( _globalNames, Form::idealD ))
- + instr->num_consts( _globalNames, Form::idealF );
-#else
- int table_entries = instr->num_consts( _globalNames, Form::idealD )
- + instr->num_consts( _globalNames, Form::idealF );
-#endif
- if( table_entries != 0 ) {
- fprintf(fp," virtual int const_size() const {");
- fprintf(fp, " return %d;", table_entries);
- fprintf(fp, " }\n");
- }
-
-
// See if there is an "ins_pipe" declaration for this instruction
if (instr->_ins_pipe) {
fprintf(fp," static const Pipeline *pipeline_class();\n");
--- a/hotspot/src/share/vm/asm/assembler.hpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/share/vm/asm/assembler.hpp Wed Dec 08 17:50:49 2010 -0800
@@ -292,7 +292,16 @@
address start_a_const(int required_space, int required_align = sizeof(double));
void end_a_const();
- // fp constants support
+ // constants support
+ address long_constant(jlong c) {
+ address ptr = start_a_const(sizeof(c), sizeof(c));
+ if (ptr != NULL) {
+ *(jlong*)ptr = c;
+ _code_pos = ptr + sizeof(c);
+ end_a_const();
+ }
+ return ptr;
+ }
address double_constant(jdouble c) {
address ptr = start_a_const(sizeof(c), sizeof(c));
if (ptr != NULL) {
@@ -311,6 +320,15 @@
}
return ptr;
}
+ address address_constant(address c) {
+ address ptr = start_a_const(sizeof(c), sizeof(c));
+ if (ptr != NULL) {
+ *(address*)ptr = c;
+ _code_pos = ptr + sizeof(c);
+ end_a_const();
+ }
+ return ptr;
+ }
address address_constant(address c, RelocationHolder const& rspec) {
address ptr = start_a_const(sizeof(c), sizeof(c));
if (ptr != NULL) {
@@ -321,8 +339,6 @@
}
return ptr;
}
- inline address address_constant(Label& L);
- inline address address_table_constant(GrowableArray<Label*> label);
// Bootstrapping aid to cope with delayed determination of constants.
// Returns a static address which will eventually contain the constant.
--- a/hotspot/src/share/vm/asm/assembler.inline.hpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/share/vm/asm/assembler.inline.hpp Wed Dec 08 17:50:49 2010 -0800
@@ -114,32 +114,4 @@
bind_loc(CodeBuffer::locator(pos, sect));
}
-address AbstractAssembler::address_constant(Label& L) {
- address c = NULL;
- address ptr = start_a_const(sizeof(c), sizeof(c));
- if (ptr != NULL) {
- relocate(Relocation::spec_simple(relocInfo::internal_word_type));
- *(address*)ptr = c = code_section()->target(L, ptr);
- _code_pos = ptr + sizeof(c);
- end_a_const();
- }
- return ptr;
-}
-
-address AbstractAssembler::address_table_constant(GrowableArray<Label*> labels) {
- int addressSize = sizeof(address);
- int sizeLabel = addressSize * labels.length();
- address ptr = start_a_const(sizeLabel, addressSize);
-
- if (ptr != NULL) {
- address *labelLoc = (address*)ptr;
- for (int i=0; i < labels.length(); i++) {
- emit_address(code_section()->target(*labels.at(i), (address)&labelLoc[i]));
- code_section()->relocate((address)&labelLoc[i], relocInfo::internal_word_type);
- }
- end_a_const();
- }
- return ptr;
-}
-
#endif // SHARE_VM_ASM_ASSEMBLER_INLINE_HPP
--- a/hotspot/src/share/vm/c1/c1_Compilation.cpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/share/vm/c1/c1_Compilation.cpp Wed Dec 08 17:50:49 2010 -0800
@@ -298,8 +298,8 @@
CHECK_BAILOUT_(no_frame_size);
- if (is_profiling()) {
- method()->build_method_data();
+ if (is_profiling() && !method()->ensure_method_data()) {
+ BAILOUT_("mdo allocation failed", no_frame_size);
}
{
@@ -484,11 +484,11 @@
if (is_profiling()) {
// Compilation failed, create MDO, which would signal the interpreter
// to start profiling on its own.
- _method->build_method_data();
+ _method->ensure_method_data();
}
} else if (is_profiling() && _would_profile) {
- ciMethodData *md = method->method_data();
- assert (md != NULL, "Should have MDO");
+ ciMethodData *md = method->method_data_or_null();
+ assert(md != NULL, "Sanity");
md->set_would_profile(_would_profile);
}
}
--- a/hotspot/src/share/vm/c1/c1_FrameMap.hpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/share/vm/c1/c1_FrameMap.hpp Wed Dec 08 17:50:49 2010 -0800
@@ -76,8 +76,8 @@
nof_cpu_regs_reg_alloc = pd_nof_cpu_regs_reg_alloc,
nof_fpu_regs_reg_alloc = pd_nof_fpu_regs_reg_alloc,
- nof_caller_save_cpu_regs = pd_nof_caller_save_cpu_regs_frame_map,
- nof_caller_save_fpu_regs = pd_nof_caller_save_fpu_regs_frame_map,
+ max_nof_caller_save_cpu_regs = pd_nof_caller_save_cpu_regs_frame_map,
+ nof_caller_save_fpu_regs = pd_nof_caller_save_fpu_regs_frame_map,
spill_slot_size_in_bytes = 4
};
@@ -97,7 +97,7 @@
static Register _cpu_rnr2reg [nof_cpu_regs];
static int _cpu_reg2rnr [nof_cpu_regs];
- static LIR_Opr _caller_save_cpu_regs [nof_caller_save_cpu_regs];
+ static LIR_Opr _caller_save_cpu_regs [max_nof_caller_save_cpu_regs];
static LIR_Opr _caller_save_fpu_regs [nof_caller_save_fpu_regs];
int _framesize;
@@ -243,7 +243,7 @@
VMReg regname(LIR_Opr opr) const;
static LIR_Opr caller_save_cpu_reg_at(int i) {
- assert(i >= 0 && i < nof_caller_save_cpu_regs, "out of bounds");
+ assert(i >= 0 && i < max_nof_caller_save_cpu_regs, "out of bounds");
return _caller_save_cpu_regs[i];
}
--- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Wed Dec 08 17:50:49 2010 -0800
@@ -2795,7 +2795,7 @@
get = append(new UnsafeGetRaw(as_BasicType(local->type()), e,
append(new Constant(new IntConstant(offset))),
0,
- true));
+ true /*unaligned*/, true /*wide*/));
}
_state->store_local(index, get);
}
@@ -3377,6 +3377,9 @@
INLINE_BAILOUT("total inlining greater than DesiredMethodLimit");
}
+ if (is_profiling() && !callee->ensure_method_data()) {
+ INLINE_BAILOUT("mdo allocation failed");
+ }
#ifndef PRODUCT
// printing
if (PrintInlining) {
--- a/hotspot/src/share/vm/c1/c1_IR.cpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/share/vm/c1/c1_IR.cpp Wed Dec 08 17:50:49 2010 -0800
@@ -504,7 +504,12 @@
count_edges(start_block, NULL);
if (compilation()->is_profiling()) {
- compilation()->method()->method_data()->set_compilation_stats(_num_loops, _num_blocks);
+ ciMethod *method = compilation()->method();
+ if (!method->is_accessor()) {
+ ciMethodData* md = method->method_data_or_null();
+ assert(md != NULL, "Sanity");
+ md->set_compilation_stats(_num_loops, _num_blocks);
+ }
}
if (_num_loops > 0) {
--- a/hotspot/src/share/vm/c1/c1_Instruction.hpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/share/vm/c1/c1_Instruction.hpp Wed Dec 08 17:50:49 2010 -0800
@@ -2110,20 +2110,23 @@
LEAF(UnsafeGetRaw, UnsafeRawOp)
private:
- bool _may_be_unaligned; // For OSREntry
+ bool _may_be_unaligned, _is_wide; // For OSREntry
public:
- UnsafeGetRaw(BasicType basic_type, Value addr, bool may_be_unaligned)
+ UnsafeGetRaw(BasicType basic_type, Value addr, bool may_be_unaligned, bool is_wide = false)
: UnsafeRawOp(basic_type, addr, false) {
_may_be_unaligned = may_be_unaligned;
+ _is_wide = is_wide;
}
- UnsafeGetRaw(BasicType basic_type, Value base, Value index, int log2_scale, bool may_be_unaligned)
+ UnsafeGetRaw(BasicType basic_type, Value base, Value index, int log2_scale, bool may_be_unaligned, bool is_wide = false)
: UnsafeRawOp(basic_type, base, index, log2_scale, false) {
_may_be_unaligned = may_be_unaligned;
+ _is_wide = is_wide;
}
- bool may_be_unaligned() { return _may_be_unaligned; }
+ bool may_be_unaligned() { return _may_be_unaligned; }
+ bool is_wide() { return _is_wide; }
};
--- a/hotspot/src/share/vm/c1/c1_LIR.cpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/share/vm/c1/c1_LIR.cpp Wed Dec 08 17:50:49 2010 -0800
@@ -1742,6 +1742,8 @@
return "unaligned move";
case lir_move_volatile:
return "volatile_move";
+ case lir_move_wide:
+ return "wide_move";
default:
ShouldNotReachHere();
return "illegal_op";
--- a/hotspot/src/share/vm/c1/c1_LIR.hpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/share/vm/c1/c1_LIR.hpp Wed Dec 08 17:50:49 2010 -0800
@@ -985,6 +985,7 @@
lir_move_normal,
lir_move_volatile,
lir_move_unaligned,
+ lir_move_wide,
lir_move_max_flag
};
@@ -1932,7 +1933,20 @@
void move(LIR_Opr src, LIR_Opr dst, CodeEmitInfo* info = NULL) { append(new LIR_Op1(lir_move, src, dst, dst->type(), lir_patch_none, info)); }
void move(LIR_Address* src, LIR_Opr dst, CodeEmitInfo* info = NULL) { append(new LIR_Op1(lir_move, LIR_OprFact::address(src), dst, src->type(), lir_patch_none, info)); }
void move(LIR_Opr src, LIR_Address* dst, CodeEmitInfo* info = NULL) { append(new LIR_Op1(lir_move, src, LIR_OprFact::address(dst), dst->type(), lir_patch_none, info)); }
-
+ void move_wide(LIR_Address* src, LIR_Opr dst, CodeEmitInfo* info = NULL) {
+ if (UseCompressedOops) {
+ append(new LIR_Op1(lir_move, LIR_OprFact::address(src), dst, src->type(), lir_patch_none, info, lir_move_wide));
+ } else {
+ move(src, dst, info);
+ }
+ }
+ void move_wide(LIR_Opr src, LIR_Address* dst, CodeEmitInfo* info = NULL) {
+ if (UseCompressedOops) {
+ append(new LIR_Op1(lir_move, src, LIR_OprFact::address(dst), dst->type(), lir_patch_none, info, lir_move_wide));
+ } else {
+ move(src, dst, info);
+ }
+ }
void volatile_move(LIR_Opr src, LIR_Opr dst, BasicType type, CodeEmitInfo* info = NULL, LIR_PatchCode patch_code = lir_patch_none) { append(new LIR_Op1(lir_move, src, dst, type, patch_code, info, lir_move_volatile)); }
void oop2reg (jobject o, LIR_Opr reg) { append(new LIR_Op1(lir_move, LIR_OprFact::oopConst(o), reg)); }
--- a/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp Wed Dec 08 17:50:49 2010 -0800
@@ -489,7 +489,9 @@
volatile_move_op(op->in_opr(), op->result_opr(), op->type(), op->info());
} else {
move_op(op->in_opr(), op->result_opr(), op->type(),
- op->patch_code(), op->info(), op->pop_fpu_stack(), op->move_kind() == lir_move_unaligned);
+ op->patch_code(), op->info(), op->pop_fpu_stack(),
+ op->move_kind() == lir_move_unaligned,
+ op->move_kind() == lir_move_wide);
}
break;
@@ -758,7 +760,7 @@
}
-void LIR_Assembler::move_op(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_PatchCode patch_code, CodeEmitInfo* info, bool pop_fpu_stack, bool unaligned) {
+void LIR_Assembler::move_op(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_PatchCode patch_code, CodeEmitInfo* info, bool pop_fpu_stack, bool unaligned, bool wide) {
if (src->is_register()) {
if (dest->is_register()) {
assert(patch_code == lir_patch_none && info == NULL, "no patching and info allowed here");
@@ -767,7 +769,7 @@
assert(patch_code == lir_patch_none && info == NULL, "no patching and info allowed here");
reg2stack(src, dest, type, pop_fpu_stack);
} else if (dest->is_address()) {
- reg2mem(src, dest, type, patch_code, info, pop_fpu_stack, unaligned);
+ reg2mem(src, dest, type, patch_code, info, pop_fpu_stack, wide, unaligned);
} else {
ShouldNotReachHere();
}
@@ -790,13 +792,13 @@
const2stack(src, dest);
} else if (dest->is_address()) {
assert(patch_code == lir_patch_none, "no patching allowed here");
- const2mem(src, dest, type, info);
+ const2mem(src, dest, type, info, wide);
} else {
ShouldNotReachHere();
}
} else if (src->is_address()) {
- mem2reg(src, dest, type, patch_code, info, unaligned);
+ mem2reg(src, dest, type, patch_code, info, wide, unaligned);
} else {
ShouldNotReachHere();
--- a/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp Wed Dec 08 17:50:49 2010 -0800
@@ -165,15 +165,17 @@
void const2reg (LIR_Opr src, LIR_Opr dest, LIR_PatchCode patch_code, CodeEmitInfo* info);
void const2stack(LIR_Opr src, LIR_Opr dest);
- void const2mem (LIR_Opr src, LIR_Opr dest, BasicType type, CodeEmitInfo* info);
+ void const2mem (LIR_Opr src, LIR_Opr dest, BasicType type, CodeEmitInfo* info, bool wide);
void reg2stack (LIR_Opr src, LIR_Opr dest, BasicType type, bool pop_fpu_stack);
void reg2reg (LIR_Opr src, LIR_Opr dest);
- void reg2mem (LIR_Opr src, LIR_Opr dest, BasicType type, LIR_PatchCode patch_code, CodeEmitInfo* info, bool pop_fpu_stack, bool unaligned);
+ void reg2mem (LIR_Opr src, LIR_Opr dest, BasicType type,
+ LIR_PatchCode patch_code, CodeEmitInfo* info,
+ bool pop_fpu_stack, bool wide, bool unaligned);
void stack2reg (LIR_Opr src, LIR_Opr dest, BasicType type);
void stack2stack(LIR_Opr src, LIR_Opr dest, BasicType type);
void mem2reg (LIR_Opr src, LIR_Opr dest, BasicType type,
- LIR_PatchCode patch_code = lir_patch_none,
- CodeEmitInfo* info = NULL, bool unaligned = false);
+ LIR_PatchCode patch_code,
+ CodeEmitInfo* info, bool wide, bool unaligned);
void prefetchr (LIR_Opr src);
void prefetchw (LIR_Opr src);
@@ -211,7 +213,7 @@
void roundfp_op(LIR_Opr src, LIR_Opr tmp, LIR_Opr dest, bool pop_fpu_stack);
void move_op(LIR_Opr src, LIR_Opr result, BasicType type,
- LIR_PatchCode patch_code, CodeEmitInfo* info, bool pop_fpu_stack, bool unaligned);
+ LIR_PatchCode patch_code, CodeEmitInfo* info, bool pop_fpu_stack, bool unaligned, bool wide);
void volatile_move_op(LIR_Opr src, LIR_Opr result, BasicType type, CodeEmitInfo* info);
void comp_mem_op(LIR_Opr src, LIR_Opr result, BasicType type, CodeEmitInfo* info); // info set for null exceptions
void comp_fl2i(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr result, LIR_Op2* op);
--- a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp Wed Dec 08 17:50:49 2010 -0800
@@ -836,11 +836,8 @@
if (if_instr->should_profile()) {
ciMethod* method = if_instr->profiled_method();
assert(method != NULL, "method should be set if branch is profiled");
- ciMethodData* md = method->method_data();
- if (md == NULL) {
- bailout("out of memory building methodDataOop");
- return;
- }
+ ciMethodData* md = method->method_data_or_null();
+ assert(md != NULL, "Sanity");
ciProfileData* data = md->bci_to_data(if_instr->profiled_bci());
assert(data != NULL, "must have profiling data");
assert(data->is_BranchData(), "need BranchData for two-way branches");
@@ -864,11 +861,11 @@
// MDO cells are intptr_t, so the data_reg width is arch-dependent.
LIR_Opr data_reg = new_pointer_register();
LIR_Address* data_addr = new LIR_Address(md_reg, data_offset_reg, data_reg->type());
- __ move(LIR_OprFact::address(data_addr), data_reg);
+ __ move(data_addr, data_reg);
// Use leal instead of add to avoid destroying condition codes on x86
LIR_Address* fake_incr_value = new LIR_Address(data_reg, DataLayout::counter_increment, T_INT);
__ leal(LIR_OprFact::address(fake_incr_value), data_reg);
- __ move(data_reg, LIR_OprFact::address(data_addr));
+ __ move(data_reg, data_addr);
}
}
@@ -1009,12 +1006,12 @@
operand_for_instruction(phi));
LIR_Opr thread_reg = getThreadPointer();
- __ move(new LIR_Address(thread_reg, in_bytes(JavaThread::exception_oop_offset()), T_OBJECT),
- exceptionOopOpr());
- __ move(LIR_OprFact::oopConst(NULL),
- new LIR_Address(thread_reg, in_bytes(JavaThread::exception_oop_offset()), T_OBJECT));
- __ move(LIR_OprFact::oopConst(NULL),
- new LIR_Address(thread_reg, in_bytes(JavaThread::exception_pc_offset()), T_OBJECT));
+ __ move_wide(new LIR_Address(thread_reg, in_bytes(JavaThread::exception_oop_offset()), T_OBJECT),
+ exceptionOopOpr());
+ __ move_wide(LIR_OprFact::oopConst(NULL),
+ new LIR_Address(thread_reg, in_bytes(JavaThread::exception_oop_offset()), T_OBJECT));
+ __ move_wide(LIR_OprFact::oopConst(NULL),
+ new LIR_Address(thread_reg, in_bytes(JavaThread::exception_pc_offset()), T_OBJECT));
LIR_Opr result = new_register(T_OBJECT);
__ move(exceptionOopOpr(), result);
@@ -1085,7 +1082,7 @@
void LIRGenerator::do_Return(Return* x) {
if (compilation()->env()->dtrace_method_probes()) {
BasicTypeList signature;
- signature.append(T_INT); // thread
+ signature.append(LP64_ONLY(T_LONG) NOT_LP64(T_INT)); // thread
signature.append(T_OBJECT); // methodOop
LIR_OprList* args = new LIR_OprList();
args->append(getThreadPointer());
@@ -1122,8 +1119,8 @@
info = state_for(x);
}
__ move(new LIR_Address(rcvr.result(), oopDesc::klass_offset_in_bytes(), T_OBJECT), result, info);
- __ move(new LIR_Address(result, Klass::java_mirror_offset_in_bytes() +
- klassOopDesc::klass_part_offset_in_bytes(), T_OBJECT), result);
+ __ move_wide(new LIR_Address(result, Klass::java_mirror_offset_in_bytes() +
+ klassOopDesc::klass_part_offset_in_bytes(), T_OBJECT), result);
}
@@ -1131,7 +1128,7 @@
void LIRGenerator::do_currentThread(Intrinsic* x) {
assert(x->number_of_arguments() == 0, "wrong type");
LIR_Opr reg = rlock_result(x);
- __ load(new LIR_Address(getThreadPointer(), in_bytes(JavaThread::threadObj_offset()), T_OBJECT), reg);
+ __ move_wide(new LIR_Address(getThreadPointer(), in_bytes(JavaThread::threadObj_offset()), T_OBJECT), reg);
}
@@ -1908,7 +1905,11 @@
if (x->may_be_unaligned() && (dst_type == T_LONG || dst_type == T_DOUBLE)) {
__ unaligned_move(addr, reg);
} else {
- __ move(addr, reg);
+ if (dst_type == T_OBJECT && x->is_wide()) {
+ __ move_wide(addr, reg);
+ } else {
+ __ move(addr, reg);
+ }
}
}
@@ -2215,11 +2216,8 @@
if (x->should_profile()) {
ciMethod* method = x->profiled_method();
assert(method != NULL, "method should be set if branch is profiled");
- ciMethodData* md = method->method_data();
- if (md == NULL) {
- bailout("out of memory building methodDataOop");
- return;
- }
+ ciMethodData* md = method->method_data_or_null();
+ assert(md != NULL, "Sanity");
ciProfileData* data = md->bci_to_data(x->profiled_bci());
assert(data != NULL, "must have profiling data");
int offset;
@@ -2287,7 +2285,7 @@
if (compilation()->env()->dtrace_method_probes()) {
BasicTypeList signature;
- signature.append(T_INT); // thread
+ signature.append(LP64_ONLY(T_LONG) NOT_LP64(T_INT)); // thread
signature.append(T_OBJECT); // methodOop
LIR_OprList* args = new LIR_OprList();
args->append(getThreadPointer());
@@ -2352,11 +2350,14 @@
} else {
LIR_Address* addr = loc->as_address_ptr();
param->load_for_store(addr->type());
- if (addr->type() == T_LONG || addr->type() == T_DOUBLE) {
- __ unaligned_move(param->result(), addr);
- } else {
- __ move(param->result(), addr);
- }
+ if (addr->type() == T_OBJECT) {
+ __ move_wide(param->result(), addr);
+ } else
+ if (addr->type() == T_LONG || addr->type() == T_DOUBLE) {
+ __ unaligned_move(param->result(), addr);
+ } else {
+ __ move(param->result(), addr);
+ }
}
}
@@ -2368,7 +2369,7 @@
} else {
assert(loc->is_address(), "just checking");
receiver->load_for_store(T_OBJECT);
- __ move(receiver->result(), loc);
+ __ move_wide(receiver->result(), loc->as_address_ptr());
}
}
}
@@ -2716,7 +2717,9 @@
} else if (level == CompLevel_full_profile) {
offset = in_bytes(backedge ? methodDataOopDesc::backedge_counter_offset() :
methodDataOopDesc::invocation_counter_offset());
- __ oop2reg(method->method_data()->constant_encoding(), counter_holder);
+ ciMethodData* md = method->method_data_or_null();
+ assert(md != NULL, "Sanity");
+ __ oop2reg(md->constant_encoding(), counter_holder);
meth = new_register(T_OBJECT);
__ oop2reg(method->constant_encoding(), meth);
} else {
--- a/hotspot/src/share/vm/c1/c1_LinearScan.cpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/share/vm/c1/c1_LinearScan.cpp Wed Dec 08 17:50:49 2010 -0800
@@ -1273,7 +1273,7 @@
int caller_save_registers[LinearScan::nof_regs];
int i;
- for (i = 0; i < FrameMap::nof_caller_save_cpu_regs; i++) {
+ for (i = 0; i < FrameMap::nof_caller_save_cpu_regs(); i++) {
LIR_Opr opr = FrameMap::caller_save_cpu_reg_at(i);
assert(opr->is_valid() && opr->is_register(), "FrameMap should not return invalid operands");
assert(reg_numHi(opr) == -1, "missing addition of range for hi-register");
@@ -3557,7 +3557,7 @@
// invalidate all caller save registers at calls
if (visitor.has_call()) {
- for (j = 0; j < FrameMap::nof_caller_save_cpu_regs; j++) {
+ for (j = 0; j < FrameMap::nof_caller_save_cpu_regs(); j++) {
state_put(input_state, reg_num(FrameMap::caller_save_cpu_reg_at(j)), NULL);
}
for (j = 0; j < FrameMap::nof_caller_save_fpu_regs; j++) {
@@ -5596,7 +5596,7 @@
_last_reg = pd_last_fpu_reg;
} else {
_first_reg = pd_first_cpu_reg;
- _last_reg = pd_last_cpu_reg;
+ _last_reg = FrameMap::last_cpu_reg();
}
assert(0 <= _first_reg && _first_reg < LinearScan::nof_regs, "out of range");
--- a/hotspot/src/share/vm/c1/c1_Runtime1.cpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/share/vm/c1/c1_Runtime1.cpp Wed Dec 08 17:50:49 2010 -0800
@@ -1174,7 +1174,7 @@
memmove(dst_addr, src_addr, length << l2es);
return ac_ok;
} else if (src->is_objArray() && dst->is_objArray()) {
- if (UseCompressedOops) { // will need for tiered
+ if (UseCompressedOops) {
narrowOop *src_addr = objArrayOop(src)->obj_at_addr<narrowOop>(src_pos);
narrowOop *dst_addr = objArrayOop(dst)->obj_at_addr<narrowOop>(dst_pos);
return obj_arraycopy_work(src, src_addr, dst, dst_addr, length);
@@ -1210,10 +1210,11 @@
assert(bs->has_write_ref_array_pre_opt(), "For pre-barrier as well.");
if (UseCompressedOops) {
bs->write_ref_array_pre((narrowOop*)dst, num);
+ Copy::conjoint_oops_atomic((narrowOop*) src, (narrowOop*) dst, num);
} else {
bs->write_ref_array_pre((oop*)dst, num);
+ Copy::conjoint_oops_atomic((oop*) src, (oop*) dst, num);
}
- Copy::conjoint_oops_atomic((oop*) src, (oop*) dst, num);
bs->write_ref_array(dst, num);
JRT_END
--- a/hotspot/src/share/vm/ci/ciMethod.cpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/share/vm/ci/ciMethod.cpp Wed Dec 08 17:50:49 2010 -0800
@@ -797,12 +797,13 @@
// ------------------------------------------------------------------
-// ciMethod::build_method_data
+// ciMethod::ensure_method_data
//
// Generate new methodDataOop objects at compile time.
-void ciMethod::build_method_data(methodHandle h_m) {
+// Return true if allocation was successful or no MDO is required.
+bool ciMethod::ensure_method_data(methodHandle h_m) {
EXCEPTION_CONTEXT;
- if (is_native() || is_abstract() || h_m()->is_accessor()) return;
+ if (is_native() || is_abstract() || h_m()->is_accessor()) return true;
if (h_m()->method_data() == NULL) {
methodOopDesc::build_interpreter_method_data(h_m, THREAD);
if (HAS_PENDING_EXCEPTION) {
@@ -812,18 +813,22 @@
if (h_m()->method_data() != NULL) {
_method_data = CURRENT_ENV->get_object(h_m()->method_data())->as_method_data();
_method_data->load_data();
+ return true;
} else {
_method_data = CURRENT_ENV->get_empty_methodData();
+ return false;
}
}
// public, retroactive version
-void ciMethod::build_method_data() {
+bool ciMethod::ensure_method_data() {
+ bool result = true;
if (_method_data == NULL || _method_data->is_empty()) {
GUARDED_VM_ENTRY({
- build_method_data(get_methodOop());
+ result = ensure_method_data(get_methodOop());
});
}
+ return result;
}
@@ -839,11 +844,6 @@
Thread* my_thread = JavaThread::current();
methodHandle h_m(my_thread, get_methodOop());
- // Create an MDO for the inlinee
- if (TieredCompilation && is_c1_compile(env->comp_level())) {
- build_method_data(h_m);
- }
-
if (h_m()->method_data() != NULL) {
_method_data = CURRENT_ENV->get_object(h_m()->method_data())->as_method_data();
_method_data->load_data();
@@ -854,6 +854,15 @@
}
+// ------------------------------------------------------------------
+// ciMethod::method_data_or_null
+// Returns a pointer to ciMethodData if MDO exists on the VM side,
+// NULL otherwise.
+ciMethodData* ciMethod::method_data_or_null() {
+ ciMethodData *md = method_data();
+ if (md->is_empty()) return NULL;
+ return md;
+}
// ------------------------------------------------------------------
// ciMethod::will_link
--- a/hotspot/src/share/vm/ci/ciMethod.hpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/share/vm/ci/ciMethod.hpp Wed Dec 08 17:50:49 2010 -0800
@@ -106,7 +106,7 @@
void check_is_loaded() const { assert(is_loaded(), "not loaded"); }
- void build_method_data(methodHandle h_m);
+ bool ensure_method_data(methodHandle h_m);
void code_at_put(int bci, Bytecodes::Code code) {
Bytecodes::check(code);
@@ -121,6 +121,7 @@
ciSymbol* name() const { return _name; }
ciInstanceKlass* holder() const { return _holder; }
ciMethodData* method_data();
+ ciMethodData* method_data_or_null();
// Signature information.
ciSignature* signature() const { return _signature; }
@@ -230,7 +231,7 @@
bool has_unloaded_classes_in_signature();
bool is_klass_loaded(int refinfo_index, bool must_be_resolved) const;
bool check_call(int refinfo_index, bool is_static) const;
- void build_method_data(); // make sure it exists in the VM also
+ bool ensure_method_data(); // make sure it exists in the VM also
int scale_count(int count, float prof_factor = 1.); // make MDO count commensurate with IIC
// JSR 292 support
--- a/hotspot/src/share/vm/classfile/classFileParser.cpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/share/vm/classfile/classFileParser.cpp Wed Dec 08 17:50:49 2010 -0800
@@ -99,12 +99,6 @@
unsigned int hashValues[SymbolTable::symbol_alloc_batch_size];
int names_count = 0;
- // Side buffer for operands of variable-sized (InvokeDynamic) entries.
- GrowableArray<int>* operands = NULL;
-#ifdef ASSERT
- GrowableArray<int>* indy_instructions = new GrowableArray<int>(THREAD, 10);
-#endif
-
// parsing Index 0 is unused
for (int index = 1; index < length; index++) {
// Each of the following case guarantees one more byte in the stream
@@ -184,36 +178,20 @@
"Class file version does not support constant tag %u in class file %s"),
tag, CHECK);
}
- if (!AllowTransitionalJSR292 && tag == JVM_CONSTANT_InvokeDynamicTrans) {
- classfile_parse_error(
+ cfs->guarantee_more(5, CHECK); // bsm_index, nt, tag/access_flags
+ u2 bootstrap_specifier_index = cfs->get_u2_fast();
+ u2 name_and_type_index = cfs->get_u2_fast();
+ if (tag == JVM_CONSTANT_InvokeDynamicTrans) {
+ if (!AllowTransitionalJSR292)
+ classfile_parse_error(
"This JVM does not support transitional InvokeDynamic tag %u in class file %s",
tag, CHECK);
+ cp->invoke_dynamic_trans_at_put(index, bootstrap_specifier_index, name_and_type_index);
+ break;
}
- bool trans_no_argc = AllowTransitionalJSR292 && (tag == JVM_CONSTANT_InvokeDynamicTrans);
- cfs->guarantee_more(7, CHECK); // bsm_index, nt, argc, ..., tag/access_flags
- u2 bootstrap_method_index = cfs->get_u2_fast();
- u2 name_and_type_index = cfs->get_u2_fast();
- int argument_count = trans_no_argc ? 0 : cfs->get_u2_fast();
- cfs->guarantee_more(2*argument_count + 1, CHECK); // argv[argc]..., tag/access_flags
- int argv_offset = constantPoolOopDesc::_indy_argv_offset;
- int op_count = argv_offset + argument_count; // bsm, nt, argc, argv[]...
- int op_base = start_operand_group(operands, op_count, CHECK);
- assert(argv_offset == 3, "else adjust next 3 assignments");
- operands->at_put(op_base + constantPoolOopDesc::_indy_bsm_offset, bootstrap_method_index);
- operands->at_put(op_base + constantPoolOopDesc::_indy_nt_offset, name_and_type_index);
- operands->at_put(op_base + constantPoolOopDesc::_indy_argc_offset, argument_count);
- for (int arg_i = 0; arg_i < argument_count; arg_i++) {
- int arg = cfs->get_u2_fast();
- operands->at_put(op_base + constantPoolOopDesc::_indy_argv_offset + arg_i, arg);
- }
- cp->invoke_dynamic_at_put(index, op_base, op_count);
-#ifdef ASSERT
- // Record the steps just taken for later checking.
- indy_instructions->append(index);
- indy_instructions->append(bootstrap_method_index);
- indy_instructions->append(name_and_type_index);
- indy_instructions->append(argument_count);
-#endif //ASSERT
+ if (_max_bootstrap_specifier_index < (int) bootstrap_specifier_index)
+ _max_bootstrap_specifier_index = (int) bootstrap_specifier_index; // collect for later
+ cp->invoke_dynamic_at_put(index, bootstrap_specifier_index, name_and_type_index);
}
break;
case JVM_CONSTANT_Integer :
@@ -316,23 +294,6 @@
oopFactory::new_symbols(cp, names_count, names, lengths, indices, hashValues, CHECK);
}
- if (operands != NULL && operands->length() > 0) {
- store_operand_array(operands, cp, CHECK);
- }
-#ifdef ASSERT
- // Re-assert the indy structures, now that assertion checking can work.
- for (int indy_i = 0; indy_i < indy_instructions->length(); ) {
- int index = indy_instructions->at(indy_i++);
- int bootstrap_method_index = indy_instructions->at(indy_i++);
- int name_and_type_index = indy_instructions->at(indy_i++);
- int argument_count = indy_instructions->at(indy_i++);
- assert(cp->check_invoke_dynamic_at(index,
- bootstrap_method_index, name_and_type_index,
- argument_count),
- "indy structure is OK");
- }
-#endif //ASSERT
-
// Copy _current pointer of local copy back to stream().
#ifdef ASSERT
assert(cfs0->current() == old_current, "non-exclusive use of stream()");
@@ -340,41 +301,6 @@
cfs0->set_current(cfs1.current());
}
-int ClassFileParser::start_operand_group(GrowableArray<int>* &operands, int op_count, TRAPS) {
- if (operands == NULL) {
- operands = new GrowableArray<int>(THREAD, 100);
- int fillp_offset = constantPoolOopDesc::_multi_operand_buffer_fill_pointer_offset;
- while (operands->length() <= fillp_offset)
- operands->append(0); // force op_base > 0, for an error check
- DEBUG_ONLY(operands->at_put(fillp_offset, (int)badHeapWordVal));
- }
- int cnt_pos = operands->append(op_count);
- int arg_pos = operands->length();
- operands->at_grow(arg_pos + op_count - 1); // grow to include the operands
- assert(operands->length() == arg_pos + op_count, "");
- int op_base = cnt_pos - constantPoolOopDesc::_multi_operand_count_offset;
- return op_base;
-}
-
-void ClassFileParser::store_operand_array(GrowableArray<int>* operands, constantPoolHandle cp, TRAPS) {
- // Collect the buffer of operands from variable-sized entries into a permanent array.
- int arraylen = operands->length();
- int fillp_offset = constantPoolOopDesc::_multi_operand_buffer_fill_pointer_offset;
- assert(operands->at(fillp_offset) == (int)badHeapWordVal, "value unused so far");
- operands->at_put(fillp_offset, arraylen);
- cp->multi_operand_buffer_grow(arraylen, CHECK);
- typeArrayOop operands_oop = cp->operands();
- assert(operands_oop->length() == arraylen, "");
- for (int i = 0; i < arraylen; i++) {
- operands_oop->int_at_put(i, operands->at(i));
- }
- cp->set_operands(operands_oop);
- // The fill_pointer is used only by constantPoolOop::copy_entry_to and friends,
- // when constant pools need to be merged. Make sure it is sane now.
- assert(cp->multi_operand_buffer_fill_pointer() == arraylen, "");
-}
-
-
bool inline valid_cp_range(int index, int length) { return (index > 0 && index < length); }
constantPoolHandle ClassFileParser::parse_constant_pool(TRAPS) {
@@ -401,7 +327,8 @@
// first verification pass - validate cross references and fixup class and string constants
for (index = 1; index < length; index++) { // Index 0 is unused
- switch (cp->tag_at(index).value()) {
+ jbyte tag = cp->tag_at(index).value();
+ switch (tag) {
case JVM_CONSTANT_Class :
ShouldNotReachHere(); // Only JVM_CONSTANT_ClassIndex should be present
break;
@@ -543,35 +470,23 @@
}
break;
case JVM_CONSTANT_InvokeDynamicTrans :
- ShouldNotReachHere(); // this tag does not appear in the heap
case JVM_CONSTANT_InvokeDynamic :
{
- int bootstrap_method_ref_index = cp->invoke_dynamic_bootstrap_method_ref_index_at(index);
int name_and_type_ref_index = cp->invoke_dynamic_name_and_type_ref_index_at(index);
- check_property((bootstrap_method_ref_index == 0 && AllowTransitionalJSR292)
- ||
- (valid_cp_range(bootstrap_method_ref_index, length) &&
- (cp->tag_at(bootstrap_method_ref_index).is_method_handle())),
- "Invalid constant pool index %u in class file %s",
- bootstrap_method_ref_index,
- CHECK_(nullHandle));
check_property(valid_cp_range(name_and_type_ref_index, length) &&
cp->tag_at(name_and_type_ref_index).is_name_and_type(),
"Invalid constant pool index %u in class file %s",
name_and_type_ref_index,
CHECK_(nullHandle));
- int argc = cp->invoke_dynamic_argument_count_at(index);
- for (int arg_i = 0; arg_i < argc; arg_i++) {
- int arg = cp->invoke_dynamic_argument_index_at(index, arg_i);
- check_property(valid_cp_range(arg, length) &&
- cp->tag_at(arg).is_loadable_constant() ||
- // temporary early forms of string and class:
- cp->tag_at(arg).is_klass_index() ||
- cp->tag_at(arg).is_string_index(),
+ if (tag == JVM_CONSTANT_InvokeDynamicTrans) {
+ int bootstrap_method_ref_index = cp->invoke_dynamic_bootstrap_method_ref_index_at(index);
+ check_property(valid_cp_range(bootstrap_method_ref_index, length) &&
+ cp->tag_at(bootstrap_method_ref_index).is_method_handle(),
"Invalid constant pool index %u in class file %s",
- arg,
+ bootstrap_method_ref_index,
CHECK_(nullHandle));
}
+ // bootstrap specifier index must be checked later, when BootstrapMethods attr is available
break;
}
default:
@@ -2429,6 +2344,76 @@
k->set_generic_signature(cp->symbol_at(signature_index));
}
+void ClassFileParser::parse_classfile_bootstrap_methods_attribute(constantPoolHandle cp, instanceKlassHandle k,
+ u4 attribute_byte_length, TRAPS) {
+ ClassFileStream* cfs = stream();
+ u1* current_start = cfs->current();
+
+ cfs->guarantee_more(2, CHECK); // length
+ int attribute_array_length = cfs->get_u2_fast();
+
+ guarantee_property(_max_bootstrap_specifier_index < attribute_array_length,
+ "Short length on BootstrapMethods in class file %s",
+ CHECK);
+
+ // The attribute contains a counted array of counted tuples of shorts,
+ // represending bootstrap specifiers:
+ // length*{bootstrap_method_index, argument_count*{argument_index}}
+ int operand_count = (attribute_byte_length - sizeof(u2)) / sizeof(u2);
+ // operand_count = number of shorts in attr, except for leading length
+
+ // The attribute is copied into a short[] array.
+ // The array begins with a series of short[2] pairs, one for each tuple.
+ int index_size = (attribute_array_length * 2);
+
+ typeArrayOop operands_oop = oopFactory::new_permanent_intArray(index_size + operand_count, CHECK);
+ typeArrayHandle operands(THREAD, operands_oop);
+ operands_oop = NULL; // tidy
+
+ int operand_fill_index = index_size;
+ int cp_size = cp->length();
+
+ for (int n = 0; n < attribute_array_length; n++) {
+ // Store a 32-bit offset into the header of the operand array.
+ assert(constantPoolOopDesc::operand_offset_at(operands(), n) == 0, "");
+ constantPoolOopDesc::operand_offset_at_put(operands(), n, operand_fill_index);
+
+ // Read a bootstrap specifier.
+ cfs->guarantee_more(sizeof(u2) * 2, CHECK); // bsm, argc
+ u2 bootstrap_method_index = cfs->get_u2_fast();
+ u2 argument_count = cfs->get_u2_fast();
+ check_property(
+ valid_cp_range(bootstrap_method_index, cp_size) &&
+ cp->tag_at(bootstrap_method_index).is_method_handle(),
+ "bootstrap_method_index %u has bad constant type in class file %s",
+ CHECK);
+ operands->short_at_put(operand_fill_index++, bootstrap_method_index);
+ operands->short_at_put(operand_fill_index++, argument_count);
+
+ cfs->guarantee_more(sizeof(u2) * argument_count, CHECK); // argv[argc]
+ for (int j = 0; j < argument_count; j++) {
+ u2 arg_index = cfs->get_u2_fast();
+ check_property(
+ valid_cp_range(arg_index, cp_size) &&
+ cp->tag_at(arg_index).is_loadable_constant(),
+ "argument_index %u has bad constant type in class file %s",
+ CHECK);
+ operands->short_at_put(operand_fill_index++, arg_index);
+ }
+ }
+
+ assert(operand_fill_index == operands()->length(), "exact fill");
+ assert(constantPoolOopDesc::operand_array_length(operands()) == attribute_array_length, "correct decode");
+
+ u1* current_end = cfs->current();
+ guarantee_property(current_end == current_start + attribute_byte_length,
+ "Bad length on BootstrapMethods in class file %s",
+ CHECK);
+
+ cp->set_operands(operands());
+}
+
+
void ClassFileParser::parse_classfile_attributes(constantPoolHandle cp, instanceKlassHandle k, TRAPS) {
ClassFileStream* cfs = stream();
// Set inner classes attribute to default sentinel
@@ -2438,6 +2423,7 @@
bool parsed_sourcefile_attribute = false;
bool parsed_innerclasses_attribute = false;
bool parsed_enclosingmethod_attribute = false;
+ bool parsed_bootstrap_methods_attribute = false;
u1* runtime_visible_annotations = NULL;
int runtime_visible_annotations_length = 0;
u1* runtime_invisible_annotations = NULL;
@@ -2536,6 +2522,12 @@
classfile_parse_error("Invalid or out-of-bounds method index in EnclosingMethod attribute in class file %s", CHECK);
}
k->set_enclosing_method_indices(class_index, method_index);
+ } else if (tag == vmSymbols::tag_bootstrap_methods() &&
+ _major_version >= Verifier::INVOKEDYNAMIC_MAJOR_VERSION) {
+ if (parsed_bootstrap_methods_attribute)
+ classfile_parse_error("Multiple BootstrapMethods attributes in class file %s", CHECK);
+ parsed_bootstrap_methods_attribute = true;
+ parse_classfile_bootstrap_methods_attribute(cp, k, attribute_length, CHECK);
} else {
// Unknown attribute
cfs->skip_u1(attribute_length, CHECK);
@@ -2551,6 +2543,11 @@
runtime_invisible_annotations_length,
CHECK);
k->set_class_annotations(annotations());
+
+ if (_max_bootstrap_specifier_index >= 0) {
+ guarantee_property(parsed_bootstrap_methods_attribute,
+ "Missing BootstrapMethods attribute in class file %s", CHECK);
+ }
}
@@ -2868,6 +2865,7 @@
PerfClassTraceTime::PARSE_CLASS);
_has_finalizer = _has_empty_finalizer = _has_vanilla_constructor = false;
+ _max_bootstrap_specifier_index = -1;
if (JvmtiExport::should_post_class_file_load_hook()) {
unsigned char* ptr = cfs->buffer();
--- a/hotspot/src/share/vm/classfile/classFileParser.hpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/share/vm/classfile/classFileParser.hpp Wed Dec 08 17:50:49 2010 -0800
@@ -50,6 +50,8 @@
bool _has_empty_finalizer;
bool _has_vanilla_constructor;
+ int _max_bootstrap_specifier_index;
+
enum { fixed_buffer_size = 128 };
u_char linenumbertable_buffer[fixed_buffer_size];
@@ -66,9 +68,6 @@
constantPoolHandle parse_constant_pool(TRAPS);
- static int start_operand_group(GrowableArray<int>* &operands, int op_count, TRAPS);
- static void store_operand_array(GrowableArray<int>* operands, constantPoolHandle cp, TRAPS);
-
// Interface parsing
objArrayHandle parse_interfaces(constantPoolHandle cp,
int length,
@@ -130,6 +129,7 @@
void parse_classfile_attributes(constantPoolHandle cp, instanceKlassHandle k, TRAPS);
void parse_classfile_synthetic_attribute(constantPoolHandle cp, instanceKlassHandle k, TRAPS);
void parse_classfile_signature_attribute(constantPoolHandle cp, instanceKlassHandle k, TRAPS);
+ void parse_classfile_bootstrap_methods_attribute(constantPoolHandle cp, instanceKlassHandle k, u4 attribute_length, TRAPS);
// Annotations handling
typeArrayHandle assemble_annotations(u1* runtime_visible_annotations,
--- a/hotspot/src/share/vm/classfile/systemDictionary.cpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp Wed Dec 08 17:50:49 2010 -0800
@@ -2010,7 +2010,7 @@
scan = WKID(meth_group_end+1);
}
WKID indy_group_start = WK_KLASS_ENUM_NAME(Linkage_klass);
- WKID indy_group_end = WK_KLASS_ENUM_NAME(InvokeDynamic_klass);
+ WKID indy_group_end = WK_KLASS_ENUM_NAME(CallSite_klass);
initialize_wk_klasses_until(indy_group_start, scan, CHECK);
if (EnableInvokeDynamic) {
initialize_wk_klasses_through(indy_group_end, scan, CHECK);
--- a/hotspot/src/share/vm/classfile/systemDictionary.hpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp Wed Dec 08 17:50:49 2010 -0800
@@ -156,8 +156,7 @@
template(WrongMethodTypeException_klass, java_dyn_WrongMethodTypeException, Opt) \
template(Linkage_klass, java_dyn_Linkage, Opt) \
template(CallSite_klass, java_dyn_CallSite, Opt) \
- template(InvokeDynamic_klass, java_dyn_InvokeDynamic, Opt) \
- /* Note: MethodHandle must be first, and InvokeDynamic last in group */ \
+ /* Note: MethodHandle must be first, and CallSite last in group */ \
\
template(StringBuffer_klass, java_lang_StringBuffer, Pre) \
template(StringBuilder_klass, java_lang_StringBuilder, Pre) \
--- a/hotspot/src/share/vm/classfile/vmSymbols.hpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp Wed Dec 08 17:50:49 2010 -0800
@@ -132,6 +132,7 @@
template(tag_runtime_invisible_parameter_annotations,"RuntimeInvisibleParameterAnnotations") \
template(tag_annotation_default, "AnnotationDefault") \
template(tag_enclosing_method, "EnclosingMethod") \
+ template(tag_bootstrap_methods, "BootstrapMethods") \
\
/* exception klasses: at least all exceptions thrown by the VM have entries here */ \
template(java_lang_ArithmeticException, "java/lang/ArithmeticException") \
--- a/hotspot/src/share/vm/code/relocInfo.cpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/share/vm/code/relocInfo.cpp Wed Dec 08 17:50:49 2010 -0800
@@ -1093,8 +1093,8 @@
tty->print_cr("(no relocs)");
return;
}
- tty->print("relocInfo@" INTPTR_FORMAT " [type=%d(%s) addr=" INTPTR_FORMAT,
- _current, type(), reloc_type_string((relocInfo::relocType) type()), _addr);
+ tty->print("relocInfo@" INTPTR_FORMAT " [type=%d(%s) addr=" INTPTR_FORMAT " offset=%d",
+ _current, type(), reloc_type_string((relocInfo::relocType) type()), _addr, _current->addr_offset());
if (current()->format() != 0)
tty->print(" format=%d", current()->format());
if (datalen() == 1) {
--- a/hotspot/src/share/vm/compiler/disassembler.cpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/share/vm/compiler/disassembler.cpp Wed Dec 08 17:50:49 2010 -0800
@@ -466,5 +466,18 @@
env.set_total_ticks(total_bucket_count);
}
+ // Print constant table.
+ if (nm->consts_size() > 0) {
+ nm->print_nmethod_labels(env.output(), nm->consts_begin());
+ int offset = 0;
+ for (address p = nm->consts_begin(); p < nm->consts_end(); p += 4, offset += 4) {
+ if ((offset % 8) == 0) {
+ env.output()->print_cr(" " INTPTR_FORMAT " (offset: %4d): " PTR32_FORMAT " " PTR64_FORMAT, (intptr_t) p, offset, *((int32_t*) p), *((int64_t*) p));
+ } else {
+ env.output()->print_cr(" " INTPTR_FORMAT " (offset: %4d): " PTR32_FORMAT, (intptr_t) p, offset, *((int32_t*) p));
+ }
+ }
+ }
+
env.decode_instructions(p, end);
}
--- a/hotspot/src/share/vm/interpreter/bytecodeTracer.cpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/share/vm/interpreter/bytecodeTracer.cpp Wed Dec 08 17:50:49 2010 -0800
@@ -346,6 +346,7 @@
break;
case JVM_CONSTANT_NameAndType:
case JVM_CONSTANT_InvokeDynamic:
+ case JVM_CONSTANT_InvokeDynamicTrans:
has_klass = false;
break;
default:
--- a/hotspot/src/share/vm/interpreter/rewriter.cpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/share/vm/interpreter/rewriter.cpp Wed Dec 08 17:50:49 2010 -0800
@@ -52,6 +52,7 @@
case JVM_CONSTANT_MethodHandle : // fall through
case JVM_CONSTANT_MethodType : // fall through
case JVM_CONSTANT_InvokeDynamic : // fall through
+ case JVM_CONSTANT_InvokeDynamicTrans: // fall through
add_cp_cache_entry(i);
break;
}
@@ -61,6 +62,7 @@
"all cp cache indexes fit in a u2");
_have_invoke_dynamic = ((tag_mask & (1 << JVM_CONSTANT_InvokeDynamic)) != 0);
+ _have_invoke_dynamic |= ((tag_mask & (1 << JVM_CONSTANT_InvokeDynamicTrans)) != 0);
}
@@ -74,7 +76,7 @@
oopFactory::new_constantPoolCache(length, methodOopDesc::IsUnsafeConc, CHECK);
cache->initialize(_cp_cache_map);
- // Don't bother to the next pass if there is no JVM_CONSTANT_InvokeDynamic.
+ // Don't bother with the next pass if there is no JVM_CONSTANT_InvokeDynamic.
if (_have_invoke_dynamic) {
for (int i = 0; i < length; i++) {
int pool_index = cp_cache_entry_pool_index(i);
--- a/hotspot/src/share/vm/oops/constantPoolKlass.cpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/share/vm/oops/constantPoolKlass.cpp Wed Dec 08 17:50:49 2010 -0800
@@ -399,6 +399,7 @@
case JVM_CONSTANT_MethodType :
st->print("signature_index=%d", cp->method_type_index_at(index));
break;
+ case JVM_CONSTANT_InvokeDynamicTrans :
case JVM_CONSTANT_InvokeDynamic :
{
st->print("bootstrap_method_index=%d", cp->invoke_dynamic_bootstrap_method_ref_index_at(index));
--- a/hotspot/src/share/vm/oops/constantPoolOop.cpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/share/vm/oops/constantPoolOop.cpp Wed Dec 08 17:50:49 2010 -0800
@@ -915,7 +915,8 @@
{
int k1 = method_type_index_at(index1);
int k2 = cp2->method_type_index_at(index2);
- if (k1 == k2) {
+ bool match = compare_entry_to(k1, cp2, k2, CHECK_false);
+ if (match) {
return true;
}
} break;
@@ -927,28 +928,33 @@
if (k1 == k2) {
int i1 = method_handle_index_at(index1);
int i2 = cp2->method_handle_index_at(index2);
- if (i1 == i2) {
+ bool match = compare_entry_to(i1, cp2, i2, CHECK_false);
+ if (match) {
return true;
}
}
} break;
case JVM_CONSTANT_InvokeDynamic:
+ case JVM_CONSTANT_InvokeDynamicTrans:
{
- int op_count = multi_operand_count_at(index1);
- if (op_count == cp2->multi_operand_count_at(index2)) {
- bool all_equal = true;
- for (int op_i = 0; op_i < op_count; op_i++) {
- int k1 = multi_operand_ref_at(index1, op_i);
- int k2 = cp2->multi_operand_ref_at(index2, op_i);
- if (k1 != k2) {
- all_equal = false;
- break;
- }
+ int k1 = invoke_dynamic_bootstrap_method_ref_index_at(index1);
+ int k2 = cp2->invoke_dynamic_bootstrap_method_ref_index_at(index2);
+ bool match = compare_entry_to(k1, cp2, k2, CHECK_false);
+ if (!match) return false;
+ k1 = invoke_dynamic_name_and_type_ref_index_at(index1);
+ k2 = cp2->invoke_dynamic_name_and_type_ref_index_at(index2);
+ match = compare_entry_to(k1, cp2, k2, CHECK_false);
+ if (!match) return false;
+ int argc = invoke_dynamic_argument_count_at(index1);
+ if (argc == cp2->invoke_dynamic_argument_count_at(index2)) {
+ for (int j = 0; j < argc; j++) {
+ k1 = invoke_dynamic_argument_index_at(index1, j);
+ k2 = cp2->invoke_dynamic_argument_index_at(index2, j);
+ match = compare_entry_to(k1, cp2, k2, CHECK_false);
+ if (!match) return false;
}
- if (all_equal) {
- return true; // got through loop; all elements equal
- }
+ return true; // got through loop; all elements equal
}
} break;
@@ -984,44 +990,18 @@
} // end compare_entry_to()
-// Grow this->operands() to the indicated length, unless it is already at least that long.
-void constantPoolOopDesc::multi_operand_buffer_grow(int min_length, TRAPS) {
- int old_length = multi_operand_buffer_fill_pointer();
- if (old_length >= min_length) return;
- int new_length = min_length;
- assert(new_length > _multi_operand_buffer_fill_pointer_offset, "");
- typeArrayHandle new_operands = oopFactory::new_permanent_intArray(new_length, CHECK);
- if (operands() == NULL) {
- new_operands->int_at_put(_multi_operand_buffer_fill_pointer_offset, old_length);
- } else {
- // copy fill pointer and everything else
- for (int i = 0; i < old_length; i++) {
- new_operands->int_at_put(i, operands()->int_at(i));
- }
- }
- set_operands(new_operands());
-}
-
-
// Copy this constant pool's entries at start_i to end_i (inclusive)
// to the constant pool to_cp's entries starting at to_i. A total of
// (end_i - start_i) + 1 entries are copied.
-void constantPoolOopDesc::copy_cp_to(int start_i, int end_i,
+void constantPoolOopDesc::copy_cp_to_impl(constantPoolHandle from_cp, int start_i, int end_i,
constantPoolHandle to_cp, int to_i, TRAPS) {
int dest_i = to_i; // leave original alone for debug purposes
- if (operands() != NULL) {
- // pre-grow the target CP's operand buffer
- int nops = this->multi_operand_buffer_fill_pointer();
- nops += to_cp->multi_operand_buffer_fill_pointer();
- to_cp->multi_operand_buffer_grow(nops, CHECK);
- }
+ for (int src_i = start_i; src_i <= end_i; /* see loop bottom */ ) {
+ copy_entry_to(from_cp, src_i, to_cp, dest_i, CHECK);
- for (int src_i = start_i; src_i <= end_i; /* see loop bottom */ ) {
- copy_entry_to(src_i, to_cp, dest_i, CHECK);
-
- switch (tag_at(src_i).value()) {
+ switch (from_cp->tag_at(src_i).value()) {
case JVM_CONSTANT_Double:
case JVM_CONSTANT_Long:
// double and long take two constant pool entries
@@ -1036,30 +1016,81 @@
break;
}
}
+
+ int from_oplen = operand_array_length(from_cp->operands());
+ int old_oplen = operand_array_length(to_cp->operands());
+ if (from_oplen != 0) {
+ // append my operands to the target's operands array
+ if (old_oplen == 0) {
+ to_cp->set_operands(from_cp->operands()); // reuse; do not merge
+ } else {
+ int old_len = to_cp->operands()->length();
+ int from_len = from_cp->operands()->length();
+ int old_off = old_oplen * sizeof(u2);
+ int from_off = from_oplen * sizeof(u2);
+ typeArrayHandle new_operands = oopFactory::new_permanent_shortArray(old_len + from_len, CHECK);
+ int fillp = 0, len = 0;
+ // first part of dest
+ Copy::conjoint_memory_atomic(to_cp->operands()->short_at_addr(0),
+ new_operands->short_at_addr(fillp),
+ (len = old_off) * sizeof(u2));
+ fillp += len;
+ // first part of src
+ Copy::conjoint_memory_atomic(to_cp->operands()->short_at_addr(0),
+ new_operands->short_at_addr(fillp),
+ (len = from_off) * sizeof(u2));
+ fillp += len;
+ // second part of dest
+ Copy::conjoint_memory_atomic(to_cp->operands()->short_at_addr(old_off),
+ new_operands->short_at_addr(fillp),
+ (len = old_len - old_off) * sizeof(u2));
+ fillp += len;
+ // second part of src
+ Copy::conjoint_memory_atomic(to_cp->operands()->short_at_addr(from_off),
+ new_operands->short_at_addr(fillp),
+ (len = from_len - from_off) * sizeof(u2));
+ fillp += len;
+ assert(fillp == new_operands->length(), "");
+
+ // Adjust indexes in the first part of the copied operands array.
+ for (int j = 0; j < from_oplen; j++) {
+ int offset = operand_offset_at(new_operands(), old_oplen + j);
+ assert(offset == operand_offset_at(from_cp->operands(), j), "correct copy");
+ offset += old_len; // every new tuple is preceded by old_len extra u2's
+ operand_offset_at_put(new_operands(), old_oplen + j, offset);
+ }
+
+ // replace target operands array with combined array
+ to_cp->set_operands(new_operands());
+ }
+ }
+
} // end copy_cp_to()
// Copy this constant pool's entry at from_i to the constant pool
// to_cp's entry at to_i.
-void constantPoolOopDesc::copy_entry_to(int from_i, constantPoolHandle to_cp,
- int to_i, TRAPS) {
+void constantPoolOopDesc::copy_entry_to(constantPoolHandle from_cp, int from_i,
+ constantPoolHandle to_cp, int to_i,
+ TRAPS) {
- switch (tag_at(from_i).value()) {
+ int tag = from_cp->tag_at(from_i).value();
+ switch (tag) {
case JVM_CONSTANT_Class:
{
- klassOop k = klass_at(from_i, CHECK);
+ klassOop k = from_cp->klass_at(from_i, CHECK);
to_cp->klass_at_put(to_i, k);
} break;
case JVM_CONSTANT_ClassIndex:
{
- jint ki = klass_index_at(from_i);
+ jint ki = from_cp->klass_index_at(from_i);
to_cp->klass_index_at_put(to_i, ki);
} break;
case JVM_CONSTANT_Double:
{
- jdouble d = double_at(from_i);
+ jdouble d = from_cp->double_at(from_i);
to_cp->double_at_put(to_i, d);
// double takes two constant pool entries so init second entry's tag
to_cp->tag_at_put(to_i + 1, JVM_CONSTANT_Invalid);
@@ -1067,33 +1098,33 @@
case JVM_CONSTANT_Fieldref:
{
- int class_index = uncached_klass_ref_index_at(from_i);
- int name_and_type_index = uncached_name_and_type_ref_index_at(from_i);
+ int class_index = from_cp->uncached_klass_ref_index_at(from_i);
+ int name_and_type_index = from_cp->uncached_name_and_type_ref_index_at(from_i);
to_cp->field_at_put(to_i, class_index, name_and_type_index);
} break;
case JVM_CONSTANT_Float:
{
- jfloat f = float_at(from_i);
+ jfloat f = from_cp->float_at(from_i);
to_cp->float_at_put(to_i, f);
} break;
case JVM_CONSTANT_Integer:
{
- jint i = int_at(from_i);
+ jint i = from_cp->int_at(from_i);
to_cp->int_at_put(to_i, i);
} break;
case JVM_CONSTANT_InterfaceMethodref:
{
- int class_index = uncached_klass_ref_index_at(from_i);
- int name_and_type_index = uncached_name_and_type_ref_index_at(from_i);
+ int class_index = from_cp->uncached_klass_ref_index_at(from_i);
+ int name_and_type_index = from_cp->uncached_name_and_type_ref_index_at(from_i);
to_cp->interface_method_at_put(to_i, class_index, name_and_type_index);
} break;
case JVM_CONSTANT_Long:
{
- jlong l = long_at(from_i);
+ jlong l = from_cp->long_at(from_i);
to_cp->long_at_put(to_i, l);
// long takes two constant pool entries so init second entry's tag
to_cp->tag_at_put(to_i + 1, JVM_CONSTANT_Invalid);
@@ -1101,39 +1132,39 @@
case JVM_CONSTANT_Methodref:
{
- int class_index = uncached_klass_ref_index_at(from_i);
- int name_and_type_index = uncached_name_and_type_ref_index_at(from_i);
+ int class_index = from_cp->uncached_klass_ref_index_at(from_i);
+ int name_and_type_index = from_cp->uncached_name_and_type_ref_index_at(from_i);
to_cp->method_at_put(to_i, class_index, name_and_type_index);
} break;
case JVM_CONSTANT_NameAndType:
{
- int name_ref_index = name_ref_index_at(from_i);
- int signature_ref_index = signature_ref_index_at(from_i);
+ int name_ref_index = from_cp->name_ref_index_at(from_i);
+ int signature_ref_index = from_cp->signature_ref_index_at(from_i);
to_cp->name_and_type_at_put(to_i, name_ref_index, signature_ref_index);
} break;
case JVM_CONSTANT_String:
{
- oop s = string_at(from_i, CHECK);
+ oop s = from_cp->string_at(from_i, CHECK);
to_cp->string_at_put(to_i, s);
} break;
case JVM_CONSTANT_StringIndex:
{
- jint si = string_index_at(from_i);
+ jint si = from_cp->string_index_at(from_i);
to_cp->string_index_at_put(to_i, si);
} break;
case JVM_CONSTANT_UnresolvedClass:
{
- symbolOop k = unresolved_klass_at(from_i);
+ symbolOop k = from_cp->unresolved_klass_at(from_i);
to_cp->unresolved_klass_at_put(to_i, k);
} break;
case JVM_CONSTANT_UnresolvedClassInError:
{
- symbolOop k = unresolved_klass_at(from_i);
+ symbolOop k = from_cp->unresolved_klass_at(from_i);
to_cp->unresolved_klass_at_put(to_i, k);
to_cp->tag_at_put(to_i, JVM_CONSTANT_UnresolvedClassInError);
} break;
@@ -1141,51 +1172,42 @@
case JVM_CONSTANT_UnresolvedString:
{
- symbolOop s = unresolved_string_at(from_i);
+ symbolOop s = from_cp->unresolved_string_at(from_i);
to_cp->unresolved_string_at_put(to_i, s);
} break;
case JVM_CONSTANT_Utf8:
{
- symbolOop s = symbol_at(from_i);
+ symbolOop s = from_cp->symbol_at(from_i);
to_cp->symbol_at_put(to_i, s);
} break;
case JVM_CONSTANT_MethodType:
{
- jint k = method_type_index_at(from_i);
+ jint k = from_cp->method_type_index_at(from_i);
to_cp->method_type_index_at_put(to_i, k);
} break;
case JVM_CONSTANT_MethodHandle:
{
- int k1 = method_handle_ref_kind_at(from_i);
- int k2 = method_handle_index_at(from_i);
+ int k1 = from_cp->method_handle_ref_kind_at(from_i);
+ int k2 = from_cp->method_handle_index_at(from_i);
to_cp->method_handle_index_at_put(to_i, k1, k2);
} break;
+ case JVM_CONSTANT_InvokeDynamicTrans:
+ {
+ int k1 = from_cp->invoke_dynamic_bootstrap_method_ref_index_at(from_i);
+ int k2 = from_cp->invoke_dynamic_name_and_type_ref_index_at(from_i);
+ to_cp->invoke_dynamic_trans_at_put(to_i, k1, k2);
+ } break;
+
case JVM_CONSTANT_InvokeDynamic:
{
- int op_count = multi_operand_count_at(from_i);
- int fillp = to_cp->multi_operand_buffer_fill_pointer();
- int to_op_base = fillp - _multi_operand_count_offset; // fillp is count offset; get to base
- to_cp->multi_operand_buffer_grow(to_op_base + op_count, CHECK);
- to_cp->operands()->int_at_put(fillp++, op_count);
- assert(fillp == to_op_base + _multi_operand_base_offset, "just wrote count, will now write args");
- for (int op_i = 0; op_i < op_count; op_i++) {
- int op = multi_operand_ref_at(from_i, op_i);
- to_cp->operands()->int_at_put(fillp++, op);
- }
- assert(fillp <= to_cp->operands()->length(), "oob");
- to_cp->set_multi_operand_buffer_fill_pointer(fillp);
- to_cp->invoke_dynamic_at_put(to_i, to_op_base, op_count);
-#ifdef ASSERT
- int k1 = invoke_dynamic_bootstrap_method_ref_index_at(from_i);
- int k2 = invoke_dynamic_name_and_type_ref_index_at(from_i);
- int k3 = invoke_dynamic_argument_count_at(from_i);
- assert(to_cp->check_invoke_dynamic_at(to_i, k1, k2, k3),
- "indy structure is OK");
-#endif //ASSERT
+ int k1 = from_cp->invoke_dynamic_bootstrap_specifier_index(from_i);
+ int k2 = from_cp->invoke_dynamic_name_and_type_ref_index_at(from_i);
+ k1 += operand_array_length(to_cp->operands()); // to_cp might already have operands
+ to_cp->invoke_dynamic_at_put(to_i, k1, k2);
} break;
// Invalid is used as the tag for the second constant pool entry
@@ -1195,7 +1217,6 @@
default:
{
- jbyte bad_value = tag_at(from_i).value(); // leave a breadcrumb
ShouldNotReachHere();
} break;
}
@@ -1406,8 +1427,9 @@
return 5;
case JVM_CONSTANT_InvokeDynamic:
- // u1 tag, u2 bsm, u2 nt, u2 argc, u2 argv[argc]
- return 7 + 2 * invoke_dynamic_argument_count_at(idx);
+ case JVM_CONSTANT_InvokeDynamicTrans:
+ // u1 tag, u2 bsm, u2 nt
+ return 5;
case JVM_CONSTANT_Long:
case JVM_CONSTANT_Double:
@@ -1620,19 +1642,15 @@
DBG(printf("JVM_CONSTANT_MethodType: %hd", idx1));
break;
}
+ case JVM_CONSTANT_InvokeDynamicTrans:
case JVM_CONSTANT_InvokeDynamic: {
- *bytes = JVM_CONSTANT_InvokeDynamic;
- idx1 = invoke_dynamic_bootstrap_method_ref_index_at(idx);
- idx2 = invoke_dynamic_name_and_type_ref_index_at(idx);
- int argc = invoke_dynamic_argument_count_at(idx);
+ *bytes = tag;
+ idx1 = extract_low_short_from_int(*int_at_addr(idx));
+ idx2 = extract_high_short_from_int(*int_at_addr(idx));
+ assert(idx2 == invoke_dynamic_name_and_type_ref_index_at(idx), "correct half of u4");
Bytes::put_Java_u2((address) (bytes+1), idx1);
Bytes::put_Java_u2((address) (bytes+3), idx2);
- Bytes::put_Java_u2((address) (bytes+5), argc);
- for (int arg_i = 0; arg_i < argc; arg_i++) {
- int arg = invoke_dynamic_argument_index_at(idx, arg_i);
- Bytes::put_Java_u2((address) (bytes+7+2*arg_i), arg);
- }
- DBG(printf("JVM_CONSTANT_InvokeDynamic: %hd %hd [%d]", idx1, idx2, argc));
+ DBG(printf("JVM_CONSTANT_InvokeDynamic: %hd %hd", idx1, idx2));
break;
}
}
--- a/hotspot/src/share/vm/oops/constantPoolOop.hpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/share/vm/oops/constantPoolOop.hpp Wed Dec 08 17:50:49 2010 -0800
@@ -179,28 +179,16 @@
*int_at_addr(which) = ref_index;
}
- void invoke_dynamic_at_put(int which, int operand_base, int operand_count) {
+ void invoke_dynamic_at_put(int which, int bootstrap_specifier_index, int name_and_type_index) {
tag_at_put(which, JVM_CONSTANT_InvokeDynamic);
- *int_at_addr(which) = operand_base; // this is the real information
+ *int_at_addr(which) = ((jint) name_and_type_index<<16) | bootstrap_specifier_index;
}
-#ifdef ASSERT
- bool check_invoke_dynamic_at(int which,
- int bootstrap_method_index,
- int name_and_type_index,
- int argument_count) {
- assert(invoke_dynamic_bootstrap_method_ref_index_at(which) == bootstrap_method_index,
- "already stored by caller");
- assert(invoke_dynamic_name_and_type_ref_index_at(which) == name_and_type_index,
- "already stored by caller");
- assert(invoke_dynamic_argument_count_at(which) == argument_count,
- "consistent argument count");
- if (argument_count != 0) {
- invoke_dynamic_argument_index_at(which, 0);
- invoke_dynamic_argument_index_at(which, argument_count - 1);
- }
- return true;
+
+ void invoke_dynamic_trans_at_put(int which, int bootstrap_method_index, int name_and_type_index) {
+ tag_at_put(which, JVM_CONSTANT_InvokeDynamicTrans);
+ *int_at_addr(which) = ((jint) name_and_type_index<<16) | bootstrap_method_index;
+ assert(AllowTransitionalJSR292, "");
}
-#endif //ASSERT
// Temporary until actual use
void unresolved_string_at_put(int which, symbolOop s) {
@@ -443,75 +431,90 @@
return symbol_at(sym);
}
- private:
- // some nodes (InvokeDynamic) have a variable number of operands, each a u2 value
- enum { _multi_operand_count_offset = -1,
- _multi_operand_base_offset = 0,
- _multi_operand_buffer_fill_pointer_offset = 0 // shared at front of operands array
- };
- int multi_operand_buffer_length() {
- return operands() == NULL ? 0 : operands()->length();
- }
- int multi_operand_buffer_fill_pointer() {
- return operands() == NULL
- ? _multi_operand_buffer_fill_pointer_offset + 1
- : operands()->int_at(_multi_operand_buffer_fill_pointer_offset);
- }
- void multi_operand_buffer_grow(int min_length, TRAPS);
- void set_multi_operand_buffer_fill_pointer(int fillp) {
- assert(operands() != NULL, "");
- operands()->int_at_put(_multi_operand_buffer_fill_pointer_offset, fillp);
- }
- int multi_operand_base_at(int which) {
+ int invoke_dynamic_name_and_type_ref_index_at(int which) {
assert(tag_at(which).is_invoke_dynamic(), "Corrupted constant pool");
- int op_base = *int_at_addr(which);
- assert(op_base > _multi_operand_buffer_fill_pointer_offset, "Corrupted operand base");
- return op_base;
+ return extract_high_short_from_int(*int_at_addr(which));
}
- int multi_operand_count_at(int which) {
- int op_base = multi_operand_base_at(which);
- assert((uint)(op_base + _multi_operand_count_offset) < (uint)operands()->length(), "oob");
- int count = operands()->int_at(op_base + _multi_operand_count_offset);
- return count;
+ int invoke_dynamic_bootstrap_specifier_index(int which) {
+ assert(tag_at(which).value() == JVM_CONSTANT_InvokeDynamic, "Corrupted constant pool");
+ return extract_low_short_from_int(*int_at_addr(which));
+ }
+ int invoke_dynamic_operand_base(int which) {
+ int bootstrap_specifier_index = invoke_dynamic_bootstrap_specifier_index(which);
+ return operand_offset_at(operands(), bootstrap_specifier_index);
}
- int multi_operand_ref_at(int which, int i) {
- int op_base = multi_operand_base_at(which);
- assert((uint)i < (uint)multi_operand_count_at(which), "oob");
- assert((uint)(op_base + _multi_operand_base_offset + i) < (uint)operands()->length(), "oob");
- return operands()->int_at(op_base + _multi_operand_base_offset + i);
+ // The first part of the operands array consists of an index into the second part.
+ // Extract a 32-bit index value from the first part.
+ static int operand_offset_at(typeArrayOop operands, int bootstrap_specifier_index) {
+ int n = (bootstrap_specifier_index * 2);
+ assert(n >= 0 && n+2 <= operands->length(), "oob");
+ // The first 32-bit index points to the beginning of the second part
+ // of the operands array. Make sure this index is in the first part.
+ DEBUG_ONLY(int second_part = build_int_from_shorts(operands->short_at(0),
+ operands->short_at(1)));
+ assert(second_part == 0 || n+2 <= second_part, "oob (2)");
+ int offset = build_int_from_shorts(operands->short_at(n+0),
+ operands->short_at(n+1));
+ // The offset itself must point into the second part of the array.
+ assert(offset == 0 || offset >= second_part && offset <= operands->length(), "oob (3)");
+ return offset;
}
- void set_multi_operand_ref_at(int which, int i, int ref) {
- DEBUG_ONLY(multi_operand_ref_at(which, i)); // trigger asserts
- int op_base = multi_operand_base_at(which);
- operands()->int_at_put(op_base + _multi_operand_base_offset + i, ref);
+ static void operand_offset_at_put(typeArrayOop operands, int bootstrap_specifier_index, int offset) {
+ int n = bootstrap_specifier_index * 2;
+ assert(n >= 0 && n+2 <= operands->length(), "oob");
+ operands->short_at_put(n+0, extract_low_short_from_int(offset));
+ operands->short_at_put(n+1, extract_high_short_from_int(offset));
+ }
+ static int operand_array_length(typeArrayOop operands) {
+ if (operands == NULL || operands->length() == 0) return 0;
+ int second_part = operand_offset_at(operands, 0);
+ return (second_part / 2);
}
- public:
- // layout of InvokeDynamic:
+#ifdef ASSERT
+ // operand tuples fit together exactly, end to end
+ static int operand_limit_at(typeArrayOop operands, int bootstrap_specifier_index) {
+ int nextidx = bootstrap_specifier_index + 1;
+ if (nextidx == operand_array_length(operands))
+ return operands->length();
+ else
+ return operand_offset_at(operands, nextidx);
+ }
+ int invoke_dynamic_operand_limit(int which) {
+ int bootstrap_specifier_index = invoke_dynamic_bootstrap_specifier_index(which);
+ return operand_limit_at(operands(), bootstrap_specifier_index);
+ }
+#endif //ASSERT
+
+ // layout of InvokeDynamic bootstrap method specifier (in second part of operands array):
enum {
_indy_bsm_offset = 0, // CONSTANT_MethodHandle bsm
- _indy_nt_offset = 1, // CONSTANT_NameAndType descr
- _indy_argc_offset = 2, // u2 argc
- _indy_argv_offset = 3 // u2 argv[argc]
+ _indy_argc_offset = 1, // u2 argc
+ _indy_argv_offset = 2 // u2 argv[argc]
};
int invoke_dynamic_bootstrap_method_ref_index_at(int which) {
assert(tag_at(which).is_invoke_dynamic(), "Corrupted constant pool");
- return multi_operand_ref_at(which, _indy_bsm_offset);
- }
- int invoke_dynamic_name_and_type_ref_index_at(int which) {
- assert(tag_at(which).is_invoke_dynamic(), "Corrupted constant pool");
- return multi_operand_ref_at(which, _indy_nt_offset);
+ if (tag_at(which).value() == JVM_CONSTANT_InvokeDynamicTrans)
+ return extract_low_short_from_int(*int_at_addr(which));
+ int op_base = invoke_dynamic_operand_base(which);
+ return operands()->short_at(op_base + _indy_bsm_offset);
}
int invoke_dynamic_argument_count_at(int which) {
assert(tag_at(which).is_invoke_dynamic(), "Corrupted constant pool");
- int argc = multi_operand_ref_at(which, _indy_argc_offset);
- DEBUG_ONLY(int op_count = multi_operand_count_at(which));
- assert(_indy_argv_offset + argc == op_count, "consistent inner and outer counts");
+ if (tag_at(which).value() == JVM_CONSTANT_InvokeDynamicTrans)
+ return 0;
+ int op_base = invoke_dynamic_operand_base(which);
+ int argc = operands()->short_at(op_base + _indy_argc_offset);
+ DEBUG_ONLY(int end_offset = op_base + _indy_argv_offset + argc;
+ int next_offset = invoke_dynamic_operand_limit(which));
+ assert(end_offset == next_offset, "matched ending");
return argc;
}
int invoke_dynamic_argument_index_at(int which, int j) {
- assert((uint)j < (uint)invoke_dynamic_argument_count_at(which), "oob");
- return multi_operand_ref_at(which, _indy_argv_offset + j);
+ int op_base = invoke_dynamic_operand_base(which);
+ DEBUG_ONLY(int argc = operands()->short_at(op_base + _indy_argc_offset));
+ assert((uint)j < (uint)argc, "oob");
+ return operands()->short_at(op_base + _indy_argv_offset + j);
}
// The following methods (name/signature/klass_ref_at, klass_ref_at_noresolve,
@@ -659,9 +662,12 @@
public:
// Merging constantPoolOop support:
bool compare_entry_to(int index1, constantPoolHandle cp2, int index2, TRAPS);
- void copy_cp_to(int start_i, int end_i, constantPoolHandle to_cp, int to_i,
- TRAPS);
- void copy_entry_to(int from_i, constantPoolHandle to_cp, int to_i, TRAPS);
+ void copy_cp_to(int start_i, int end_i, constantPoolHandle to_cp, int to_i, TRAPS) {
+ constantPoolHandle h_this(THREAD, this);
+ copy_cp_to_impl(h_this, start_i, end_i, to_cp, to_i, THREAD);
+ }
+ static void copy_cp_to_impl(constantPoolHandle from_cp, int start_i, int end_i, constantPoolHandle to_cp, int to_i, TRAPS);
+ static void copy_entry_to(constantPoolHandle from_cp, int from_i, constantPoolHandle to_cp, int to_i, TRAPS);
int find_matching_entry(int pattern_i, constantPoolHandle search_cp, TRAPS);
int orig_length() const { return _orig_length; }
void set_orig_length(int orig_length) { _orig_length = orig_length; }
--- a/hotspot/src/share/vm/opto/c2_globals.hpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/share/vm/opto/c2_globals.hpp Wed Dec 08 17:50:49 2010 -0800
@@ -284,6 +284,9 @@
develop(bool, SparcV9RegsHiBitsZero, true, \
"Assume Sparc V9 I&L registers on V8+ systems are zero-extended") \
\
+ product(bool, UseRDPCForConstantTableBase, false, \
+ "Use Sparc RDPC instruction for the constant table base.") \
+ \
develop(intx, PrintIdealGraphLevel, 0, \
"Print ideal graph to XML file / network interface. " \
"By default attempts to connect to the visualizer on a socket.") \
--- a/hotspot/src/share/vm/opto/compile.cpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/share/vm/opto/compile.cpp Wed Dec 08 17:50:49 2010 -0800
@@ -75,6 +75,18 @@
# include "adfiles/ad_zero.hpp"
#endif
+
+// -------------------- Compile::mach_constant_base_node -----------------------
+// Constant table base node singleton.
+MachConstantBaseNode* Compile::mach_constant_base_node() {
+ if (_mach_constant_base_node == NULL) {
+ _mach_constant_base_node = new (C) MachConstantBaseNode();
+ _mach_constant_base_node->add_req(C->root());
+ }
+ return _mach_constant_base_node;
+}
+
+
/// Support for intrinsics.
// Return the index at which m must be inserted (or already exists).
@@ -432,13 +444,14 @@
}
-void Compile::init_scratch_buffer_blob() {
- if( scratch_buffer_blob() != NULL ) return;
+void Compile::init_scratch_buffer_blob(int const_size) {
+ if (scratch_buffer_blob() != NULL) return;
// Construct a temporary CodeBuffer to have it construct a BufferBlob
// Cache this BufferBlob for this compile.
ResourceMark rm;
- int size = (MAX_inst_size + MAX_stubs_size + MAX_const_size);
+ _scratch_const_size = const_size;
+ int size = (MAX_inst_size + MAX_stubs_size + _scratch_const_size);
BufferBlob* blob = BufferBlob::create("Compile::scratch_buffer", size);
// Record the buffer blob for next time.
set_scratch_buffer_blob(blob);
@@ -455,9 +468,19 @@
}
+void Compile::clear_scratch_buffer_blob() {
+ assert(scratch_buffer_blob(), "no BufferBlob set");
+ set_scratch_buffer_blob(NULL);
+ set_scratch_locs_memory(NULL);
+}
+
+
//-----------------------scratch_emit_size-------------------------------------
// Helper function that computes size by emitting code
uint Compile::scratch_emit_size(const Node* n) {
+ // Start scratch_emit_size section.
+ set_in_scratch_emit_size(true);
+
// Emit into a trash buffer and count bytes emitted.
// This is a pretty expensive way to compute a size,
// but it works well enough if seldom used.
@@ -476,13 +499,20 @@
address blob_end = (address)locs_buf;
assert(blob->content_contains(blob_end), "sanity");
CodeBuffer buf(blob_begin, blob_end - blob_begin);
- buf.initialize_consts_size(MAX_const_size);
+ buf.initialize_consts_size(_scratch_const_size);
buf.initialize_stubs_size(MAX_stubs_size);
assert(locs_buf != NULL, "sanity");
- int lsize = MAX_locs_size / 2;
- buf.insts()->initialize_shared_locs(&locs_buf[0], lsize);
- buf.stubs()->initialize_shared_locs(&locs_buf[lsize], lsize);
+ int lsize = MAX_locs_size / 3;
+ buf.consts()->initialize_shared_locs(&locs_buf[lsize * 0], lsize);
+ buf.insts()->initialize_shared_locs( &locs_buf[lsize * 1], lsize);
+ buf.stubs()->initialize_shared_locs( &locs_buf[lsize * 2], lsize);
+
+ // Do the emission.
n->emit(buf, this->regalloc());
+
+ // End scratch_emit_size section.
+ set_in_scratch_emit_size(false);
+
return buf.insts_size();
}
@@ -516,10 +546,13 @@
_orig_pc_slot(0),
_orig_pc_slot_offset_in_bytes(0),
_has_method_handle_invokes(false),
+ _mach_constant_base_node(NULL),
_node_bundling_limit(0),
_node_bundling_base(NULL),
_java_calls(0),
_inner_loops(0),
+ _scratch_const_size(-1),
+ _in_scratch_emit_size(false),
#ifndef PRODUCT
_trace_opto_output(TraceOptoOutput || method()->has_option("TraceOptoOutput")),
_printer(IdealGraphPrinter::printer()),
@@ -553,7 +586,7 @@
if (ProfileTraps) {
// Make sure the method being compiled gets its own MDO,
// so we can at least track the decompile_count().
- method()->build_method_data();
+ method()->ensure_method_data();
}
Init(::AliasLevel);
@@ -783,6 +816,7 @@
_failure_reason(NULL),
_code_buffer("Compile::Fill_buffer"),
_has_method_handle_invokes(false),
+ _mach_constant_base_node(NULL),
_node_bundling_limit(0),
_node_bundling_base(NULL),
_java_calls(0),
@@ -2862,3 +2896,207 @@
_log->done("phase nodes='%d'", C->unique());
}
}
+
+//=============================================================================
+// Two Constant's are equal when the type and the value are equal.
+bool Compile::Constant::operator==(const Constant& other) {
+ if (type() != other.type() ) return false;
+ if (can_be_reused() != other.can_be_reused()) return false;
+ // For floating point values we compare the bit pattern.
+ switch (type()) {
+ case T_FLOAT: return (_value.i == other._value.i);
+ case T_LONG:
+ case T_DOUBLE: return (_value.j == other._value.j);
+ case T_OBJECT:
+ case T_ADDRESS: return (_value.l == other._value.l);
+ case T_VOID: return (_value.l == other._value.l); // jump-table entries
+ default: ShouldNotReachHere();
+ }
+ return false;
+}
+
+// Emit constants grouped in the following order:
+static BasicType type_order[] = {
+ T_FLOAT, // 32-bit
+ T_OBJECT, // 32 or 64-bit
+ T_ADDRESS, // 32 or 64-bit
+ T_DOUBLE, // 64-bit
+ T_LONG, // 64-bit
+ T_VOID, // 32 or 64-bit (jump-tables are at the end of the constant table for code emission reasons)
+ T_ILLEGAL
+};
+
+static int type_to_size_in_bytes(BasicType t) {
+ switch (t) {
+ case T_LONG: return sizeof(jlong );
+ case T_FLOAT: return sizeof(jfloat );
+ case T_DOUBLE: return sizeof(jdouble);
+ // We use T_VOID as marker for jump-table entries (labels) which
+ // need an interal word relocation.
+ case T_VOID:
+ case T_ADDRESS:
+ case T_OBJECT: return sizeof(jobject);
+ }
+
+ ShouldNotReachHere();
+ return -1;
+}
+
+void Compile::ConstantTable::calculate_offsets_and_size() {
+ int size = 0;
+ for (int t = 0; type_order[t] != T_ILLEGAL; t++) {
+ BasicType type = type_order[t];
+
+ for (int i = 0; i < _constants.length(); i++) {
+ Constant con = _constants.at(i);
+ if (con.type() != type) continue; // Skip other types.
+
+ // Align size for type.
+ int typesize = type_to_size_in_bytes(con.type());
+ size = align_size_up(size, typesize);
+
+ // Set offset.
+ con.set_offset(size);
+ _constants.at_put(i, con);
+
+ // Add type size.
+ size = size + typesize;
+ }
+ }
+
+ // Align size up to the next section start (which is insts; see
+ // CodeBuffer::align_at_start).
+ assert(_size == -1, "already set?");
+ _size = align_size_up(size, CodeEntryAlignment);
+
+ if (Matcher::constant_table_absolute_addressing) {
+ set_table_base_offset(0); // No table base offset required
+ } else {
+ if (UseRDPCForConstantTableBase) {
+ // table base offset is set in MachConstantBaseNode::emit
+ } else {
+ // When RDPC is not used, the table base is set into the middle of
+ // the constant table.
+ int half_size = _size / 2;
+ assert(half_size * 2 == _size, "sanity");
+ set_table_base_offset(-half_size);
+ }
+ }
+}
+
+void Compile::ConstantTable::emit(CodeBuffer& cb) {
+ MacroAssembler _masm(&cb);
+ for (int t = 0; type_order[t] != T_ILLEGAL; t++) {
+ BasicType type = type_order[t];
+
+ for (int i = 0; i < _constants.length(); i++) {
+ Constant con = _constants.at(i);
+ if (con.type() != type) continue; // Skip other types.
+
+ address constant_addr;
+ switch (con.type()) {
+ case T_LONG: constant_addr = _masm.long_constant( con.get_jlong() ); break;
+ case T_FLOAT: constant_addr = _masm.float_constant( con.get_jfloat() ); break;
+ case T_DOUBLE: constant_addr = _masm.double_constant(con.get_jdouble()); break;
+ case T_OBJECT: {
+ jobject obj = con.get_jobject();
+ int oop_index = _masm.oop_recorder()->find_index(obj);
+ constant_addr = _masm.address_constant((address) obj, oop_Relocation::spec(oop_index));
+ break;
+ }
+ case T_ADDRESS: {
+ address addr = (address) con.get_jobject();
+ constant_addr = _masm.address_constant(addr);
+ break;
+ }
+ // We use T_VOID as marker for jump-table entries (labels) which
+ // need an interal word relocation.
+ case T_VOID: {
+ // Write a dummy word. The real value is filled in later
+ // in fill_jump_table_in_constant_table.
+ address addr = (address) con.get_jobject();
+ constant_addr = _masm.address_constant(addr);
+ break;
+ }
+ default: ShouldNotReachHere();
+ }
+ assert(constant_addr != NULL, "consts section too small");
+ assert((constant_addr - _masm.code()->consts()->start()) == con.offset(), err_msg("must be: %d == %d", constant_addr - _masm.code()->consts()->start(), con.offset()));
+ }
+ }
+}
+
+int Compile::ConstantTable::find_offset(Constant& con) const {
+ int idx = _constants.find(con);
+ assert(idx != -1, "constant must be in constant table");
+ int offset = _constants.at(idx).offset();
+ assert(offset != -1, "constant table not emitted yet?");
+ return offset;
+}
+
+void Compile::ConstantTable::add(Constant& con) {
+ if (con.can_be_reused()) {
+ int idx = _constants.find(con);
+ if (idx != -1 && _constants.at(idx).can_be_reused()) {
+ return;
+ }
+ }
+ (void) _constants.append(con);
+}
+
+Compile::Constant Compile::ConstantTable::add(BasicType type, jvalue value) {
+ Constant con(type, value);
+ add(con);
+ return con;
+}
+
+Compile::Constant Compile::ConstantTable::add(MachOper* oper) {
+ jvalue value;
+ BasicType type = oper->type()->basic_type();
+ switch (type) {
+ case T_LONG: value.j = oper->constantL(); break;
+ case T_FLOAT: value.f = oper->constantF(); break;
+ case T_DOUBLE: value.d = oper->constantD(); break;
+ case T_OBJECT:
+ case T_ADDRESS: value.l = (jobject) oper->constant(); break;
+ default: ShouldNotReachHere();
+ }
+ return add(type, value);
+}
+
+Compile::Constant Compile::ConstantTable::allocate_jump_table(MachConstantNode* n) {
+ jvalue value;
+ // We can use the node pointer here to identify the right jump-table
+ // as this method is called from Compile::Fill_buffer right before
+ // the MachNodes are emitted and the jump-table is filled (means the
+ // MachNode pointers do not change anymore).
+ value.l = (jobject) n;
+ Constant con(T_VOID, value, false); // Labels of a jump-table cannot be reused.
+ for (uint i = 0; i < n->outcnt(); i++) {
+ add(con);
+ }
+ return con;
+}
+
+void Compile::ConstantTable::fill_jump_table(CodeBuffer& cb, MachConstantNode* n, GrowableArray<Label*> labels) const {
+ // If called from Compile::scratch_emit_size do nothing.
+ if (Compile::current()->in_scratch_emit_size()) return;
+
+ assert(labels.is_nonempty(), "must be");
+ assert((uint) labels.length() == n->outcnt(), err_msg("must be equal: %d == %d", labels.length(), n->outcnt()));
+
+ // Since MachConstantNode::constant_offset() also contains
+ // table_base_offset() we need to subtract the table_base_offset()
+ // to get the plain offset into the constant table.
+ int offset = n->constant_offset() - table_base_offset();
+
+ MacroAssembler _masm(&cb);
+ address* jump_table_base = (address*) (_masm.code()->consts()->start() + offset);
+
+ for (int i = 0; i < labels.length(); i++) {
+ address* constant_addr = &jump_table_base[i];
+ assert(*constant_addr == (address) n, "all jump-table entries must contain node pointer");
+ *constant_addr = cb.consts()->target(*labels.at(i), (address) constant_addr);
+ cb.consts()->relocate((address) constant_addr, relocInfo::internal_word_type);
+ }
+}
--- a/hotspot/src/share/vm/opto/compile.hpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/share/vm/opto/compile.hpp Wed Dec 08 17:50:49 2010 -0800
@@ -48,7 +48,10 @@
class InlineTree;
class Int_Array;
class Matcher;
+class MachConstantNode;
+class MachConstantBaseNode;
class MachNode;
+class MachOper;
class MachSafePointNode;
class Node;
class Node_Array;
@@ -139,6 +142,81 @@
trapHistLength = methodDataOopDesc::_trap_hist_limit
};
+ // Constant entry of the constant table.
+ class Constant {
+ private:
+ BasicType _type;
+ jvalue _value;
+ int _offset; // offset of this constant (in bytes) relative to the constant table base.
+ bool _can_be_reused; // true (default) if the value can be shared with other users.
+
+ public:
+ Constant() : _type(T_ILLEGAL), _offset(-1), _can_be_reused(true) { _value.l = 0; }
+ Constant(BasicType type, jvalue value, bool can_be_reused = true) :
+ _type(type),
+ _value(value),
+ _offset(-1),
+ _can_be_reused(can_be_reused)
+ {}
+
+ bool operator==(const Constant& other);
+
+ BasicType type() const { return _type; }
+
+ jlong get_jlong() const { return _value.j; }
+ jfloat get_jfloat() const { return _value.f; }
+ jdouble get_jdouble() const { return _value.d; }
+ jobject get_jobject() const { return _value.l; }
+
+ int offset() const { return _offset; }
+ void set_offset(int offset) { _offset = offset; }
+
+ bool can_be_reused() const { return _can_be_reused; }
+ };
+
+ // Constant table.
+ class ConstantTable {
+ private:
+ GrowableArray<Constant> _constants; // Constants of this table.
+ int _size; // Size in bytes the emitted constant table takes (including padding).
+ int _table_base_offset; // Offset of the table base that gets added to the constant offsets.
+
+ public:
+ ConstantTable() :
+ _size(-1),
+ _table_base_offset(-1) // We can use -1 here since the constant table is always bigger than 2 bytes (-(size / 2), see MachConstantBaseNode::emit).
+ {}
+
+ int size() const { assert(_size != -1, "size not yet calculated"); return _size; }
+
+ void set_table_base_offset(int x) { assert(_table_base_offset == -1, "set only once"); _table_base_offset = x; }
+ int table_base_offset() const { assert(_table_base_offset != -1, "table base offset not yet set"); return _table_base_offset; }
+
+ void emit(CodeBuffer& cb);
+
+ // Returns the offset of the last entry (the top) of the constant table.
+ int top_offset() const { assert(_constants.top().offset() != -1, "constant not yet bound"); return _constants.top().offset(); }
+
+ void calculate_offsets_and_size();
+ int find_offset(Constant& con) const;
+
+ void add(Constant& con);
+ Constant add(BasicType type, jvalue value);
+ Constant add(MachOper* oper);
+ Constant add(jfloat f) {
+ jvalue value; value.f = f;
+ return add(T_FLOAT, value);
+ }
+ Constant add(jdouble d) {
+ jvalue value; value.d = d;
+ return add(T_DOUBLE, value);
+ }
+
+ // Jump table
+ Constant allocate_jump_table(MachConstantNode* n);
+ void fill_jump_table(CodeBuffer& cb, MachConstantNode* n, GrowableArray<Label*> labels) const;
+ };
+
private:
// Fixed parameters to this compilation.
const int _compile_id;
@@ -212,6 +290,11 @@
Node* _recent_alloc_obj;
Node* _recent_alloc_ctl;
+ // Constant table
+ ConstantTable _constant_table; // The constant table for this compile.
+ MachConstantBaseNode* _mach_constant_base_node; // Constant table base node singleton.
+
+
// Blocked array of debugging and profiling information,
// tracked per node.
enum { _log2_node_notes_block_size = 8,
@@ -272,6 +355,8 @@
static int _CompiledZap_count; // counter compared against CompileZap[First/Last]
BufferBlob* _scratch_buffer_blob; // For temporary code buffers.
relocInfo* _scratch_locs_memory; // For temporary code buffers.
+ int _scratch_const_size; // For temporary code buffers.
+ bool _in_scratch_emit_size; // true when in scratch_emit_size.
public:
// Accessors
@@ -454,6 +539,12 @@
_recent_alloc_obj = obj;
}
+ // Constant table
+ ConstantTable& constant_table() { return _constant_table; }
+
+ MachConstantBaseNode* mach_constant_base_node();
+ bool has_mach_constant_base_node() const { return _mach_constant_base_node != NULL; }
+
// Handy undefined Node
Node* top() const { return _top; }
@@ -605,13 +696,16 @@
Dependencies* dependencies() { return env()->dependencies(); }
static int CompiledZap_count() { return _CompiledZap_count; }
BufferBlob* scratch_buffer_blob() { return _scratch_buffer_blob; }
- void init_scratch_buffer_blob();
+ void init_scratch_buffer_blob(int const_size);
+ void clear_scratch_buffer_blob();
void set_scratch_buffer_blob(BufferBlob* b) { _scratch_buffer_blob = b; }
relocInfo* scratch_locs_memory() { return _scratch_locs_memory; }
void set_scratch_locs_memory(relocInfo* b) { _scratch_locs_memory = b; }
// emit to scratch blob, report resulting size
uint scratch_emit_size(const Node* n);
+ void set_in_scratch_emit_size(bool x) { _in_scratch_emit_size = x; }
+ bool in_scratch_emit_size() const { return _in_scratch_emit_size; }
enum ScratchBufferBlob {
MAX_inst_size = 1024,
@@ -692,7 +786,7 @@
void Fill_buffer();
// Determine which variable sized branches can be shortened
- void Shorten_branches(Label *labels, int& code_size, int& reloc_size, int& stub_size, int& const_size);
+ void Shorten_branches(Label *labels, int& code_size, int& reloc_size, int& stub_size);
// Compute the size of first NumberOfLoopInstrToAlign instructions
// at the head of a loop.
--- a/hotspot/src/share/vm/opto/gcm.cpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/share/vm/opto/gcm.cpp Wed Dec 08 17:50:49 2010 -0800
@@ -89,7 +89,7 @@
assert(in0 != NULL, "Only control-dependent");
const Node *p = in0->is_block_proj();
if (p != NULL && p != n) { // Control from a block projection?
- assert(!n->pinned() || n->is_SafePointScalarObject(), "only SafePointScalarObject pinned node is expected here");
+ assert(!n->pinned() || n->is_MachConstantBase() || n->is_SafePointScalarObject(), "only pinned MachConstantBase or SafePointScalarObject node is expected here");
// Find trailing Region
Block *pb = _bbs[in0->_idx]; // Block-projection already has basic block
uint j = 0;
--- a/hotspot/src/share/vm/opto/graphKit.cpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/share/vm/opto/graphKit.cpp Wed Dec 08 17:50:49 2010 -0800
@@ -1841,7 +1841,7 @@
// Note: If ProfileTraps is true, and if a deopt. actually
// occurs here, the runtime will make sure an MDO exists. There is
- // no need to call method()->build_method_data() at this point.
+ // no need to call method()->ensure_method_data() at this point.
#ifdef ASSERT
if (!must_throw) {
--- a/hotspot/src/share/vm/opto/machnode.cpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/share/vm/opto/machnode.cpp Wed Dec 08 17:50:49 2010 -0800
@@ -489,6 +489,20 @@
}
#endif
+
+//=============================================================================
+int MachConstantNode::constant_offset() {
+ int offset = _constant.offset();
+ // Bind the offset lazily.
+ if (offset == -1) {
+ Compile::ConstantTable& constant_table = Compile::current()->constant_table();
+ offset = constant_table.table_base_offset() + constant_table.find_offset(_constant);
+ _constant.set_offset(offset);
+ }
+ return offset;
+}
+
+
//=============================================================================
#ifndef PRODUCT
void MachNullCheckNode::format( PhaseRegAlloc *ra_, outputStream *st ) const {
--- a/hotspot/src/share/vm/opto/machnode.hpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/share/vm/opto/machnode.hpp Wed Dec 08 17:50:49 2010 -0800
@@ -231,9 +231,6 @@
// Return number of relocatable values contained in this instruction
virtual int reloc() const { return 0; }
- // Return number of words used for double constants in this instruction
- virtual int const_size() const { return 0; }
-
// Hash and compare over operands. Used to do GVN on machine Nodes.
virtual uint hash() const;
virtual uint cmp( const Node &n ) const;
@@ -348,6 +345,65 @@
#endif
};
+//------------------------------MachConstantBaseNode--------------------------
+// Machine node that represents the base address of the constant table.
+class MachConstantBaseNode : public MachIdealNode {
+public:
+ static const RegMask& _out_RegMask; // We need the out_RegMask statically in MachConstantNode::in_RegMask().
+
+public:
+ MachConstantBaseNode() : MachIdealNode() {
+ init_class_id(Class_MachConstantBase);
+ }
+ virtual const class Type* bottom_type() const { return TypeRawPtr::NOTNULL; }
+ virtual uint ideal_reg() const { return Op_RegP; }
+ virtual uint oper_input_base() const { return 1; }
+
+ virtual void emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const;
+ virtual uint size(PhaseRegAlloc* ra_) const;
+ virtual bool pinned() const { return UseRDPCForConstantTableBase; }
+
+ static const RegMask& static_out_RegMask() { return _out_RegMask; }
+ virtual const RegMask& out_RegMask() const { return static_out_RegMask(); }
+
+#ifndef PRODUCT
+ virtual const char* Name() const { return "MachConstantBaseNode"; }
+ virtual void format(PhaseRegAlloc*, outputStream* st) const;
+#endif
+};
+
+//------------------------------MachConstantNode-------------------------------
+// Machine node that holds a constant which is stored in the constant table.
+class MachConstantNode : public MachNode {
+protected:
+ Compile::Constant _constant; // This node's constant.
+
+public:
+ MachConstantNode() : MachNode() {
+ init_class_id(Class_MachConstant);
+ }
+
+ virtual void eval_constant(Compile* C) {
+#ifdef ASSERT
+ tty->print("missing MachConstantNode eval_constant function: ");
+ dump();
+#endif
+ ShouldNotCallThis();
+ }
+
+ virtual const RegMask &in_RegMask(uint idx) const {
+ if (idx == mach_constant_base_node_input())
+ return MachConstantBaseNode::static_out_RegMask();
+ return MachNode::in_RegMask(idx);
+ }
+
+ // Input edge of MachConstantBaseNode.
+ uint mach_constant_base_node_input() const { return req() - 1; }
+
+ int constant_offset();
+ int constant_offset() const { return ((MachConstantNode*) this)->constant_offset(); }
+};
+
//------------------------------MachUEPNode-----------------------------------
// Machine Unvalidated Entry Point Node
class MachUEPNode : public MachIdealNode {
--- a/hotspot/src/share/vm/opto/matcher.hpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/share/vm/opto/matcher.hpp Wed Dec 08 17:50:49 2010 -0800
@@ -365,6 +365,10 @@
// registers? True for Intel but false for most RISCs
static const bool clone_shift_expressions;
+ // Should constant table entries be accessed with loads using
+ // absolute addressing? True for x86 but false for most RISCs.
+ static const bool constant_table_absolute_addressing;
+
static bool narrow_oop_use_complex_address();
// Generate implicit null check for narrow oops if it can fold
--- a/hotspot/src/share/vm/opto/memnode.cpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/share/vm/opto/memnode.cpp Wed Dec 08 17:50:49 2010 -0800
@@ -3599,10 +3599,12 @@
intptr_t size_limit = phase->find_intptr_t_con(size_in_bytes, max_jint);
if (zeroes_done + BytesPerLong >= size_limit) {
assert(allocation() != NULL, "");
- Node* klass_node = allocation()->in(AllocateNode::KlassNode);
- ciKlass* k = phase->type(klass_node)->is_klassptr()->klass();
- if (zeroes_done == k->layout_helper())
- zeroes_done = size_limit;
+ if (allocation()->Opcode() == Op_Allocate) {
+ Node* klass_node = allocation()->in(AllocateNode::KlassNode);
+ ciKlass* k = phase->type(klass_node)->is_klassptr()->klass();
+ if (zeroes_done == k->layout_helper())
+ zeroes_done = size_limit;
+ }
}
if (zeroes_done < size_limit) {
rawmem = ClearArrayNode::clear_memory(rawctl, rawmem, rawptr,
--- a/hotspot/src/share/vm/opto/node.hpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/share/vm/opto/node.hpp Wed Dec 08 17:50:49 2010 -0800
@@ -81,6 +81,8 @@
class MachCallNode;
class MachCallRuntimeNode;
class MachCallStaticJavaNode;
+class MachConstantBaseNode;
+class MachConstantNode;
class MachIfNode;
class MachNode;
class MachNullCheckNode;
@@ -566,10 +568,12 @@
DEFINE_CLASS_ID(MachCallDynamicJava, MachCallJava, 1)
DEFINE_CLASS_ID(MachCallRuntime, MachCall, 1)
DEFINE_CLASS_ID(MachCallLeaf, MachCallRuntime, 0)
- DEFINE_CLASS_ID(MachSpillCopy, Mach, 1)
- DEFINE_CLASS_ID(MachNullCheck, Mach, 2)
- DEFINE_CLASS_ID(MachIf, Mach, 3)
- DEFINE_CLASS_ID(MachTemp, Mach, 4)
+ DEFINE_CLASS_ID(MachSpillCopy, Mach, 1)
+ DEFINE_CLASS_ID(MachNullCheck, Mach, 2)
+ DEFINE_CLASS_ID(MachIf, Mach, 3)
+ DEFINE_CLASS_ID(MachTemp, Mach, 4)
+ DEFINE_CLASS_ID(MachConstantBase, Mach, 5)
+ DEFINE_CLASS_ID(MachConstant, Mach, 6)
DEFINE_CLASS_ID(Proj, Node, 2)
DEFINE_CLASS_ID(CatchProj, Proj, 0)
@@ -734,6 +738,8 @@
DEFINE_CLASS_QUERY(MachCallLeaf)
DEFINE_CLASS_QUERY(MachCallRuntime)
DEFINE_CLASS_QUERY(MachCallStaticJava)
+ DEFINE_CLASS_QUERY(MachConstantBase)
+ DEFINE_CLASS_QUERY(MachConstant)
DEFINE_CLASS_QUERY(MachIf)
DEFINE_CLASS_QUERY(MachNullCheck)
DEFINE_CLASS_QUERY(MachReturn)
--- a/hotspot/src/share/vm/opto/output.cpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/share/vm/opto/output.cpp Wed Dec 08 17:50:49 2010 -0800
@@ -61,11 +61,6 @@
// RootNode goes
assert( _cfg->_broot->_nodes.size() == 0, "" );
- // Initialize the space for the BufferBlob used to find and verify
- // instruction size in MachNode::emit_size()
- init_scratch_buffer_blob();
- if (failing()) return; // Out of memory
-
// The number of new nodes (mostly MachNop) is proportional to
// the number of java calls and inner loops which are aligned.
if ( C->check_node_count((NodeLimitFudgeFactor + C->java_calls()*3 +
@@ -333,7 +328,7 @@
//----------------------Shorten_branches---------------------------------------
// The architecture description provides short branch variants for some long
// branch instructions. Replace eligible long branches with short branches.
-void Compile::Shorten_branches(Label *labels, int& code_size, int& reloc_size, int& stub_size, int& const_size) {
+void Compile::Shorten_branches(Label *labels, int& code_size, int& reloc_size, int& stub_size) {
// fill in the nop array for bundling computations
MachNode *_nop_list[Bundle::_nop_count];
@@ -353,12 +348,11 @@
// Size in bytes of all relocation entries, including those in local stubs.
// Start with 2-bytes of reloc info for the unvalidated entry point
reloc_size = 1; // Number of relocation entries
- const_size = 0; // size of fp constants in words
// Make three passes. The first computes pessimistic blk_starts,
- // relative jmp_end, reloc_size and const_size information.
- // The second performs short branch substitution using the pessimistic
- // sizing. The third inserts nops where needed.
+ // relative jmp_end and reloc_size information. The second performs
+ // short branch substitution using the pessimistic sizing. The
+ // third inserts nops where needed.
Node *nj; // tmp
@@ -381,7 +375,6 @@
MachNode *mach = nj->as_Mach();
blk_size += (mach->alignment_required() - 1) * relocInfo::addr_unit(); // assume worst case padding
reloc_size += mach->reloc();
- const_size += mach->const_size();
if( mach->is_MachCall() ) {
MachCallNode *mcall = mach->as_MachCall();
// This destination address is NOT PC-relative
@@ -398,10 +391,6 @@
if (min_offset_from_last_call == 0) {
blk_size += nop_size;
}
- } else if (mach->ideal_Opcode() == Op_Jump) {
- const_size += b->_num_succs; // Address table size
- // The size is valid even for 64 bit since it is
- // multiplied by 2*jintSize on this method exit.
}
}
min_offset_from_last_call += inst_size;
@@ -562,10 +551,6 @@
// a relocation index.
// The CodeBuffer will expand the locs array if this estimate is too low.
reloc_size *= 10 / sizeof(relocInfo);
-
- // Adjust const_size to number of bytes
- const_size *= 2*jintSize; // both float and double take two words per entry
-
}
//------------------------------FillLocArray-----------------------------------
@@ -1102,10 +1087,39 @@
blk_labels[i].init();
}
+ if (has_mach_constant_base_node()) {
+ // Fill the constant table.
+ // Note: This must happen before Shorten_branches.
+ for (i = 0; i < _cfg->_num_blocks; i++) {
+ Block* b = _cfg->_blocks[i];
+
+ for (uint j = 0; j < b->_nodes.size(); j++) {
+ Node* n = b->_nodes[j];
+
+ // If the node is a MachConstantNode evaluate the constant
+ // value section.
+ if (n->is_MachConstant()) {
+ MachConstantNode* machcon = n->as_MachConstant();
+ machcon->eval_constant(C);
+ }
+ }
+ }
+
+ // Calculate the offsets of the constants and the size of the
+ // constant table (including the padding to the next section).
+ constant_table().calculate_offsets_and_size();
+ const_req = constant_table().size();
+ }
+
+ // Initialize the space for the BufferBlob used to find and verify
+ // instruction size in MachNode::emit_size()
+ init_scratch_buffer_blob(const_req);
+ if (failing()) return; // Out of memory
+
// If this machine supports different size branch offsets, then pre-compute
// the length of the blocks
if( _matcher->is_short_branch_offset(-1, 0) ) {
- Shorten_branches(blk_labels, code_req, locs_req, stub_req, const_req);
+ Shorten_branches(blk_labels, code_req, locs_req, stub_req);
labels_not_set = false;
}
@@ -1121,12 +1135,12 @@
code_req = const_req = stub_req = exception_handler_req = deopt_handler_req = 0x10; // force expansion
int total_req =
+ const_req +
code_req +
pad_req +
stub_req +
exception_handler_req +
- deopt_handler_req + // deopt handler
- const_req;
+ deopt_handler_req; // deopt handler
if (has_method_handle_invokes())
total_req += deopt_handler_req; // deopt MH handler
@@ -1180,6 +1194,11 @@
NonSafepointEmitter non_safepoints(this); // emit non-safepoints lazily
+ // Emit the constant table.
+ if (has_mach_constant_base_node()) {
+ constant_table().emit(*cb);
+ }
+
// ------------------
// Now fill in the code buffer
Node *delay_slot = NULL;
@@ -1196,12 +1215,13 @@
cb->flush_bundle(true);
// Define the label at the beginning of the basic block
- if( labels_not_set )
- MacroAssembler(cb).bind( blk_labels[b->_pre_order] );
-
- else
- assert( blk_labels[b->_pre_order].loc_pos() == cb->insts_size(),
- "label position does not match code offset" );
+ if (labels_not_set) {
+ MacroAssembler(cb).bind(blk_labels[b->_pre_order]);
+ } else {
+ assert(blk_labels[b->_pre_order].loc_pos() == cb->insts_size(),
+ err_msg("label position does not match code offset: %d != %d",
+ blk_labels[b->_pre_order].loc_pos(), cb->insts_size()));
+ }
uint last_inst = b->_nodes.size();
@@ -1718,9 +1738,17 @@
// Create a data structure for all the scheduling information
Scheduling scheduling(Thread::current()->resource_area(), *this);
+ // Initialize the space for the BufferBlob used to find and verify
+ // instruction size in MachNode::emit_size()
+ init_scratch_buffer_blob(MAX_const_size);
+ if (failing()) return; // Out of memory
+
// Walk backwards over each basic block, computing the needed alignment
// Walk over all the basic blocks
scheduling.DoScheduling();
+
+ // Clear the BufferBlob used for scheduling.
+ clear_scratch_buffer_blob();
}
//------------------------------ComputeLocalLatenciesForward-------------------
--- a/hotspot/src/share/vm/opto/postaloc.cpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/share/vm/opto/postaloc.cpp Wed Dec 08 17:50:49 2010 -0800
@@ -200,6 +200,19 @@
// then reloaded BUT survives in a register the whole way.
Node *val = skip_copies(n->in(k));
+ if (val == x && nk_idx != 0 &&
+ regnd[nk_reg] != NULL && regnd[nk_reg] != x &&
+ n2lidx(x) == n2lidx(regnd[nk_reg])) {
+ // When rematerialzing nodes and stretching lifetimes, the
+ // allocator will reuse the original def for multidef LRG instead
+ // of the current reaching def because it can't know it's safe to
+ // do so. After allocation completes if they are in the same LRG
+ // then it should use the current reaching def instead.
+ n->set_req(k, regnd[nk_reg]);
+ blk_adjust += yank_if_dead(val, current_block, &value, ®nd);
+ val = skip_copies(n->in(k));
+ }
+
if( val == x ) return blk_adjust; // No progress?
bool single = is_single_register(val->ideal_reg());
--- a/hotspot/src/share/vm/prims/jvm.h Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/share/vm/prims/jvm.h Wed Dec 08 17:50:49 2010 -0800
@@ -1063,7 +1063,8 @@
JVM_CONSTANT_MethodHandle = 15, // JSR 292
JVM_CONSTANT_MethodType = 16, // JSR 292
JVM_CONSTANT_InvokeDynamicTrans = 17, // JSR 292, only occurs in old class files
- JVM_CONSTANT_InvokeDynamic = 18 // JSR 292
+ JVM_CONSTANT_InvokeDynamic = 18, // JSR 292
+ JVM_CONSTANT_ExternalMax = 18 // Last tag found in classfiles
};
/* JVM_CONSTANT_MethodHandle subtypes */
--- a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp Wed Dec 08 17:50:49 2010 -0800
@@ -214,7 +214,7 @@
case JVM_CONSTANT_Double: // fall through
case JVM_CONSTANT_Long:
{
- scratch_cp->copy_entry_to(scratch_i, *merge_cp_p, *merge_cp_length_p,
+ constantPoolOopDesc::copy_entry_to(scratch_cp, scratch_i, *merge_cp_p, *merge_cp_length_p,
THREAD);
if (scratch_i != *merge_cp_length_p) {
@@ -239,7 +239,7 @@
case JVM_CONSTANT_UnresolvedClass: // fall through
case JVM_CONSTANT_UnresolvedString:
{
- scratch_cp->copy_entry_to(scratch_i, *merge_cp_p, *merge_cp_length_p,
+ constantPoolOopDesc::copy_entry_to(scratch_cp, scratch_i, *merge_cp_p, *merge_cp_length_p,
THREAD);
if (scratch_i != *merge_cp_length_p) {
@@ -1093,13 +1093,13 @@
case JVM_CONSTANT_Long:
// just copy the entry to *merge_cp_p, but double and long take
// two constant pool entries
- old_cp->copy_entry_to(old_i, *merge_cp_p, old_i, CHECK_0);
+ constantPoolOopDesc::copy_entry_to(old_cp, old_i, *merge_cp_p, old_i, CHECK_0);
old_i++;
break;
default:
// just copy the entry to *merge_cp_p
- old_cp->copy_entry_to(old_i, *merge_cp_p, old_i, CHECK_0);
+ constantPoolOopDesc::copy_entry_to(old_cp, old_i, *merge_cp_p, old_i, CHECK_0);
break;
}
} // end for each old_cp entry
--- a/hotspot/src/share/vm/prims/methodHandleWalk.cpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/share/vm/prims/methodHandleWalk.cpp Wed Dec 08 17:50:49 2010 -0800
@@ -968,16 +968,11 @@
if (tailcall) {
// Actually, in order to make these methods more recognizable,
- // let's put them in holder classes MethodHandle and InvokeDynamic.
- // That way stack walkers and compiler heuristics can recognize them.
- _target_klass = (for_invokedynamic()
- ? SystemDictionary::InvokeDynamic_klass()
- : SystemDictionary::MethodHandle_klass());
+ // let's put them in holder class MethodHandle. That way stack
+ // walkers and compiler heuristics can recognize them.
+ _target_klass = SystemDictionary::MethodHandle_klass();
}
- // instanceKlass* ik = instanceKlass::cast(klass);
- // tty->print_cr("MethodHandleCompiler::make_invoke: %s %s.%s%s", Bytecodes::name(op), ik->external_name(), name->as_C_string(), signature->as_C_string());
-
// Inline the method.
InvocationCounter* ic = m->invocation_counter();
ic->set_carry_flag();
--- a/hotspot/src/share/vm/prims/methodHandleWalk.hpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/share/vm/prims/methodHandleWalk.hpp Wed Dec 08 17:50:49 2010 -0800
@@ -412,8 +412,7 @@
// Tests if the given class is a MH adapter holder.
static bool klass_is_method_handle_adapter_holder(klassOop klass) {
- return (klass == SystemDictionary::MethodHandle_klass() ||
- klass == SystemDictionary::InvokeDynamic_klass());
+ return (klass == SystemDictionary::MethodHandle_klass());
}
};
--- a/hotspot/src/share/vm/prims/methodHandles.cpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/share/vm/prims/methodHandles.cpp Wed Dec 08 17:50:49 2010 -0800
@@ -485,9 +485,8 @@
Handle polymorphic_method_type;
bool polymorphic_signature = false;
if ((flags & ALL_KINDS) == IS_METHOD &&
- (defc() == SystemDictionary::InvokeDynamic_klass() ||
- (defc() == SystemDictionary::MethodHandle_klass() &&
- methodOopDesc::is_method_handle_invoke_name(name()))))
+ (defc() == SystemDictionary::MethodHandle_klass() &&
+ methodOopDesc::is_method_handle_invoke_name(name())))
polymorphic_signature = true;
// convert the external string or reflective type to an internal signature
--- a/hotspot/src/share/vm/runtime/arguments.cpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/share/vm/runtime/arguments.cpp Wed Dec 08 17:50:49 2010 -0800
@@ -1007,24 +1007,9 @@
void Arguments::check_compressed_oops_compat() {
#ifdef _LP64
assert(UseCompressedOops, "Precondition");
-# if defined(COMPILER1) && !defined(TIERED)
- // Until c1 supports compressed oops turn them off.
- FLAG_SET_DEFAULT(UseCompressedOops, false);
-# else
// Is it on by default or set on ergonomically
bool is_on_by_default = FLAG_IS_DEFAULT(UseCompressedOops) || FLAG_IS_ERGO(UseCompressedOops);
- // Tiered currently doesn't work with compressed oops
- if (TieredCompilation) {
- if (is_on_by_default) {
- FLAG_SET_DEFAULT(UseCompressedOops, false);
- return;
- } else {
- vm_exit_during_initialization(
- "Tiered compilation is not supported with compressed oops yet", NULL);
- }
- }
-
// If dumping an archive or forcing its use, disable compressed oops if possible
if (DumpSharedSpaces || RequireSharedSpaces) {
if (is_on_by_default) {
@@ -1038,9 +1023,7 @@
// UseSharedSpaces is on by default. With compressed oops, we turn it off.
FLAG_SET_DEFAULT(UseSharedSpaces, false);
}
-
-# endif // defined(COMPILER1) && !defined(TIERED)
-#endif // _LP64
+#endif
}
void Arguments::set_tiered_flags() {
@@ -3075,11 +3058,9 @@
// Set flags based on ergonomics.
set_ergonomics_flags();
-#ifdef _LP64
if (UseCompressedOops) {
check_compressed_oops_compat();
}
-#endif
// Check the GC selections again.
if (!check_gc_consistency()) {
--- a/hotspot/src/share/vm/runtime/thread.cpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/share/vm/runtime/thread.cpp Wed Dec 08 17:50:49 2010 -0800
@@ -3231,12 +3231,6 @@
warning("java.lang.ArithmeticException has not been initialized");
warning("java.lang.StackOverflowError has not been initialized");
}
-
- if (EnableInvokeDynamic) {
- // JSR 292: An intialized java.dyn.InvokeDynamic is required in
- // the compiler.
- initialize_class(vmSymbolHandles::java_dyn_InvokeDynamic(), CHECK_0);
- }
}
// See : bugid 4211085.
--- a/hotspot/src/share/vm/runtime/vmStructs.cpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/share/vm/runtime/vmStructs.cpp Wed Dec 08 17:50:49 2010 -0800
@@ -1676,10 +1676,7 @@
/* constantPoolOop layout enum for InvokeDynamic */ \
/*************************************************/ \
\
- declare_constant(constantPoolOopDesc::_multi_operand_count_offset) \
- declare_constant(constantPoolOopDesc::_multi_operand_base_offset) \
declare_constant(constantPoolOopDesc::_indy_bsm_offset) \
- declare_constant(constantPoolOopDesc::_indy_nt_offset) \
declare_constant(constantPoolOopDesc::_indy_argc_offset) \
declare_constant(constantPoolOopDesc::_indy_argv_offset) \
\
--- a/hotspot/src/share/vm/utilities/constantTag.cpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/share/vm/utilities/constantTag.cpp Wed Dec 08 17:50:49 2010 -0800
@@ -93,6 +93,8 @@
return "MethodType";
case JVM_CONSTANT_InvokeDynamic :
return "InvokeDynamic";
+ case JVM_CONSTANT_InvokeDynamicTrans :
+ return "InvokeDynamic/transitional";
case JVM_CONSTANT_Object :
return "Object";
case JVM_CONSTANT_Utf8 :
--- a/hotspot/src/share/vm/utilities/constantTag.hpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/share/vm/utilities/constantTag.hpp Wed Dec 08 17:50:49 2010 -0800
@@ -86,7 +86,8 @@
bool is_method_type() const { return _tag == JVM_CONSTANT_MethodType; }
bool is_method_handle() const { return _tag == JVM_CONSTANT_MethodHandle; }
- bool is_invoke_dynamic() const { return _tag == JVM_CONSTANT_InvokeDynamic; }
+ bool is_invoke_dynamic() const { return (_tag == JVM_CONSTANT_InvokeDynamic ||
+ _tag == JVM_CONSTANT_InvokeDynamicTrans); }
bool is_loadable_constant() const {
return ((_tag >= JVM_CONSTANT_Integer && _tag <= JVM_CONSTANT_String) ||
--- a/hotspot/src/share/vm/utilities/debug.cpp Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/src/share/vm/utilities/debug.cpp Wed Dec 08 17:50:49 2010 -0800
@@ -399,8 +399,14 @@
extern "C" void disnm(intptr_t p) {
Command c("disnm");
CodeBlob* cb = CodeCache::find_blob((address) p);
- cb->print();
- Disassembler::decode(cb);
+ nmethod* nm = cb->as_nmethod_or_null();
+ if (nm) {
+ nm->print();
+ Disassembler::decode(nm);
+ } else {
+ cb->print();
+ Disassembler::decode(cb);
+ }
}
--- a/hotspot/test/compiler/6991596/Test6991596.java Wed Dec 08 04:50:35 2010 -0800
+++ b/hotspot/test/compiler/6991596/Test6991596.java Wed Dec 08 17:50:49 2010 -0800
@@ -35,7 +35,7 @@
public class Test6991596 {
private static final Class CLASS = Test6991596.class;
private static final String NAME = "foo";
- private static final boolean DEBUG = false;
+ private static final boolean DEBUG = System.getProperty("DEBUG", "false").equals("true");
public static void main(String[] args) throws Throwable {
testboolean();
@@ -47,7 +47,7 @@
}
// Helpers to get various methods.
- static MethodHandle getmh1(Class ret, Class arg) {
+ static MethodHandle getmh1(Class ret, Class arg) throws NoAccessException {
return MethodHandles.lookup().findStatic(CLASS, NAME, MethodType.methodType(ret, arg));
}
static MethodHandle getmh2(MethodHandle mh1, Class ret, Class arg) {
@@ -76,38 +76,38 @@
MethodHandle mh2 = getmh2(mh1, boolean.class, boolean.class);
// TODO add this for all cases when the bugs are fixed.
//MethodHandle mh3 = getmh3(mh1, boolean.class, boolean.class);
- boolean a = mh1.<boolean>invokeExact((boolean) x);
- boolean b = mh2.<boolean>invokeExact(x);
+ boolean a = (boolean) mh1.invokeExact((boolean) x);
+ boolean b = (boolean) mh2.invokeExact(x);
//boolean c = mh3.<boolean>invokeExact((boolean) x);
- assert a == b : a + " != " + b;
- //assert c == x : c + " != " + x;
+ check(x, a, b);
+ //check(x, c, x);
}
// byte
{
MethodHandle mh1 = getmh1( byte.class, byte.class );
MethodHandle mh2 = getmh2(mh1, byte.class, boolean.class);
- byte a = mh1.<byte>invokeExact((byte) (x ? 1 : 0));
- byte b = mh2.<byte>invokeExact(x);
- assert a == b : a + " != " + b;
+ byte a = (byte) mh1.invokeExact((byte) (x ? 1 : 0));
+ byte b = (byte) mh2.invokeExact(x);
+ check(x, a, b);
}
// char
{
MethodHandle mh1 = getmh1( char.class, char.class);
MethodHandle mh2 = getmh2(mh1, char.class, boolean.class);
- char a = mh1.<char>invokeExact((char) (x ? 1 : 0));
- char b = mh2.<char>invokeExact(x);
- assert a == b : a + " != " + b;
+ char a = (char) mh1.invokeExact((char) (x ? 1 : 0));
+ char b = (char) mh2.invokeExact(x);
+ check(x, a, b);
}
// short
{
MethodHandle mh1 = getmh1( short.class, short.class);
MethodHandle mh2 = getmh2(mh1, short.class, boolean.class);
- short a = mh1.<short>invokeExact((short) (x ? 1 : 0));
- short b = mh2.<short>invokeExact(x);
- assert a == b : a + " != " + b;
+ short a = (short) mh1.invokeExact((short) (x ? 1 : 0));
+ short b = (short) mh2.invokeExact(x);
+ check(x, a, b);
}
}
@@ -134,36 +134,36 @@
{
MethodHandle mh1 = getmh1( boolean.class, boolean.class);
MethodHandle mh2 = getmh2(mh1, boolean.class, byte.class);
- boolean a = mh1.<boolean>invokeExact((x & 1) == 1);
- boolean b = mh2.<boolean>invokeExact(x);
- assert a == b : a + " != " + b;
+ boolean a = (boolean) mh1.invokeExact((x & 1) == 1);
+ boolean b = (boolean) mh2.invokeExact(x);
+ check(x, a, b);
}
// byte
{
MethodHandle mh1 = getmh1( byte.class, byte.class);
MethodHandle mh2 = getmh2(mh1, byte.class, byte.class);
- byte a = mh1.<byte>invokeExact((byte) x);
- byte b = mh2.<byte>invokeExact(x);
- assert a == b : a + " != " + b;
+ byte a = (byte) mh1.invokeExact((byte) x);
+ byte b = (byte) mh2.invokeExact(x);
+ check(x, a, b);
}
// char
{
MethodHandle mh1 = getmh1( char.class, char.class);
MethodHandle mh2 = getmh2(mh1, char.class, byte.class);
- char a = mh1.<char>invokeExact((char) x);
- char b = mh2.<char>invokeExact(x);
- assert a == b : a + " != " + b;
+ char a = (char) mh1.invokeExact((char) x);
+ char b = (char) mh2.invokeExact(x);
+ check(x, a, b);
}
// short
{
MethodHandle mh1 = getmh1( short.class, short.class);
MethodHandle mh2 = getmh2(mh1, short.class, byte.class);
- short a = mh1.<short>invokeExact((short) x);
- short b = mh2.<short>invokeExact(x);
- assert a == b : a + " != " + b;
+ short a = (short) mh1.invokeExact((short) x);
+ short b = (short) mh2.invokeExact(x);
+ check(x, a, b);
}
}
@@ -188,36 +188,36 @@
{
MethodHandle mh1 = getmh1( boolean.class, boolean.class);
MethodHandle mh2 = getmh2(mh1, boolean.class, char.class);
- boolean a = mh1.<boolean>invokeExact((x & 1) == 1);
- boolean b = mh2.<boolean>invokeExact(x);
- assert a == b : a + " != " + b;
+ boolean a = (boolean) mh1.invokeExact((x & 1) == 1);
+ boolean b = (boolean) mh2.invokeExact(x);
+ check(x, a, b);
}
// byte
{
MethodHandle mh1 = getmh1( byte.class, byte.class);
MethodHandle mh2 = getmh2(mh1, byte.class, char.class);
- byte a = mh1.<byte>invokeExact((byte) x);
- byte b = mh2.<byte>invokeExact(x);
- assert a == b : a + " != " + b;
+ byte a = (byte) mh1.invokeExact((byte) x);
+ byte b = (byte) mh2.invokeExact(x);
+ check(x, a, b);
}
// char
{
MethodHandle mh1 = getmh1( char.class, char.class);
MethodHandle mh2 = getmh2(mh1, char.class, char.class);
- char a = mh1.<char>invokeExact((char) x);
- char b = mh2.<char>invokeExact(x);
- assert a == b : a + " != " + b;
+ char a = (char) mh1.invokeExact((char) x);
+ char b = (char) mh2.invokeExact(x);
+ check(x, a, b);
}
// short
{
MethodHandle mh1 = getmh1( short.class, short.class);
MethodHandle mh2 = getmh2(mh1, short.class, char.class);
- short a = mh1.<short>invokeExact((short) x);
- short b = mh2.<short>invokeExact(x);
- assert a == b : a + " != " + b;
+ short a = (short) mh1.invokeExact((short) x);
+ short b = (short) mh2.invokeExact(x);
+ check(x, a, b);
}
}
@@ -248,36 +248,36 @@
{
MethodHandle mh1 = getmh1( boolean.class, boolean.class);
MethodHandle mh2 = getmh2(mh1, boolean.class, short.class);
- boolean a = mh1.<boolean>invokeExact((x & 1) == 1);
- boolean b = mh2.<boolean>invokeExact(x);
- assert a == b : a + " != " + b;
+ boolean a = (boolean) mh1.invokeExact((x & 1) == 1);
+ boolean b = (boolean) mh2.invokeExact(x);
+ check(x, a, b);
}
// byte
{
MethodHandle mh1 = getmh1( byte.class, byte.class);
MethodHandle mh2 = getmh2(mh1, byte.class, short.class);
- byte a = mh1.<byte>invokeExact((byte) x);
- byte b = mh2.<byte>invokeExact(x);
- assert a == b : a + " != " + b;
+ byte a = (byte) mh1.invokeExact((byte) x);
+ byte b = (byte) mh2.invokeExact(x);
+ check(x, a, b);
}
// char
{
MethodHandle mh1 = getmh1( char.class, char.class);
MethodHandle mh2 = getmh2(mh1, char.class, short.class);
- char a = mh1.<char>invokeExact((char) x);
- char b = mh2.<char>invokeExact(x);
- assert a == b : a + " != " + b;
+ char a = (char) mh1.invokeExact((char) x);
+ char b = (char) mh2.invokeExact(x);
+ check(x, a, b);
}
// short
{
MethodHandle mh1 = getmh1( short.class, short.class);
MethodHandle mh2 = getmh2(mh1, short.class, short.class);
- short a = mh1.<short>invokeExact((short) x);
- short b = mh2.<short>invokeExact(x);
- assert a == b : a + " != " + b;
+ short a = (short) mh1.invokeExact((short) x);
+ short b = (short) mh2.invokeExact(x);
+ check(x, a, b);
}
}
@@ -316,45 +316,46 @@
{
MethodHandle mh1 = getmh1( boolean.class, boolean.class);
MethodHandle mh2 = getmh2(mh1, boolean.class, int.class);
- boolean a = mh1.<boolean>invokeExact((x & 1) == 1);
- boolean b = mh2.<boolean>invokeExact(x);
- assert a == b : a + " != " + b;
+ boolean a = (boolean) mh1.invokeExact((x & 1) == 1);
+ boolean b = (boolean) mh2.invokeExact(x);
+ check(x, a, b);
}
// byte
{
MethodHandle mh1 = getmh1( byte.class, byte.class);
MethodHandle mh2 = getmh2(mh1, byte.class, int.class);
- byte a = mh1.<byte>invokeExact((byte) x);
- byte b = mh2.<byte>invokeExact(x);
- assert a == b : a + " != " + b;
+ byte a = (byte) mh1.invokeExact((byte) x);
+ byte b = (byte) mh2.invokeExact(x);
+ check(x, a, b);
}
// char
{
MethodHandle mh1 = getmh1( char.class, char.class);
MethodHandle mh2 = getmh2(mh1, char.class, int.class);
- char a = mh1.<char>invokeExact((char) x);
- char b = mh2.<char>invokeExact(x);
- assert a == b : a + " != " + b;
+ char a = (char) mh1.invokeExact((char) x);
+ char b = (char) mh2.invokeExact(x);
+ check(x, a, b);
}
// short
{
MethodHandle mh1 = getmh1( short.class, short.class);
MethodHandle mh2 = getmh2(mh1, short.class, int.class);
- short a = mh1.<short>invokeExact((short) x);
- short b = mh2.<short>invokeExact(x);
+ short a = (short) mh1.invokeExact((short) x);
+ short b = (short) mh2.invokeExact(x);
assert a == b : a + " != " + b;
+ check(x, a, b);
}
// int
{
MethodHandle mh1 = getmh1( int.class, int.class);
MethodHandle mh2 = getmh2(mh1, int.class, int.class);
- int a = mh1.<int>invokeExact((int) x);
- int b = mh2.<int>invokeExact(x);
- assert a == b : a + " != " + b;
+ int a = (int) mh1.invokeExact((int) x);
+ int b = (int) mh2.invokeExact(x);
+ check(x, a, b);
}
}
@@ -395,48 +396,65 @@
{
MethodHandle mh1 = getmh1( boolean.class, boolean.class);
MethodHandle mh2 = getmh2(mh1, boolean.class, long.class);
- boolean a = mh1.<boolean>invokeExact((x & 1L) == 1L);
- boolean b = mh2.<boolean>invokeExact(x);
- assert a == b : a + " != " + b;
+ boolean a = (boolean) mh1.invokeExact((x & 1L) == 1L);
+ boolean b = (boolean) mh2.invokeExact(x);
+ check(x, a, b);
}
// byte
{
MethodHandle mh1 = getmh1( byte.class, byte.class);
MethodHandle mh2 = getmh2(mh1, byte.class, long.class);
- byte a = mh1.<byte>invokeExact((byte) x);
- byte b = mh2.<byte>invokeExact(x);
- assert a == b : a + " != " + b;
+ byte a = (byte) mh1.invokeExact((byte) x);
+ byte b = (byte) mh2.invokeExact(x);
+ check(x, a, b);
}
// char
{
MethodHandle mh1 = getmh1( char.class, char.class);
MethodHandle mh2 = getmh2(mh1, char.class, long.class);
- char a = mh1.<char>invokeExact((char) x);
- char b = mh2.<char>invokeExact(x);
- assert a == b : a + " != " + b;
+ char a = (char) mh1.invokeExact((char) x);
+ char b = (char) mh2.invokeExact(x);
+ check(x, a, b);
}
// short
{
MethodHandle mh1 = getmh1( short.class, short.class);
MethodHandle mh2 = getmh2(mh1, short.class, long.class);
- short a = mh1.<short>invokeExact((short) x);
- short b = mh2.<short>invokeExact(x);
- assert a == b : a + " != " + b;
+ short a = (short) mh1.invokeExact((short) x);
+ short b = (short) mh2.invokeExact(x);
+ check(x, a, b);
}
// int
{
MethodHandle mh1 = getmh1( int.class, int.class);
MethodHandle mh2 = getmh2(mh1, int.class, long.class);
- int a = mh1.<int>invokeExact((int) x);
- int b = mh2.<int>invokeExact(x);
- assert a == b : a + " != " + b;
+ int a = (int) mh1.invokeExact((int) x);
+ int b = (int) mh2.invokeExact(x);
+ check(x, a, b);
}
+ }
- }
+ static void check(boolean x, boolean e, boolean a) { p(z2h(x), z2h(e), z2h(a)); assert e == a : z2h(x) + ": " + z2h(e) + " != " + z2h(a); }
+ static void check(boolean x, byte e, byte a) { p(z2h(x), i2h(e), i2h(a)); assert e == a : z2h(x) + ": " + i2h(e) + " != " + i2h(a); }
+ static void check(boolean x, int e, int a) { p(z2h(x), i2h(e), i2h(a)); assert e == a : z2h(x) + ": " + i2h(e) + " != " + i2h(a); }
+
+ static void check(int x, boolean e, boolean a) { p(i2h(x), z2h(e), z2h(a)); assert e == a : i2h(x) + ": " + z2h(e) + " != " + z2h(a); }
+ static void check(int x, byte e, byte a) { p(i2h(x), i2h(e), i2h(a)); assert e == a : i2h(x) + ": " + i2h(e) + " != " + i2h(a); }
+ static void check(int x, int e, int a) { p(i2h(x), i2h(e), i2h(a)); assert e == a : i2h(x) + ": " + i2h(e) + " != " + i2h(a); }
+
+ static void check(long x, boolean e, boolean a) { p(l2h(x), z2h(e), z2h(a)); assert e == a : l2h(x) + ": " + z2h(e) + " != " + z2h(a); }
+ static void check(long x, byte e, byte a) { p(l2h(x), i2h(e), i2h(a)); assert e == a : l2h(x) + ": " + i2h(e) + " != " + i2h(a); }
+ static void check(long x, int e, int a) { p(l2h(x), i2h(e), i2h(a)); assert e == a : l2h(x) + ": " + i2h(e) + " != " + i2h(a); }
+
+ static void p(String x, String e, String a) { if (DEBUG) System.out.println(x + ": expected: " + e + ", actual: " + a); }
+
+ static String z2h(boolean x) { return x ? "1" : "0"; }
+ static String i2h(int x) { return Integer.toHexString(x); }
+ static String l2h(long x) { return Long.toHexString(x); }
// to int
public static boolean foo(boolean i) { return i; }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/7002666/Test7002666.java Wed Dec 08 17:50:49 2010 -0800
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/**
+ * @test
+ * @bug 7002666
+ * @summary eclipse CDT projects crash with compressed oops
+ *
+ * @run main/othervm -Xbatch -XX:CompileOnly=Test7002666.test,java/lang/reflect/Array Test7002666
+ *
+ * This will only reliably fail with a fastdebug build since it relies
+ * on seeing garbage in the heap to die. It could be made more
+ * reliable in product mode but that would require greatly increasing
+ * the runtime.
+ */
+
+public class Test7002666 {
+ public static void main(String[] args) {
+ for (int i = 0; i < 25000; i++) {
+ Object[] a = test(Test7002666.class, new Test7002666());
+ if (a[0] != null) {
+ // The element should be null but if it's not then
+ // we've hit the bug. This will most likely crash but
+ // at least throw an exception.
+ System.err.println(a[0]);
+ throw new InternalError(a[0].toString());
+
+ }
+ }
+ }
+ public static Object[] test(Class c, Object o) {
+ // allocate an array small enough to be trigger the bug
+ Object[] a = (Object[])java.lang.reflect.Array.newInstance(c, 1);
+ return a;
+ }
+}