--- a/hotspot/src/cpu/sparc/vm/sparc.ad Tue Sep 15 16:50:50 2009 -0700
+++ b/hotspot/src/cpu/sparc/vm/sparc.ad Fri Sep 18 06:02:17 2009 -0700
@@ -5707,7 +5707,7 @@
effect(TEMP dst, TEMP tmp);
ins_cost(MEMORY_REF_COST + 2*DEFAULT_COST);
- size(3*4);
+ size((3+1)*4); // set may use two instructions.
format %{ "LDUH $mem,$dst\t! ushort/char & 16-bit mask -> long\n\t"
"SET $mask,$tmp\n\t"
"AND $dst,$tmp,$dst" %}
@@ -5851,7 +5851,7 @@
effect(TEMP dst, TEMP tmp);
ins_cost(MEMORY_REF_COST + 2*DEFAULT_COST);
- size(3*4);
+ size((3+1)*4); // set may use two instructions.
format %{ "LDUW $mem,$dst\t! int & 32-bit mask -> long\n\t"
"SET $mask,$tmp\n\t"
"AND $dst,$tmp,$dst" %}
--- a/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp Tue Sep 15 16:50:50 2009 -0700
+++ b/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp Fri Sep 18 06:02:17 2009 -0700
@@ -827,8 +827,8 @@
case vmIntrinsics::_dsin: __ sin (calc_input, calc_result, tmp1, tmp2); break;
case vmIntrinsics::_dcos: __ cos (calc_input, calc_result, tmp1, tmp2); break;
case vmIntrinsics::_dtan: __ tan (calc_input, calc_result, tmp1, tmp2); break;
- case vmIntrinsics::_dlog: __ log (calc_input, calc_result, LIR_OprFact::illegalOpr); break;
- case vmIntrinsics::_dlog10: __ log10(calc_input, calc_result, LIR_OprFact::illegalOpr); break;
+ case vmIntrinsics::_dlog: __ log (calc_input, calc_result, tmp1); break;
+ case vmIntrinsics::_dlog10: __ log10(calc_input, calc_result, tmp1); break;
default: ShouldNotReachHere();
}
--- a/hotspot/src/cpu/x86/vm/c1_LinearScan_x86.cpp Tue Sep 15 16:50:50 2009 -0700
+++ b/hotspot/src/cpu/x86/vm/c1_LinearScan_x86.cpp Fri Sep 18 06:02:17 2009 -0700
@@ -764,8 +764,6 @@
break;
}
- case lir_log:
- case lir_log10:
case lir_abs:
case lir_sqrt: {
// Right argument appears to be unused
@@ -785,6 +783,30 @@
break;
}
+ case lir_log:
+ case lir_log10: {
+ // log and log10 needs one temporary fpu stack slot, so there is ontemporary
+ // registers stored in temp of the operation.
+ // the stack allocator must guarantee that the stack slots are really free,
+ // otherwise there might be a stack overflow.
+ assert(right->is_illegal(), "must be");
+ assert(left->is_fpu_register(), "must be");
+ assert(res->is_fpu_register(), "must be");
+ assert(op2->tmp_opr()->is_fpu_register(), "must be");
+
+ insert_free_if_dead(op2->tmp_opr());
+ insert_free_if_dead(res, left);
+ insert_exchange(left);
+ do_rename(left, res);
+
+ new_left = to_fpu_stack_top(res);
+ new_res = new_left;
+
+ op2->set_fpu_stack_size(sim()->stack_size());
+ assert(sim()->stack_size() <= 7, "at least one stack slot must be free");
+ break;
+ }
+
case lir_tan:
case lir_sin:
--- a/hotspot/src/share/vm/c1/c1_LIR.cpp Tue Sep 15 16:50:50 2009 -0700
+++ b/hotspot/src/share/vm/c1/c1_LIR.cpp Fri Sep 18 06:02:17 2009 -0700
@@ -567,8 +567,6 @@
case lir_rem:
case lir_sqrt:
case lir_abs:
- case lir_log:
- case lir_log10:
case lir_logic_and:
case lir_logic_or:
case lir_logic_xor:
@@ -644,13 +642,16 @@
case lir_tan:
case lir_sin:
- case lir_cos: {
+ case lir_cos:
+ case lir_log:
+ case lir_log10: {
assert(op->as_Op2() != NULL, "must be");
LIR_Op2* op2 = (LIR_Op2*)op;
- // sin and cos need two temporary fpu stack slots, so register
- // two temp operands. Register input operand as temp to
- // guarantee that they do not overlap
+ // On x86 tan/sin/cos need two temporary fpu stack slots and
+ // log/log10 need one so handle opr2 and tmp as temp inputs.
+ // Register input operand as temp to guarantee that it doesn't
+ // overlap with the input.
assert(op2->_info == NULL, "not used");
assert(op2->_opr1->is_valid(), "used");
do_input(op2->_opr1); do_temp(op2->_opr1);
--- a/hotspot/src/share/vm/c1/c1_LIR.hpp Tue Sep 15 16:50:50 2009 -0700
+++ b/hotspot/src/share/vm/c1/c1_LIR.hpp Fri Sep 18 06:02:17 2009 -0700
@@ -1840,8 +1840,8 @@
void abs (LIR_Opr from, LIR_Opr to, LIR_Opr tmp) { append(new LIR_Op2(lir_abs , from, tmp, to)); }
void sqrt(LIR_Opr from, LIR_Opr to, LIR_Opr tmp) { append(new LIR_Op2(lir_sqrt, from, tmp, to)); }
- void log (LIR_Opr from, LIR_Opr to, LIR_Opr tmp) { append(new LIR_Op2(lir_log, from, tmp, to)); }
- void log10 (LIR_Opr from, LIR_Opr to, LIR_Opr tmp) { append(new LIR_Op2(lir_log10, from, tmp, to)); }
+ void log (LIR_Opr from, LIR_Opr to, LIR_Opr tmp) { append(new LIR_Op2(lir_log, from, LIR_OprFact::illegalOpr, to, tmp)); }
+ void log10 (LIR_Opr from, LIR_Opr to, LIR_Opr tmp) { append(new LIR_Op2(lir_log10, from, LIR_OprFact::illegalOpr, to, tmp)); }
void sin (LIR_Opr from, LIR_Opr to, LIR_Opr tmp1, LIR_Opr tmp2) { append(new LIR_Op2(lir_sin , from, tmp1, to, tmp2)); }
void cos (LIR_Opr from, LIR_Opr to, LIR_Opr tmp1, LIR_Opr tmp2) { append(new LIR_Op2(lir_cos , from, tmp1, to, tmp2)); }
void tan (LIR_Opr from, LIR_Opr to, LIR_Opr tmp1, LIR_Opr tmp2) { append(new LIR_Op2(lir_tan , from, tmp1, to, tmp2)); }
--- a/hotspot/src/share/vm/classfile/javaClasses.cpp Tue Sep 15 16:50:50 2009 -0700
+++ b/hotspot/src/share/vm/classfile/javaClasses.cpp Fri Sep 18 06:02:17 2009 -0700
@@ -252,7 +252,7 @@
typeArrayOop value = java_lang_String::value(obj);
int offset = java_lang_String::offset(obj);
int length = java_lang_String::length(obj);
- jchar* base = value->char_at_addr(offset);
+ jchar* base = (length == 0) ? NULL : value->char_at_addr(offset);
symbolOop sym = SymbolTable::lookup_unicode(base, length, THREAD);
return symbolHandle(THREAD, sym);
}
@@ -261,7 +261,7 @@
typeArrayOop value = java_lang_String::value(java_string);
int offset = java_lang_String::offset(java_string);
int length = java_lang_String::length(java_string);
- jchar* base = value->char_at_addr(offset);
+ jchar* base = (length == 0) ? NULL : value->char_at_addr(offset);
return SymbolTable::probe_unicode(base, length);
}
--- a/hotspot/src/share/vm/opto/escape.cpp Tue Sep 15 16:50:50 2009 -0700
+++ b/hotspot/src/share/vm/opto/escape.cpp Fri Sep 18 06:02:17 2009 -0700
@@ -439,6 +439,11 @@
Node *base = addp->in(AddPNode::Base)->uncast();
if (base->is_top()) { // The AddP case #3 and #6.
base = addp->in(AddPNode::Address)->uncast();
+ while (base->is_AddP()) {
+ // Case #6 (unsafe access) may have several chained AddP nodes.
+ assert(base->in(AddPNode::Base)->is_top(), "expected unsafe access address only");
+ base = base->in(AddPNode::Address)->uncast();
+ }
assert(base->Opcode() == Op_ConP || base->Opcode() == Op_ThreadLocal ||
base->Opcode() == Op_CastX2P || base->is_DecodeN() ||
(base->is_Mem() && base->bottom_type() == TypeRawPtr::NOTNULL) ||
--- a/hotspot/src/share/vm/opto/graphKit.cpp Tue Sep 15 16:50:50 2009 -0700
+++ b/hotspot/src/share/vm/opto/graphKit.cpp Fri Sep 18 06:02:17 2009 -0700
@@ -622,11 +622,13 @@
//---------------------------PreserveReexecuteState----------------------------
PreserveReexecuteState::PreserveReexecuteState(GraphKit* kit) {
+ assert(!kit->stopped(), "must call stopped() before");
_kit = kit;
_sp = kit->sp();
_reexecute = kit->jvms()->_reexecute;
}
PreserveReexecuteState::~PreserveReexecuteState() {
+ if (_kit->stopped()) return;
_kit->jvms()->_reexecute = _reexecute;
_kit->set_sp(_sp);
}
@@ -1086,7 +1088,7 @@
alen = _gvn.transform( new (C, 3) LoadRangeNode(0, immutable_memory(), r_adr, TypeInt::POS));
} else {
alen = alloc->Ideal_length();
- Node* ccast = alloc->make_ideal_length(_gvn.type(array)->is_aryptr(), &_gvn);
+ Node* ccast = alloc->make_ideal_length(_gvn.type(array)->is_oopptr(), &_gvn);
if (ccast != alen) {
alen = _gvn.transform(ccast);
}
@@ -1123,8 +1125,8 @@
case T_OBJECT : {
const Type *t = _gvn.type( value );
- const TypeInstPtr* tp = t->isa_instptr();
- if (tp != NULL && !tp->klass()->is_loaded()
+ const TypeOopPtr* tp = t->isa_oopptr();
+ if (tp != NULL && tp->klass() != NULL && !tp->klass()->is_loaded()
// Only for do_null_check, not any of its siblings:
&& !assert_null && null_control == NULL) {
// Usually, any field access or invocation on an unloaded oop type
--- a/hotspot/src/share/vm/opto/library_call.cpp Tue Sep 15 16:50:50 2009 -0700
+++ b/hotspot/src/share/vm/opto/library_call.cpp Fri Sep 18 06:02:17 2009 -0700
@@ -3903,19 +3903,10 @@
guarantee(alloc != NULL && alloc->maybe_set_complete(&_gvn), "");
}
- // Cast to Object for arraycopy.
- // We can't use the original CheckCastPP since it should be moved
- // after the arraycopy to prevent stores flowing above it.
- Node* new_obj = new(C, 2) CheckCastPPNode(alloc_obj->in(0), raw_obj,
- TypeInstPtr::NOTNULL);
- new_obj = _gvn.transform(new_obj);
- // Substitute in the locally valid dest_oop.
- replace_in_map(alloc_obj, new_obj);
-
// Copy the fastest available way.
// TODO: generate fields copies for small objects instead.
Node* src = obj;
- Node* dest = new_obj;
+ Node* dest = alloc_obj;
Node* size = _gvn.transform(obj_size);
// Exclude the header but include array length to copy by 8 bytes words.
@@ -3961,7 +3952,7 @@
int raw_adr_idx = Compile::AliasIdxRaw;
post_barrier(control(),
memory(raw_adr_type),
- new_obj,
+ alloc_obj,
no_particular_field,
raw_adr_idx,
no_particular_value,
@@ -3969,16 +3960,8 @@
false);
}
- // Move the original CheckCastPP after arraycopy.
- _gvn.hash_delete(alloc_obj);
- alloc_obj->set_req(0, control());
- // Replace raw memory edge with new CheckCastPP to have a live oop
- // at safepoints instead of raw value.
- assert(new_obj->is_CheckCastPP() && new_obj->in(1) == alloc_obj->in(1), "sanity");
- alloc_obj->set_req(1, new_obj); // cast to the original type
- _gvn.hash_find_insert(alloc_obj); // put back into GVN table
- // Restore in the locally valid dest_oop.
- replace_in_map(new_obj, alloc_obj);
+ // Do not let reads from the cloned object float above the arraycopy.
+ insert_mem_bar(Op_MemBarCPUOrder);
}
//------------------------inline_native_clone----------------------------
@@ -4448,15 +4431,6 @@
assert(init->is_complete(), "we just did this");
assert(dest->is_CheckCastPP(), "sanity");
assert(dest->in(0)->in(0) == init, "dest pinned");
-
- // Cast to Object for arraycopy.
- // We can't use the original CheckCastPP since it should be moved
- // after the arraycopy to prevent stores flowing above it.
- Node* new_obj = new(C, 2) CheckCastPPNode(dest->in(0), dest->in(1),
- TypeInstPtr::NOTNULL);
- dest = _gvn.transform(new_obj);
- // Substitute in the locally valid dest_oop.
- replace_in_map(original_dest, dest);
adr_type = TypeRawPtr::BOTTOM; // all initializations are into raw memory
// From this point on, every exit path is responsible for
// initializing any non-copied parts of the object to zero.
@@ -4786,18 +4760,6 @@
set_i_o( _gvn.transform(result_i_o) );
set_memory( _gvn.transform(result_memory), adr_type );
- if (dest != original_dest) {
- // Pin the "finished" array node after the arraycopy/zeroing operations.
- _gvn.hash_delete(original_dest);
- original_dest->set_req(0, control());
- // Replace raw memory edge with new CheckCastPP to have a live oop
- // at safepoints instead of raw value.
- assert(dest->is_CheckCastPP() && dest->in(1) == original_dest->in(1), "sanity");
- original_dest->set_req(1, dest); // cast to the original type
- _gvn.hash_find_insert(original_dest); // put back into GVN table
- // Restore in the locally valid dest_oop.
- replace_in_map(dest, original_dest);
- }
// The memory edges above are precise in order to model effects around
// array copies accurately to allow value numbering of field loads around
// arraycopy. Such field loads, both before and after, are common in Java
@@ -4808,7 +4770,9 @@
// The next memory barrier is added to avoid it. If the arraycopy can be
// optimized away (which it can, sometimes) then we can manually remove
// the membar also.
- if (InsertMemBarAfterArraycopy)
+ //
+ // Do not let reads from the cloned object float above the arraycopy.
+ if (InsertMemBarAfterArraycopy || alloc != NULL)
insert_mem_bar(Op_MemBarCPUOrder);
}
--- a/hotspot/src/share/vm/opto/superword.cpp Tue Sep 15 16:50:50 2009 -0700
+++ b/hotspot/src/share/vm/opto/superword.cpp Fri Sep 18 06:02:17 2009 -0700
@@ -990,8 +990,8 @@
// (5) We know there is no dependence cycle, so there in no other case;
// (6) Finally, all memory ops in another single pack should be moved in the same direction.
//
-// To schedule a load pack: the memory edge of every loads in the pack must be
-// the same as the memory edge of the last executed load in the pack
+// To schedule a load pack, we use the memory state of either the first or the last load in
+// the pack, based on the dependence constraint.
void SuperWord::co_locate_pack(Node_List* pk) {
if (pk->at(0)->is_Store()) {
MemNode* first = executed_first(pk)->as_Mem();
@@ -1076,15 +1076,32 @@
current = my_mem->as_Mem();
} // end while
} else if (pk->at(0)->is_Load()) { //load
- // all use the memory state that the last executed load uses
- LoadNode* last_load = executed_last(pk)->as_Load();
- Node* last_mem = last_load->in(MemNode::Memory);
- _igvn.hash_delete(last_mem);
- // Give each load same memory state as last
+ // all loads in the pack should have the same memory state. By default,
+ // we use the memory state of the last load. However, if any load could
+ // not be moved down due to the dependence constraint, we use the memory
+ // state of the first load.
+ Node* last_mem = executed_last(pk)->in(MemNode::Memory);
+ Node* first_mem = executed_first(pk)->in(MemNode::Memory);
+ bool schedule_last = true;
+ for (uint i = 0; i < pk->size(); i++) {
+ Node* ld = pk->at(i);
+ for (Node* current = last_mem; current != ld->in(MemNode::Memory);
+ current=current->in(MemNode::Memory)) {
+ assert(current != first_mem, "corrupted memory graph");
+ if(current->is_Mem() && !independent(current, ld)){
+ schedule_last = false; // a later store depends on this load
+ break;
+ }
+ }
+ }
+
+ Node* mem_input = schedule_last ? last_mem : first_mem;
+ _igvn.hash_delete(mem_input);
+ // Give each load the same memory state
for (uint i = 0; i < pk->size(); i++) {
LoadNode* ld = pk->at(i)->as_Load();
_igvn.hash_delete(ld);
- ld->set_req(MemNode::Memory, last_mem);
+ ld->set_req(MemNode::Memory, mem_input);
_igvn._worklist.push(ld);
}
}
--- a/hotspot/src/share/vm/opto/type.cpp Tue Sep 15 16:50:50 2009 -0700
+++ b/hotspot/src/share/vm/opto/type.cpp Fri Sep 18 06:02:17 2009 -0700
@@ -2236,12 +2236,12 @@
//------------------------------make-------------------------------------------
const TypeOopPtr *TypeOopPtr::make(PTR ptr,
- int offset) {
+ int offset, int instance_id) {
assert(ptr != Constant, "no constant generic pointers");
ciKlass* k = ciKlassKlass::make();
bool xk = false;
ciObject* o = NULL;
- return (TypeOopPtr*)(new TypeOopPtr(OopPtr, ptr, k, xk, o, offset, InstanceBot))->hashcons();
+ return (TypeOopPtr*)(new TypeOopPtr(OopPtr, ptr, k, xk, o, offset, instance_id))->hashcons();
}
@@ -2330,7 +2330,8 @@
case OopPtr: { // Meeting to other OopPtrs
const TypeOopPtr *tp = t->is_oopptr();
- return make( meet_ptr(tp->ptr()), meet_offset(tp->offset()) );
+ int instance_id = meet_instance_id(tp->instance_id());
+ return make( meet_ptr(tp->ptr()), meet_offset(tp->offset()), instance_id );
}
case InstPtr: // For these, flip the call around to cut down
@@ -2801,7 +2802,7 @@
case OopPtr: { // Meeting to OopPtrs
// Found a OopPtr type vs self-InstPtr type
- const TypePtr *tp = t->is_oopptr();
+ const TypeOopPtr *tp = t->is_oopptr();
int offset = meet_offset(tp->offset());
PTR ptr = meet_ptr(tp->ptr());
switch (tp->ptr()) {
@@ -2812,8 +2813,10 @@
(ptr == Constant ? const_oop() : NULL), offset, instance_id);
}
case NotNull:
- case BotPTR:
- return TypeOopPtr::make(ptr, offset);
+ case BotPTR: {
+ int instance_id = meet_instance_id(tp->instance_id());
+ return TypeOopPtr::make(ptr, offset, instance_id);
+ }
default: typerr(t);
}
}
@@ -3259,7 +3262,7 @@
case OopPtr: { // Meeting to OopPtrs
// Found a OopPtr type vs self-AryPtr type
- const TypePtr *tp = t->is_oopptr();
+ const TypeOopPtr *tp = t->is_oopptr();
int offset = meet_offset(tp->offset());
PTR ptr = meet_ptr(tp->ptr());
switch (tp->ptr()) {
@@ -3270,8 +3273,10 @@
_ary, _klass, _klass_is_exact, offset, instance_id);
}
case BotPTR:
- case NotNull:
- return TypeOopPtr::make(ptr, offset);
+ case NotNull: {
+ int instance_id = meet_instance_id(tp->instance_id());
+ return TypeOopPtr::make(ptr, offset, instance_id);
+ }
default: ShouldNotReachHere();
}
}
--- a/hotspot/src/share/vm/opto/type.hpp Tue Sep 15 16:50:50 2009 -0700
+++ b/hotspot/src/share/vm/opto/type.hpp Fri Sep 18 06:02:17 2009 -0700
@@ -714,7 +714,7 @@
static const TypeOopPtr* make_from_constant(ciObject* o);
// Make a generic (unclassed) pointer to an oop.
- static const TypeOopPtr* make(PTR ptr, int offset);
+ static const TypeOopPtr* make(PTR ptr, int offset, int instance_id = InstanceBot);
ciObject* const_oop() const { return _const_oop; }
virtual ciKlass* klass() const { return _klass; }
--- a/hotspot/test/compiler/6636138/Test1.java Tue Sep 15 16:50:50 2009 -0700
+++ b/hotspot/test/compiler/6636138/Test1.java Fri Sep 18 06:02:17 2009 -0700
@@ -45,7 +45,7 @@
for (int i = 0; i < src.length; i++) {
if (src[i] != ref[i]) {
System.out.println("Error: src and ref don't match at " + i);
- System.exit(-1);
+ System.exit(97);
}
}
}
--- a/hotspot/test/compiler/6636138/Test2.java Tue Sep 15 16:50:50 2009 -0700
+++ b/hotspot/test/compiler/6636138/Test2.java Fri Sep 18 06:02:17 2009 -0700
@@ -51,7 +51,7 @@
int value = (i-1 + src.length)%src.length; // correct value after shifting
if (src[i] != value) {
System.out.println("Error: src["+i+"] should be "+ value + " instead of " + src[i]);
- System.exit(-1);
+ System.exit(97);
}
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/6855215/Test6855215.java Fri Sep 18 06:02:17 2009 -0700
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ */
+
+/**
+ * @test
+ * @bug 6855215
+ * @summary Calculation error (NaN) after about 1500 calculations
+ *
+ * @run main/othervm -Xbatch -XX:UseSSE=0 Test6855215
+ */
+
+public class Test6855215 {
+ private double m;
+ private double b;
+
+ public static double log10(double x) {
+ return Math.log(x) / Math.log(10);
+ }
+
+ void calcMapping(double xmin, double xmax, double ymin, double ymax) {
+ m = (ymax - ymin) / (log10(xmax) - log10(xmin));
+ b = (log10(xmin) * ymax - log10(xmax) * ymin);
+ }
+
+ public static void main(String[] args) {
+ Test6855215 c = new Test6855215();
+ for (int i = 0; i < 30000; i++) {
+ c.calcMapping(91, 121, 177, 34);
+ if (c.m != c.m) {
+ throw new InternalError();
+ }
+ }
+ }
+}
--- a/hotspot/test/compiler/6865031/Test.java Tue Sep 15 16:50:50 2009 -0700
+++ b/hotspot/test/compiler/6865031/Test.java Fri Sep 18 06:02:17 2009 -0700
@@ -26,7 +26,7 @@
* @test
* @bug 6865031
* @summary Application gives bad result (throws bad exception) with compressed oops
- * @run main/othervm -XX:+UseCompressedOops -XX:HeapBaseMinAddress=32g -XX:-LoopUnswitching -XX:CompileCommand=inline,AbstractMemoryEfficientList.equals Test hello goodbye
+ * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UseCompressedOops -XX:HeapBaseMinAddress=32g -XX:-LoopUnswitching -XX:CompileCommand=inline,AbstractMemoryEfficientList.equals Test hello goodbye
*/
import java.lang.ref.ReferenceQueue;