--- a/hotspot/make/aix/makefiles/adjust-mflags.sh Wed Mar 05 10:20:30 2014 +0100
+++ b/hotspot/make/aix/makefiles/adjust-mflags.sh Wed Mar 05 01:26:52 2014 -0800
@@ -1,6 +1,6 @@
#! /bin/sh
#
-# Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1999, 2014, 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
@@ -64,7 +64,7 @@
echo "$MFLAGS" \
| sed '
s/^-/ -/
- s/ -\([^ ][^ ]*\)j/ -\1 -j/
+ s/ -\([^ I][^ I]*\)j/ -\1 -j/
s/ -j[0-9][0-9]*/ -j/
s/ -j\([^ ]\)/ -j -\1/
s/ -j/ -j'${HOTSPOT_BUILD_JOBS:-${default_build_jobs}}'/
--- a/hotspot/make/linux/makefiles/zeroshark.make Wed Mar 05 10:20:30 2014 +0100
+++ b/hotspot/make/linux/makefiles/zeroshark.make Wed Mar 05 01:26:52 2014 -0800
@@ -25,6 +25,9 @@
# Setup common to Zero (non-Shark) and Shark versions of VM
+# override this from the main file because some version of llvm do not like -Wundef
+WARNING_FLAGS = -Wpointer-arith -Wsign-compare -Wunused-function -Wunused-value
+
# The copied fdlibm routines in sharedRuntimeTrig.o must not be optimized
OPT_CFLAGS/sharedRuntimeTrig.o = $(OPT_CFLAGS/NOOPT)
# The copied fdlibm routines in sharedRuntimeTrans.o must not be optimized
--- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Wed Mar 05 10:20:30 2014 +0100
+++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Wed Mar 05 01:26:52 2014 -0800
@@ -1436,7 +1436,7 @@
bool need_mem_bar = false;
if (method()->name() == ciSymbol::object_initializer_name() &&
- scope()->wrote_final()) {
+ (scope()->wrote_final() || (AlwaysSafeConstructors && scope()->wrote_fields()))) {
need_mem_bar = true;
}
@@ -1550,6 +1550,10 @@
scope()->set_wrote_final();
}
+ if (code == Bytecodes::_putfield) {
+ scope()->set_wrote_fields();
+ }
+
const int offset = !needs_patching ? field->offset() : -1;
switch (code) {
case Bytecodes::_getstatic: {
@@ -3767,11 +3771,14 @@
}
// now perform tests that are based on flag settings
- if (callee->force_inline()) {
- if (inline_level() > MaxForceInlineLevel) INLINE_BAILOUT("MaxForceInlineLevel");
- print_inlining(callee, "force inline by annotation");
- } else if (callee->should_inline()) {
- print_inlining(callee, "force inline by CompileOracle");
+ if (callee->force_inline() || callee->should_inline()) {
+ if (inline_level() > MaxForceInlineLevel ) INLINE_BAILOUT("MaxForceInlineLevel");
+ if (recursive_inline_level(callee) > MaxRecursiveInlineLevel) INLINE_BAILOUT("recursive inlining too deep");
+
+ const char* msg = "";
+ if (callee->force_inline()) msg = "force inline by annotation";
+ if (callee->should_inline()) msg = "force inline by CompileOracle";
+ print_inlining(callee, msg);
} else {
// use heuristic controls on inlining
if (inline_level() > MaxInlineLevel ) INLINE_BAILOUT("inlining too deep");
--- a/hotspot/src/share/vm/c1/c1_IR.cpp Wed Mar 05 10:20:30 2014 +0100
+++ b/hotspot/src/share/vm/c1/c1_IR.cpp Wed Mar 05 01:26:52 2014 -0800
@@ -142,6 +142,7 @@
_number_of_locks = 0;
_monitor_pairing_ok = method->has_balanced_monitors();
_wrote_final = false;
+ _wrote_fields = false;
_start = NULL;
if (osr_bci == -1) {
--- a/hotspot/src/share/vm/c1/c1_IR.hpp Wed Mar 05 10:20:30 2014 +0100
+++ b/hotspot/src/share/vm/c1/c1_IR.hpp Wed Mar 05 01:26:52 2014 -0800
@@ -150,6 +150,7 @@
int _number_of_locks; // the number of monitor lock slots needed
bool _monitor_pairing_ok; // the monitor pairing info
bool _wrote_final; // has written final field
+ bool _wrote_fields; // has written fields
BlockBegin* _start; // the start block, successsors are method entries
BitMap _requires_phi_function; // bit is set if phi functions at loop headers are necessary for a local variable
@@ -184,6 +185,9 @@
BlockBegin* start() const { return _start; }
void set_wrote_final() { _wrote_final = true; }
bool wrote_final () const { return _wrote_final; }
+ void set_wrote_fields() { _wrote_fields = true; }
+ bool wrote_fields () const { return _wrote_fields; }
+
};
--- a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp Wed Mar 05 10:20:30 2014 +0100
+++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp Wed Mar 05 01:26:52 2014 -0800
@@ -1734,7 +1734,8 @@
(info ? new CodeEmitInfo(info) : NULL));
}
- if (is_volatile && !needs_patching) {
+ bool needs_atomic_access = is_volatile || AlwaysAtomicAccesses;
+ if (needs_atomic_access && !needs_patching) {
volatile_field_store(value.result(), address, info);
} else {
LIR_PatchCode patch_code = needs_patching ? lir_patch_normal : lir_patch_none;
@@ -1807,7 +1808,8 @@
address = generate_address(object.result(), x->offset(), field_type);
}
- if (is_volatile && !needs_patching) {
+ bool needs_atomic_access = is_volatile || AlwaysAtomicAccesses;
+ if (needs_atomic_access && !needs_patching) {
volatile_field_load(address, reg, info);
} else {
LIR_PatchCode patch_code = needs_patching ? lir_patch_normal : lir_patch_none;
--- a/hotspot/src/share/vm/c1/c1_Runtime1.cpp Wed Mar 05 10:20:30 2014 +0100
+++ b/hotspot/src/share/vm/c1/c1_Runtime1.cpp Wed Mar 05 01:26:52 2014 -0800
@@ -809,11 +809,10 @@
int bci = vfst.bci();
Bytecodes::Code code = caller_method()->java_code_at(bci);
-#ifndef PRODUCT
// this is used by assertions in the access_field_patching_id
BasicType patch_field_type = T_ILLEGAL;
-#endif // PRODUCT
bool deoptimize_for_volatile = false;
+ bool deoptimize_for_atomic = false;
int patch_field_offset = -1;
KlassHandle init_klass(THREAD, NULL); // klass needed by load_klass_patching code
KlassHandle load_klass(THREAD, NULL); // klass needed by load_klass_patching code
@@ -839,11 +838,24 @@
// is the path for patching field offsets. load_klass is only
// used for patching references to oops which don't need special
// handling in the volatile case.
+
deoptimize_for_volatile = result.access_flags().is_volatile();
-#ifndef PRODUCT
+ // If we are patching a field which should be atomic, then
+ // the generated code is not correct either, force deoptimizing.
+ // We need to only cover T_LONG and T_DOUBLE fields, as we can
+ // break access atomicity only for them.
+
+ // Strictly speaking, the deoptimizaation on 64-bit platforms
+ // is unnecessary, and T_LONG stores on 32-bit platforms need
+ // to be handled by special patching code when AlwaysAtomicAccesses
+ // becomes product feature. At this point, we are still going
+ // for the deoptimization for consistency against volatile
+ // accesses.
+
patch_field_type = result.field_type();
-#endif
+ deoptimize_for_atomic = (AlwaysAtomicAccesses && (patch_field_type == T_DOUBLE || patch_field_type == T_LONG));
+
} else if (load_klass_or_mirror_patch_id) {
Klass* k = NULL;
switch (code) {
@@ -918,13 +930,19 @@
ShouldNotReachHere();
}
- if (deoptimize_for_volatile) {
- // At compile time we assumed the field wasn't volatile but after
- // loading it turns out it was volatile so we have to throw the
+ if (deoptimize_for_volatile || deoptimize_for_atomic) {
+ // At compile time we assumed the field wasn't volatile/atomic but after
+ // loading it turns out it was volatile/atomic so we have to throw the
// compiled code out and let it be regenerated.
if (TracePatching) {
- tty->print_cr("Deoptimizing for patching volatile field reference");
+ if (deoptimize_for_volatile) {
+ tty->print_cr("Deoptimizing for patching volatile field reference");
+ }
+ if (deoptimize_for_atomic) {
+ tty->print_cr("Deoptimizing for patching atomic field reference");
+ }
}
+
// It's possible the nmethod was invalidated in the last
// safepoint, but if it's still alive then make it not_entrant.
nmethod* nm = CodeCache::find_nmethod(caller_frame.pc());
--- a/hotspot/src/share/vm/ci/ciMethod.cpp Wed Mar 05 10:20:30 2014 +0100
+++ b/hotspot/src/share/vm/ci/ciMethod.cpp Wed Mar 05 01:26:52 2014 -0800
@@ -724,6 +724,11 @@
VM_ENTRY_MARK;
+ // Disable CHA for default methods for now
+ if (root_m->get_Method()->is_default_method()) {
+ return NULL;
+ }
+
methodHandle target;
{
MutexLocker locker(Compile_lock);
--- a/hotspot/src/share/vm/opto/c2_globals.hpp Wed Mar 05 10:20:30 2014 +0100
+++ b/hotspot/src/share/vm/opto/c2_globals.hpp Wed Mar 05 01:26:52 2014 -0800
@@ -452,7 +452,7 @@
product(bool, EliminateAutoBox, true, \
"Control optimizations for autobox elimination") \
\
- experimental(bool, UseImplicitStableValues, false, \
+ diagnostic(bool, UseImplicitStableValues, true, \
"Mark well-known stable fields as such (e.g. String.value)") \
\
product(intx, AutoBoxCacheMax, 128, \
--- a/hotspot/src/share/vm/opto/parse.hpp Wed Mar 05 10:20:30 2014 +0100
+++ b/hotspot/src/share/vm/opto/parse.hpp Wed Mar 05 01:26:52 2014 -0800
@@ -338,6 +338,8 @@
GraphKit _exits; // Record all normal returns and throws here.
bool _wrote_final; // Did we write a final field?
bool _wrote_volatile; // Did we write a volatile field?
+ bool _wrote_stable; // Did we write a @Stable field?
+ bool _wrote_fields; // Did we write any field?
bool _count_invocations; // update and test invocation counter
bool _method_data_update; // update method data oop
Node* _alloc_with_final; // An allocation node with final field
@@ -383,6 +385,10 @@
void set_wrote_final(bool z) { _wrote_final = z; }
bool wrote_volatile() const { return _wrote_volatile; }
void set_wrote_volatile(bool z) { _wrote_volatile = z; }
+ bool wrote_stable() const { return _wrote_stable; }
+ void set_wrote_stable(bool z) { _wrote_stable = z; }
+ bool wrote_fields() const { return _wrote_fields; }
+ void set_wrote_fields(bool z) { _wrote_fields = z; }
bool count_invocations() const { return _count_invocations; }
bool method_data_update() const { return _method_data_update; }
Node* alloc_with_final() const { return _alloc_with_final; }
--- a/hotspot/src/share/vm/opto/parse1.cpp Wed Mar 05 10:20:30 2014 +0100
+++ b/hotspot/src/share/vm/opto/parse1.cpp Wed Mar 05 01:26:52 2014 -0800
@@ -391,6 +391,8 @@
_depth = 1 + (caller->has_method() ? caller->depth() : 0);
_wrote_final = false;
_wrote_volatile = false;
+ _wrote_stable = false;
+ _wrote_fields = false;
_alloc_with_final = NULL;
_entry_bci = InvocationEntryBci;
_tf = NULL;
@@ -908,26 +910,35 @@
Node* iophi = _exits.i_o();
_exits.set_i_o(gvn().transform(iophi));
- // On PPC64, also add MemBarRelease for constructors which write
- // volatile fields. As support_IRIW_for_not_multiple_copy_atomic_cpu
- // is set on PPC64, no sync instruction is issued after volatile
- // stores. We want to quarantee the same behaviour as on platforms
- // with total store order, although this is not required by the Java
- // memory model. So as with finals, we add a barrier here.
- if (wrote_final() PPC64_ONLY(|| (wrote_volatile() && method()->is_initializer()))) {
- // This method (which must be a constructor by the rules of Java)
- // wrote a final. The effects of all initializations must be
- // committed to memory before any code after the constructor
- // publishes the reference to the newly constructor object.
- // Rather than wait for the publication, we simply block the
- // writes here. Rather than put a barrier on only those writes
- // which are required to complete, we force all writes to complete.
- //
- // "All bets are off" unless the first publication occurs after a
- // normal return from the constructor. We do not attempt to detect
- // such unusual early publications. But no barrier is needed on
- // exceptional returns, since they cannot publish normally.
- //
+ // Figure out if we need to emit the trailing barrier. The barrier is only
+ // needed in the constructors, and only in three cases:
+ //
+ // 1. The constructor wrote a final. The effects of all initializations
+ // must be committed to memory before any code after the constructor
+ // publishes the reference to the newly constructed object. Rather
+ // than wait for the publication, we simply block the writes here.
+ // Rather than put a barrier on only those writes which are required
+ // to complete, we force all writes to complete.
+ //
+ // 2. On PPC64, also add MemBarRelease for constructors which write
+ // volatile fields. As support_IRIW_for_not_multiple_copy_atomic_cpu
+ // is set on PPC64, no sync instruction is issued after volatile
+ // stores. We want to guarantee the same behavior as on platforms
+ // with total store order, although this is not required by the Java
+ // memory model. So as with finals, we add a barrier here.
+ //
+ // 3. Experimental VM option is used to force the barrier if any field
+ // was written out in the constructor.
+ //
+ // "All bets are off" unless the first publication occurs after a
+ // normal return from the constructor. We do not attempt to detect
+ // such unusual early publications. But no barrier is needed on
+ // exceptional returns, since they cannot publish normally.
+ //
+ if (method()->is_initializer() &&
+ (wrote_final() ||
+ PPC64_ONLY(wrote_volatile() ||)
+ (AlwaysSafeConstructors && wrote_fields()))) {
_exits.insert_mem_bar(Op_MemBarRelease, alloc_with_final());
#ifndef PRODUCT
if (PrintOpto && (Verbose || WizardMode)) {
@@ -937,6 +948,19 @@
#endif
}
+ // Any method can write a @Stable field; insert memory barriers after
+ // those also. If there is a predecessor allocation node, bind the
+ // barrier there.
+ if (wrote_stable()) {
+ _exits.insert_mem_bar(Op_MemBarRelease, alloc_with_final());
+#ifndef PRODUCT
+ if (PrintOpto && (Verbose || WizardMode)) {
+ method()->print_name();
+ tty->print_cr(" writes @Stable and needs a memory barrier");
+ }
+#endif
+ }
+
for (MergeMemStream mms(_exits.merged_memory()); mms.next_non_empty(); ) {
// transform each slice of the original memphi:
mms.set_memory(_gvn.transform(mms.memory()));
--- a/hotspot/src/share/vm/opto/parse3.cpp Wed Mar 05 10:20:30 2014 +0100
+++ b/hotspot/src/share/vm/opto/parse3.cpp Wed Mar 05 01:26:52 2014 -0800
@@ -233,7 +233,8 @@
// Build the load.
//
MemNode::MemOrd mo = is_vol ? MemNode::acquire : MemNode::unordered;
- Node* ld = make_load(NULL, adr, type, bt, adr_type, mo, is_vol);
+ bool needs_atomic_access = is_vol || AlwaysAtomicAccesses;
+ Node* ld = make_load(NULL, adr, type, bt, adr_type, mo, needs_atomic_access);
// Adjust Java stack
if (type2size[bt] == 1)
@@ -314,7 +315,8 @@
}
store = store_oop_to_object(control(), obj, adr, adr_type, val, field_type, bt, mo);
} else {
- store = store_to_memory(control(), adr, val, bt, adr_type, mo, is_vol);
+ bool needs_atomic_access = is_vol || AlwaysAtomicAccesses;
+ store = store_to_memory(control(), adr, val, bt, adr_type, mo, needs_atomic_access);
}
// If reference is volatile, prevent following volatiles ops from
@@ -332,13 +334,23 @@
}
}
+ if (is_field) {
+ set_wrote_fields(true);
+ }
+
// If the field is final, the rules of Java say we are in <init> or <clinit>.
// Note the presence of writes to final non-static fields, so that we
// can insert a memory barrier later on to keep the writes from floating
// out of the constructor.
// Any method can write a @Stable field; insert memory barriers after those also.
if (is_field && (field->is_final() || field->is_stable())) {
- set_wrote_final(true);
+ if (field->is_final()) {
+ set_wrote_final(true);
+ }
+ if (field->is_stable()) {
+ set_wrote_stable(true);
+ }
+
// Preserve allocation ptr to create precedent edge to it in membar
// generated on exit from constructor.
if (C->eliminate_boxing() &&
--- a/hotspot/src/share/vm/runtime/globals.hpp Wed Mar 05 10:20:30 2014 +0100
+++ b/hotspot/src/share/vm/runtime/globals.hpp Wed Mar 05 01:26:52 2014 -0800
@@ -535,6 +535,9 @@
develop(bool, CleanChunkPoolAsync, falseInEmbedded, \
"Clean the chunk pool asynchronously") \
\
+ experimental(bool, AlwaysSafeConstructors, false, \
+ "Force safe construction, as if all fields are final.") \
+ \
/* Temporary: See 6948537 */ \
experimental(bool, UseMemSetInBOT, true, \
"(Unstable) uses memset in BOT updates in GC code") \
@@ -2984,7 +2987,8 @@
"maximum number of nested recursive calls that are inlined") \
\
develop(intx, MaxForceInlineLevel, 100, \
- "maximum number of nested @ForceInline calls that are inlined") \
+ "maximum number of nested calls that are forced for inlining " \
+ "(using CompilerOracle or marked w/ @ForceInline)") \
\
product_pd(intx, InlineSmallCode, \
"Only inline already compiled methods if their code size is " \
@@ -3795,8 +3799,8 @@
experimental(bool, TrustFinalNonStaticFields, false, \
"trust final non-static declarations for constant folding") \
\
- experimental(bool, FoldStableValues, false, \
- "Private flag to control optimizations for stable variables") \
+ diagnostic(bool, FoldStableValues, true, \
+ "Optimize loads from stable fields (marked w/ @Stable)") \
\
develop(bool, TraceInvokeDynamic, false, \
"trace internal invoke dynamic operations") \
@@ -3864,6 +3868,9 @@
"Allocation less than this value will be allocated " \
"using malloc. Larger allocations will use mmap.") \
\
+ experimental(bool, AlwaysAtomicAccesses, false, \
+ "Accesses to all variables should always be atomic") \
+ \
product(bool, EnableTracing, false, \
"Enable event-based tracing") \
\
--- a/hotspot/src/share/vm/runtime/thread.cpp Wed Mar 05 10:20:30 2014 +0100
+++ b/hotspot/src/share/vm/runtime/thread.cpp Wed Mar 05 01:26:52 2014 -0800
@@ -910,7 +910,7 @@
cur != VMOperationRequest_lock &&
cur != VMOperationQueue_lock) ||
cur->rank() == Mutex::special) {
- warning("Thread holding lock at safepoint that vm can block on: %s", cur->name());
+ fatal(err_msg("Thread holding lock at safepoint that vm can block on: %s", cur->name()));
}
}
}
--- a/hotspot/src/share/vm/shark/llvmHeaders.hpp Wed Mar 05 10:20:30 2014 +0100
+++ b/hotspot/src/share/vm/shark/llvmHeaders.hpp Wed Mar 05 01:26:52 2014 -0800
@@ -36,21 +36,43 @@
#endif
#include <llvm/Analysis/Verifier.h>
+#include <llvm/ExecutionEngine/ExecutionEngine.h>
+
+// includes specific to each version
+#if SHARK_LLVM_VERSION <= 31
+#include <llvm/Support/IRBuilder.h>
+#include <llvm/Type.h>
#include <llvm/Argument.h>
#include <llvm/Constants.h>
#include <llvm/DerivedTypes.h>
-#include <llvm/ExecutionEngine/ExecutionEngine.h>
#include <llvm/Instructions.h>
#include <llvm/LLVMContext.h>
#include <llvm/Module.h>
-#if SHARK_LLVM_VERSION <= 31
-#include <llvm/Support/IRBuilder.h>
-#else
+#elif SHARK_LLVM_VERSION <= 32
#include <llvm/IRBuilder.h>
+#include <llvm/Type.h>
+#include <llvm/Argument.h>
+#include <llvm/Constants.h>
+#include <llvm/DerivedTypes.h>
+#include <llvm/Instructions.h>
+#include <llvm/LLVMContext.h>
+#include <llvm/Module.h>
+#else // SHARK_LLVM_VERSION <= 34
+#include <llvm/IR/IRBuilder.h>
+#include <llvm/IR/Argument.h>
+#include <llvm/IR/Constants.h>
+#include <llvm/IR/DerivedTypes.h>
+#include <llvm/ExecutionEngine/ExecutionEngine.h>
+#include <llvm/IR/Instructions.h>
+#include <llvm/IR/LLVMContext.h>
+#include <llvm/IR/Module.h>
+#include <llvm/ADT/StringRef.h>
+#include <llvm/IR/Type.h>
#endif
+
+// common includes
#include <llvm/Support/Threading.h>
#include <llvm/Support/TargetSelect.h>
-#include <llvm/Type.h>
#include <llvm/ExecutionEngine/JITMemoryManager.h>
#include <llvm/Support/CommandLine.h>
#include <llvm/ExecutionEngine/MCJIT.h>
--- a/hotspot/src/share/vm/shark/sharkCompiler.cpp Wed Mar 05 10:20:30 2014 +0100
+++ b/hotspot/src/share/vm/shark/sharkCompiler.cpp Wed Mar 05 01:26:52 2014 -0800
@@ -364,3 +364,7 @@
*(dst++) = '\0';
return buf;
}
+
+void SharkCompiler::print_timers() {
+ // do nothing
+}
--- a/hotspot/src/share/vm/shark/sharkCompiler.hpp Wed Mar 05 10:20:30 2014 +0100
+++ b/hotspot/src/share/vm/shark/sharkCompiler.hpp Wed Mar 05 01:26:52 2014 -0800
@@ -56,6 +56,9 @@
// Compile a normal (bytecode) method and install it in the VM
void compile_method(ciEnv* env, ciMethod* target, int entry_bci);
+ // Print compilation timers and statistics
+ void print_timers();
+
// Generate a wrapper for a native (JNI) method
nmethod* generate_native_wrapper(MacroAssembler* masm,
methodHandle target,
--- a/hotspot/src/share/vm/shark/sharkInliner.cpp Wed Mar 05 10:20:30 2014 +0100
+++ b/hotspot/src/share/vm/shark/sharkInliner.cpp Wed Mar 05 01:26:52 2014 -0800
@@ -744,6 +744,10 @@
}
bool SharkInliner::attempt_inline(ciMethod *target, SharkState *state) {
+ if (!Inline) {
+ return false;
+ }
+
if (SharkIntrinsics::is_intrinsic(target)) {
SharkIntrinsics::inline_intrinsic(target, state);
return true;
--- a/hotspot/src/share/vm/shark/sharkMemoryManager.cpp Wed Mar 05 10:20:30 2014 +0100
+++ b/hotspot/src/share/vm/shark/sharkMemoryManager.cpp Wed Mar 05 01:26:52 2014 -0800
@@ -59,18 +59,6 @@
entry->set_code_limit(FunctionEnd);
}
-unsigned char* SharkMemoryManager::startExceptionTable(const Function* F,
- uintptr_t& ActualSize) {
- return mm()->startExceptionTable(F, ActualSize);
-}
-
-void SharkMemoryManager::endExceptionTable(const Function* F,
- unsigned char* TableStart,
- unsigned char* TableEnd,
- unsigned char* FrameRegister) {
- mm()->endExceptionTable(F, TableStart, TableEnd, FrameRegister);
-}
-
void SharkMemoryManager::setMemoryWritable() {
mm()->setMemoryWritable();
}
@@ -79,10 +67,6 @@
mm()->setMemoryExecutable();
}
-void SharkMemoryManager::deallocateExceptionTable(void *ptr) {
- mm()->deallocateExceptionTable(ptr);
-}
-
void SharkMemoryManager::deallocateFunctionBody(void *ptr) {
mm()->deallocateFunctionBody(ptr);
}
@@ -96,6 +80,17 @@
return mm()->getPointerToNamedFunction(Name, AbortOnFailure);
}
+void SharkMemoryManager::setPoisonMemory(bool poison) {
+ mm()->setPoisonMemory(poison);
+}
+
+unsigned char *SharkMemoryManager::allocateSpace(intptr_t Size,
+ unsigned int Alignment) {
+ return mm()->allocateSpace(Size, Alignment);
+}
+
+#if SHARK_LLVM_VERSION <= 32
+
uint8_t* SharkMemoryManager::allocateCodeSection(uintptr_t Size, unsigned Alignment, unsigned SectionID) {
return mm()->allocateCodeSection(Size, Alignment, SectionID);
}
@@ -104,11 +99,34 @@
return mm()->allocateDataSection(Size, Alignment, SectionID);
}
-void SharkMemoryManager::setPoisonMemory(bool poison) {
- mm()->setPoisonMemory(poison);
+void SharkMemoryManager::deallocateExceptionTable(void *ptr) {
+ mm()->deallocateExceptionTable(ptr);
+}
+
+unsigned char* SharkMemoryManager::startExceptionTable(const Function* F,
+ uintptr_t& ActualSize) {
+ return mm()->startExceptionTable(F, ActualSize);
+}
+
+void SharkMemoryManager::endExceptionTable(const Function* F,
+ unsigned char* TableStart,
+ unsigned char* TableEnd,
+ unsigned char* FrameRegister) {
+ mm()->endExceptionTable(F, TableStart, TableEnd, FrameRegister);
}
-unsigned char *SharkMemoryManager::allocateSpace(intptr_t Size,
- unsigned int Alignment) {
- return mm()->allocateSpace(Size, Alignment);
+#else
+
+uint8_t *SharkMemoryManager::allocateCodeSection(uintptr_t Size, unsigned Alignment, unsigned SectionID, StringRef SectionName) {
+ return mm()->allocateCodeSection(Size, Alignment, SectionID, SectionName);
}
+
+uint8_t* SharkMemoryManager::allocateDataSection(uintptr_t Size, unsigned Alignment, unsigned SectionID, StringRef SectionName, bool IsReadOnly) {
+ return mm()->allocateDataSection(Size, Alignment, SectionID, SectionName, IsReadOnly);
+}
+
+bool SharkMemoryManager::finalizeMemory(std::string *ErrMsg) {
+ return mm()->finalizeMemory(ErrMsg);
+}
+
+#endif
--- a/hotspot/src/share/vm/shark/sharkMemoryManager.hpp Wed Mar 05 10:20:30 2014 +0100
+++ b/hotspot/src/share/vm/shark/sharkMemoryManager.hpp Wed Mar 05 01:26:52 2014 -0800
@@ -69,23 +69,32 @@
void endFunctionBody(const llvm::Function* F,
unsigned char* FunctionStart,
unsigned char* FunctionEnd);
- unsigned char* startExceptionTable(const llvm::Function* F,
- uintptr_t& ActualSize);
- void endExceptionTable(const llvm::Function* F,
- unsigned char* TableStart,
- unsigned char* TableEnd,
- unsigned char* FrameRegister);
+
void *getPointerToNamedFunction(const std::string &Name, bool AbortOnFailure = true);
- uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, unsigned SectionID);
- uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, unsigned SectionID);
void setPoisonMemory(bool);
uint8_t* allocateGlobal(uintptr_t, unsigned int);
void setMemoryWritable();
void setMemoryExecutable();
- void deallocateExceptionTable(void *ptr);
void deallocateFunctionBody(void *ptr);
unsigned char *allocateSpace(intptr_t Size,
unsigned int Alignment);
+
+#if SHARK_LLVM_VERSION <= 32
+uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, unsigned SectionID);
+uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, unsigned SectionID);
+unsigned char* startExceptionTable(const llvm::Function* F,
+ uintptr_t& ActualSize);
+void deallocateExceptionTable(void *ptr);
+void endExceptionTable(const llvm::Function* F,
+ unsigned char* TableStart,
+ unsigned char* TableEnd,
+ unsigned char* FrameRegister);
+#else
+uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, unsigned SectionID, llvm::StringRef SectionName);
+uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, unsigned SectionID, llvm::StringRef SectionName, bool IsReadOnly);
+bool finalizeMemory(std::string *ErrMsg = 0);
+#endif
+
};
#endif // SHARE_VM_SHARK_SHARKMEMORYMANAGER_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/inlining/InlineDefaultMethod1.java Wed Mar 05 01:26:52 2014 -0800
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2014, 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 8036100
+ * @summary Default method returns true for a while, and then returns false
+ * @run main/othervm -Xcomp -XX:CompileOnly=InlineDefaultMethod1::test
+ * -XX:CompileOnly=I1::m -XX:CompileOnly=I2::m
+ * InlineDefaultMethod1
+ */
+interface I1 {
+ default public int m() { return 0; }
+}
+
+interface I2 extends I1 {
+ default public int m() { return 1; }
+}
+
+abstract class A implements I1 {
+}
+
+class B extends A implements I2 {
+}
+
+public class InlineDefaultMethod1 {
+ public static void test(A obj) {
+ int id = obj.m();
+ if (id != 1) {
+ throw new AssertionError("Called wrong method: 1 != "+id);
+ }
+ }
+
+ public static void main(String[] args) throws InterruptedException {
+ test(new B());
+ System.out.println("TEST PASSED");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/stable/TestStableBoolean.java Wed Mar 05 01:26:52 2014 -0800
@@ -0,0 +1,627 @@
+/*
+ * Copyright (c) 2014, 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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 TestStableBoolean
+ * @summary tests on stable fields and arrays
+ * @library /testlibrary
+ * @compile -XDignore.symbol.file TestStableBoolean.java
+ * @run main ClassFileInstaller
+ * java/lang/invoke/TestStableBoolean
+ * java/lang/invoke/TestStableBoolean$BooleanStable
+ * java/lang/invoke/TestStableBoolean$StaticBooleanStable
+ * java/lang/invoke/TestStableBoolean$VolatileBooleanStable
+ * java/lang/invoke/TestStableBoolean$BooleanArrayDim1
+ * java/lang/invoke/TestStableBoolean$BooleanArrayDim2
+ * java/lang/invoke/TestStableBoolean$BooleanArrayDim3
+ * java/lang/invoke/TestStableBoolean$BooleanArrayDim4
+ * java/lang/invoke/TestStableBoolean$ObjectArrayLowerDim0
+ * java/lang/invoke/TestStableBoolean$ObjectArrayLowerDim1
+ * java/lang/invoke/TestStableBoolean$NestedStableField
+ * java/lang/invoke/TestStableBoolean$NestedStableField$A
+ * java/lang/invoke/TestStableBoolean$NestedStableField1
+ * java/lang/invoke/TestStableBoolean$NestedStableField1$A
+ * java/lang/invoke/TestStableBoolean$NestedStableField2
+ * java/lang/invoke/TestStableBoolean$NestedStableField2$A
+ * java/lang/invoke/TestStableBoolean$NestedStableField3
+ * java/lang/invoke/TestStableBoolean$NestedStableField3$A
+ * java/lang/invoke/TestStableBoolean$DefaultValue
+ * java/lang/invoke/TestStableBoolean$ObjectArrayLowerDim2
+ *
+ * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions
+ * -XX:+UnlockDiagnosticVMOptions -XX:+FoldStableValues -XX:+UseCompressedOop
+ * -server -XX:-TieredCompilation -Xcomp
+ * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ * java.lang.invoke.TestStableBoolean
+ *
+ * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions
+ * -XX:+UnlockDiagnosticVMOptions -XX:+FoldStableValues -XX:-UseCompressedOop
+ * -server -XX:-TieredCompilation -Xcomp
+ * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ * java.lang.invoke.TestStableBoolean
+ *
+ * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions
+ * -XX:+UnlockDiagnosticVMOptions -XX:-FoldStableValues -XX:+UseCompressedOop
+ * -server -XX:-TieredCompilation -Xcomp
+ * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ * java.lang.invoke.TestStableBoolean
+ *
+ * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions
+ * -XX:+UnlockDiagnosticVMOptions -XX:-FoldStableValues -XX:-UseCompressedOop
+ * -server -XX:-TieredCompilation -Xcomp
+ * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ * java.lang.invoke.TestStableBoolean
+ */
+package java.lang.invoke;
+
+import com.sun.management.HotSpotDiagnosticMXBean;
+import com.sun.management.VMOption;
+import sun.management.ManagementFactoryHelper;
+import java.lang.reflect.InvocationTargetException;
+
+public class TestStableBoolean {
+ public static void main(String[] args) throws Exception {
+ System.out.println("@Stable enabled: "+isStableEnabled);
+ System.out.println();
+
+ run(DefaultValue.class);
+ run(BooleanStable.class);
+ run(StaticBooleanStable.class);
+ run(VolatileBooleanStable.class);
+
+ // @Stable arrays: Dim 1-4
+ run(BooleanArrayDim1.class);
+ run(BooleanArrayDim2.class);
+ run(BooleanArrayDim3.class);
+ run(BooleanArrayDim4.class);
+
+ // @Stable Object field: dynamic arrays
+ run(ObjectArrayLowerDim0.class);
+ run(ObjectArrayLowerDim1.class);
+ run(ObjectArrayLowerDim2.class);
+
+ // Nested @Stable fields
+ run(NestedStableField.class);
+ run(NestedStableField1.class);
+ run(NestedStableField2.class);
+ run(NestedStableField3.class);
+
+ if (failed) {
+ throw new Error("TEST FAILED");
+ }
+ }
+
+ /* ==================================================== */
+
+ static class DefaultValue {
+ public @Stable boolean v;
+
+ public static final DefaultValue c = new DefaultValue();
+ public static boolean get() { return c.v; }
+ public static void test() throws Exception {
+ boolean val1 = get();
+ c.v = true; boolean val2 = get();
+ assertEquals(val1, false);
+ assertEquals(val2, true);
+ }
+ }
+
+ /* ==================================================== */
+
+ static class BooleanStable {
+ public @Stable boolean v;
+
+ public static final BooleanStable c = new BooleanStable();
+ public static boolean get() { return c.v; }
+ public static void test() throws Exception {
+ c.v = true; boolean val1 = get();
+ c.v = false; boolean val2 = get();
+ assertEquals(val1, true);
+ assertEquals(val2, (isStableEnabled ? true : false));
+ }
+ }
+
+ /* ==================================================== */
+
+ static class StaticBooleanStable {
+ public static @Stable boolean v;
+
+ public static final StaticBooleanStable c = new StaticBooleanStable();
+ public static boolean get() { return c.v; }
+ public static void test() throws Exception {
+ c.v = true; boolean val1 = get();
+ c.v = false; boolean val2 = get();
+ assertEquals(val1, true);
+ assertEquals(val2, (isStableEnabled ? true : false));
+ }
+ }
+
+ /* ==================================================== */
+
+ static class VolatileBooleanStable {
+ public @Stable volatile boolean v;
+
+ public static final VolatileBooleanStable c = new VolatileBooleanStable();
+ public static boolean get() { return c.v; }
+ public static void test() throws Exception {
+ c.v = true; boolean val1 = get();
+ c.v = false; boolean val2 = get();
+ assertEquals(val1, true);
+ assertEquals(val2, (isStableEnabled ? true : false));
+ }
+ }
+
+ /* ==================================================== */
+ // @Stable array == field && all components are stable
+
+ static class BooleanArrayDim1 {
+ public @Stable boolean[] v;
+
+ public static final BooleanArrayDim1 c = new BooleanArrayDim1();
+ public static boolean get() { return c.v[0]; }
+ public static boolean get1() { return c.v[10]; }
+ public static boolean[] get2() { return c.v; }
+ public static void test() throws Exception {
+ {
+ c.v = new boolean[1]; c.v[0] = true; boolean val1 = get();
+ c.v[0] = false; boolean val2 = get();
+ assertEquals(val1, true);
+ assertEquals(val2, (isStableEnabled ? true : false));
+ }
+
+ {
+ c.v = new boolean[20]; c.v[10] = true; boolean val1 = get1();
+ c.v[10] = false; boolean val2 = get1();
+ assertEquals(val1, true);
+ assertEquals(val2, (isStableEnabled ? true : false));
+ }
+
+ {
+ c.v = new boolean[1]; boolean[] val1 = get2();
+ c.v = new boolean[1]; boolean[] val2 = get2();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class BooleanArrayDim2 {
+ public @Stable boolean[][] v;
+
+ public static final BooleanArrayDim2 c = new BooleanArrayDim2();
+ public static boolean get() { return c.v[0][0]; }
+ public static boolean[] get1() { return c.v[0]; }
+ public static boolean[][] get2() { return c.v; }
+ public static void test() throws Exception {
+ {
+ c.v = new boolean[1][1]; c.v[0][0] = true; boolean val1 = get();
+ c.v[0][0] = false; boolean val2 = get();
+ assertEquals(val1, true);
+ assertEquals(val2, (isStableEnabled ? true : false));
+
+ c.v = new boolean[1][1]; c.v[0][0] = false; boolean val3 = get();
+ assertEquals(val3, (isStableEnabled ? true : false));
+
+ c.v[0] = new boolean[1]; c.v[0][0] = false; boolean val4 = get();
+ assertEquals(val4, (isStableEnabled ? true : false));
+ }
+
+ {
+ c.v = new boolean[1][1]; boolean[] val1 = get1();
+ c.v[0] = new boolean[1]; boolean[] val2 = get1();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new boolean[1][1]; boolean[][] val1 = get2();
+ c.v = new boolean[1][1]; boolean[][] val2 = get2();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class BooleanArrayDim3 {
+ public @Stable boolean[][][] v;
+
+ public static final BooleanArrayDim3 c = new BooleanArrayDim3();
+ public static boolean get() { return c.v[0][0][0]; }
+ public static boolean[] get1() { return c.v[0][0]; }
+ public static boolean[][] get2() { return c.v[0]; }
+ public static boolean[][][] get3() { return c.v; }
+ public static void test() throws Exception {
+ {
+ c.v = new boolean[1][1][1]; c.v[0][0][0] = true; boolean val1 = get();
+ c.v[0][0][0] = false; boolean val2 = get();
+ assertEquals(val1, true);
+ assertEquals(val2, (isStableEnabled ? true : false));
+
+ c.v = new boolean[1][1][1]; c.v[0][0][0] = false; boolean val3 = get();
+ assertEquals(val3, (isStableEnabled ? true : false));
+
+ c.v[0] = new boolean[1][1]; c.v[0][0][0] = false; boolean val4 = get();
+ assertEquals(val4, (isStableEnabled ? true : false));
+
+ c.v[0][0] = new boolean[1]; c.v[0][0][0] = false; boolean val5 = get();
+ assertEquals(val5, (isStableEnabled ? true : false));
+ }
+
+ {
+ c.v = new boolean[1][1][1]; boolean[] val1 = get1();
+ c.v[0][0] = new boolean[1]; boolean[] val2 = get1();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new boolean[1][1][1]; boolean[][] val1 = get2();
+ c.v[0] = new boolean[1][1]; boolean[][] val2 = get2();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new boolean[1][1][1]; boolean[][][] val1 = get3();
+ c.v = new boolean[1][1][1]; boolean[][][] val2 = get3();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class BooleanArrayDim4 {
+ public @Stable boolean[][][][] v;
+
+ public static final BooleanArrayDim4 c = new BooleanArrayDim4();
+ public static boolean get() { return c.v[0][0][0][0]; }
+ public static boolean[] get1() { return c.v[0][0][0]; }
+ public static boolean[][] get2() { return c.v[0][0]; }
+ public static boolean[][][] get3() { return c.v[0]; }
+ public static boolean[][][][] get4() { return c.v; }
+ public static void test() throws Exception {
+ {
+ c.v = new boolean[1][1][1][1]; c.v[0][0][0][0] = true; boolean val1 = get();
+ c.v[0][0][0][0] = false; boolean val2 = get();
+ assertEquals(val1, true);
+ assertEquals(val2, (isStableEnabled ? true : false));
+
+ c.v = new boolean[1][1][1][1]; c.v[0][0][0][0] = false; boolean val3 = get();
+ assertEquals(val3, (isStableEnabled ? true : false));
+
+ c.v[0] = new boolean[1][1][1]; c.v[0][0][0][0] = false; boolean val4 = get();
+ assertEquals(val4, (isStableEnabled ? true : false));
+
+ c.v[0][0] = new boolean[1][1]; c.v[0][0][0][0] = false; boolean val5 = get();
+ assertEquals(val5, (isStableEnabled ? true : false));
+
+ c.v[0][0][0] = new boolean[1]; c.v[0][0][0][0] = false; boolean val6 = get();
+ assertEquals(val6, (isStableEnabled ? true : false));
+ }
+
+ {
+ c.v = new boolean[1][1][1][1]; boolean[] val1 = get1();
+ c.v[0][0][0] = new boolean[1]; boolean[] val2 = get1();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new boolean[1][1][1][1]; boolean[][] val1 = get2();
+ c.v[0][0] = new boolean[1][1]; boolean[][] val2 = get2();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new boolean[1][1][1][1]; boolean[][][] val1 = get3();
+ c.v[0] = new boolean[1][1][1]; boolean[][][] val2 = get3();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new boolean[1][1][1][1]; boolean[][][][] val1 = get4();
+ c.v = new boolean[1][1][1][1]; boolean[][][][] val2 = get4();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ }
+ }
+
+ /* ==================================================== */
+ // Dynamic Dim is higher than static
+
+ static class ObjectArrayLowerDim0 {
+ public @Stable Object v;
+
+ public static final ObjectArrayLowerDim0 c = new ObjectArrayLowerDim0();
+ public static boolean get() { return ((boolean[])c.v)[0]; }
+ public static boolean[] get1() { return (boolean[])c.v; }
+ public static boolean[] get2() { return (boolean[])c.v; }
+
+ public static void test() throws Exception {
+ {
+ c.v = new boolean[1]; ((boolean[])c.v)[0] = true; boolean val1 = get();
+ ((boolean[])c.v)[0] = false; boolean val2 = get();
+
+ assertEquals(val1, true);
+ assertEquals(val2, false);
+ }
+
+ {
+ c.v = new boolean[1]; boolean[] val1 = get1();
+ c.v = new boolean[1]; boolean[] val2 = get1();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class ObjectArrayLowerDim1 {
+ public @Stable Object[] v;
+
+ public static final ObjectArrayLowerDim1 c = new ObjectArrayLowerDim1();
+ public static boolean get() { return ((boolean[][])c.v)[0][0]; }
+ public static boolean[] get1() { return (boolean[])(c.v[0]); }
+ public static Object[] get2() { return c.v; }
+
+ public static void test() throws Exception {
+ {
+ c.v = new boolean[1][1]; ((boolean[][])c.v)[0][0] = true; boolean val1 = get();
+ ((boolean[][])c.v)[0][0] = false; boolean val2 = get();
+
+ assertEquals(val1, true);
+ assertEquals(val2, false);
+ }
+
+ {
+ c.v = new boolean[1][1]; c.v[0] = new boolean[0]; boolean[] val1 = get1();
+ c.v[0] = new boolean[0]; boolean[] val2 = get1();
+
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new boolean[0][0]; Object[] val1 = get2();
+ c.v = new boolean[0][0]; Object[] val2 = get2();
+
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class ObjectArrayLowerDim2 {
+ public @Stable Object[][] v;
+
+ public static final ObjectArrayLowerDim2 c = new ObjectArrayLowerDim2();
+ public static boolean get() { return ((boolean[][][])c.v)[0][0][0]; }
+ public static boolean[] get1() { return (boolean[])(c.v[0][0]); }
+ public static boolean[][] get2() { return (boolean[][])(c.v[0]); }
+ public static Object[][] get3() { return c.v; }
+
+ public static void test() throws Exception {
+ {
+ c.v = new boolean[1][1][1]; ((boolean[][][])c.v)[0][0][0] = true; boolean val1 = get();
+ ((boolean[][][])c.v)[0][0][0] = false; boolean val2 = get();
+
+ assertEquals(val1, true);
+ assertEquals(val2, false);
+ }
+
+ {
+ c.v = new boolean[1][1][1]; c.v[0][0] = new boolean[0]; boolean[] val1 = get1();
+ c.v[0][0] = new boolean[0]; boolean[] val2 = get1();
+
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new boolean[1][1][1]; c.v[0] = new boolean[0][0]; boolean[][] val1 = get2();
+ c.v[0] = new boolean[0][0]; boolean[][] val2 = get2();
+
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new boolean[0][0][0]; Object[][] val1 = get3();
+ c.v = new boolean[0][0][0]; Object[][] val2 = get3();
+
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class NestedStableField {
+ static class A {
+ public @Stable boolean a;
+
+ }
+ public @Stable A v;
+
+ public static final NestedStableField c = new NestedStableField();
+ public static A get() { return c.v; }
+ public static boolean get1() { return get().a; }
+
+ public static void test() throws Exception {
+ {
+ c.v = new A(); c.v.a = true; A val1 = get();
+ c.v.a = false; A val2 = get();
+
+ assertEquals(val1.a, false);
+ assertEquals(val2.a, false);
+ }
+
+ {
+ c.v = new A(); c.v.a = true; boolean val1 = get1();
+ c.v.a = false; boolean val2 = get1();
+ c.v = new A(); c.v.a = false; boolean val3 = get1();
+
+ assertEquals(val1, true);
+ assertEquals(val2, (isStableEnabled ? true : false));
+ assertEquals(val3, (isStableEnabled ? true : false));
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class NestedStableField1 {
+ static class A {
+ public @Stable boolean a;
+ public @Stable A next;
+ }
+ public @Stable A v;
+
+ public static final NestedStableField1 c = new NestedStableField1();
+ public static A get() { return c.v.next.next.next.next.next.next.next; }
+ public static boolean get1() { return get().a; }
+
+ public static void test() throws Exception {
+ {
+ c.v = new A(); c.v.next = new A(); c.v.next.next = c.v;
+ c.v.a = true; c.v.next.a = true; A val1 = get();
+ c.v.a = false; c.v.next.a = false; A val2 = get();
+
+ assertEquals(val1.a, false);
+ assertEquals(val2.a, false);
+ }
+
+ {
+ c.v = new A(); c.v.next = c.v;
+ c.v.a = true; boolean val1 = get1();
+ c.v.a = false; boolean val2 = get1();
+ c.v = new A(); c.v.next = c.v;
+ c.v.a = false; boolean val3 = get1();
+
+ assertEquals(val1, true);
+ assertEquals(val2, (isStableEnabled ? true : false));
+ assertEquals(val3, (isStableEnabled ? true : false));
+ }
+ }
+ }
+ /* ==================================================== */
+
+ static class NestedStableField2 {
+ static class A {
+ public @Stable boolean a;
+ public @Stable A left;
+ public A right;
+ }
+
+ public @Stable A v;
+
+ public static final NestedStableField2 c = new NestedStableField2();
+ public static boolean get() { return c.v.left.left.left.a; }
+ public static boolean get1() { return c.v.left.left.right.left.a; }
+
+ public static void test() throws Exception {
+ {
+ c.v = new A(); c.v.left = c.v.right = c.v;
+ c.v.a = true; boolean val1 = get(); boolean val2 = get1();
+ c.v.a = false; boolean val3 = get(); boolean val4 = get1();
+
+ assertEquals(val1, true);
+ assertEquals(val3, (isStableEnabled ? true : false));
+
+ assertEquals(val2, true);
+ assertEquals(val4, false);
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class NestedStableField3 {
+ static class A {
+ public @Stable boolean a;
+ public @Stable A[] left;
+ public A[] right;
+ }
+
+ public @Stable A[] v;
+
+ public static final NestedStableField3 c = new NestedStableField3();
+ public static boolean get() { return c.v[0].left[1].left[0].left[1].a; }
+ public static boolean get1() { return c.v[1].left[0].left[1].right[0].left[1].a; }
+
+ public static void test() throws Exception {
+ {
+ A elem = new A();
+ c.v = new A[] { elem, elem }; c.v[0].left = c.v[0].right = c.v;
+ elem.a = true; boolean val1 = get(); boolean val2 = get1();
+ elem.a = false; boolean val3 = get(); boolean val4 = get1();
+
+ assertEquals(val1, true);
+ assertEquals(val3, (isStableEnabled ? true : false));
+
+ assertEquals(val2, true);
+ assertEquals(val4, false);
+ }
+ }
+ }
+
+ /* ==================================================== */
+ // Auxiliary methods
+ static void assertEquals(boolean i, boolean j) { if (i != j) throw new AssertionError(i + " != " + j); }
+ static void assertTrue(boolean b) { if (!b) throw new AssertionError(); }
+
+ static boolean failed = false;
+
+ public static void run(Class<?> test) {
+ Throwable ex = null;
+ System.out.print(test.getName()+": ");
+ try {
+ test.getMethod("test").invoke(null);
+ } catch (InvocationTargetException e) {
+ ex = e.getCause();
+ } catch (Throwable e) {
+ ex = e;
+ } finally {
+ if (ex == null) {
+ System.out.println("PASSED");
+ } else {
+ failed = true;
+ System.out.println("FAILED");
+ ex.printStackTrace(System.out);
+ }
+ }
+ }
+
+ static final boolean isStableEnabled;
+ static {
+ HotSpotDiagnosticMXBean diagnostic
+ = ManagementFactoryHelper.getDiagnosticMXBean();
+ VMOption tmp;
+ try {
+ tmp = diagnostic.getVMOption("FoldStableValues");
+ } catch (IllegalArgumentException e) {
+ tmp = null;
+ }
+ isStableEnabled = (tmp == null ? false : Boolean.parseBoolean(tmp.getValue()));
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/stable/TestStableByte.java Wed Mar 05 01:26:52 2014 -0800
@@ -0,0 +1,632 @@
+/*
+ * Copyright (c) 2014, 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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 TestStableByte
+ * @summary tests on stable fields and arrays
+ * @library /testlibrary
+ * @compile -XDignore.symbol.file TestStableByte.java
+ * @run main ClassFileInstaller
+ * java/lang/invoke/TestStableByte
+ * java/lang/invoke/TestStableByte$ByteStable
+ * java/lang/invoke/TestStableByte$StaticByteStable
+ * java/lang/invoke/TestStableByte$VolatileByteStable
+ * java/lang/invoke/TestStableByte$ByteArrayDim1
+ * java/lang/invoke/TestStableByte$ByteArrayDim2
+ * java/lang/invoke/TestStableByte$ByteArrayDim3
+ * java/lang/invoke/TestStableByte$ByteArrayDim4
+ * java/lang/invoke/TestStableByte$ObjectArrayLowerDim0
+ * java/lang/invoke/TestStableByte$ObjectArrayLowerDim1
+ * java/lang/invoke/TestStableByte$NestedStableField
+ * java/lang/invoke/TestStableByte$NestedStableField$A
+ * java/lang/invoke/TestStableByte$NestedStableField1
+ * java/lang/invoke/TestStableByte$NestedStableField1$A
+ * java/lang/invoke/TestStableByte$NestedStableField2
+ * java/lang/invoke/TestStableByte$NestedStableField2$A
+ * java/lang/invoke/TestStableByte$NestedStableField3
+ * java/lang/invoke/TestStableByte$NestedStableField3$A
+ * java/lang/invoke/TestStableByte$DefaultValue
+ * java/lang/invoke/TestStableByte$ObjectArrayLowerDim2
+ *
+ * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions
+ * -XX:+UnlockDiagnosticVMOptions -XX:+FoldStableValues -XX:+UseCompressedOop
+ * -server -XX:-TieredCompilation -Xcomp
+ * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ * java.lang.invoke.TestStableByte
+ *
+ * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions
+ * -XX:+UnlockDiagnosticVMOptions -XX:+FoldStableValues -XX:-UseCompressedOop
+ * -server -XX:-TieredCompilation -Xcomp
+ * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ * java.lang.invoke.TestStableByte
+ *
+ * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions
+ * -XX:+UnlockDiagnosticVMOptions -XX:-FoldStableValues -XX:+UseCompressedOop
+ * -server -XX:-TieredCompilation -Xcomp
+ * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ * java.lang.invoke.TestStableByte
+ *
+ * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions
+ * -XX:+UnlockDiagnosticVMOptions -XX:-FoldStableValues -XX:-UseCompressedOop
+ * -server -XX:-TieredCompilation -Xcomp
+ * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ * java.lang.invoke.TestStableByte
+ */
+package java.lang.invoke;
+
+import com.sun.management.HotSpotDiagnosticMXBean;
+import com.sun.management.VMOption;
+import sun.management.ManagementFactoryHelper;
+import java.lang.reflect.InvocationTargetException;
+
+public class TestStableByte {
+ public static void main(String[] args) throws Exception {
+ System.out.println("@Stable enabled: "+isStableEnabled);
+ System.out.println();
+
+ run(DefaultValue.class);
+ run(ByteStable.class);
+ run(StaticByteStable.class);
+ run(VolatileByteStable.class);
+
+ // @Stable arrays: Dim 1-4
+ run(ByteArrayDim1.class);
+ run(ByteArrayDim2.class);
+ run(ByteArrayDim3.class);
+ run(ByteArrayDim4.class);
+
+ // @Stable Object field: dynamic arrays
+ run(ObjectArrayLowerDim0.class);
+ run(ObjectArrayLowerDim1.class);
+ run(ObjectArrayLowerDim2.class);
+
+ // Nested @Stable fields
+ run(NestedStableField.class);
+ run(NestedStableField1.class);
+ run(NestedStableField2.class);
+ run(NestedStableField3.class);
+
+ if (failed) {
+ throw new Error("TEST FAILED");
+ }
+ }
+
+ /* ==================================================== */
+
+ static class DefaultValue {
+ public @Stable byte v;
+
+ public static final DefaultValue c = new DefaultValue();
+ public static byte get() { return c.v; }
+ public static void test() throws Exception {
+ byte val1 = get();
+ c.v = 1; byte val2 = get();
+ assertEquals(val1, 0);
+ assertEquals(val2, 1);
+ }
+ }
+
+ /* ==================================================== */
+
+ static class ByteStable {
+ public @Stable byte v;
+
+ public static final ByteStable c = new ByteStable();
+ public static byte get() { return c.v; }
+ public static void test() throws Exception {
+ c.v = 5; byte val1 = get();
+ c.v = 127; byte val2 = get();
+ assertEquals(val1, 5);
+ assertEquals(val2, (isStableEnabled ? 5 : 127));
+ }
+ }
+
+ /* ==================================================== */
+
+ static class StaticByteStable {
+ public static @Stable byte v;
+
+ public static final StaticByteStable c = new StaticByteStable();
+ public static byte get() { return c.v; }
+ public static void test() throws Exception {
+ c.v = 5; byte val1 = get();
+ c.v = 127; byte val2 = get();
+ assertEquals(val1, 5);
+ assertEquals(val2, (isStableEnabled ? 5 : 127));
+ }
+ }
+
+ /* ==================================================== */
+
+ static class VolatileByteStable {
+ public @Stable volatile byte v;
+
+ public static final VolatileByteStable c = new VolatileByteStable();
+ public static byte get() { return c.v; }
+ public static void test() throws Exception {
+ c.v = 5; byte val1 = get();
+ c.v = 127; byte val2 = get();
+ assertEquals(val1, 5);
+ assertEquals(val2, (isStableEnabled ? 5 : 127));
+ }
+ }
+
+ /* ==================================================== */
+ // @Stable array == field && all components are stable
+
+ static class ByteArrayDim1 {
+ public @Stable byte[] v;
+
+ public static final ByteArrayDim1 c = new ByteArrayDim1();
+ public static byte get() { return c.v[0]; }
+ public static byte get1() { return c.v[10]; }
+ public static byte[] get2() { return c.v; }
+ public static void test() throws Exception {
+ {
+ c.v = new byte[1]; c.v[0] = 1; byte val1 = get();
+ c.v[0] = 2; byte val2 = get();
+ assertEquals(val1, 1);
+ assertEquals(val2, (isStableEnabled ? 1 : 2));
+
+ c.v = new byte[1]; c.v[0] = 3; byte val3 = get();
+ assertEquals(val3, (isStableEnabled ? 1 : 3));
+ }
+
+ {
+ c.v = new byte[20]; c.v[10] = 1; byte val1 = get1();
+ c.v[10] = 2; byte val2 = get1();
+ assertEquals(val1, 1);
+ assertEquals(val2, (isStableEnabled ? 1 : 2));
+
+ c.v = new byte[20]; c.v[10] = 3; byte val3 = get1();
+ assertEquals(val3, (isStableEnabled ? 1 : 3));
+ }
+
+ {
+ c.v = new byte[1]; byte[] val1 = get2();
+ c.v = new byte[1]; byte[] val2 = get2();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class ByteArrayDim2 {
+ public @Stable byte[][] v;
+
+ public static final ByteArrayDim2 c = new ByteArrayDim2();
+ public static byte get() { return c.v[0][0]; }
+ public static byte[] get1() { return c.v[0]; }
+ public static byte[][] get2() { return c.v; }
+ public static void test() throws Exception {
+ {
+ c.v = new byte[1][1]; c.v[0][0] = 1; byte val1 = get();
+ c.v[0][0] = 2; byte val2 = get();
+ assertEquals(val1, 1);
+ assertEquals(val2, (isStableEnabled ? 1 : 2));
+
+ c.v = new byte[1][1]; c.v[0][0] = 3; byte val3 = get();
+ assertEquals(val3, (isStableEnabled ? 1 : 3));
+
+ c.v[0] = new byte[1]; c.v[0][0] = 4; byte val4 = get();
+ assertEquals(val4, (isStableEnabled ? 1 : 4));
+ }
+
+ {
+ c.v = new byte[1][1]; byte[] val1 = get1();
+ c.v[0] = new byte[1]; byte[] val2 = get1();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new byte[1][1]; byte[][] val1 = get2();
+ c.v = new byte[1][1]; byte[][] val2 = get2();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class ByteArrayDim3 {
+ public @Stable byte[][][] v;
+
+ public static final ByteArrayDim3 c = new ByteArrayDim3();
+ public static byte get() { return c.v[0][0][0]; }
+ public static byte[] get1() { return c.v[0][0]; }
+ public static byte[][] get2() { return c.v[0]; }
+ public static byte[][][] get3() { return c.v; }
+ public static void test() throws Exception {
+ {
+ c.v = new byte[1][1][1]; c.v[0][0][0] = 1; byte val1 = get();
+ c.v[0][0][0] = 2; byte val2 = get();
+ assertEquals(val1, 1);
+ assertEquals(val2, (isStableEnabled ? 1 : 2));
+
+ c.v = new byte[1][1][1]; c.v[0][0][0] = 3; byte val3 = get();
+ assertEquals(val3, (isStableEnabled ? 1 : 3));
+
+ c.v[0] = new byte[1][1]; c.v[0][0][0] = 4; byte val4 = get();
+ assertEquals(val4, (isStableEnabled ? 1 : 4));
+
+ c.v[0][0] = new byte[1]; c.v[0][0][0] = 5; byte val5 = get();
+ assertEquals(val5, (isStableEnabled ? 1 : 5));
+ }
+
+ {
+ c.v = new byte[1][1][1]; byte[] val1 = get1();
+ c.v[0][0] = new byte[1]; byte[] val2 = get1();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new byte[1][1][1]; byte[][] val1 = get2();
+ c.v[0] = new byte[1][1]; byte[][] val2 = get2();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new byte[1][1][1]; byte[][][] val1 = get3();
+ c.v = new byte[1][1][1]; byte[][][] val2 = get3();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class ByteArrayDim4 {
+ public @Stable byte[][][][] v;
+
+ public static final ByteArrayDim4 c = new ByteArrayDim4();
+ public static byte get() { return c.v[0][0][0][0]; }
+ public static byte[] get1() { return c.v[0][0][0]; }
+ public static byte[][] get2() { return c.v[0][0]; }
+ public static byte[][][] get3() { return c.v[0]; }
+ public static byte[][][][] get4() { return c.v; }
+ public static void test() throws Exception {
+ {
+ c.v = new byte[1][1][1][1]; c.v[0][0][0][0] = 1; byte val1 = get();
+ c.v[0][0][0][0] = 2; byte val2 = get();
+ assertEquals(val1, 1);
+ assertEquals(val2, (isStableEnabled ? 1 : 2));
+
+ c.v = new byte[1][1][1][1]; c.v[0][0][0][0] = 3; byte val3 = get();
+ assertEquals(val3, (isStableEnabled ? 1 : 3));
+
+ c.v[0] = new byte[1][1][1]; c.v[0][0][0][0] = 4; byte val4 = get();
+ assertEquals(val4, (isStableEnabled ? 1 : 4));
+
+ c.v[0][0] = new byte[1][1]; c.v[0][0][0][0] = 5; byte val5 = get();
+ assertEquals(val5, (isStableEnabled ? 1 : 5));
+
+ c.v[0][0][0] = new byte[1]; c.v[0][0][0][0] = 6; byte val6 = get();
+ assertEquals(val6, (isStableEnabled ? 1 : 6));
+ }
+
+ {
+ c.v = new byte[1][1][1][1]; byte[] val1 = get1();
+ c.v[0][0][0] = new byte[1]; byte[] val2 = get1();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new byte[1][1][1][1]; byte[][] val1 = get2();
+ c.v[0][0] = new byte[1][1]; byte[][] val2 = get2();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new byte[1][1][1][1]; byte[][][] val1 = get3();
+ c.v[0] = new byte[1][1][1]; byte[][][] val2 = get3();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new byte[1][1][1][1]; byte[][][][] val1 = get4();
+ c.v = new byte[1][1][1][1]; byte[][][][] val2 = get4();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ }
+ }
+
+ /* ==================================================== */
+ // Dynamic Dim is higher than static
+
+ static class ObjectArrayLowerDim0 {
+ public @Stable Object v;
+
+ public static final ObjectArrayLowerDim0 c = new ObjectArrayLowerDim0();
+ public static byte get() { return ((byte[])c.v)[0]; }
+ public static byte[] get1() { return (byte[])c.v; }
+
+ public static void test() throws Exception {
+ {
+ c.v = new byte[1]; ((byte[])c.v)[0] = 1; byte val1 = get();
+ ((byte[])c.v)[0] = 2; byte val2 = get();
+
+ assertEquals(val1, 1);
+ assertEquals(val2, 2);
+ }
+
+ {
+ c.v = new byte[1]; byte[] val1 = get1();
+ c.v = new byte[1]; byte[] val2 = get1();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class ObjectArrayLowerDim1 {
+ public @Stable Object[] v;
+
+ public static final ObjectArrayLowerDim1 c = new ObjectArrayLowerDim1();
+ public static byte get() { return ((byte[][])c.v)[0][0]; }
+ public static byte[] get1() { return (byte[])(c.v[0]); }
+ public static Object[] get2() { return c.v; }
+
+ public static void test() throws Exception {
+ {
+ c.v = new byte[1][1]; ((byte[][])c.v)[0][0] = 1; byte val1 = get();
+ ((byte[][])c.v)[0][0] = 2; byte val2 = get();
+
+ assertEquals(val1, 1);
+ assertEquals(val2, 2);
+ }
+
+ {
+ c.v = new byte[1][1]; c.v[0] = new byte[0]; byte[] val1 = get1();
+ c.v[0] = new byte[0]; byte[] val2 = get1();
+
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new byte[0][0]; Object[] val1 = get2();
+ c.v = new byte[0][0]; Object[] val2 = get2();
+
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class ObjectArrayLowerDim2 {
+ public @Stable Object[][] v;
+
+ public static final ObjectArrayLowerDim2 c = new ObjectArrayLowerDim2();
+ public static byte get() { return ((byte[][][])c.v)[0][0][0]; }
+ public static byte[] get1() { return (byte[])(c.v[0][0]); }
+ public static byte[][] get2() { return (byte[][])(c.v[0]); }
+ public static Object[][] get3() { return c.v; }
+
+ public static void test() throws Exception {
+ {
+ c.v = new byte[1][1][1]; ((byte[][][])c.v)[0][0][0] = 1; byte val1 = get();
+ ((byte[][][])c.v)[0][0][0] = 2; byte val2 = get();
+
+ assertEquals(val1, 1);
+ assertEquals(val2, 2);
+ }
+
+ {
+ c.v = new byte[1][1][1]; c.v[0][0] = new byte[0]; byte[] val1 = get1();
+ c.v[0][0] = new byte[0]; byte[] val2 = get1();
+
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new byte[1][1][1]; c.v[0] = new byte[0][0]; byte[][] val1 = get2();
+ c.v[0] = new byte[0][0]; byte[][] val2 = get2();
+
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new byte[0][0][0]; Object[][] val1 = get3();
+ c.v = new byte[0][0][0]; Object[][] val2 = get3();
+
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class NestedStableField {
+ static class A {
+ public @Stable byte a;
+
+ }
+ public @Stable A v;
+
+ public static final NestedStableField c = new NestedStableField();
+ public static A get() { return c.v; }
+ public static byte get1() { return get().a; }
+
+ public static void test() throws Exception {
+ {
+ c.v = new A(); c.v.a = 1; A val1 = get();
+ c.v.a = 2; A val2 = get();
+
+ assertEquals(val1.a, 2);
+ assertEquals(val2.a, 2);
+ }
+
+ {
+ c.v = new A(); c.v.a = 1; byte val1 = get1();
+ c.v.a = 2; byte val2 = get1();
+ c.v = new A(); c.v.a = 3; byte val3 = get1();
+
+ assertEquals(val1, 1);
+ assertEquals(val2, (isStableEnabled ? 1 : 2));
+ assertEquals(val3, (isStableEnabled ? 1 : 3));
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class NestedStableField1 {
+ static class A {
+ public @Stable byte a;
+ public @Stable A next;
+ }
+ public @Stable A v;
+
+ public static final NestedStableField1 c = new NestedStableField1();
+ public static A get() { return c.v.next.next.next.next.next.next.next; }
+ public static byte get1() { return get().a; }
+
+ public static void test() throws Exception {
+ {
+ c.v = new A(); c.v.next = new A(); c.v.next.next = c.v;
+ c.v.a = 1; c.v.next.a = 1; A val1 = get();
+ c.v.a = 2; c.v.next.a = 2; A val2 = get();
+
+ assertEquals(val1.a, 2);
+ assertEquals(val2.a, 2);
+ }
+
+ {
+ c.v = new A(); c.v.next = c.v;
+ c.v.a = 1; byte val1 = get1();
+ c.v.a = 2; byte val2 = get1();
+ c.v = new A(); c.v.next = c.v;
+ c.v.a = 3; byte val3 = get1();
+
+ assertEquals(val1, 1);
+ assertEquals(val2, (isStableEnabled ? 1 : 2));
+ assertEquals(val3, (isStableEnabled ? 1 : 3));
+ }
+ }
+ }
+ /* ==================================================== */
+
+ static class NestedStableField2 {
+ static class A {
+ public @Stable byte a;
+ public @Stable A left;
+ public A right;
+ }
+
+ public @Stable A v;
+
+ public static final NestedStableField2 c = new NestedStableField2();
+ public static byte get() { return c.v.left.left.left.a; }
+ public static byte get1() { return c.v.left.left.right.left.a; }
+
+ public static void test() throws Exception {
+ {
+ c.v = new A(); c.v.left = c.v.right = c.v;
+ c.v.a = 1; byte val1 = get(); byte val2 = get1();
+ c.v.a = 2; byte val3 = get(); byte val4 = get1();
+
+ assertEquals(val1, 1);
+ assertEquals(val3, (isStableEnabled ? 1 : 2));
+
+ assertEquals(val2, 1);
+ assertEquals(val4, 2);
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class NestedStableField3 {
+ static class A {
+ public @Stable byte a;
+ public @Stable A[] left;
+ public A[] right;
+ }
+
+ public @Stable A[] v;
+
+ public static final NestedStableField3 c = new NestedStableField3();
+ public static byte get() { return c.v[0].left[1].left[0].left[1].a; }
+ public static byte get1() { return c.v[1].left[0].left[1].right[0].left[1].a; }
+
+ public static void test() throws Exception {
+ {
+ A elem = new A();
+ c.v = new A[] { elem, elem }; c.v[0].left = c.v[0].right = c.v;
+ elem.a = 1; byte val1 = get(); byte val2 = get1();
+ elem.a = 2; byte val3 = get(); byte val4 = get1();
+
+ assertEquals(val1, 1);
+ assertEquals(val3, (isStableEnabled ? 1 : 2));
+
+ assertEquals(val2, 1);
+ assertEquals(val4, 2);
+ }
+ }
+ }
+
+ /* ==================================================== */
+ // Auxiliary methods
+ static void assertEquals(int i, int j) { if (i != j) throw new AssertionError(i + " != " + j); }
+ static void assertTrue(boolean b) { if (!b) throw new AssertionError(); }
+
+ static boolean failed = false;
+
+ public static void run(Class<?> test) {
+ Throwable ex = null;
+ System.out.print(test.getName()+": ");
+ try {
+ test.getMethod("test").invoke(null);
+ } catch (InvocationTargetException e) {
+ ex = e.getCause();
+ } catch (Throwable e) {
+ ex = e;
+ } finally {
+ if (ex == null) {
+ System.out.println("PASSED");
+ } else {
+ failed = true;
+ System.out.println("FAILED");
+ ex.printStackTrace(System.out);
+ }
+ }
+ }
+
+ static final boolean isStableEnabled;
+ static {
+ HotSpotDiagnosticMXBean diagnostic
+ = ManagementFactoryHelper.getDiagnosticMXBean();
+ VMOption tmp;
+ try {
+ tmp = diagnostic.getVMOption("FoldStableValues");
+ } catch (IllegalArgumentException e) {
+ tmp = null;
+ }
+ isStableEnabled = (tmp == null ? false : Boolean.parseBoolean(tmp.getValue()));
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/stable/TestStableChar.java Wed Mar 05 01:26:52 2014 -0800
@@ -0,0 +1,631 @@
+/*
+ * Copyright (c) 2014, 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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 TestStableChar
+ * @summary tests on stable fields and arrays
+ * @library /testlibrary
+ * @compile -XDignore.symbol.file TestStableChar.java
+ * @run main ClassFileInstaller
+ * java/lang/invoke/TestStableChar
+ * java/lang/invoke/TestStableChar$CharStable
+ * java/lang/invoke/TestStableChar$StaticCharStable
+ * java/lang/invoke/TestStableChar$VolatileCharStable
+ * java/lang/invoke/TestStableChar$CharArrayDim1
+ * java/lang/invoke/TestStableChar$CharArrayDim2
+ * java/lang/invoke/TestStableChar$CharArrayDim3
+ * java/lang/invoke/TestStableChar$CharArrayDim4
+ * java/lang/invoke/TestStableChar$ObjectArrayLowerDim0
+ * java/lang/invoke/TestStableChar$ObjectArrayLowerDim1
+ * java/lang/invoke/TestStableChar$NestedStableField
+ * java/lang/invoke/TestStableChar$NestedStableField$A
+ * java/lang/invoke/TestStableChar$NestedStableField1
+ * java/lang/invoke/TestStableChar$NestedStableField1$A
+ * java/lang/invoke/TestStableChar$NestedStableField2
+ * java/lang/invoke/TestStableChar$NestedStableField2$A
+ * java/lang/invoke/TestStableChar$NestedStableField3
+ * java/lang/invoke/TestStableChar$NestedStableField3$A
+ * java/lang/invoke/TestStableChar$DefaultValue
+ * java/lang/invoke/TestStableChar$ObjectArrayLowerDim2
+ *
+ * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions
+ * -XX:+UnlockDiagnosticVMOptions -XX:+FoldStableValues -XX:-UseCompressedOop
+ * -server -XX:-TieredCompilation -Xcomp
+ * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ * java.lang.invoke.TestStableChar
+ *
+ * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions
+ * -XX:+UnlockDiagnosticVMOptions -XX:+FoldStableValues -XX:+UseCompressedOop
+ * -server -XX:-TieredCompilation -Xcomp
+ * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ * java.lang.invoke.TestStableChar
+ *
+ * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions
+ * -XX:+UnlockDiagnosticVMOptions -XX:-FoldStableValues -XX:+UseCompressedOop
+ * -server -XX:-TieredCompilation -Xcomp
+ * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ * java.lang.invoke.TestStableChar
+ *
+ * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions
+ * -XX:+UnlockDiagnosticVMOptions -XX:-FoldStableValues -XX:-UseCompressedOop
+ * -server -XX:-TieredCompilation -Xcomp
+ * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ * java.lang.invoke.TestStableChar
+ */
+package java.lang.invoke;
+
+import com.sun.management.HotSpotDiagnosticMXBean;
+import com.sun.management.VMOption;
+import sun.management.ManagementFactoryHelper;
+import java.lang.reflect.InvocationTargetException;
+
+public class TestStableChar {
+ public static void main(String[] args) throws Exception {
+ System.out.println("@Stable enabled: "+isStableEnabled);
+ System.out.println();
+
+ run(DefaultValue.class);
+ run(CharStable.class);
+ run(StaticCharStable.class);
+ run(VolatileCharStable.class);
+
+ // @Stable arrays: Dim 1-4
+ run(CharArrayDim1.class);
+ run(CharArrayDim2.class);
+ run(CharArrayDim3.class);
+ run(CharArrayDim4.class);
+
+ // @Stable Object field: dynamic arrays
+ run(ObjectArrayLowerDim0.class);
+ run(ObjectArrayLowerDim1.class);
+ run(ObjectArrayLowerDim2.class);
+
+ // Nested @Stable fields
+ run(NestedStableField.class);
+ run(NestedStableField1.class);
+ run(NestedStableField2.class);
+ run(NestedStableField3.class);
+
+ if (failed) {
+ throw new Error("TEST FAILED");
+ }
+ }
+
+ /* ==================================================== */
+
+ static class DefaultValue {
+ public @Stable char v;
+
+ public static final DefaultValue c = new DefaultValue();
+ public static char get() { return c.v; }
+ public static void test() throws Exception {
+ char val1 = get();
+ c.v = 'a'; char val2 = get();
+ assertEquals(val1, 0);
+ assertEquals(val2, 'a');
+ }
+ }
+
+ /* ==================================================== */
+
+ static class CharStable {
+ public @Stable char v;
+
+ public static final CharStable c = new CharStable();
+ public static char get() { return c.v; }
+ public static void test() throws Exception {
+ c.v = 'a'; char val1 = get();
+ c.v = 'b'; char val2 = get();
+ assertEquals(val1, 'a');
+ assertEquals(val2, (isStableEnabled ? 'a' : 'b'));
+ }
+ }
+
+ /* ==================================================== */
+
+ static class StaticCharStable {
+ public @Stable char v;
+
+ public static final StaticCharStable c = new StaticCharStable();
+ public static char get() { return c.v; }
+ public static void test() throws Exception {
+ c.v = 'a'; char val1 = get();
+ c.v = 'b'; char val2 = get();
+ assertEquals(val1, 'a');
+ assertEquals(val2, (isStableEnabled ? 'a' : 'b'));
+ }
+ }
+
+ /* ==================================================== */
+
+ static class VolatileCharStable {
+ public @Stable volatile char v;
+
+ public static final VolatileCharStable c = new VolatileCharStable();
+ public static char get() { return c.v; }
+ public static void test() throws Exception {
+ c.v = 'a'; char val1 = get();
+ c.v = 'b'; char val2 = get();
+ assertEquals(val1, 'a');
+ assertEquals(val2, (isStableEnabled ? 'a' : 'b'));
+ }
+ }
+
+ /* ==================================================== */
+ // @Stable array == field && all components are stable
+
+ static class CharArrayDim1 {
+ public @Stable char[] v;
+
+ public static final CharArrayDim1 c = new CharArrayDim1();
+ public static char get() { return c.v[0]; }
+ public static char get1() { return c.v[10]; }
+ public static char[] get2() { return c.v; }
+ public static void test() throws Exception {
+ {
+ c.v = new char[1]; c.v[0] = 'a'; char val1 = get();
+ c.v[0] = 'b'; char val2 = get();
+ assertEquals(val1, 'a');
+ assertEquals(val2, (isStableEnabled ? 'a' : 'b'));
+
+ c.v = new char[1]; c.v[0] = 'c'; char val3 = get();
+ assertEquals(val3, (isStableEnabled ? 'a' : 'c'));
+ }
+
+ {
+ c.v = new char[20]; c.v[10] = 'a'; char val1 = get1();
+ c.v[10] = 'b'; char val2 = get1();
+ assertEquals(val1, 'a');
+ assertEquals(val2, (isStableEnabled ? 'a' : 'b'));
+
+ c.v = new char[20]; c.v[10] = 'c'; char val3 = get1();
+ assertEquals(val3, (isStableEnabled ? 'a' : 'c'));
+ }
+
+ {
+ c.v = new char[1]; char[] val1 = get2();
+ c.v = new char[1]; char[] val2 = get2();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class CharArrayDim2 {
+ public @Stable char[][] v;
+
+ public static final CharArrayDim2 c = new CharArrayDim2();
+ public static char get() { return c.v[0][0]; }
+ public static char[] get1() { return c.v[0]; }
+ public static char[][] get2() { return c.v; }
+ public static void test() throws Exception {
+ {
+ c.v = new char[1][1]; c.v[0][0] = 'a'; char val1 = get();
+ c.v[0][0] = 'b'; char val2 = get();
+ assertEquals(val1, 'a');
+ assertEquals(val2, (isStableEnabled ? 'a' : 'b'));
+
+ c.v = new char[1][1]; c.v[0][0] = 'c'; char val3 = get();
+ assertEquals(val3, (isStableEnabled ? 'a' : 'c'));
+
+ c.v[0] = new char[1]; c.v[0][0] = 'd'; char val4 = get();
+ assertEquals(val4, (isStableEnabled ? 'a' : 'd'));
+ }
+
+ {
+ c.v = new char[1][1]; char[] val1 = get1();
+ c.v[0] = new char[1]; char[] val2 = get1();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new char[1][1]; char[][] val1 = get2();
+ c.v = new char[1][1]; char[][] val2 = get2();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class CharArrayDim3 {
+ public @Stable char[][][] v;
+
+ public static final CharArrayDim3 c = new CharArrayDim3();
+ public static char get() { return c.v[0][0][0]; }
+ public static char[] get1() { return c.v[0][0]; }
+ public static char[][] get2() { return c.v[0]; }
+ public static char[][][] get3() { return c.v; }
+ public static void test() throws Exception {
+ {
+ c.v = new char[1][1][1]; c.v[0][0][0] = 'a'; char val1 = get();
+ c.v[0][0][0] = 'b'; char val2 = get();
+ assertEquals(val1, 'a');
+ assertEquals(val2, (isStableEnabled ? 'a' : 'b'));
+
+ c.v = new char[1][1][1]; c.v[0][0][0] = 'c'; char val3 = get();
+ assertEquals(val3, (isStableEnabled ? 'a' : 'c'));
+
+ c.v[0] = new char[1][1]; c.v[0][0][0] = 'd'; char val4 = get();
+ assertEquals(val4, (isStableEnabled ? 'a' : 'd'));
+
+ c.v[0][0] = new char[1]; c.v[0][0][0] = 'e'; char val5 = get();
+ assertEquals(val5, (isStableEnabled ? 'a' : 'e'));
+ }
+
+ {
+ c.v = new char[1][1][1]; char[] val1 = get1();
+ c.v[0][0] = new char[1]; char[] val2 = get1();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new char[1][1][1]; char[][] val1 = get2();
+ c.v[0] = new char[1][1]; char[][] val2 = get2();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new char[1][1][1]; char[][][] val1 = get3();
+ c.v = new char[1][1][1]; char[][][] val2 = get3();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class CharArrayDim4 {
+ public @Stable char[][][][] v;
+
+ public static final CharArrayDim4 c = new CharArrayDim4();
+ public static char get() { return c.v[0][0][0][0]; }
+ public static char[] get1() { return c.v[0][0][0]; }
+ public static char[][] get2() { return c.v[0][0]; }
+ public static char[][][] get3() { return c.v[0]; }
+ public static char[][][][] get4() { return c.v; }
+ public static void test() throws Exception {
+ {
+ c.v = new char[1][1][1][1]; c.v[0][0][0][0] = 'a'; char val1 = get();
+ c.v[0][0][0][0] = 'b'; char val2 = get();
+ assertEquals(val1, 'a');
+ assertEquals(val2, (isStableEnabled ? 'a' : 'b'));
+
+ c.v = new char[1][1][1][1]; c.v[0][0][0][0] = 'c'; char val3 = get();
+ assertEquals(val3, (isStableEnabled ? 'a' : 'c'));
+
+ c.v[0] = new char[1][1][1]; c.v[0][0][0][0] = 'd'; char val4 = get();
+ assertEquals(val4, (isStableEnabled ? 'a' : 'd'));
+
+ c.v[0][0] = new char[1][1]; c.v[0][0][0][0] = 'e'; char val5 = get();
+ assertEquals(val5, (isStableEnabled ? 'a' : 'e'));
+
+ c.v[0][0][0] = new char[1]; c.v[0][0][0][0] = 'f'; char val6 = get();
+ assertEquals(val6, (isStableEnabled ? 'a' : 'f'));
+ }
+
+ {
+ c.v = new char[1][1][1][1]; char[] val1 = get1();
+ c.v[0][0][0] = new char[1]; char[] val2 = get1();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new char[1][1][1][1]; char[][] val1 = get2();
+ c.v[0][0] = new char[1][1]; char[][] val2 = get2();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new char[1][1][1][1]; char[][][] val1 = get3();
+ c.v[0] = new char[1][1][1]; char[][][] val2 = get3();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new char[1][1][1][1]; char[][][][] val1 = get4();
+ c.v = new char[1][1][1][1]; char[][][][] val2 = get4();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ }
+ }
+
+ /* ==================================================== */
+ // Dynamic Dim is higher than static
+ static class ObjectArrayLowerDim0 {
+ public @Stable Object v;
+
+ public static final ObjectArrayLowerDim0 c = new ObjectArrayLowerDim0();
+ public static char get() { return ((char[])c.v)[0]; }
+ public static char[] get1() { return (char[])c.v; }
+
+ public static void test() throws Exception {
+ {
+ c.v = new char[1]; ((char[])c.v)[0] = 'a'; char val1 = get();
+ ((char[])c.v)[0] = 'b'; char val2 = get();
+
+ assertEquals(val1, 'a');
+ assertEquals(val2, 'b');
+ }
+
+ {
+ c.v = new char[1]; char[] val1 = get1();
+ c.v = new char[1]; char[] val2 = get1();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class ObjectArrayLowerDim1 {
+ public @Stable Object[] v;
+
+ public static final ObjectArrayLowerDim1 c = new ObjectArrayLowerDim1();
+ public static char get() { return ((char[][])c.v)[0][0]; }
+ public static char[] get1() { return (char[])(c.v[0]); }
+ public static Object[] get2() { return c.v; }
+
+ public static void test() throws Exception {
+ {
+ c.v = new char[1][1]; ((char[][])c.v)[0][0] = 'a'; char val1 = get();
+ ((char[][])c.v)[0][0] = 'b'; char val2 = get();
+
+ assertEquals(val1, 'a');
+ assertEquals(val2, 'b');
+ }
+
+ {
+ c.v = new char[1][1]; c.v[0] = new char[0]; char[] val1 = get1();
+ c.v[0] = new char[0]; char[] val2 = get1();
+
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new char[0][0]; Object[] val1 = get2();
+ c.v = new char[0][0]; Object[] val2 = get2();
+
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class ObjectArrayLowerDim2 {
+ public @Stable Object[][] v;
+
+ public static final ObjectArrayLowerDim2 c = new ObjectArrayLowerDim2();
+ public static char get() { return ((char[][][])c.v)[0][0][0]; }
+ public static char[] get1() { return (char[])(c.v[0][0]); }
+ public static char[][] get2() { return (char[][])(c.v[0]); }
+ public static Object[][] get3() { return c.v; }
+
+ public static void test() throws Exception {
+ {
+ c.v = new char[1][1][1]; ((char[][][])c.v)[0][0][0] = 'a'; char val1 = get();
+ ((char[][][])c.v)[0][0][0] = 'b'; char val2 = get();
+
+ assertEquals(val1, 'a');
+ assertEquals(val2, 'b');
+ }
+
+ {
+ c.v = new char[1][1][1]; c.v[0][0] = new char[0]; char[] val1 = get1();
+ c.v[0][0] = new char[0]; char[] val2 = get1();
+
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new char[1][1][1]; c.v[0] = new char[0][0]; char[][] val1 = get2();
+ c.v[0] = new char[0][0]; char[][] val2 = get2();
+
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new char[0][0][0]; Object[][] val1 = get3();
+ c.v = new char[0][0][0]; Object[][] val2 = get3();
+
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class NestedStableField {
+ static class A {
+ public @Stable char a;
+
+ }
+ public @Stable A v;
+
+ public static final NestedStableField c = new NestedStableField();
+ public static A get() { return c.v; }
+ public static char get1() { return get().a; }
+
+ public static void test() throws Exception {
+ {
+ c.v = new A(); c.v.a = 'a'; A val1 = get();
+ c.v.a = 'b'; A val2 = get();
+
+ assertEquals(val1.a, 'b');
+ assertEquals(val2.a, 'b');
+ }
+
+ {
+ c.v = new A(); c.v.a = 'a'; char val1 = get1();
+ c.v.a = 'b'; char val2 = get1();
+ c.v = new A(); c.v.a = 'c'; char val3 = get1();
+
+ assertEquals(val1, 'a');
+ assertEquals(val2, (isStableEnabled ? 'a' : 'b'));
+ assertEquals(val3, (isStableEnabled ? 'a' : 'c'));
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class NestedStableField1 {
+ static class A {
+ public @Stable char a;
+ public @Stable A next;
+ }
+ public @Stable A v;
+
+ public static final NestedStableField1 c = new NestedStableField1();
+ public static A get() { return c.v.next.next.next.next.next.next.next; }
+ public static char get1() { return get().a; }
+
+ public static void test() throws Exception {
+ {
+ c.v = new A(); c.v.next = new A(); c.v.next.next = c.v;
+ c.v.a = 'a'; c.v.next.a = 'a'; A val1 = get();
+ c.v.a = 'b'; c.v.next.a = 'b'; A val2 = get();
+
+ assertEquals(val1.a, 'b');
+ assertEquals(val2.a, 'b');
+ }
+
+ {
+ c.v = new A(); c.v.next = c.v;
+ c.v.a = 'a'; char val1 = get1();
+ c.v.a = 'b'; char val2 = get1();
+ c.v = new A(); c.v.next = c.v;
+ c.v.a = 'c'; char val3 = get1();
+
+ assertEquals(val1, 'a');
+ assertEquals(val2, (isStableEnabled ? 'a' : 'b'));
+ assertEquals(val3, (isStableEnabled ? 'a' : 'c'));
+ }
+ }
+ }
+ /* ==================================================== */
+
+ static class NestedStableField2 {
+ static class A {
+ public @Stable char a;
+ public @Stable A left;
+ public A right;
+ }
+
+ public @Stable A v;
+
+ public static final NestedStableField2 c = new NestedStableField2();
+ public static char get() { return c.v.left.left.left.a; }
+ public static char get1() { return c.v.left.left.right.left.a; }
+
+ public static void test() throws Exception {
+ {
+ c.v = new A(); c.v.left = c.v.right = c.v;
+ c.v.a = 'a'; char val1 = get(); char val2 = get1();
+ c.v.a = 'b'; char val3 = get(); char val4 = get1();
+
+ assertEquals(val1, 'a');
+ assertEquals(val3, (isStableEnabled ? 'a' : 'b'));
+
+ assertEquals(val2, 'a');
+ assertEquals(val4, 'b');
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class NestedStableField3 {
+ static class A {
+ public @Stable char a;
+ public @Stable A[] left;
+ public A[] right;
+ }
+
+ public @Stable A[] v;
+
+ public static final NestedStableField3 c = new NestedStableField3();
+ public static char get() { return c.v[0].left[1].left[0].left[1].a; }
+ public static char get1() { return c.v[1].left[0].left[1].right[0].left[1].a; }
+
+ public static void test() throws Exception {
+ {
+ A elem = new A();
+ c.v = new A[] { elem, elem }; c.v[0].left = c.v[0].right = c.v;
+ elem.a = 'a'; char val1 = get(); char val2 = get1();
+ elem.a = 'b'; char val3 = get(); char val4 = get1();
+
+ assertEquals(val1, 'a');
+ assertEquals(val3, (isStableEnabled ? 'a' : 'b'));
+
+ assertEquals(val2, 'a');
+ assertEquals(val4, 'b');
+ }
+ }
+ }
+
+ /* ==================================================== */
+ // Auxiliary methods
+ static void assertEquals(int i, int j) { if (i != j) throw new AssertionError(i + " != " + j); }
+ static void assertTrue(boolean b) { if (!b) throw new AssertionError(); }
+
+ static boolean failed = false;
+
+ public static void run(Class<?> test) {
+ Throwable ex = null;
+ System.out.print(test.getName()+": ");
+ try {
+ test.getMethod("test").invoke(null);
+ } catch (InvocationTargetException e) {
+ ex = e.getCause();
+ } catch (Throwable e) {
+ ex = e;
+ } finally {
+ if (ex == null) {
+ System.out.println("PASSED");
+ } else {
+ failed = true;
+ System.out.println("FAILED");
+ ex.printStackTrace(System.out);
+ }
+ }
+ }
+
+ static final boolean isStableEnabled;
+ static {
+ HotSpotDiagnosticMXBean diagnostic
+ = ManagementFactoryHelper.getDiagnosticMXBean();
+ VMOption tmp;
+ try {
+ tmp = diagnostic.getVMOption("FoldStableValues");
+ } catch (IllegalArgumentException e) {
+ tmp = null;
+ }
+ isStableEnabled = (tmp == null ? false : Boolean.parseBoolean(tmp.getValue()));
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/stable/TestStableDouble.java Wed Mar 05 01:26:52 2014 -0800
@@ -0,0 +1,632 @@
+/*
+ * Copyright (c) 2014, 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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 TestStableDouble
+ * @summary tests on stable fields and arrays
+ * @library /testlibrary
+ * @compile -XDignore.symbol.file TestStableDouble.java
+ * @run main ClassFileInstaller
+ * java/lang/invoke/TestStableDouble
+ * java/lang/invoke/TestStableDouble$DoubleStable
+ * java/lang/invoke/TestStableDouble$StaticDoubleStable
+ * java/lang/invoke/TestStableDouble$VolatileDoubleStable
+ * java/lang/invoke/TestStableDouble$DoubleArrayDim1
+ * java/lang/invoke/TestStableDouble$DoubleArrayDim2
+ * java/lang/invoke/TestStableDouble$DoubleArrayDim3
+ * java/lang/invoke/TestStableDouble$DoubleArrayDim4
+ * java/lang/invoke/TestStableDouble$ObjectArrayLowerDim0
+ * java/lang/invoke/TestStableDouble$ObjectArrayLowerDim1
+ * java/lang/invoke/TestStableDouble$NestedStableField
+ * java/lang/invoke/TestStableDouble$NestedStableField$A
+ * java/lang/invoke/TestStableDouble$NestedStableField1
+ * java/lang/invoke/TestStableDouble$NestedStableField1$A
+ * java/lang/invoke/TestStableDouble$NestedStableField2
+ * java/lang/invoke/TestStableDouble$NestedStableField2$A
+ * java/lang/invoke/TestStableDouble$NestedStableField3
+ * java/lang/invoke/TestStableDouble$NestedStableField3$A
+ * java/lang/invoke/TestStableDouble$DefaultValue
+ * java/lang/invoke/TestStableDouble$ObjectArrayLowerDim2
+ *
+ * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions
+ * -XX:+UnlockDiagnosticVMOptions -XX:+FoldStableValues -XX:+UseCompressedOop
+ * -server -XX:-TieredCompilation -Xcomp
+ * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ * java.lang.invoke.TestStableDouble
+ *
+ * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions
+ * -XX:+UnlockDiagnosticVMOptions -XX:+FoldStableValues -XX:-UseCompressedOop
+ * -server -XX:-TieredCompilation -Xcomp
+ * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ * java.lang.invoke.TestStableDouble
+ *
+ * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions
+ * -XX:+UnlockDiagnosticVMOptions -XX:-FoldStableValues -XX:+UseCompressedOop
+ * -server -XX:-TieredCompilation -Xcomp
+ * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ * java.lang.invoke.TestStableDouble
+ *
+ * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions
+ * -XX:+UnlockDiagnosticVMOptions -XX:-FoldStableValues -XX:-UseCompressedOop
+ * -server -XX:-TieredCompilation -Xcomp
+ * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ * java.lang.invoke.TestStableDouble
+ */
+package java.lang.invoke;
+
+import com.sun.management.HotSpotDiagnosticMXBean;
+import com.sun.management.VMOption;
+import sun.management.ManagementFactoryHelper;
+import java.lang.reflect.InvocationTargetException;
+
+public class TestStableDouble {
+ public static void main(String[] args) throws Exception {
+ System.out.println("@Stable enabled: "+isStableEnabled);
+ System.out.println();
+
+ run(DefaultValue.class);
+ run(DoubleStable.class);
+ run(StaticDoubleStable.class);
+ run(VolatileDoubleStable.class);
+
+ // @Stable arrays: Dim 1-4
+ run(DoubleArrayDim1.class);
+ run(DoubleArrayDim2.class);
+ run(DoubleArrayDim3.class);
+ run(DoubleArrayDim4.class);
+
+ // @Stable Object field: dynamic arrays
+ run(ObjectArrayLowerDim0.class);
+ run(ObjectArrayLowerDim1.class);
+ run(ObjectArrayLowerDim2.class);
+
+ // Nested @Stable fields
+ run(NestedStableField.class);
+ run(NestedStableField1.class);
+ run(NestedStableField2.class);
+ run(NestedStableField3.class);
+
+ if (failed) {
+ throw new Error("TEST FAILED");
+ }
+ }
+
+ /* ==================================================== */
+
+ static class DefaultValue {
+ public @Stable double v;
+
+ public static final DefaultValue c = new DefaultValue();
+ public static double get() { return c.v; }
+ public static void test() throws Exception {
+ double val1 = get();
+ c.v = 1.0; double val2 = get();
+ assertEquals(val1, 0);
+ assertEquals(val2, 1.0);
+ }
+ }
+
+ /* ==================================================== */
+
+ static class DoubleStable {
+ public @Stable double v;
+
+ public static final DoubleStable c = new DoubleStable();
+ public static double get() { return c.v; }
+ public static void test() throws Exception {
+ c.v = 1.0; double val1 = get();
+ c.v = Double.MAX_VALUE; double val2 = get();
+ assertEquals(val1, 1.0);
+ assertEquals(val2, (isStableEnabled ? 1.0 : Double.MAX_VALUE));
+ }
+ }
+
+ /* ==================================================== */
+
+ static class StaticDoubleStable {
+ public static @Stable double v;
+
+ public static final StaticDoubleStable c = new StaticDoubleStable();
+ public static double get() { return c.v; }
+ public static void test() throws Exception {
+ c.v = 1.0; double val1 = get();
+ c.v = Double.MAX_VALUE; double val2 = get();
+ assertEquals(val1, 1.0);
+ assertEquals(val2, (isStableEnabled ? 1.0 : Double.MAX_VALUE));
+ }
+ }
+
+ /* ==================================================== */
+
+ static class VolatileDoubleStable {
+ public @Stable double v;
+
+ public static final VolatileDoubleStable c = new VolatileDoubleStable();
+ public static double get() { return c.v; }
+ public static void test() throws Exception {
+ c.v = 1.0; double val1 = get();
+ c.v = Double.MAX_VALUE; double val2 = get();
+ assertEquals(val1, 1.0);
+ assertEquals(val2, (isStableEnabled ? 1.0 : Double.MAX_VALUE));
+ }
+ }
+
+ /* ==================================================== */
+ // @Stable array == field && all components are stable
+
+ static class DoubleArrayDim1 {
+ public @Stable double[] v;
+
+ public static final DoubleArrayDim1 c = new DoubleArrayDim1();
+ public static double get() { return c.v[0]; }
+ public static double get1() { return c.v[10]; }
+ public static double[] get2() { return c.v; }
+ public static void test() throws Exception {
+ {
+ c.v = new double[1]; c.v[0] = 1.0; double val1 = get();
+ c.v[0] = 2.0; double val2 = get();
+ assertEquals(val1, 1.0);
+ assertEquals(val2, (isStableEnabled ? 1.0 : 2.0));
+
+ c.v = new double[1]; c.v[0] = 3.0; double val3 = get();
+ assertEquals(val3, (isStableEnabled ? 1.0 : 3.0));
+ }
+
+ {
+ c.v = new double[20]; c.v[10] = 1.0; double val1 = get1();
+ c.v[10] = 2.0; double val2 = get1();
+ assertEquals(val1, 1.0);
+ assertEquals(val2, (isStableEnabled ? 1.0 : 2.0));
+
+ c.v = new double[20]; c.v[10] = 3.0; double val3 = get1();
+ assertEquals(val3, (isStableEnabled ? 1.0 : 3.0));
+ }
+
+ {
+ c.v = new double[1]; double[] val1 = get2();
+ c.v = new double[1]; double[] val2 = get2();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class DoubleArrayDim2 {
+ public @Stable double[][] v;
+
+ public static final DoubleArrayDim2 c = new DoubleArrayDim2();
+ public static double get() { return c.v[0][0]; }
+ public static double[] get1() { return c.v[0]; }
+ public static double[][] get2() { return c.v; }
+ public static void test() throws Exception {
+ {
+ c.v = new double[1][1]; c.v[0][0] = 1.0; double val1 = get();
+ c.v[0][0] = 2.0; double val2 = get();
+ assertEquals(val1, 1.0);
+ assertEquals(val2, (isStableEnabled ? 1.0 : 2.0));
+
+ c.v = new double[1][1]; c.v[0][0] = 3.0; double val3 = get();
+ assertEquals(val3, (isStableEnabled ? 1.0 : 3.0));
+
+ c.v[0] = new double[1]; c.v[0][0] = 4.0; double val4 = get();
+ assertEquals(val4, (isStableEnabled ? 1.0 : 4.0));
+ }
+
+ {
+ c.v = new double[1][1]; double[] val1 = get1();
+ c.v[0] = new double[1]; double[] val2 = get1();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new double[1][1]; double[][] val1 = get2();
+ c.v = new double[1][1]; double[][] val2 = get2();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class DoubleArrayDim3 {
+ public @Stable double[][][] v;
+
+ public static final DoubleArrayDim3 c = new DoubleArrayDim3();
+ public static double get() { return c.v[0][0][0]; }
+ public static double[] get1() { return c.v[0][0]; }
+ public static double[][] get2() { return c.v[0]; }
+ public static double[][][] get3() { return c.v; }
+ public static void test() throws Exception {
+ {
+ c.v = new double[1][1][1]; c.v[0][0][0] = 1.0; double val1 = get();
+ c.v[0][0][0] = 2.0; double val2 = get();
+ assertEquals(val1, 1.0);
+ assertEquals(val2, (isStableEnabled ? 1.0 : 2.0));
+
+ c.v = new double[1][1][1]; c.v[0][0][0] = 3.0; double val3 = get();
+ assertEquals(val3, (isStableEnabled ? 1.0 : 3.0));
+
+ c.v[0] = new double[1][1]; c.v[0][0][0] = 4.0; double val4 = get();
+ assertEquals(val4, (isStableEnabled ? 1.0 : 4.0));
+
+ c.v[0][0] = new double[1]; c.v[0][0][0] = 5.0; double val5 = get();
+ assertEquals(val5, (isStableEnabled ? 1.0 : 5.0));
+ }
+
+ {
+ c.v = new double[1][1][1]; double[] val1 = get1();
+ c.v[0][0] = new double[1]; double[] val2 = get1();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new double[1][1][1]; double[][] val1 = get2();
+ c.v[0] = new double[1][1]; double[][] val2 = get2();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new double[1][1][1]; double[][][] val1 = get3();
+ c.v = new double[1][1][1]; double[][][] val2 = get3();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class DoubleArrayDim4 {
+ public @Stable double[][][][] v;
+
+ public static final DoubleArrayDim4 c = new DoubleArrayDim4();
+ public static double get() { return c.v[0][0][0][0]; }
+ public static double[] get1() { return c.v[0][0][0]; }
+ public static double[][] get2() { return c.v[0][0]; }
+ public static double[][][] get3() { return c.v[0]; }
+ public static double[][][][] get4() { return c.v; }
+ public static void test() throws Exception {
+ {
+ c.v = new double[1][1][1][1]; c.v[0][0][0][0] = 1.0; double val1 = get();
+ c.v[0][0][0][0] = 2.0; double val2 = get();
+ assertEquals(val1, 1.0);
+ assertEquals(val2, (isStableEnabled ? 1.0 : 2.0));
+
+ c.v = new double[1][1][1][1]; c.v[0][0][0][0] = 3.0; double val3 = get();
+ assertEquals(val3, (isStableEnabled ? 1.0 : 3.0));
+
+ c.v[0] = new double[1][1][1]; c.v[0][0][0][0] = 4.0; double val4 = get();
+ assertEquals(val4, (isStableEnabled ? 1.0 : 4.0));
+
+ c.v[0][0] = new double[1][1]; c.v[0][0][0][0] = 5.0; double val5 = get();
+ assertEquals(val5, (isStableEnabled ? 1.0 : 5.0));
+
+ c.v[0][0][0] = new double[1]; c.v[0][0][0][0] = 6.0; double val6 = get();
+ assertEquals(val6, (isStableEnabled ? 1.0 : 6.0));
+ }
+
+ {
+ c.v = new double[1][1][1][1]; double[] val1 = get1();
+ c.v[0][0][0] = new double[1]; double[] val2 = get1();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new double[1][1][1][1]; double[][] val1 = get2();
+ c.v[0][0] = new double[1][1]; double[][] val2 = get2();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new double[1][1][1][1]; double[][][] val1 = get3();
+ c.v[0] = new double[1][1][1]; double[][][] val2 = get3();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new double[1][1][1][1]; double[][][][] val1 = get4();
+ c.v = new double[1][1][1][1]; double[][][][] val2 = get4();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ }
+ }
+
+ /* ==================================================== */
+ // Dynamic Dim is higher than static
+
+ static class ObjectArrayLowerDim0 {
+ public @Stable Object v;
+
+ public static final ObjectArrayLowerDim0 c = new ObjectArrayLowerDim0();
+ public static double get() { return ((double[])c.v)[0]; }
+ public static double[] get1() { return (double[])c.v; }
+
+ public static void test() throws Exception {
+ {
+ c.v = new double[1]; ((double[])c.v)[0] = 1.0; double val1 = get();
+ ((double[])c.v)[0] = 2.0; double val2 = get();
+
+ assertEquals(val1, 1.0);
+ assertEquals(val2, 2.0);
+ }
+
+ {
+ c.v = new double[1]; double[] val1 = get1();
+ c.v = new double[1]; double[] val2 = get1();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class ObjectArrayLowerDim1 {
+ public @Stable Object[] v;
+
+ public static final ObjectArrayLowerDim1 c = new ObjectArrayLowerDim1();
+ public static double get() { return ((double[][])c.v)[0][0]; }
+ public static double[] get1() { return (double[])(c.v[0]); }
+ public static Object[] get2() { return c.v; }
+
+ public static void test() throws Exception {
+ {
+ c.v = new double[1][1]; ((double[][])c.v)[0][0] = 1.0; double val1 = get();
+ ((double[][])c.v)[0][0] = 2.0; double val2 = get();
+
+ assertEquals(val1, 1.0);
+ assertEquals(val2, 2.0);
+ }
+
+ {
+ c.v = new double[1][1]; c.v[0] = new double[0]; double[] val1 = get1();
+ c.v[0] = new double[0]; double[] val2 = get1();
+
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new double[0][0]; Object[] val1 = get2();
+ c.v = new double[0][0]; Object[] val2 = get2();
+
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class ObjectArrayLowerDim2 {
+ public @Stable Object[][] v;
+
+ public static final ObjectArrayLowerDim2 c = new ObjectArrayLowerDim2();
+ public static double get() { return ((double[][][])c.v)[0][0][0]; }
+ public static double[] get1() { return (double[])(c.v[0][0]); }
+ public static double[][] get2() { return (double[][])(c.v[0]); }
+ public static Object[][] get3() { return c.v; }
+
+ public static void test() throws Exception {
+ {
+ c.v = new double[1][1][1]; ((double[][][])c.v)[0][0][0] = 1.0; double val1 = get();
+ ((double[][][])c.v)[0][0][0] = 2.0; double val2 = get();
+
+ assertEquals(val1, 1.0);
+ assertEquals(val2, 2.0);
+ }
+
+ {
+ c.v = new double[1][1][1]; c.v[0][0] = new double[0]; double[] val1 = get1();
+ c.v[0][0] = new double[0]; double[] val2 = get1();
+
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new double[1][1][1]; c.v[0] = new double[0][0]; double[][] val1 = get2();
+ c.v[0] = new double[0][0]; double[][] val2 = get2();
+
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new double[0][0][0]; Object[][] val1 = get3();
+ c.v = new double[0][0][0]; Object[][] val2 = get3();
+
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class NestedStableField {
+ static class A {
+ public @Stable double a;
+
+ }
+ public @Stable A v;
+
+ public static final NestedStableField c = new NestedStableField();
+ public static A get() { return c.v; }
+ public static double get1() { return get().a; }
+
+ public static void test() throws Exception {
+ {
+ c.v = new A(); c.v.a = 1.0; A val1 = get();
+ c.v.a = 2.0; A val2 = get();
+
+ assertEquals(val1.a, 2.0);
+ assertEquals(val2.a, 2.0);
+ }
+
+ {
+ c.v = new A(); c.v.a = 1.0; double val1 = get1();
+ c.v.a = 2.0; double val2 = get1();
+ c.v = new A(); c.v.a = 3.0; double val3 = get1();
+
+ assertEquals(val1, 1.0);
+ assertEquals(val2, (isStableEnabled ? 1.0 : 2.0));
+ assertEquals(val3, (isStableEnabled ? 1.0 : 3.0));
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class NestedStableField1 {
+ static class A {
+ public @Stable double a;
+ public @Stable A next;
+ }
+ public @Stable A v;
+
+ public static final NestedStableField1 c = new NestedStableField1();
+ public static A get() { return c.v.next.next.next.next.next.next.next; }
+ public static double get1() { return get().a; }
+
+ public static void test() throws Exception {
+ {
+ c.v = new A(); c.v.next = new A(); c.v.next.next = c.v;
+ c.v.a = 1.0; c.v.next.a = 1.0; A val1 = get();
+ c.v.a = 2.0; c.v.next.a = 2.0; A val2 = get();
+
+ assertEquals(val1.a, 2.0);
+ assertEquals(val2.a, 2.0);
+ }
+
+ {
+ c.v = new A(); c.v.next = c.v;
+ c.v.a = 1.0; double val1 = get1();
+ c.v.a = 2.0; double val2 = get1();
+ c.v = new A(); c.v.next = c.v;
+ c.v.a = 3.0; double val3 = get1();
+
+ assertEquals(val1, 1.0);
+ assertEquals(val2, (isStableEnabled ? 1.0 : 2.0));
+ assertEquals(val3, (isStableEnabled ? 1.0 : 3.0));
+ }
+ }
+ }
+ /* ==================================================== */
+
+ static class NestedStableField2 {
+ static class A {
+ public @Stable double a;
+ public @Stable A left;
+ public A right;
+ }
+
+ public @Stable A v;
+
+ public static final NestedStableField2 c = new NestedStableField2();
+ public static double get() { return c.v.left.left.left.a; }
+ public static double get1() { return c.v.left.left.right.left.a; }
+
+ public static void test() throws Exception {
+ {
+ c.v = new A(); c.v.left = c.v.right = c.v;
+ c.v.a = 1.0; double val1 = get(); double val2 = get1();
+ c.v.a = 2.0; double val3 = get(); double val4 = get1();
+
+ assertEquals(val1, 1.0);
+ assertEquals(val3, (isStableEnabled ? 1.0 : 2.0));
+
+ assertEquals(val2, 1.0);
+ assertEquals(val4, 2.0);
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class NestedStableField3 {
+ static class A {
+ public @Stable double a;
+ public @Stable A[] left;
+ public A[] right;
+ }
+
+ public @Stable A[] v;
+
+ public static final NestedStableField3 c = new NestedStableField3();
+ public static double get() { return c.v[0].left[1].left[0].left[1].a; }
+ public static double get1() { return c.v[1].left[0].left[1].right[0].left[1].a; }
+
+ public static void test() throws Exception {
+ {
+ A elem = new A();
+ c.v = new A[] { elem, elem }; c.v[0].left = c.v[0].right = c.v;
+ elem.a = 1.0; double val1 = get(); double val2 = get1();
+ elem.a = 2.0; double val3 = get(); double val4 = get1();
+
+ assertEquals(val1, 1.0);
+ assertEquals(val3, (isStableEnabled ? 1.0 : 2.0));
+
+ assertEquals(val2, 1.0);
+ assertEquals(val4, 2.0);
+ }
+ }
+ }
+
+ /* ==================================================== */
+ // Auxiliary methods
+ static void assertEquals(double i, double j) { if (i != j) throw new AssertionError(i + " != " + j); }
+ static void assertTrue(boolean b) { if (!b) throw new AssertionError(); }
+
+ static boolean failed = false;
+
+ public static void run(Class<?> test) {
+ Throwable ex = null;
+ System.out.print(test.getName()+": ");
+ try {
+ test.getMethod("test").invoke(null);
+ } catch (InvocationTargetException e) {
+ ex = e.getCause();
+ } catch (Throwable e) {
+ ex = e;
+ } finally {
+ if (ex == null) {
+ System.out.println("PASSED");
+ } else {
+ failed = true;
+ System.out.println("FAILED");
+ ex.printStackTrace(System.out);
+ }
+ }
+ }
+
+ static final boolean isStableEnabled;
+ static {
+ HotSpotDiagnosticMXBean diagnostic
+ = ManagementFactoryHelper.getDiagnosticMXBean();
+ VMOption tmp;
+ try {
+ tmp = diagnostic.getVMOption("FoldStableValues");
+ } catch (IllegalArgumentException e) {
+ tmp = null;
+ }
+ isStableEnabled = (tmp == null ? false : Boolean.parseBoolean(tmp.getValue()));
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/stable/TestStableFloat.java Wed Mar 05 01:26:52 2014 -0800
@@ -0,0 +1,632 @@
+/*
+ * Copyright (c) 2014, 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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 TestStableFloat
+ * @summary tests on stable fields and arrays
+ * @library /testlibrary
+ * @compile -XDignore.symbol.file TestStableFloat.java
+ * @run main ClassFileInstaller
+ * java/lang/invoke/TestStableFloat
+ * java/lang/invoke/TestStableFloat$FloatStable
+ * java/lang/invoke/TestStableFloat$StaticFloatStable
+ * java/lang/invoke/TestStableFloat$VolatileFloatStable
+ * java/lang/invoke/TestStableFloat$FloatArrayDim1
+ * java/lang/invoke/TestStableFloat$FloatArrayDim2
+ * java/lang/invoke/TestStableFloat$FloatArrayDim3
+ * java/lang/invoke/TestStableFloat$FloatArrayDim4
+ * java/lang/invoke/TestStableFloat$ObjectArrayLowerDim0
+ * java/lang/invoke/TestStableFloat$ObjectArrayLowerDim1
+ * java/lang/invoke/TestStableFloat$NestedStableField
+ * java/lang/invoke/TestStableFloat$NestedStableField$A
+ * java/lang/invoke/TestStableFloat$NestedStableField1
+ * java/lang/invoke/TestStableFloat$NestedStableField1$A
+ * java/lang/invoke/TestStableFloat$NestedStableField2
+ * java/lang/invoke/TestStableFloat$NestedStableField2$A
+ * java/lang/invoke/TestStableFloat$NestedStableField3
+ * java/lang/invoke/TestStableFloat$NestedStableField3$A
+ * java/lang/invoke/TestStableFloat$DefaultValue
+ * java/lang/invoke/TestStableFloat$ObjectArrayLowerDim2
+ *
+ * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions
+ * -XX:+UnlockDiagnosticVMOptions -XX:+FoldStableValues -XX:+UseCompressedOop
+ * -server -XX:-TieredCompilation -Xcomp
+ * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ * java.lang.invoke.TestStableFloat
+ *
+ * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions
+ * -XX:+UnlockDiagnosticVMOptions -XX:+FoldStableValues -XX:-UseCompressedOop
+ * -server -XX:-TieredCompilation -Xcomp
+ * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ * java.lang.invoke.TestStableFloat
+ *
+ * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions
+ * -XX:+UnlockDiagnosticVMOptions -XX:-FoldStableValues -XX:+UseCompressedOop
+ * -server -XX:-TieredCompilation -Xcomp
+ * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ * java.lang.invoke.TestStableFloat
+ *
+ * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions
+ * -XX:+UnlockDiagnosticVMOptions -XX:-FoldStableValues -XX:-UseCompressedOop
+ * -server -XX:-TieredCompilation -Xcomp
+ * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ * java.lang.invoke.TestStableFloat
+ */
+package java.lang.invoke;
+
+import com.sun.management.HotSpotDiagnosticMXBean;
+import com.sun.management.VMOption;
+import sun.management.ManagementFactoryHelper;
+import java.lang.reflect.InvocationTargetException;
+
+public class TestStableFloat {
+ public static void main(String[] args) throws Exception {
+ System.out.println("@Stable enabled: "+isStableEnabled);
+ System.out.println();
+
+ run(DefaultValue.class);
+ run(FloatStable.class);
+ run(StaticFloatStable.class);
+ run(VolatileFloatStable.class);
+
+ // @Stable arrays: Dim 1-4
+ run(FloatArrayDim1.class);
+ run(FloatArrayDim2.class);
+ run(FloatArrayDim3.class);
+ run(FloatArrayDim4.class);
+
+ // @Stable Object field: dynamic arrays
+ run(ObjectArrayLowerDim0.class);
+ run(ObjectArrayLowerDim1.class);
+ run(ObjectArrayLowerDim2.class);
+
+ // Nested @Stable fields
+ run(NestedStableField.class);
+ run(NestedStableField1.class);
+ run(NestedStableField2.class);
+ run(NestedStableField3.class);
+
+ if (failed) {
+ throw new Error("TEST FAILED");
+ }
+ }
+
+ /* ==================================================== */
+
+ static class DefaultValue {
+ public @Stable float v;
+
+ public static final DefaultValue c = new DefaultValue();
+ public static float get() { return c.v; }
+ public static void test() throws Exception {
+ float val1 = get();
+ c.v = 1.0F; float val2 = get();
+ assertEquals(val1, 0F);
+ assertEquals(val2, 1.0F);
+ }
+ }
+
+ /* ==================================================== */
+
+ static class FloatStable {
+ public @Stable float v;
+
+ public static final FloatStable c = new FloatStable();
+ public static float get() { return c.v; }
+ public static void test() throws Exception {
+ c.v = 1.0F; float val1 = get();
+ c.v = 2.0F; float val2 = get();
+ assertEquals(val1, 1.0F);
+ assertEquals(val2, (isStableEnabled ? 1.0F : 2.0F));
+ }
+ }
+
+ /* ==================================================== */
+
+ static class StaticFloatStable {
+ public static @Stable float v;
+
+ public static final StaticFloatStable c = new StaticFloatStable();
+ public static float get() { return c.v; }
+ public static void test() throws Exception {
+ c.v = 1.0F; float val1 = get();
+ c.v = 2.0F; float val2 = get();
+ assertEquals(val1, 1.0F);
+ assertEquals(val2, (isStableEnabled ? 1.0F : 2.0F));
+ }
+ }
+
+ /* ==================================================== */
+
+ static class VolatileFloatStable {
+ public @Stable volatile float v;
+
+ public static final VolatileFloatStable c = new VolatileFloatStable();
+ public static float get() { return c.v; }
+ public static void test() throws Exception {
+ c.v = 1.0F; float val1 = get();
+ c.v = 2.0F; float val2 = get();
+ assertEquals(val1, 1.0F);
+ assertEquals(val2, (isStableEnabled ? 1.0F : 2.0F));
+ }
+ }
+
+ /* ==================================================== */
+ // @Stable array == field && all components are stable
+
+ static class FloatArrayDim1 {
+ public @Stable float[] v;
+
+ public static final FloatArrayDim1 c = new FloatArrayDim1();
+ public static float get() { return c.v[0]; }
+ public static float get1() { return c.v[10]; }
+ public static float[] get2() { return c.v; }
+ public static void test() throws Exception {
+ {
+ c.v = new float[1]; c.v[0] = 1.0F; float val1 = get();
+ c.v[0] = 2.0F; float val2 = get();
+ assertEquals(val1, 1.0F);
+ assertEquals(val2, (isStableEnabled ? 1.0F : 2.0F));
+
+ c.v = new float[1]; c.v[0] = 3.0F; float val3 = get();
+ assertEquals(val3, (isStableEnabled ? 1.0F : 3.0F));
+ }
+
+ {
+ c.v = new float[20]; c.v[10] = 1.0F; float val1 = get1();
+ c.v[10] = 2.0F; float val2 = get1();
+ assertEquals(val1, 1.0F);
+ assertEquals(val2, (isStableEnabled ? 1.0F : 2.0F));
+
+ c.v = new float[20]; c.v[10] = 3.0F; float val3 = get1();
+ assertEquals(val3, (isStableEnabled ? 1.0F : 3.0F));
+ }
+
+ {
+ c.v = new float[1]; float[] val1 = get2();
+ c.v = new float[1]; float[] val2 = get2();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class FloatArrayDim2 {
+ public @Stable float[][] v;
+
+ public static final FloatArrayDim2 c = new FloatArrayDim2();
+ public static float get() { return c.v[0][0]; }
+ public static float[] get1() { return c.v[0]; }
+ public static float[][] get2() { return c.v; }
+ public static void test() throws Exception {
+ {
+ c.v = new float[1][1]; c.v[0][0] = 1.0F; float val1 = get();
+ c.v[0][0] = 2.0F; float val2 = get();
+ assertEquals(val1, 1.0F);
+ assertEquals(val2, (isStableEnabled ? 1.0F : 2.0F));
+
+ c.v = new float[1][1]; c.v[0][0] = 3.0F; float val3 = get();
+ assertEquals(val3, (isStableEnabled ? 1.0F : 3.0F));
+
+ c.v[0] = new float[1]; c.v[0][0] = 4.0F; float val4 = get();
+ assertEquals(val4, (isStableEnabled ? 1.0F : 4.0F));
+ }
+
+ {
+ c.v = new float[1][1]; float[] val1 = get1();
+ c.v[0] = new float[1]; float[] val2 = get1();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new float[1][1]; float[][] val1 = get2();
+ c.v = new float[1][1]; float[][] val2 = get2();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class FloatArrayDim3 {
+ public @Stable float[][][] v;
+
+ public static final FloatArrayDim3 c = new FloatArrayDim3();
+ public static float get() { return c.v[0][0][0]; }
+ public static float[] get1() { return c.v[0][0]; }
+ public static float[][] get2() { return c.v[0]; }
+ public static float[][][] get3() { return c.v; }
+ public static void test() throws Exception {
+ {
+ c.v = new float[1][1][1]; c.v[0][0][0] = 1.0F; float val1 = get();
+ c.v[0][0][0] = 2.0F; float val2 = get();
+ assertEquals(val1, 1.0F);
+ assertEquals(val2, (isStableEnabled ? 1.0F : 2.0F));
+
+ c.v = new float[1][1][1]; c.v[0][0][0] = 3.0F; float val3 = get();
+ assertEquals(val3, (isStableEnabled ? 1.0F : 3.0F));
+
+ c.v[0] = new float[1][1]; c.v[0][0][0] = 4.0F; float val4 = get();
+ assertEquals(val4, (isStableEnabled ? 1.0F : 4.0F));
+
+ c.v[0][0] = new float[1]; c.v[0][0][0] = 5.0F; float val5 = get();
+ assertEquals(val5, (isStableEnabled ? 1.0F : 5.0F));
+ }
+
+ {
+ c.v = new float[1][1][1]; float[] val1 = get1();
+ c.v[0][0] = new float[1]; float[] val2 = get1();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new float[1][1][1]; float[][] val1 = get2();
+ c.v[0] = new float[1][1]; float[][] val2 = get2();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new float[1][1][1]; float[][][] val1 = get3();
+ c.v = new float[1][1][1]; float[][][] val2 = get3();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class FloatArrayDim4 {
+ public @Stable float[][][][] v;
+
+ public static final FloatArrayDim4 c = new FloatArrayDim4();
+ public static float get() { return c.v[0][0][0][0]; }
+ public static float[] get1() { return c.v[0][0][0]; }
+ public static float[][] get2() { return c.v[0][0]; }
+ public static float[][][] get3() { return c.v[0]; }
+ public static float[][][][] get4() { return c.v; }
+ public static void test() throws Exception {
+ {
+ c.v = new float[1][1][1][1]; c.v[0][0][0][0] = 1.0F; float val1 = get();
+ c.v[0][0][0][0] = 2.0F; float val2 = get();
+ assertEquals(val1, 1.0F);
+ assertEquals(val2, (isStableEnabled ? 1.0F : 2.0F));
+
+ c.v = new float[1][1][1][1]; c.v[0][0][0][0] = 3.0F; float val3 = get();
+ assertEquals(val3, (isStableEnabled ? 1.0F : 3.0F));
+
+ c.v[0] = new float[1][1][1]; c.v[0][0][0][0] = 4.0F; float val4 = get();
+ assertEquals(val4, (isStableEnabled ? 1.0F : 4.0F));
+
+ c.v[0][0] = new float[1][1]; c.v[0][0][0][0] = 5.0F; float val5 = get();
+ assertEquals(val5, (isStableEnabled ? 1.0F : 5.0F));
+
+ c.v[0][0][0] = new float[1]; c.v[0][0][0][0] = 6.0F; float val6 = get();
+ assertEquals(val6, (isStableEnabled ? 1.0F : 6.0F));
+ }
+
+ {
+ c.v = new float[1][1][1][1]; float[] val1 = get1();
+ c.v[0][0][0] = new float[1]; float[] val2 = get1();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new float[1][1][1][1]; float[][] val1 = get2();
+ c.v[0][0] = new float[1][1]; float[][] val2 = get2();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new float[1][1][1][1]; float[][][] val1 = get3();
+ c.v[0] = new float[1][1][1]; float[][][] val2 = get3();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new float[1][1][1][1]; float[][][][] val1 = get4();
+ c.v = new float[1][1][1][1]; float[][][][] val2 = get4();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ }
+ }
+
+ /* ==================================================== */
+ // Dynamic Dim is higher than static
+
+ static class ObjectArrayLowerDim0 {
+ public @Stable Object v;
+
+ public static final ObjectArrayLowerDim0 c = new ObjectArrayLowerDim0();
+ public static float get() { return ((float[])c.v)[0]; }
+ public static float[] get1() { return (float[])c.v; }
+
+ public static void test() throws Exception {
+ {
+ c.v = new float[1]; ((float[])c.v)[0] = 1.0F; float val1 = get();
+ ((float[])c.v)[0] = 2.0F; float val2 = get();
+
+ assertEquals(val1, 1.0F);
+ assertEquals(val2, 2.0F);
+ }
+
+ {
+ c.v = new float[1]; float[] val1 = get1();
+ c.v = new float[1]; float[] val2 = get1();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class ObjectArrayLowerDim1 {
+ public @Stable Object[] v;
+
+ public static final ObjectArrayLowerDim1 c = new ObjectArrayLowerDim1();
+ public static float get() { return ((float[][])c.v)[0][0]; }
+ public static float[] get1() { return (float[])(c.v[0]); }
+ public static Object[] get2() { return c.v; }
+
+ public static void test() throws Exception {
+ {
+ c.v = new float[1][1]; ((float[][])c.v)[0][0] = 1.0F; float val1 = get();
+ ((float[][])c.v)[0][0] = 2.0F; float val2 = get();
+
+ assertEquals(val1, 1.0F);
+ assertEquals(val2, 2.0F);
+ }
+
+ {
+ c.v = new float[1][1]; c.v[0] = new float[0]; float[] val1 = get1();
+ c.v[0] = new float[0]; float[] val2 = get1();
+
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new float[0][0]; Object[] val1 = get2();
+ c.v = new float[0][0]; Object[] val2 = get2();
+
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class ObjectArrayLowerDim2 {
+ public @Stable Object[][] v;
+
+ public static final ObjectArrayLowerDim2 c = new ObjectArrayLowerDim2();
+ public static float get() { return ((float[][][])c.v)[0][0][0]; }
+ public static float[] get1() { return (float[])(c.v[0][0]); }
+ public static float[][] get2() { return (float[][])(c.v[0]); }
+ public static Object[][] get3() { return c.v; }
+
+ public static void test() throws Exception {
+ {
+ c.v = new float[1][1][1]; ((float[][][])c.v)[0][0][0] = 1.0F; float val1 = get();
+ ((float[][][])c.v)[0][0][0] = 2.0F; float val2 = get();
+
+ assertEquals(val1, 1.0F);
+ assertEquals(val2, 2.0F);
+ }
+
+ {
+ c.v = new float[1][1][1]; c.v[0][0] = new float[0]; float[] val1 = get1();
+ c.v[0][0] = new float[0]; float[] val2 = get1();
+
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new float[1][1][1]; c.v[0] = new float[0][0]; float[][] val1 = get2();
+ c.v[0] = new float[0][0]; float[][] val2 = get2();
+
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new float[0][0][0]; Object[][] val1 = get3();
+ c.v = new float[0][0][0]; Object[][] val2 = get3();
+
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class NestedStableField {
+ static class A {
+ public @Stable float a;
+
+ }
+ public @Stable A v;
+
+ public static final NestedStableField c = new NestedStableField();
+ public static A get() { return c.v; }
+ public static float get1() { return get().a; }
+
+ public static void test() throws Exception {
+ {
+ c.v = new A(); c.v.a = 1.0F; A val1 = get();
+ c.v.a = 2.0F; A val2 = get();
+
+ assertEquals(val1.a, 2.0F);
+ assertEquals(val2.a, 2.0F);
+ }
+
+ {
+ c.v = new A(); c.v.a = 1.0F; float val1 = get1();
+ c.v.a = 2.0F; float val2 = get1();
+ c.v = new A(); c.v.a = 3.0F; float val3 = get1();
+
+ assertEquals(val1, 1.0F);
+ assertEquals(val2, (isStableEnabled ? 1.0F : 2.0F));
+ assertEquals(val3, (isStableEnabled ? 1.0F : 3.0F));
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class NestedStableField1 {
+ static class A {
+ public @Stable float a;
+ public @Stable A next;
+ }
+ public @Stable A v;
+
+ public static final NestedStableField1 c = new NestedStableField1();
+ public static A get() { return c.v.next.next.next.next.next.next.next; }
+ public static float get1() { return get().a; }
+
+ public static void test() throws Exception {
+ {
+ c.v = new A(); c.v.next = new A(); c.v.next.next = c.v;
+ c.v.a = 1.0F; c.v.next.a = 1.0F; A val1 = get();
+ c.v.a = 2.0F; c.v.next.a = 2.0F; A val2 = get();
+
+ assertEquals(val1.a, 2.0F);
+ assertEquals(val2.a, 2.0F);
+ }
+
+ {
+ c.v = new A(); c.v.next = c.v;
+ c.v.a = 1.0F; float val1 = get1();
+ c.v.a = 2.0F; float val2 = get1();
+ c.v = new A(); c.v.next = c.v;
+ c.v.a = 3.0F; float val3 = get1();
+
+ assertEquals(val1, 1.0F);
+ assertEquals(val2, (isStableEnabled ? 1.0F : 2.0F));
+ assertEquals(val3, (isStableEnabled ? 1.0F : 3.0F));
+ }
+ }
+ }
+ /* ==================================================== */
+
+ static class NestedStableField2 {
+ static class A {
+ public @Stable float a;
+ public @Stable A left;
+ public A right;
+ }
+
+ public @Stable A v;
+
+ public static final NestedStableField2 c = new NestedStableField2();
+ public static float get() { return c.v.left.left.left.a; }
+ public static float get1() { return c.v.left.left.right.left.a; }
+
+ public static void test() throws Exception {
+ {
+ c.v = new A(); c.v.left = c.v.right = c.v;
+ c.v.a = 1.0F; float val1 = get(); float val2 = get1();
+ c.v.a = 2.0F; float val3 = get(); float val4 = get1();
+
+ assertEquals(val1, 1.0F);
+ assertEquals(val3, (isStableEnabled ? 1.0F : 2.0F));
+
+ assertEquals(val2, 1.0F);
+ assertEquals(val4, 2.0F);
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class NestedStableField3 {
+ static class A {
+ public @Stable float a;
+ public @Stable A[] left;
+ public A[] right;
+ }
+
+ public @Stable A[] v;
+
+ public static final NestedStableField3 c = new NestedStableField3();
+ public static float get() { return c.v[0].left[1].left[0].left[1].a; }
+ public static float get1() { return c.v[1].left[0].left[1].right[0].left[1].a; }
+
+ public static void test() throws Exception {
+ {
+ A elem = new A();
+ c.v = new A[] { elem, elem }; c.v[0].left = c.v[0].right = c.v;
+ elem.a = 1.0F; float val1 = get(); float val2 = get1();
+ elem.a = 2.0F; float val3 = get(); float val4 = get1();
+
+ assertEquals(val1, 1.0F);
+ assertEquals(val3, (isStableEnabled ? 1.0F : 2.0F));
+
+ assertEquals(val2, 1.0F);
+ assertEquals(val4, 2.0F);
+ }
+ }
+ }
+
+ /* ==================================================== */
+ // Auxiliary methods
+ static void assertEquals(float i, float j) { if (i != j) throw new AssertionError(i + " != " + j); }
+ static void assertTrue(boolean b) { if (!b) throw new AssertionError(); }
+
+ static boolean failed = false;
+
+ public static void run(Class<?> test) {
+ Throwable ex = null;
+ System.out.print(test.getName()+": ");
+ try {
+ test.getMethod("test").invoke(null);
+ } catch (InvocationTargetException e) {
+ ex = e.getCause();
+ } catch (Throwable e) {
+ ex = e;
+ } finally {
+ if (ex == null) {
+ System.out.println("PASSED");
+ } else {
+ failed = true;
+ System.out.println("FAILED");
+ ex.printStackTrace(System.out);
+ }
+ }
+ }
+
+ static final boolean isStableEnabled;
+ static {
+ HotSpotDiagnosticMXBean diagnostic
+ = ManagementFactoryHelper.getDiagnosticMXBean();
+ VMOption tmp;
+ try {
+ tmp = diagnostic.getVMOption("FoldStableValues");
+ } catch (IllegalArgumentException e) {
+ tmp = null;
+ }
+ isStableEnabled = (tmp == null ? false : Boolean.parseBoolean(tmp.getValue()));
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/stable/TestStableInt.java Wed Mar 05 01:26:52 2014 -0800
@@ -0,0 +1,632 @@
+/*
+ * Copyright (c) 2014, 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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 TestStableInt
+ * @summary tests on stable fields and arrays
+ * @library /testlibrary
+ * @compile -XDignore.symbol.file TestStableInt.java
+ * @run main ClassFileInstaller
+ * java/lang/invoke/TestStableInt
+ * java/lang/invoke/TestStableInt$IntStable
+ * java/lang/invoke/TestStableInt$StaticIntStable
+ * java/lang/invoke/TestStableInt$VolatileIntStable
+ * java/lang/invoke/TestStableInt$IntArrayDim1
+ * java/lang/invoke/TestStableInt$IntArrayDim2
+ * java/lang/invoke/TestStableInt$IntArrayDim3
+ * java/lang/invoke/TestStableInt$IntArrayDim4
+ * java/lang/invoke/TestStableInt$ObjectArrayLowerDim0
+ * java/lang/invoke/TestStableInt$ObjectArrayLowerDim1
+ * java/lang/invoke/TestStableInt$NestedStableField
+ * java/lang/invoke/TestStableInt$NestedStableField$A
+ * java/lang/invoke/TestStableInt$NestedStableField1
+ * java/lang/invoke/TestStableInt$NestedStableField1$A
+ * java/lang/invoke/TestStableInt$NestedStableField2
+ * java/lang/invoke/TestStableInt$NestedStableField2$A
+ * java/lang/invoke/TestStableInt$NestedStableField3
+ * java/lang/invoke/TestStableInt$NestedStableField3$A
+ * java/lang/invoke/TestStableInt$DefaultValue
+ * java/lang/invoke/TestStableInt$ObjectArrayLowerDim2
+ *
+ * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions
+ * -XX:+UnlockDiagnosticVMOptions -XX:+FoldStableValues -XX:+UseCompressedOop
+ * -server -XX:-TieredCompilation -Xcomp
+ * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ * java.lang.invoke.TestStableInt
+ *
+ * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions
+ * -XX:+UnlockDiagnosticVMOptions -XX:+FoldStableValues -XX:-UseCompressedOop
+ * -server -XX:-TieredCompilation -Xcomp
+ * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ * java.lang.invoke.TestStableInt
+ *
+ * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions
+ * -XX:+UnlockDiagnosticVMOptions -XX:-FoldStableValues -XX:+UseCompressedOop
+ * -server -XX:-TieredCompilation -Xcomp
+ * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ * java.lang.invoke.TestStableInt
+ *
+ * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions
+ * -XX:+UnlockDiagnosticVMOptions -XX:-FoldStableValues -XX:-UseCompressedOop
+ * -server -XX:-TieredCompilation -Xcomp
+ * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ * java.lang.invoke.TestStableInt
+ */
+package java.lang.invoke;
+
+import com.sun.management.HotSpotDiagnosticMXBean;
+import com.sun.management.VMOption;
+import sun.management.ManagementFactoryHelper;
+import java.lang.reflect.InvocationTargetException;
+
+public class TestStableInt {
+ public static void main(String[] args) throws Exception {
+ System.out.println("@Stable enabled: "+isStableEnabled);
+ System.out.println();
+
+ run(DefaultValue.class);
+ run(IntStable.class);
+ run(StaticIntStable.class);
+ run(VolatileIntStable.class);
+
+ // @Stable arrays: Dim 1-4
+ run(IntArrayDim1.class);
+ run(IntArrayDim2.class);
+ run(IntArrayDim3.class);
+ run(IntArrayDim4.class);
+
+ // @Stable Object field: dynamic arrays
+ run(ObjectArrayLowerDim0.class);
+ run(ObjectArrayLowerDim1.class);
+ run(ObjectArrayLowerDim2.class);
+
+ // Nested @Stable fields
+ run(NestedStableField.class);
+ run(NestedStableField1.class);
+ run(NestedStableField2.class);
+ run(NestedStableField3.class);
+
+ if (failed) {
+ throw new Error("TEST FAILED");
+ }
+ }
+
+ /* ==================================================== */
+
+ static class DefaultValue {
+ public @Stable int v;
+
+ public static final DefaultValue c = new DefaultValue();
+ public static int get() { return c.v; }
+ public static void test() throws Exception {
+ int val1 = get();
+ c.v = 1; int val2 = get();
+ assertEquals(val1, 0);
+ assertEquals(val2, 1);
+ }
+ }
+
+ /* ==================================================== */
+
+ static class IntStable {
+ public @Stable int v;
+
+ public static final IntStable c = new IntStable();
+ public static int get() { return c.v; }
+ public static void test() throws Exception {
+ c.v = 1; int val1 = get();
+ c.v = 2; int val2 = get();
+ assertEquals(val1, 1);
+ assertEquals(val2, (isStableEnabled ? 1 : 2));
+ }
+ }
+
+ /* ==================================================== */
+
+ static class StaticIntStable {
+ public static @Stable int v;
+
+ public static final StaticIntStable c = new StaticIntStable();
+ public static int get() { return c.v; }
+ public static void test() throws Exception {
+ c.v = 1; int val1 = get();
+ c.v = 2; int val2 = get();
+ assertEquals(val1, 1);
+ assertEquals(val2, (isStableEnabled ? 1 : 2));
+ }
+ }
+
+ /* ==================================================== */
+
+ static class VolatileIntStable {
+ public @Stable volatile int v;
+
+ public static final VolatileIntStable c = new VolatileIntStable();
+ public static int get() { return c.v; }
+ public static void test() throws Exception {
+ c.v = 1; int val1 = get();
+ c.v = 2; int val2 = get();
+ assertEquals(val1, 1);
+ assertEquals(val2, (isStableEnabled ? 1 : 2));
+ }
+ }
+
+ /* ==================================================== */
+ // @Stable array == field && all components are stable
+
+ static class IntArrayDim1 {
+ public @Stable int[] v;
+
+ public static final IntArrayDim1 c = new IntArrayDim1();
+ public static int get() { return c.v[0]; }
+ public static int get1() { return c.v[10]; }
+ public static int[] get2() { return c.v; }
+ public static void test() throws Exception {
+ {
+ c.v = new int[1]; c.v[0] = 1; int val1 = get();
+ c.v[0] = 2; int val2 = get();
+ assertEquals(val1, 1);
+ assertEquals(val2, (isStableEnabled ? 1 : 2));
+
+ c.v = new int[1]; c.v[0] = 3; int val3 = get();
+ assertEquals(val3, (isStableEnabled ? 1 : 3));
+ }
+
+ {
+ c.v = new int[20]; c.v[10] = 1; int val1 = get1();
+ c.v[10] = 2; int val2 = get1();
+ assertEquals(val1, 1);
+ assertEquals(val2, (isStableEnabled ? 1 : 2));
+
+ c.v = new int[20]; c.v[10] = 3; int val3 = get1();
+ assertEquals(val3, (isStableEnabled ? 1 : 3));
+ }
+
+ {
+ c.v = new int[1]; int[] val1 = get2();
+ c.v = new int[1]; int[] val2 = get2();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class IntArrayDim2 {
+ public @Stable int[][] v;
+
+ public static final IntArrayDim2 c = new IntArrayDim2();
+ public static int get() { return c.v[0][0]; }
+ public static int[] get1() { return c.v[0]; }
+ public static int[][] get2() { return c.v; }
+ public static void test() throws Exception {
+ {
+ c.v = new int[1][1]; c.v[0][0] = 1; int val1 = get();
+ c.v[0][0] = 2; int val2 = get();
+ assertEquals(val1, 1);
+ assertEquals(val2, (isStableEnabled ? 1 : 2));
+
+ c.v = new int[1][1]; c.v[0][0] = 3; int val3 = get();
+ assertEquals(val3, (isStableEnabled ? 1 : 3));
+
+ c.v[0] = new int[1]; c.v[0][0] = 4; int val4 = get();
+ assertEquals(val4, (isStableEnabled ? 1 : 4));
+ }
+
+ {
+ c.v = new int[1][1]; int[] val1 = get1();
+ c.v[0] = new int[1]; int[] val2 = get1();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new int[1][1]; int[][] val1 = get2();
+ c.v = new int[1][1]; int[][] val2 = get2();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class IntArrayDim3 {
+ public @Stable int[][][] v;
+
+ public static final IntArrayDim3 c = new IntArrayDim3();
+ public static int get() { return c.v[0][0][0]; }
+ public static int[] get1() { return c.v[0][0]; }
+ public static int[][] get2() { return c.v[0]; }
+ public static int[][][] get3() { return c.v; }
+ public static void test() throws Exception {
+ {
+ c.v = new int[1][1][1]; c.v[0][0][0] = 1; int val1 = get();
+ c.v[0][0][0] = 2; int val2 = get();
+ assertEquals(val1, 1);
+ assertEquals(val2, (isStableEnabled ? 1 : 2));
+
+ c.v = new int[1][1][1]; c.v[0][0][0] = 3; int val3 = get();
+ assertEquals(val3, (isStableEnabled ? 1 : 3));
+
+ c.v[0] = new int[1][1]; c.v[0][0][0] = 4; int val4 = get();
+ assertEquals(val4, (isStableEnabled ? 1 : 4));
+
+ c.v[0][0] = new int[1]; c.v[0][0][0] = 5; int val5 = get();
+ assertEquals(val5, (isStableEnabled ? 1 : 5));
+ }
+
+ {
+ c.v = new int[1][1][1]; int[] val1 = get1();
+ c.v[0][0] = new int[1]; int[] val2 = get1();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new int[1][1][1]; int[][] val1 = get2();
+ c.v[0] = new int[1][1]; int[][] val2 = get2();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new int[1][1][1]; int[][][] val1 = get3();
+ c.v = new int[1][1][1]; int[][][] val2 = get3();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class IntArrayDim4 {
+ public @Stable int[][][][] v;
+
+ public static final IntArrayDim4 c = new IntArrayDim4();
+ public static int get() { return c.v[0][0][0][0]; }
+ public static int[] get1() { return c.v[0][0][0]; }
+ public static int[][] get2() { return c.v[0][0]; }
+ public static int[][][] get3() { return c.v[0]; }
+ public static int[][][][] get4() { return c.v; }
+ public static void test() throws Exception {
+ {
+ c.v = new int[1][1][1][1]; c.v[0][0][0][0] = 1; int val1 = get();
+ c.v[0][0][0][0] = 2; int val2 = get();
+ assertEquals(val1, 1);
+ assertEquals(val2, (isStableEnabled ? 1 : 2));
+
+ c.v = new int[1][1][1][1]; c.v[0][0][0][0] = 3; int val3 = get();
+ assertEquals(val3, (isStableEnabled ? 1 : 3));
+
+ c.v[0] = new int[1][1][1]; c.v[0][0][0][0] = 4; int val4 = get();
+ assertEquals(val4, (isStableEnabled ? 1 : 4));
+
+ c.v[0][0] = new int[1][1]; c.v[0][0][0][0] = 5; int val5 = get();
+ assertEquals(val5, (isStableEnabled ? 1 : 5));
+
+ c.v[0][0][0] = new int[1]; c.v[0][0][0][0] = 6; int val6 = get();
+ assertEquals(val6, (isStableEnabled ? 1 : 6));
+ }
+
+ {
+ c.v = new int[1][1][1][1]; int[] val1 = get1();
+ c.v[0][0][0] = new int[1]; int[] val2 = get1();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new int[1][1][1][1]; int[][] val1 = get2();
+ c.v[0][0] = new int[1][1]; int[][] val2 = get2();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new int[1][1][1][1]; int[][][] val1 = get3();
+ c.v[0] = new int[1][1][1]; int[][][] val2 = get3();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new int[1][1][1][1]; int[][][][] val1 = get4();
+ c.v = new int[1][1][1][1]; int[][][][] val2 = get4();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ }
+ }
+
+ /* ==================================================== */
+ // Dynamic Dim is higher than static
+
+ static class ObjectArrayLowerDim0 {
+ public @Stable Object v;
+
+ public static final ObjectArrayLowerDim0 c = new ObjectArrayLowerDim0();
+ public static int get() { return ((int[])c.v)[0]; }
+ public static int[] get1() { return (int[])c.v; }
+
+ public static void test() throws Exception {
+ {
+ c.v = new int[1]; ((int[])c.v)[0] = 1; int val1 = get();
+ ((int[])c.v)[0] = 2; int val2 = get();
+
+ assertEquals(val1, 1);
+ assertEquals(val2, 2);
+ }
+
+ {
+ c.v = new int[1]; int[] val1 = get1();
+ c.v = new int[1]; int[] val2 = get1();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class ObjectArrayLowerDim1 {
+ public @Stable Object[] v;
+
+ public static final ObjectArrayLowerDim1 c = new ObjectArrayLowerDim1();
+ public static int get() { return ((int[][])c.v)[0][0]; }
+ public static int[] get1() { return (int[])(c.v[0]); }
+ public static Object[] get2() { return c.v; }
+
+ public static void test() throws Exception {
+ {
+ c.v = new int[1][1]; ((int[][])c.v)[0][0] = 1; int val1 = get();
+ ((int[][])c.v)[0][0] = 2; int val2 = get();
+
+ assertEquals(val1, 1);
+ assertEquals(val2, 2);
+ }
+
+ {
+ c.v = new int[1][1]; c.v[0] = new int[0]; int[] val1 = get1();
+ c.v[0] = new int[0]; int[] val2 = get1();
+
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new int[0][0]; Object[] val1 = get2();
+ c.v = new int[0][0]; Object[] val2 = get2();
+
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class ObjectArrayLowerDim2 {
+ public @Stable Object[][] v;
+
+ public static final ObjectArrayLowerDim2 c = new ObjectArrayLowerDim2();
+ public static int get() { return ((int[][][])c.v)[0][0][0]; }
+ public static int[] get1() { return (int[])(c.v[0][0]); }
+ public static int[][] get2() { return (int[][])(c.v[0]); }
+ public static Object[][] get3() { return c.v; }
+
+ public static void test() throws Exception {
+ {
+ c.v = new int[1][1][1]; ((int[][][])c.v)[0][0][0] = 1; int val1 = get();
+ ((int[][][])c.v)[0][0][0] = 2; int val2 = get();
+
+ assertEquals(val1, 1);
+ assertEquals(val2, 2);
+ }
+
+ {
+ c.v = new int[1][1][1]; c.v[0][0] = new int[0]; int[] val1 = get1();
+ c.v[0][0] = new int[0]; int[] val2 = get1();
+
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new int[1][1][1]; c.v[0] = new int[0][0]; int[][] val1 = get2();
+ c.v[0] = new int[0][0]; int[][] val2 = get2();
+
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new int[0][0][0]; Object[][] val1 = get3();
+ c.v = new int[0][0][0]; Object[][] val2 = get3();
+
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class NestedStableField {
+ static class A {
+ public @Stable int a;
+
+ }
+ public @Stable A v;
+
+ public static final NestedStableField c = new NestedStableField();
+ public static A get() { return c.v; }
+ public static int get1() { return get().a; }
+
+ public static void test() throws Exception {
+ {
+ c.v = new A(); c.v.a = 1; A val1 = get();
+ c.v.a = 2; A val2 = get();
+
+ assertEquals(val1.a, 2);
+ assertEquals(val2.a, 2);
+ }
+
+ {
+ c.v = new A(); c.v.a = 1; int val1 = get1();
+ c.v.a = 2; int val2 = get1();
+ c.v = new A(); c.v.a = 3; int val3 = get1();
+
+ assertEquals(val1, 1);
+ assertEquals(val2, (isStableEnabled ? 1 : 2));
+ assertEquals(val3, (isStableEnabled ? 1 : 3));
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class NestedStableField1 {
+ static class A {
+ public @Stable int a;
+ public @Stable A next;
+ }
+ public @Stable A v;
+
+ public static final NestedStableField1 c = new NestedStableField1();
+ public static A get() { return c.v.next.next.next.next.next.next.next; }
+ public static int get1() { return get().a; }
+
+ public static void test() throws Exception {
+ {
+ c.v = new A(); c.v.next = new A(); c.v.next.next = c.v;
+ c.v.a = 1; c.v.next.a = 1; A val1 = get();
+ c.v.a = 2; c.v.next.a = 2; A val2 = get();
+
+ assertEquals(val1.a, 2);
+ assertEquals(val2.a, 2);
+ }
+
+ {
+ c.v = new A(); c.v.next = c.v;
+ c.v.a = 1; int val1 = get1();
+ c.v.a = 2; int val2 = get1();
+ c.v = new A(); c.v.next = c.v;
+ c.v.a = 3; int val3 = get1();
+
+ assertEquals(val1, 1);
+ assertEquals(val2, (isStableEnabled ? 1 : 2));
+ assertEquals(val3, (isStableEnabled ? 1 : 3));
+ }
+ }
+ }
+ /* ==================================================== */
+
+ static class NestedStableField2 {
+ static class A {
+ public @Stable int a;
+ public @Stable A left;
+ public A right;
+ }
+
+ public @Stable A v;
+
+ public static final NestedStableField2 c = new NestedStableField2();
+ public static int get() { return c.v.left.left.left.a; }
+ public static int get1() { return c.v.left.left.right.left.a; }
+
+ public static void test() throws Exception {
+ {
+ c.v = new A(); c.v.left = c.v.right = c.v;
+ c.v.a = 1; int val1 = get(); int val2 = get1();
+ c.v.a = 2; int val3 = get(); int val4 = get1();
+
+ assertEquals(val1, 1);
+ assertEquals(val3, (isStableEnabled ? 1 : 2));
+
+ assertEquals(val2, 1);
+ assertEquals(val4, 2);
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class NestedStableField3 {
+ static class A {
+ public @Stable int a;
+ public @Stable A[] left;
+ public A[] right;
+ }
+
+ public @Stable A[] v;
+
+ public static final NestedStableField3 c = new NestedStableField3();
+ public static int get() { return c.v[0].left[1].left[0].left[1].a; }
+ public static int get1() { return c.v[1].left[0].left[1].right[0].left[1].a; }
+
+ public static void test() throws Exception {
+ {
+ A elem = new A();
+ c.v = new A[] { elem, elem }; c.v[0].left = c.v[0].right = c.v;
+ elem.a = 1; int val1 = get(); int val2 = get1();
+ elem.a = 2; int val3 = get(); int val4 = get1();
+
+ assertEquals(val1, 1);
+ assertEquals(val3, (isStableEnabled ? 1 : 2));
+
+ assertEquals(val2, 1);
+ assertEquals(val4, 2);
+ }
+ }
+ }
+
+ /* ==================================================== */
+ // Auxiliary methods
+ static void assertEquals(int i, int j) { if (i != j) throw new AssertionError(i + " != " + j); }
+ static void assertTrue(boolean b) { if (!b) throw new AssertionError(); }
+
+ static boolean failed = false;
+
+ public static void run(Class<?> test) {
+ Throwable ex = null;
+ System.out.print(test.getName()+": ");
+ try {
+ test.getMethod("test").invoke(null);
+ } catch (InvocationTargetException e) {
+ ex = e.getCause();
+ } catch (Throwable e) {
+ ex = e;
+ } finally {
+ if (ex == null) {
+ System.out.println("PASSED");
+ } else {
+ failed = true;
+ System.out.println("FAILED");
+ ex.printStackTrace(System.out);
+ }
+ }
+ }
+
+ static final boolean isStableEnabled;
+ static {
+ HotSpotDiagnosticMXBean diagnostic
+ = ManagementFactoryHelper.getDiagnosticMXBean();
+ VMOption tmp;
+ try {
+ tmp = diagnostic.getVMOption("FoldStableValues");
+ } catch (IllegalArgumentException e) {
+ tmp = null;
+ }
+ isStableEnabled = (tmp == null ? false : Boolean.parseBoolean(tmp.getValue()));
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/stable/TestStableLong.java Wed Mar 05 01:26:52 2014 -0800
@@ -0,0 +1,632 @@
+/*
+ * Copyright (c) 2014, 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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 TestStableLong
+ * @summary tests on stable fields and arrays
+ * @library /testlibrary
+ * @compile -XDignore.symbol.file TestStableLong.java
+ * @run main ClassFileInstaller
+ * java/lang/invoke/TestStableLong
+ * java/lang/invoke/TestStableLong$LongStable
+ * java/lang/invoke/TestStableLong$StaticLongStable
+ * java/lang/invoke/TestStableLong$VolatileLongStable
+ * java/lang/invoke/TestStableLong$LongArrayDim1
+ * java/lang/invoke/TestStableLong$LongArrayDim2
+ * java/lang/invoke/TestStableLong$LongArrayDim3
+ * java/lang/invoke/TestStableLong$LongArrayDim4
+ * java/lang/invoke/TestStableLong$ObjectArrayLowerDim0
+ * java/lang/invoke/TestStableLong$ObjectArrayLowerDim1
+ * java/lang/invoke/TestStableLong$NestedStableField
+ * java/lang/invoke/TestStableLong$NestedStableField$A
+ * java/lang/invoke/TestStableLong$NestedStableField1
+ * java/lang/invoke/TestStableLong$NestedStableField1$A
+ * java/lang/invoke/TestStableLong$NestedStableField2
+ * java/lang/invoke/TestStableLong$NestedStableField2$A
+ * java/lang/invoke/TestStableLong$NestedStableField3
+ * java/lang/invoke/TestStableLong$NestedStableField3$A
+ * java/lang/invoke/TestStableLong$DefaultValue
+ * java/lang/invoke/TestStableLong$ObjectArrayLowerDim2
+ *
+ * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions
+ * -XX:+UnlockDiagnosticVMOptions -XX:+FoldStableValues -XX:+UseCompressedOop
+ * -server -XX:-TieredCompilation -Xcomp
+ * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ * java.lang.invoke.TestStableLong
+ *
+ * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions
+ * -XX:+UnlockDiagnosticVMOptions -XX:+FoldStableValues -XX:-UseCompressedOop
+ * -server -XX:-TieredCompilation -Xcomp
+ * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ * java.lang.invoke.TestStableLong
+ *
+ * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions
+ * -XX:+UnlockDiagnosticVMOptions -XX:-FoldStableValues -XX:+UseCompressedOop
+ * -server -XX:-TieredCompilation -Xcomp
+ * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ * java.lang.invoke.TestStableLong
+ *
+ * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions
+ * -XX:+UnlockDiagnosticVMOptions -XX:-FoldStableValues -XX:-UseCompressedOop
+ * -server -XX:-TieredCompilation -Xcomp
+ * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ * java.lang.invoke.TestStableLong
+ */
+package java.lang.invoke;
+
+import com.sun.management.HotSpotDiagnosticMXBean;
+import com.sun.management.VMOption;
+import sun.management.ManagementFactoryHelper;
+import java.lang.reflect.InvocationTargetException;
+
+public class TestStableLong {
+ public static void main(String[] args) throws Exception {
+ System.out.println("@Stable enabled: "+isStableEnabled);
+ System.out.println();
+
+ run(DefaultValue.class);
+ run(LongStable.class);
+ run(StaticLongStable.class);
+ run(VolatileLongStable.class);
+
+ // @Stable arrays: Dim 1-4
+ run(LongArrayDim1.class);
+ run(LongArrayDim2.class);
+ run(LongArrayDim3.class);
+ run(LongArrayDim4.class);
+
+ // @Stable Object field: dynamic arrays
+ run(ObjectArrayLowerDim0.class);
+ run(ObjectArrayLowerDim1.class);
+ run(ObjectArrayLowerDim2.class);
+
+ // Nested @Stable fields
+ run(NestedStableField.class);
+ run(NestedStableField1.class);
+ run(NestedStableField2.class);
+ run(NestedStableField3.class);
+
+ if (failed) {
+ throw new Error("TEST FAILED");
+ }
+ }
+
+ /* ==================================================== */
+
+ static class DefaultValue {
+ public @Stable long v;
+
+ public static final DefaultValue c = new DefaultValue();
+ public static long get() { return c.v; }
+ public static void test() throws Exception {
+ long val1 = get();
+ c.v = 1L; long val2 = get();
+ assertEquals(val1, 0);
+ assertEquals(val2, 1L);
+ }
+ }
+
+ /* ==================================================== */
+
+ static class LongStable {
+ public @Stable long v;
+
+ public static final LongStable c = new LongStable();
+ public static long get() { return c.v; }
+ public static void test() throws Exception {
+ c.v = 5; long val1 = get();
+ c.v = Long.MAX_VALUE; long val2 = get();
+ assertEquals(val1, 5);
+ assertEquals(val2, (isStableEnabled ? 5 : Long.MAX_VALUE));
+ }
+ }
+
+ /* ==================================================== */
+
+ static class StaticLongStable {
+ public static @Stable long v;
+
+ public static final StaticLongStable c = new StaticLongStable();
+ public static long get() { return c.v; }
+ public static void test() throws Exception {
+ c.v = 5; long val1 = get();
+ c.v = Long.MAX_VALUE; long val2 = get();
+ assertEquals(val1, 5);
+ assertEquals(val2, (isStableEnabled ? 5 : Long.MAX_VALUE));
+ }
+ }
+
+ /* ==================================================== */
+
+ static class VolatileLongStable {
+ public @Stable volatile long v;
+
+ public static final VolatileLongStable c = new VolatileLongStable();
+ public static long get() { return c.v; }
+ public static void test() throws Exception {
+ c.v = 5; long val1 = get();
+ c.v = Long.MAX_VALUE; long val2 = get();
+ assertEquals(val1, 5);
+ assertEquals(val2, (isStableEnabled ? 5 : Long.MAX_VALUE));
+ }
+ }
+
+ /* ==================================================== */
+ // @Stable array == field && all components are stable
+
+ static class LongArrayDim1 {
+ public @Stable long[] v;
+
+ public static final LongArrayDim1 c = new LongArrayDim1();
+ public static long get() { return c.v[0]; }
+ public static long get1() { return c.v[10]; }
+ public static long[] get2() { return c.v; }
+ public static void test() throws Exception {
+ {
+ c.v = new long[1]; c.v[0] = 1; long val1 = get();
+ c.v[0] = 2; long val2 = get();
+ assertEquals(val1, 1);
+ assertEquals(val2, (isStableEnabled ? 1 : 2));
+
+ c.v = new long[1]; c.v[0] = 3; long val3 = get();
+ assertEquals(val3, (isStableEnabled ? 1 : 3));
+ }
+
+ {
+ c.v = new long[20]; c.v[10] = 1; long val1 = get1();
+ c.v[10] = 2; long val2 = get1();
+ assertEquals(val1, 1);
+ assertEquals(val2, (isStableEnabled ? 1 : 2));
+
+ c.v = new long[20]; c.v[10] = 3; long val3 = get1();
+ assertEquals(val3, (isStableEnabled ? 1 : 3));
+ }
+
+ {
+ c.v = new long[1]; long[] val1 = get2();
+ c.v = new long[1]; long[] val2 = get2();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class LongArrayDim2 {
+ public @Stable long[][] v;
+
+ public static final LongArrayDim2 c = new LongArrayDim2();
+ public static long get() { return c.v[0][0]; }
+ public static long[] get1() { return c.v[0]; }
+ public static long[][] get2() { return c.v; }
+ public static void test() throws Exception {
+ {
+ c.v = new long[1][1]; c.v[0][0] = 1; long val1 = get();
+ c.v[0][0] = 2; long val2 = get();
+ assertEquals(val1, 1);
+ assertEquals(val2, (isStableEnabled ? 1 : 2));
+
+ c.v = new long[1][1]; c.v[0][0] = 3; long val3 = get();
+ assertEquals(val3, (isStableEnabled ? 1 : 3));
+
+ c.v[0] = new long[1]; c.v[0][0] = 4; long val4 = get();
+ assertEquals(val4, (isStableEnabled ? 1 : 4));
+ }
+
+ {
+ c.v = new long[1][1]; long[] val1 = get1();
+ c.v[0] = new long[1]; long[] val2 = get1();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new long[1][1]; long[][] val1 = get2();
+ c.v = new long[1][1]; long[][] val2 = get2();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class LongArrayDim3 {
+ public @Stable long[][][] v;
+
+ public static final LongArrayDim3 c = new LongArrayDim3();
+ public static long get() { return c.v[0][0][0]; }
+ public static long[] get1() { return c.v[0][0]; }
+ public static long[][] get2() { return c.v[0]; }
+ public static long[][][] get3() { return c.v; }
+ public static void test() throws Exception {
+ {
+ c.v = new long[1][1][1]; c.v[0][0][0] = 1; long val1 = get();
+ c.v[0][0][0] = 2; long val2 = get();
+ assertEquals(val1, 1);
+ assertEquals(val2, (isStableEnabled ? 1 : 2));
+
+ c.v = new long[1][1][1]; c.v[0][0][0] = 3; long val3 = get();
+ assertEquals(val3, (isStableEnabled ? 1 : 3));
+
+ c.v[0] = new long[1][1]; c.v[0][0][0] = 4; long val4 = get();
+ assertEquals(val4, (isStableEnabled ? 1 : 4));
+
+ c.v[0][0] = new long[1]; c.v[0][0][0] = 5; long val5 = get();
+ assertEquals(val5, (isStableEnabled ? 1 : 5));
+ }
+
+ {
+ c.v = new long[1][1][1]; long[] val1 = get1();
+ c.v[0][0] = new long[1]; long[] val2 = get1();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new long[1][1][1]; long[][] val1 = get2();
+ c.v[0] = new long[1][1]; long[][] val2 = get2();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new long[1][1][1]; long[][][] val1 = get3();
+ c.v = new long[1][1][1]; long[][][] val2 = get3();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class LongArrayDim4 {
+ public @Stable long[][][][] v;
+
+ public static final LongArrayDim4 c = new LongArrayDim4();
+ public static long get() { return c.v[0][0][0][0]; }
+ public static long[] get1() { return c.v[0][0][0]; }
+ public static long[][] get2() { return c.v[0][0]; }
+ public static long[][][] get3() { return c.v[0]; }
+ public static long[][][][] get4() { return c.v; }
+ public static void test() throws Exception {
+ {
+ c.v = new long[1][1][1][1]; c.v[0][0][0][0] = 1; long val1 = get();
+ c.v[0][0][0][0] = 2; long val2 = get();
+ assertEquals(val1, 1);
+ assertEquals(val2, (isStableEnabled ? 1 : 2));
+
+ c.v = new long[1][1][1][1]; c.v[0][0][0][0] = 3; long val3 = get();
+ assertEquals(val3, (isStableEnabled ? 1 : 3));
+
+ c.v[0] = new long[1][1][1]; c.v[0][0][0][0] = 4; long val4 = get();
+ assertEquals(val4, (isStableEnabled ? 1 : 4));
+
+ c.v[0][0] = new long[1][1]; c.v[0][0][0][0] = 5; long val5 = get();
+ assertEquals(val5, (isStableEnabled ? 1 : 5));
+
+ c.v[0][0][0] = new long[1]; c.v[0][0][0][0] = 6; long val6 = get();
+ assertEquals(val6, (isStableEnabled ? 1 : 6));
+ }
+
+ {
+ c.v = new long[1][1][1][1]; long[] val1 = get1();
+ c.v[0][0][0] = new long[1]; long[] val2 = get1();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new long[1][1][1][1]; long[][] val1 = get2();
+ c.v[0][0] = new long[1][1]; long[][] val2 = get2();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new long[1][1][1][1]; long[][][] val1 = get3();
+ c.v[0] = new long[1][1][1]; long[][][] val2 = get3();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new long[1][1][1][1]; long[][][][] val1 = get4();
+ c.v = new long[1][1][1][1]; long[][][][] val2 = get4();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ }
+ }
+
+ /* ==================================================== */
+ // Dynamic Dim is higher than static
+
+ static class ObjectArrayLowerDim0 {
+ public @Stable Object v;
+
+ public static final ObjectArrayLowerDim0 c = new ObjectArrayLowerDim0();
+ public static long get() { return ((long[])c.v)[0]; }
+ public static long[] get1() { return (long[])c.v; }
+
+ public static void test() throws Exception {
+ {
+ c.v = new long[1]; ((long[])c.v)[0] = 1; long val1 = get();
+ ((long[])c.v)[0] = 2; long val2 = get();
+
+ assertEquals(val1, 1);
+ assertEquals(val2, 2);
+ }
+
+ {
+ c.v = new long[1]; long[] val1 = get1();
+ c.v = new long[1]; long[] val2 = get1();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class ObjectArrayLowerDim1 {
+ public @Stable Object[] v;
+
+ public static final ObjectArrayLowerDim1 c = new ObjectArrayLowerDim1();
+ public static long get() { return ((long[][])c.v)[0][0]; }
+ public static long[] get1() { return (long[])(c.v[0]); }
+ public static Object[] get2() { return c.v; }
+
+ public static void test() throws Exception {
+ {
+ c.v = new long[1][1]; ((long[][])c.v)[0][0] = 1; long val1 = get();
+ ((long[][])c.v)[0][0] = 2; long val2 = get();
+
+ assertEquals(val1, 1);
+ assertEquals(val2, 2);
+ }
+
+ {
+ c.v = new long[1][1]; c.v[0] = new long[0]; long[] val1 = get1();
+ c.v[0] = new long[0]; long[] val2 = get1();
+
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new long[0][0]; Object[] val1 = get2();
+ c.v = new long[0][0]; Object[] val2 = get2();
+
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class ObjectArrayLowerDim2 {
+ public @Stable Object[][] v;
+
+ public static final ObjectArrayLowerDim2 c = new ObjectArrayLowerDim2();
+ public static long get() { return ((long[][][])c.v)[0][0][0]; }
+ public static long[] get1() { return (long[])(c.v[0][0]); }
+ public static long[][] get2() { return (long[][])(c.v[0]); }
+ public static Object[][] get3() { return c.v; }
+
+ public static void test() throws Exception {
+ {
+ c.v = new long[1][1][1]; ((long[][][])c.v)[0][0][0] = 1L; long val1 = get();
+ ((long[][][])c.v)[0][0][0] = 2L; long val2 = get();
+
+ assertEquals(val1, 1L);
+ assertEquals(val2, 2L);
+ }
+
+ {
+ c.v = new long[1][1][1]; c.v[0][0] = new long[0]; long[] val1 = get1();
+ c.v[0][0] = new long[0]; long[] val2 = get1();
+
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new long[1][1][1]; c.v[0] = new long[0][0]; long[][] val1 = get2();
+ c.v[0] = new long[0][0]; long[][] val2 = get2();
+
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new long[0][0][0]; Object[][] val1 = get3();
+ c.v = new long[0][0][0]; Object[][] val2 = get3();
+
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class NestedStableField {
+ static class A {
+ public @Stable long a;
+
+ }
+ public @Stable A v;
+
+ public static final NestedStableField c = new NestedStableField();
+ public static A get() { return c.v; }
+ public static long get1() { return get().a; }
+
+ public static void test() throws Exception {
+ {
+ c.v = new A(); c.v.a = 1; A val1 = get();
+ c.v.a = 2; A val2 = get();
+
+ assertEquals(val1.a, 2);
+ assertEquals(val2.a, 2);
+ }
+
+ {
+ c.v = new A(); c.v.a = 1; long val1 = get1();
+ c.v.a = 2; long val2 = get1();
+ c.v = new A(); c.v.a = 3; long val3 = get1();
+
+ assertEquals(val1, 1);
+ assertEquals(val2, (isStableEnabled ? 1 : 2));
+ assertEquals(val3, (isStableEnabled ? 1 : 3));
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class NestedStableField1 {
+ static class A {
+ public @Stable long a;
+ public @Stable A next;
+ }
+ public @Stable A v;
+
+ public static final NestedStableField1 c = new NestedStableField1();
+ public static A get() { return c.v.next.next.next.next.next.next.next; }
+ public static long get1() { return get().a; }
+
+ public static void test() throws Exception {
+ {
+ c.v = new A(); c.v.next = new A(); c.v.next.next = c.v;
+ c.v.a = 1; c.v.next.a = 1; A val1 = get();
+ c.v.a = 2; c.v.next.a = 2; A val2 = get();
+
+ assertEquals(val1.a, 2);
+ assertEquals(val2.a, 2);
+ }
+
+ {
+ c.v = new A(); c.v.next = c.v;
+ c.v.a = 1; long val1 = get1();
+ c.v.a = 2; long val2 = get1();
+ c.v = new A(); c.v.next = c.v;
+ c.v.a = 3; long val3 = get1();
+
+ assertEquals(val1, 1);
+ assertEquals(val2, (isStableEnabled ? 1 : 2));
+ assertEquals(val3, (isStableEnabled ? 1 : 3));
+ }
+ }
+ }
+ /* ==================================================== */
+
+ static class NestedStableField2 {
+ static class A {
+ public @Stable long a;
+ public @Stable A left;
+ public A right;
+ }
+
+ public @Stable A v;
+
+ public static final NestedStableField2 c = new NestedStableField2();
+ public static long get() { return c.v.left.left.left.a; }
+ public static long get1() { return c.v.left.left.right.left.a; }
+
+ public static void test() throws Exception {
+ {
+ c.v = new A(); c.v.left = c.v.right = c.v;
+ c.v.a = 1; long val1 = get(); long val2 = get1();
+ c.v.a = 2; long val3 = get(); long val4 = get1();
+
+ assertEquals(val1, 1);
+ assertEquals(val3, (isStableEnabled ? 1 : 2));
+
+ assertEquals(val2, 1);
+ assertEquals(val4, 2);
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class NestedStableField3 {
+ static class A {
+ public @Stable long a;
+ public @Stable A[] left;
+ public A[] right;
+ }
+
+ public @Stable A[] v;
+
+ public static final NestedStableField3 c = new NestedStableField3();
+ public static long get() { return c.v[0].left[1].left[0].left[1].a; }
+ public static long get1() { return c.v[1].left[0].left[1].right[0].left[1].a; }
+
+ public static void test() throws Exception {
+ {
+ A elem = new A();
+ c.v = new A[] { elem, elem }; c.v[0].left = c.v[0].right = c.v;
+ elem.a = 1; long val1 = get(); long val2 = get1();
+ elem.a = 2; long val3 = get(); long val4 = get1();
+
+ assertEquals(val1, 1);
+ assertEquals(val3, (isStableEnabled ? 1 : 2));
+
+ assertEquals(val2, 1);
+ assertEquals(val4, 2);
+ }
+ }
+ }
+
+ /* ==================================================== */
+ // Auxiliary methods
+ static void assertEquals(long i, long j) { if (i != j) throw new AssertionError(i + " != " + j); }
+ static void assertTrue(boolean b) { if (!b) throw new AssertionError(); }
+
+ static boolean failed = false;
+
+ public static void run(Class<?> test) {
+ Throwable ex = null;
+ System.out.print(test.getName()+": ");
+ try {
+ test.getMethod("test").invoke(null);
+ } catch (InvocationTargetException e) {
+ ex = e.getCause();
+ } catch (Throwable e) {
+ ex = e;
+ } finally {
+ if (ex == null) {
+ System.out.println("PASSED");
+ } else {
+ failed = true;
+ System.out.println("FAILED");
+ ex.printStackTrace(System.out);
+ }
+ }
+ }
+
+ static final boolean isStableEnabled;
+ static {
+ HotSpotDiagnosticMXBean diagnostic
+ = ManagementFactoryHelper.getDiagnosticMXBean();
+ VMOption tmp;
+ try {
+ tmp = diagnostic.getVMOption("FoldStableValues");
+ } catch (IllegalArgumentException e) {
+ tmp = null;
+ }
+ isStableEnabled = (tmp == null ? false : Boolean.parseBoolean(tmp.getValue()));
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/stable/TestStableObject.java Wed Mar 05 01:26:52 2014 -0800
@@ -0,0 +1,635 @@
+/*
+ * Copyright (c) 2014, 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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 TestStableObject
+ * @summary tests on stable fields and arrays
+ * @library /testlibrary
+ * @compile -XDignore.symbol.file TestStableObject.java
+ * @run main ClassFileInstaller
+ * java/lang/invoke/TestStableObject
+ * java/lang/invoke/TestStableObject$ObjectStable
+ * java/lang/invoke/TestStableObject$StaticObjectStable
+ * java/lang/invoke/TestStableObject$VolatileObjectStable
+ * java/lang/invoke/TestStableObject$ObjectArrayDim1
+ * java/lang/invoke/TestStableObject$ObjectArrayDim2
+ * java/lang/invoke/TestStableObject$ObjectArrayDim3
+ * java/lang/invoke/TestStableObject$ObjectArrayDim4
+ * java/lang/invoke/TestStableObject$ObjectArrayLowerDim0
+ * java/lang/invoke/TestStableObject$ObjectArrayLowerDim1
+ * java/lang/invoke/TestStableObject$NestedStableField
+ * java/lang/invoke/TestStableObject$NestedStableField$A
+ * java/lang/invoke/TestStableObject$NestedStableField1
+ * java/lang/invoke/TestStableObject$NestedStableField1$A
+ * java/lang/invoke/TestStableObject$NestedStableField2
+ * java/lang/invoke/TestStableObject$NestedStableField2$A
+ * java/lang/invoke/TestStableObject$NestedStableField3
+ * java/lang/invoke/TestStableObject$NestedStableField3$A
+ * java/lang/invoke/TestStableObject$Values
+ * java/lang/invoke/TestStableObject$DefaultValue
+ * java/lang/invoke/TestStableObject$ObjectArrayLowerDim2
+ *
+ * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions
+ * -XX:+UnlockDiagnosticVMOptions -XX:+FoldStableValues -XX:+UseCompressedOop
+ * -server -XX:-TieredCompilation -Xcomp
+ * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ * java.lang.invoke.TestStableObject
+ *
+ * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions
+ * -XX:+UnlockDiagnosticVMOptions -XX:+FoldStableValues -XX:-UseCompressedOop
+ * -server -XX:-TieredCompilation -Xcomp
+ * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ * java.lang.invoke.TestStableObject
+ *
+ * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions
+ * -XX:+UnlockDiagnosticVMOptions -XX:-FoldStableValues -XX:+UseCompressedOop
+ * -server -XX:-TieredCompilation -Xcomp
+ * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ * java.lang.invoke.TestStableObject
+ *
+ * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions
+ * -XX:+UnlockDiagnosticVMOptions -XX:-FoldStableValues -XX:-UseCompressedOop
+ * -server -XX:-TieredCompilation -Xcomp
+ * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ * java.lang.invoke.TestStableObject
+ */
+package java.lang.invoke;
+
+import com.sun.management.HotSpotDiagnosticMXBean;
+import com.sun.management.VMOption;
+import sun.management.ManagementFactoryHelper;
+import java.lang.reflect.InvocationTargetException;
+
+public class TestStableObject {
+ public static void main(String[] args) throws Exception {
+ System.out.println("@Stable enabled: "+isStableEnabled);
+ System.out.println();
+
+ run(DefaultValue.class);
+ run(ObjectStable.class);
+ run(StaticObjectStable.class);
+ run(VolatileObjectStable.class);
+
+ // @Stable arrays: Dim 1-4
+ run(ObjectArrayDim1.class);
+ run(ObjectArrayDim2.class);
+ run(ObjectArrayDim3.class);
+ run(ObjectArrayDim4.class);
+
+ // @Stable Object field: dynamic arrays
+ run(ObjectArrayLowerDim0.class);
+ run(ObjectArrayLowerDim1.class);
+ run(ObjectArrayLowerDim2.class);
+
+ // Nested @Stable fields
+ run(NestedStableField.class);
+ run(NestedStableField1.class);
+ run(NestedStableField2.class);
+ run(NestedStableField3.class);
+
+ if (failed) {
+ throw new Error("TEST FAILED");
+ }
+ }
+
+ /* ==================================================== */
+
+ enum Values {A, B, C, D, E, F}
+
+ static class DefaultValue {
+ public @Stable Object v;
+
+ public static final DefaultValue c = new DefaultValue();
+ public static Object get() { return c.v; }
+ public static void test() throws Exception {
+ Object val1 = get();
+ c.v = Values.A; Object val2 = get();
+ assertEquals(val1, null);
+ assertEquals(val2, Values.A);
+ }
+ }
+
+ /* ==================================================== */
+
+ static class ObjectStable {
+ public @Stable Values v;
+
+ public static final ObjectStable c = new ObjectStable ();
+ public static Values get() { return c.v; }
+ public static void test() throws Exception {
+ c.v = Values.A; Values val1 = get();
+ c.v = Values.B; Values val2 = get();
+ assertEquals(val1, Values.A);
+ assertEquals(val2, (isStableEnabled ? Values.A : Values.B));
+ }
+ }
+
+ /* ==================================================== */
+
+ static class StaticObjectStable {
+ public static @Stable Values v;
+
+ public static final ObjectStable c = new ObjectStable ();
+ public static Values get() { return c.v; }
+ public static void test() throws Exception {
+ c.v = Values.A; Values val1 = get();
+ c.v = Values.B; Values val2 = get();
+ assertEquals(val1, Values.A);
+ assertEquals(val2, (isStableEnabled ? Values.A : Values.B));
+ }
+ }
+
+ /* ==================================================== */
+
+ static class VolatileObjectStable {
+ public @Stable volatile Values v;
+
+ public static final VolatileObjectStable c = new VolatileObjectStable ();
+ public static Values get() { return c.v; }
+ public static void test() throws Exception {
+ c.v = Values.A; Values val1 = get();
+ c.v = Values.B; Values val2 = get();
+ assertEquals(val1, Values.A);
+ assertEquals(val2, (isStableEnabled ? Values.A : Values.B));
+ }
+ }
+
+ /* ==================================================== */
+ // @Stable array == field && all components are stable
+
+ static class ObjectArrayDim1 {
+ public @Stable Object[] v;
+
+ public static final ObjectArrayDim1 c = new ObjectArrayDim1();
+ public static Object get() { return c.v[0]; }
+ public static Object get1() { return c.v[10]; }
+ public static Object[] get2() { return c.v; }
+ public static void test() throws Exception {
+ {
+ c.v = new Object[1]; c.v[0] = Values.A; Object val1 = get();
+ c.v[0] = Values.B; Object val2 = get();
+ assertEquals(val1, Values.A);
+ assertEquals(val2, (isStableEnabled ? Values.A : Values.B));
+
+ c.v = new Object[1]; c.v[0] = Values.C; Object val3 = get();
+ assertEquals(val3, (isStableEnabled ? Values.A : Values.C));
+ }
+
+ {
+ c.v = new Object[20]; c.v[10] = Values.A; Object val1 = get1();
+ c.v[10] = Values.B; Object val2 = get1();
+ assertEquals(val1, Values.A);
+ assertEquals(val2, (isStableEnabled ? Values.A : Values.B));
+
+ c.v = new Object[20]; c.v[10] = Values.C; Object val3 = get1();
+ assertEquals(val3, (isStableEnabled ? Values.A : Values.C));
+ }
+
+ {
+ c.v = new Object[1]; Object[] val1 = get2();
+ c.v = new Object[1]; Object[] val2 = get2();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class ObjectArrayDim2 {
+ public @Stable Object[][] v;
+
+ public static final ObjectArrayDim2 c = new ObjectArrayDim2();
+ public static Object get() { return c.v[0][0]; }
+ public static Object[] get1() { return c.v[0]; }
+ public static Object[][] get2() { return c.v; }
+ public static void test() throws Exception {
+ {
+ c.v = new Object[1][1]; c.v[0][0] = Values.A; Object val1 = get();
+ c.v[0][0] = Values.B; Object val2 = get();
+ assertEquals(val1, Values.A);
+ assertEquals(val2, (isStableEnabled ? Values.A : Values.B));
+
+ c.v = new Object[1][1]; c.v[0][0] = Values.C; Object val3 = get();
+ assertEquals(val3, (isStableEnabled ? Values.A : Values.C));
+
+ c.v[0] = new Object[1]; c.v[0][0] = Values.D; Object val4 = get();
+ assertEquals(val4, (isStableEnabled ? Values.A : Values.D));
+ }
+
+ {
+ c.v = new Object[1][1]; Object[] val1 = get1();
+ c.v[0] = new Object[1]; Object[] val2 = get1();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new Object[1][1]; Object[][] val1 = get2();
+ c.v = new Object[1][1]; Object[][] val2 = get2();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class ObjectArrayDim3 {
+ public @Stable Object[][][] v;
+
+ public static final ObjectArrayDim3 c = new ObjectArrayDim3();
+ public static Object get() { return c.v[0][0][0]; }
+ public static Object[] get1() { return c.v[0][0]; }
+ public static Object[][] get2() { return c.v[0]; }
+ public static Object[][][] get3() { return c.v; }
+ public static void test() throws Exception {
+ {
+ c.v = new Object[1][1][1]; c.v[0][0][0] = Values.A; Object val1 = get();
+ c.v[0][0][0] = Values.B; Object val2 = get();
+ assertEquals(val1, Values.A);
+ assertEquals(val2, (isStableEnabled ? Values.A : Values.B));
+
+ c.v = new Object[1][1][1]; c.v[0][0][0] = Values.C; Object val3 = get();
+ assertEquals(val3, (isStableEnabled ? Values.A : Values.C));
+
+ c.v[0] = new Object[1][1]; c.v[0][0][0] = Values.D; Object val4 = get();
+ assertEquals(val4, (isStableEnabled ? Values.A : Values.D));
+
+ c.v[0][0] = new Object[1]; c.v[0][0][0] = Values.E; Object val5 = get();
+ assertEquals(val5, (isStableEnabled ? Values.A : Values.E));
+ }
+
+ {
+ c.v = new Object[1][1][1]; Object[] val1 = get1();
+ c.v[0][0] = new Object[1]; Object[] val2 = get1();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new Object[1][1][1]; Object[][] val1 = get2();
+ c.v[0] = new Object[1][1]; Object[][] val2 = get2();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new Object[1][1][1]; Object[][][] val1 = get3();
+ c.v = new Object[1][1][1]; Object[][][] val2 = get3();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class ObjectArrayDim4 {
+ public @Stable Object[][][][] v;
+
+ public static final ObjectArrayDim4 c = new ObjectArrayDim4();
+ public static Object get() { return c.v[0][0][0][0]; }
+ public static Object[] get1() { return c.v[0][0][0]; }
+ public static Object[][] get2() { return c.v[0][0]; }
+ public static Object[][][] get3() { return c.v[0]; }
+ public static Object[][][][] get4() { return c.v; }
+ public static void test() throws Exception {
+ {
+ c.v = new Object[1][1][1][1]; c.v[0][0][0][0] = Values.A; Object val1 = get();
+ c.v[0][0][0][0] = Values.B; Object val2 = get();
+ assertEquals(val1, Values.A);
+ assertEquals(val2, (isStableEnabled ? Values.A : Values.B));
+
+ c.v = new Object[1][1][1][1]; c.v[0][0][0][0] = Values.C; Object val3 = get();
+ assertEquals(val3, (isStableEnabled ? Values.A : Values.C));
+
+ c.v[0] = new Object[1][1][1]; c.v[0][0][0][0] = Values.D; Object val4 = get();
+ assertEquals(val4, (isStableEnabled ? Values.A : Values.D));
+
+ c.v[0][0] = new Object[1][1]; c.v[0][0][0][0] = Values.E; Object val5 = get();
+ assertEquals(val5, (isStableEnabled ? Values.A : Values.E));
+
+ c.v[0][0][0] = new Object[1]; c.v[0][0][0][0] = Values.F; Object val6 = get();
+ assertEquals(val6, (isStableEnabled ? Values.A : Values.F));
+ }
+
+ {
+ c.v = new Object[1][1][1][1]; Object[] val1 = get1();
+ c.v[0][0][0] = new Object[1]; Object[] val2 = get1();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new Object[1][1][1][1]; Object[][] val1 = get2();
+ c.v[0][0] = new Object[1][1]; Object[][] val2 = get2();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new Object[1][1][1][1]; Object[][][] val1 = get3();
+ c.v[0] = new Object[1][1][1]; Object[][][] val2 = get3();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new Object[1][1][1][1]; Object[][][][] val1 = get4();
+ c.v = new Object[1][1][1][1]; Object[][][][] val2 = get4();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ }
+ }
+
+ /* ==================================================== */
+ // Dynamic Dim is higher than static
+
+ static class ObjectArrayLowerDim0 {
+ public @Stable Object v;
+
+ public static final ObjectArrayLowerDim0 c = new ObjectArrayLowerDim0();
+ public static Object get() { return ((Object[])c.v)[0]; }
+ public static Object[] get1() { return (Object[])c.v; }
+
+ public static void test() throws Exception {
+ {
+ c.v = new Object[1]; ((Object[])c.v)[0] = Values.A; Object val1 = get();
+ ((Object[])c.v)[0] = Values.B; Object val2 = get();
+
+ assertEquals(val1, Values.A);
+ assertEquals(val2, Values.B);
+ }
+
+ {
+ c.v = new Object[1]; Object[] val1 = get1();
+ c.v = new Object[1]; Object[] val2 = get1();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class ObjectArrayLowerDim1 {
+ public @Stable Object[] v;
+
+ public static final ObjectArrayLowerDim1 c = new ObjectArrayLowerDim1();
+ public static Object get() { return ((Object[][])c.v)[0][0]; }
+ public static Object[] get1() { return (Object[])(c.v[0]); }
+ public static Object[] get2() { return c.v; }
+
+ public static void test() throws Exception {
+ {
+ c.v = new Object[1][1]; ((Object[][])c.v)[0][0] = Values.A; Object val1 = get();
+ ((Object[][])c.v)[0][0] = Values.B; Object val2 = get();
+
+ assertEquals(val1, Values.A);
+ assertEquals(val2, Values.B);
+ }
+
+ {
+ c.v = new Object[1][1]; c.v[0] = new Object[0]; Object[] val1 = get1();
+ c.v[0] = new Object[0]; Object[] val2 = get1();
+
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new Object[0][0]; Object[] val1 = get2();
+ c.v = new Object[0][0]; Object[] val2 = get2();
+
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class ObjectArrayLowerDim2 {
+ public @Stable Object[][] v;
+
+ public static final ObjectArrayLowerDim2 c = new ObjectArrayLowerDim2();
+ public static Object get() { return ((Object[][][])c.v)[0][0][0]; }
+ public static Object[] get1() { return (Object[])(c.v[0][0]); }
+ public static Object[][] get2() { return (Object[][])(c.v[0]); }
+ public static Object[][] get3() { return c.v; }
+
+ public static void test() throws Exception {
+ {
+ c.v = new Object[1][1][1]; ((Object[][][])c.v)[0][0][0] = Values.A; Object val1 = get();
+ ((Object[][][])c.v)[0][0][0] = Values.B; Object val2 = get();
+
+ assertEquals(val1, Values.A);
+ assertEquals(val2, Values.B);
+ }
+
+ {
+ c.v = new Object[1][1][1]; c.v[0][0] = new Object[0]; Object[] val1 = get1();
+ c.v[0][0] = new Object[0]; Object[] val2 = get1();
+
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new Object[1][1][1]; c.v[0] = new Object[0][0]; Object[][] val1 = get2();
+ c.v[0] = new Object[0][0]; Object[][] val2 = get2();
+
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new Object[0][0][0]; Object[][] val1 = get3();
+ c.v = new Object[0][0][0]; Object[][] val2 = get3();
+
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class NestedStableField {
+ static class A {
+ public @Stable Object a;
+
+ }
+ public @Stable A v;
+
+ public static final NestedStableField c = new NestedStableField();
+ public static A get() { return c.v; }
+ public static Object get1() { return get().a; }
+
+ public static void test() throws Exception {
+ {
+ c.v = new A(); c.v.a = Values.A; A val1 = get();
+ c.v.a = Values.B; A val2 = get();
+
+ assertEquals(val1.a, Values.B);
+ assertEquals(val2.a, Values.B);
+ }
+
+ {
+ c.v = new A(); c.v.a = Values.A; Object val1 = get1();
+ c.v.a = Values.B; Object val2 = get1();
+ c.v = new A(); c.v.a = Values.C; Object val3 = get1();
+
+ assertEquals(val1, Values.A);
+ assertEquals(val2, (isStableEnabled ? Values.A : Values.B));
+ assertEquals(val3, (isStableEnabled ? Values.A : Values.C));
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class NestedStableField1 {
+ static class A {
+ public @Stable Object a;
+ public @Stable A next;
+ }
+ public @Stable A v;
+
+ public static final NestedStableField1 c = new NestedStableField1();
+ public static A get() { return c.v.next.next.next.next.next.next.next; }
+ public static Object get1() { return get().a; }
+
+ public static void test() throws Exception {
+ {
+ c.v = new A(); c.v.next = new A(); c.v.next.next = c.v;
+ c.v.a = Values.A; c.v.next.a = Values.A; A val1 = get();
+ c.v.a = Values.B; c.v.next.a = Values.B; A val2 = get();
+
+ assertEquals(val1.a, Values.B);
+ assertEquals(val2.a, Values.B);
+ }
+
+ {
+ c.v = new A(); c.v.next = c.v;
+ c.v.a = Values.A; Object val1 = get1();
+ c.v.a = Values.B; Object val2 = get1();
+ c.v = new A(); c.v.next = c.v;
+ c.v.a = Values.C; Object val3 = get1();
+
+ assertEquals(val1, Values.A);
+ assertEquals(val2, (isStableEnabled ? Values.A : Values.B));
+ assertEquals(val3, (isStableEnabled ? Values.A : Values.C));
+ }
+ }
+ }
+ /* ==================================================== */
+
+ static class NestedStableField2 {
+ static class A {
+ public @Stable Object a;
+ public @Stable A left;
+ public A right;
+ }
+
+ public @Stable A v;
+
+ public static final NestedStableField2 c = new NestedStableField2();
+ public static Object get() { return c.v.left.left.left.a; }
+ public static Object get1() { return c.v.left.left.right.left.a; }
+
+ public static void test() throws Exception {
+ {
+ c.v = new A(); c.v.left = c.v.right = c.v;
+ c.v.a = Values.A; Object val1 = get(); Object val2 = get1();
+ c.v.a = Values.B; Object val3 = get(); Object val4 = get1();
+
+ assertEquals(val1, Values.A);
+ assertEquals(val3, (isStableEnabled ? Values.A : Values.B));
+
+ assertEquals(val2, Values.A);
+ assertEquals(val4, Values.B);
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class NestedStableField3 {
+ static class A {
+ public @Stable Object a;
+ public @Stable A[] left;
+ public A[] right;
+ }
+
+ public @Stable A[] v;
+
+ public static final NestedStableField3 c = new NestedStableField3();
+ public static Object get() { return c.v[0].left[1].left[0].left[1].a; }
+ public static Object get1() { return c.v[1].left[0].left[1].right[0].left[1].a; }
+
+ public static void test() throws Exception {
+ {
+ A elem = new A();
+ c.v = new A[] { elem, elem }; c.v[0].left = c.v[0].right = c.v;
+ elem.a = Values.A; Object val1 = get(); Object val2 = get1();
+ elem.a = Values.B; Object val3 = get(); Object val4 = get1();
+
+ assertEquals(val1, Values.A);
+ assertEquals(val3, (isStableEnabled ? Values.A : Values.B));
+
+ assertEquals(val2, Values.A);
+ assertEquals(val4, Values.B);
+ }
+ }
+ }
+
+ /* ==================================================== */
+ // Auxiliary methods
+ static void assertEquals(Object i, Object j) { if (i != j) throw new AssertionError(i + " != " + j); }
+ static void assertTrue(boolean b) { if (!b) throw new AssertionError(); }
+
+ static boolean failed = false;
+
+ public static void run(Class<?> test) {
+ Throwable ex = null;
+ System.out.print(test.getName()+": ");
+ try {
+ test.getMethod("test").invoke(null);
+ } catch (InvocationTargetException e) {
+ ex = e.getCause();
+ } catch (Throwable e) {
+ ex = e;
+ } finally {
+ if (ex == null) {
+ System.out.println("PASSED");
+ } else {
+ failed = true;
+ System.out.println("FAILED");
+ ex.printStackTrace(System.out);
+ }
+ }
+ }
+
+ static final boolean isStableEnabled;
+ static {
+ HotSpotDiagnosticMXBean diagnostic
+ = ManagementFactoryHelper.getDiagnosticMXBean();
+ VMOption tmp;
+ try {
+ tmp = diagnostic.getVMOption("FoldStableValues");
+ } catch (IllegalArgumentException e) {
+ tmp = null;
+ }
+ isStableEnabled = (tmp == null ? false : Boolean.parseBoolean(tmp.getValue()));
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/stable/TestStableShort.java Wed Mar 05 01:26:52 2014 -0800
@@ -0,0 +1,632 @@
+/*
+ * Copyright (c) 2014, 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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 TestStableShort
+ * @summary tests on stable fields and arrays
+ * @library /testlibrary
+ * @compile -XDignore.symbol.file TestStableShort.java
+ * @run main ClassFileInstaller
+ * java/lang/invoke/TestStableShort
+ * java/lang/invoke/TestStableShort$ShortStable
+ * java/lang/invoke/TestStableShort$StaticShortStable
+ * java/lang/invoke/TestStableShort$VolatileShortStable
+ * java/lang/invoke/TestStableShort$ShortArrayDim1
+ * java/lang/invoke/TestStableShort$ShortArrayDim2
+ * java/lang/invoke/TestStableShort$ShortArrayDim3
+ * java/lang/invoke/TestStableShort$ShortArrayDim4
+ * java/lang/invoke/TestStableShort$ObjectArrayLowerDim0
+ * java/lang/invoke/TestStableShort$ObjectArrayLowerDim1
+ * java/lang/invoke/TestStableShort$NestedStableField
+ * java/lang/invoke/TestStableShort$NestedStableField$A
+ * java/lang/invoke/TestStableShort$NestedStableField1
+ * java/lang/invoke/TestStableShort$NestedStableField1$A
+ * java/lang/invoke/TestStableShort$NestedStableField2
+ * java/lang/invoke/TestStableShort$NestedStableField2$A
+ * java/lang/invoke/TestStableShort$NestedStableField3
+ * java/lang/invoke/TestStableShort$NestedStableField3$A
+ * java/lang/invoke/TestStableShort$DefaultValue
+ * java/lang/invoke/TestStableShort$ObjectArrayLowerDim2
+ *
+ * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions
+ * -XX:+UnlockDiagnosticVMOptions -XX:+FoldStableValues -XX:+UseCompressedOop
+ * -server -XX:-TieredCompilation -Xcomp
+ * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ * java.lang.invoke.TestStableShort
+ *
+ * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions
+ * -XX:+UnlockDiagnosticVMOptions -XX:+FoldStableValues -XX:-UseCompressedOop
+ * -server -XX:-TieredCompilation -Xcomp
+ * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ * java.lang.invoke.TestStableShort
+ *
+ * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions
+ * -XX:+UnlockDiagnosticVMOptions -XX:-FoldStableValues -XX:+UseCompressedOop
+ * -server -XX:-TieredCompilation -Xcomp
+ * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ * java.lang.invoke.TestStableShort
+ *
+ * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions
+ * -XX:+UnlockDiagnosticVMOptions -XX:-FoldStableValues -XX:-UseCompressedOop
+ * -server -XX:-TieredCompilation -Xcomp
+ * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4
+ * java.lang.invoke.TestStableShort
+ */
+package java.lang.invoke;
+
+import com.sun.management.HotSpotDiagnosticMXBean;
+import com.sun.management.VMOption;
+import sun.management.ManagementFactoryHelper;
+import java.lang.reflect.InvocationTargetException;
+
+public class TestStableShort {
+ public static void main(String[] args) throws Exception {
+ System.out.println("@Stable enabled: "+isStableEnabled);
+ System.out.println();
+
+ run(DefaultValue.class);
+ run(ShortStable.class);
+ run(StaticShortStable.class);
+ run(VolatileShortStable.class);
+
+ // @Stable arrays: Dim 1-4
+ run(ShortArrayDim1.class);
+ run(ShortArrayDim2.class);
+ run(ShortArrayDim3.class);
+ run(ShortArrayDim4.class);
+
+ // @Stable Object field: dynamic arrays
+ run(ObjectArrayLowerDim0.class);
+ run(ObjectArrayLowerDim1.class);
+ run(ObjectArrayLowerDim2.class);
+
+ // Nested @Stable fields
+ run(NestedStableField.class);
+ run(NestedStableField1.class);
+ run(NestedStableField2.class);
+ run(NestedStableField3.class);
+
+ if (failed) {
+ throw new Error("TEST FAILED");
+ }
+ }
+
+ /* ==================================================== */
+
+ static class DefaultValue {
+ public @Stable short v;
+
+ public static final DefaultValue c = new DefaultValue();
+ public static short get() { return c.v; }
+ public static void test() throws Exception {
+ short val1 = get();
+ c.v = 1; short val2 = get();
+ assertEquals(val1, 0);
+ assertEquals(val2, 1);
+ }
+ }
+
+ /* ==================================================== */
+
+ static class ShortStable {
+ public @Stable short v;
+
+ public static final ShortStable c = new ShortStable();
+ public static short get() { return c.v; }
+ public static void test() throws Exception {
+ c.v = 1; short val1 = get();
+ c.v = 32767; short val2 = get();
+ assertEquals(val1, 1);
+ assertEquals(val2, (isStableEnabled ? 1 : 32767));
+ }
+ }
+
+ /* ==================================================== */
+
+ static class StaticShortStable {
+ public static @Stable short v;
+
+ public static final StaticShortStable c = new StaticShortStable();
+ public static short get() { return c.v; }
+ public static void test() throws Exception {
+ c.v = 1; short val1 = get();
+ c.v = 32767; short val2 = get();
+ assertEquals(val1, 1);
+ assertEquals(val2, (isStableEnabled ? 1 : 32767));
+ }
+ }
+
+ /* ==================================================== */
+
+ static class VolatileShortStable {
+ public @Stable volatile short v;
+
+ public static final VolatileShortStable c = new VolatileShortStable();
+ public static short get() { return c.v; }
+ public static void test() throws Exception {
+ c.v = 1; short val1 = get();
+ c.v = 32767; short val2 = get();
+ assertEquals(val1, 1);
+ assertEquals(val2, (isStableEnabled ? 1 : 32767));
+ }
+ }
+
+ /* ==================================================== */
+ // @Stable array == field && all components are stable
+
+ static class ShortArrayDim1 {
+ public @Stable short[] v;
+
+ public static final ShortArrayDim1 c = new ShortArrayDim1();
+ public static short get() { return c.v[0]; }
+ public static short get1() { return c.v[10]; }
+ public static short[] get2() { return c.v; }
+ public static void test() throws Exception {
+ {
+ c.v = new short[1]; c.v[0] = 1; short val1 = get();
+ c.v[0] = 2; short val2 = get();
+ assertEquals(val1, 1);
+ assertEquals(val2, (isStableEnabled ? 1 : 2));
+
+ c.v = new short[1]; c.v[0] = 3; short val3 = get();
+ assertEquals(val3, (isStableEnabled ? 1 : 3));
+ }
+
+ {
+ c.v = new short[20]; c.v[10] = 1; short val1 = get1();
+ c.v[10] = 2; short val2 = get1();
+ assertEquals(val1, 1);
+ assertEquals(val2, (isStableEnabled ? 1 : 2));
+
+ c.v = new short[20]; c.v[10] = 3; short val3 = get1();
+ assertEquals(val3, (isStableEnabled ? 1 : 3));
+ }
+
+ {
+ c.v = new short[1]; short[] val1 = get2();
+ c.v = new short[1]; short[] val2 = get2();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class ShortArrayDim2 {
+ public @Stable short[][] v;
+
+ public static final ShortArrayDim2 c = new ShortArrayDim2();
+ public static short get() { return c.v[0][0]; }
+ public static short[] get1() { return c.v[0]; }
+ public static short[][] get2() { return c.v; }
+ public static void test() throws Exception {
+ {
+ c.v = new short[1][1]; c.v[0][0] = 1; short val1 = get();
+ c.v[0][0] = 2; short val2 = get();
+ assertEquals(val1, 1);
+ assertEquals(val2, (isStableEnabled ? 1 : 2));
+
+ c.v = new short[1][1]; c.v[0][0] = 3; short val3 = get();
+ assertEquals(val3, (isStableEnabled ? 1 : 3));
+
+ c.v[0] = new short[1]; c.v[0][0] = 4; short val4 = get();
+ assertEquals(val4, (isStableEnabled ? 1 : 4));
+ }
+
+ {
+ c.v = new short[1][1]; short[] val1 = get1();
+ c.v[0] = new short[1]; short[] val2 = get1();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new short[1][1]; short[][] val1 = get2();
+ c.v = new short[1][1]; short[][] val2 = get2();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class ShortArrayDim3 {
+ public @Stable short[][][] v;
+
+ public static final ShortArrayDim3 c = new ShortArrayDim3();
+ public static short get() { return c.v[0][0][0]; }
+ public static short[] get1() { return c.v[0][0]; }
+ public static short[][] get2() { return c.v[0]; }
+ public static short[][][] get3() { return c.v; }
+ public static void test() throws Exception {
+ {
+ c.v = new short[1][1][1]; c.v[0][0][0] = 1; short val1 = get();
+ c.v[0][0][0] = 2; short val2 = get();
+ assertEquals(val1, 1);
+ assertEquals(val2, (isStableEnabled ? 1 : 2));
+
+ c.v = new short[1][1][1]; c.v[0][0][0] = 3; short val3 = get();
+ assertEquals(val3, (isStableEnabled ? 1 : 3));
+
+ c.v[0] = new short[1][1]; c.v[0][0][0] = 4; short val4 = get();
+ assertEquals(val4, (isStableEnabled ? 1 : 4));
+
+ c.v[0][0] = new short[1]; c.v[0][0][0] = 5; short val5 = get();
+ assertEquals(val5, (isStableEnabled ? 1 : 5));
+ }
+
+ {
+ c.v = new short[1][1][1]; short[] val1 = get1();
+ c.v[0][0] = new short[1]; short[] val2 = get1();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new short[1][1][1]; short[][] val1 = get2();
+ c.v[0] = new short[1][1]; short[][] val2 = get2();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new short[1][1][1]; short[][][] val1 = get3();
+ c.v = new short[1][1][1]; short[][][] val2 = get3();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class ShortArrayDim4 {
+ public @Stable short[][][][] v;
+
+ public static final ShortArrayDim4 c = new ShortArrayDim4();
+ public static short get() { return c.v[0][0][0][0]; }
+ public static short[] get1() { return c.v[0][0][0]; }
+ public static short[][] get2() { return c.v[0][0]; }
+ public static short[][][] get3() { return c.v[0]; }
+ public static short[][][][] get4() { return c.v; }
+ public static void test() throws Exception {
+ {
+ c.v = new short[1][1][1][1]; c.v[0][0][0][0] = 1; short val1 = get();
+ c.v[0][0][0][0] = 2; short val2 = get();
+ assertEquals(val1, 1);
+ assertEquals(val2, (isStableEnabled ? 1 : 2));
+
+ c.v = new short[1][1][1][1]; c.v[0][0][0][0] = 3; short val3 = get();
+ assertEquals(val3, (isStableEnabled ? 1 : 3));
+
+ c.v[0] = new short[1][1][1]; c.v[0][0][0][0] = 4; short val4 = get();
+ assertEquals(val4, (isStableEnabled ? 1 : 4));
+
+ c.v[0][0] = new short[1][1]; c.v[0][0][0][0] = 5; short val5 = get();
+ assertEquals(val5, (isStableEnabled ? 1 : 5));
+
+ c.v[0][0][0] = new short[1]; c.v[0][0][0][0] = 6; short val6 = get();
+ assertEquals(val6, (isStableEnabled ? 1 : 6));
+ }
+
+ {
+ c.v = new short[1][1][1][1]; short[] val1 = get1();
+ c.v[0][0][0] = new short[1]; short[] val2 = get1();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new short[1][1][1][1]; short[][] val1 = get2();
+ c.v[0][0] = new short[1][1]; short[][] val2 = get2();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new short[1][1][1][1]; short[][][] val1 = get3();
+ c.v[0] = new short[1][1][1]; short[][][] val2 = get3();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new short[1][1][1][1]; short[][][][] val1 = get4();
+ c.v = new short[1][1][1][1]; short[][][][] val2 = get4();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ }
+ }
+
+ /* ==================================================== */
+ // Dynamic Dim is higher than static
+
+ static class ObjectArrayLowerDim0 {
+ public @Stable Object v;
+
+ public static final ObjectArrayLowerDim0 c = new ObjectArrayLowerDim0();
+ public static short get() { return ((short[])c.v)[0]; }
+ public static short[] get1() { return (short[])c.v; }
+
+ public static void test() throws Exception {
+ {
+ c.v = new short[1]; ((short[])c.v)[0] = 1; short val1 = get();
+ ((short[])c.v)[0] = 2; short val2 = get();
+
+ assertEquals(val1, 1);
+ assertEquals(val2, 2);
+ }
+
+ {
+ c.v = new short[1]; short[] val1 = get1();
+ c.v = new short[1]; short[] val2 = get1();
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class ObjectArrayLowerDim1 {
+ public @Stable Object[] v;
+
+ public static final ObjectArrayLowerDim1 c = new ObjectArrayLowerDim1();
+ public static short get() { return ((short[][])c.v)[0][0]; }
+ public static short[] get1() { return (short[])(c.v[0]); }
+ public static Object[] get2() { return c.v; }
+
+ public static void test() throws Exception {
+ {
+ c.v = new short[1][1]; ((short[][])c.v)[0][0] = 1; short val1 = get();
+ ((short[][])c.v)[0][0] = 2; short val2 = get();
+
+ assertEquals(val1, 1);
+ assertEquals(val2, 2);
+ }
+
+ {
+ c.v = new short[1][1]; c.v[0] = new short[0]; short[] val1 = get1();
+ c.v[0] = new short[0]; short[] val2 = get1();
+
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new short[0][0]; Object[] val1 = get2();
+ c.v = new short[0][0]; Object[] val2 = get2();
+
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class ObjectArrayLowerDim2 {
+ public @Stable Object[][] v;
+
+ public static final ObjectArrayLowerDim2 c = new ObjectArrayLowerDim2();
+ public static short get() { return ((short[][][])c.v)[0][0][0]; }
+ public static short[] get1() { return (short[])(c.v[0][0]); }
+ public static short[][] get2() { return (short[][])(c.v[0]); }
+ public static Object[][] get3() { return c.v; }
+
+ public static void test() throws Exception {
+ {
+ c.v = new short[1][1][1]; ((short[][][])c.v)[0][0][0] = 1; short val1 = get();
+ ((short[][][])c.v)[0][0][0] = 2; short val2 = get();
+
+ assertEquals(val1, 1);
+ assertEquals(val2, 2);
+ }
+
+ {
+ c.v = new short[1][1][1]; c.v[0][0] = new short[0]; short[] val1 = get1();
+ c.v[0][0] = new short[0]; short[] val2 = get1();
+
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new short[1][1][1]; c.v[0] = new short[0][0]; short[][] val1 = get2();
+ c.v[0] = new short[0][0]; short[][] val2 = get2();
+
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+
+ {
+ c.v = new short[0][0][0]; Object[][] val1 = get3();
+ c.v = new short[0][0][0]; Object[][] val2 = get3();
+
+ assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2)));
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class NestedStableField {
+ static class A {
+ public @Stable short a;
+
+ }
+ public @Stable A v;
+
+ public static final NestedStableField c = new NestedStableField();
+ public static A get() { return c.v; }
+ public static short get1() { return get().a; }
+
+ public static void test() throws Exception {
+ {
+ c.v = new A(); c.v.a = 1; A val1 = get();
+ c.v.a = 2; A val2 = get();
+
+ assertEquals(val1.a, 2);
+ assertEquals(val2.a, 2);
+ }
+
+ {
+ c.v = new A(); c.v.a = 1; short val1 = get1();
+ c.v.a = 2; short val2 = get1();
+ c.v = new A(); c.v.a = 3; short val3 = get1();
+
+ assertEquals(val1, 1);
+ assertEquals(val2, (isStableEnabled ? 1 : 2));
+ assertEquals(val3, (isStableEnabled ? 1 : 3));
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class NestedStableField1 {
+ static class A {
+ public @Stable short a;
+ public @Stable A next;
+ }
+ public @Stable A v;
+
+ public static final NestedStableField1 c = new NestedStableField1();
+ public static A get() { return c.v.next.next.next.next.next.next.next; }
+ public static short get1() { return get().a; }
+
+ public static void test() throws Exception {
+ {
+ c.v = new A(); c.v.next = new A(); c.v.next.next = c.v;
+ c.v.a = 1; c.v.next.a = 1; A val1 = get();
+ c.v.a = 2; c.v.next.a = 2; A val2 = get();
+
+ assertEquals(val1.a, 2);
+ assertEquals(val2.a, 2);
+ }
+
+ {
+ c.v = new A(); c.v.next = c.v;
+ c.v.a = 1; short val1 = get1();
+ c.v.a = 2; short val2 = get1();
+ c.v = new A(); c.v.next = c.v;
+ c.v.a = 3; short val3 = get1();
+
+ assertEquals(val1, 1);
+ assertEquals(val2, (isStableEnabled ? 1 : 2));
+ assertEquals(val3, (isStableEnabled ? 1 : 3));
+ }
+ }
+ }
+ /* ==================================================== */
+
+ static class NestedStableField2 {
+ static class A {
+ public @Stable short a;
+ public @Stable A left;
+ public A right;
+ }
+
+ public @Stable A v;
+
+ public static final NestedStableField2 c = new NestedStableField2();
+ public static short get() { return c.v.left.left.left.a; }
+ public static short get1() { return c.v.left.left.right.left.a; }
+
+ public static void test() throws Exception {
+ {
+ c.v = new A(); c.v.left = c.v.right = c.v;
+ c.v.a = 1; short val1 = get(); short val2 = get1();
+ c.v.a = 2; short val3 = get(); short val4 = get1();
+
+ assertEquals(val1, 1);
+ assertEquals(val3, (isStableEnabled ? 1 : 2));
+
+ assertEquals(val2, 1);
+ assertEquals(val4, 2);
+ }
+ }
+ }
+
+ /* ==================================================== */
+
+ static class NestedStableField3 {
+ static class A {
+ public @Stable short a;
+ public @Stable A[] left;
+ public A[] right;
+ }
+
+ public @Stable A[] v;
+
+ public static final NestedStableField3 c = new NestedStableField3();
+ public static short get() { return c.v[0].left[1].left[0].left[1].a; }
+ public static short get1() { return c.v[1].left[0].left[1].right[0].left[1].a; }
+
+ public static void test() throws Exception {
+ {
+ A elem = new A();
+ c.v = new A[] { elem, elem }; c.v[0].left = c.v[0].right = c.v;
+ elem.a = 1; short val1 = get(); short val2 = get1();
+ elem.a = 2; short val3 = get(); short val4 = get1();
+
+ assertEquals(val1, 1);
+ assertEquals(val3, (isStableEnabled ? 1 : 2));
+
+ assertEquals(val2, 1);
+ assertEquals(val4, 2);
+ }
+ }
+ }
+
+ /* ==================================================== */
+ // Auxiliary methods
+ static void assertEquals(int i, int j) { if (i != j) throw new AssertionError(i + " != " + j); }
+ static void assertTrue(boolean b) { if (!b) throw new AssertionError(); }
+
+ static boolean failed = false;
+
+ public static void run(Class<?> test) {
+ Throwable ex = null;
+ System.out.print(test.getName()+": ");
+ try {
+ test.getMethod("test").invoke(null);
+ } catch (InvocationTargetException e) {
+ ex = e.getCause();
+ } catch (Throwable e) {
+ ex = e;
+ } finally {
+ if (ex == null) {
+ System.out.println("PASSED");
+ } else {
+ failed = true;
+ System.out.println("FAILED");
+ ex.printStackTrace(System.out);
+ }
+ }
+ }
+
+ static final boolean isStableEnabled;
+ static {
+ HotSpotDiagnosticMXBean diagnostic
+ = ManagementFactoryHelper.getDiagnosticMXBean();
+ VMOption tmp;
+ try {
+ tmp = diagnostic.getVMOption("FoldStableValues");
+ } catch (IllegalArgumentException e) {
+ tmp = null;
+ }
+ isStableEnabled = (tmp == null ? false : Boolean.parseBoolean(tmp.getValue()));
+ }
+}
--- a/hotspot/test/compiler/uncommontrap/TestSpecTrapClassUnloading.java Wed Mar 05 10:20:30 2014 +0100
+++ b/hotspot/test/compiler/uncommontrap/TestSpecTrapClassUnloading.java Wed Mar 05 01:26:52 2014 -0800
@@ -25,7 +25,7 @@
* @test
* @bug 8031752
* @summary speculative traps need to be cleaned up at GC
- * @run main/othervm -XX:-TieredCompilation -XX:-UseOnStackReplacement -XX:-BackgroundCompilation -XX:+UnlockExperimentalVMOptions -XX:+UseTypeSpeculation -XX:TypeProfileLevel=222 -XX:CompileCommand=exclude,java.lang.reflect.Method::invoke -XX:CompileCommand=exclude,sun.reflect.DelegatingMethodAccessorImpl::invoke -Xmx1M TestSpecTrapClassUnloading
+ * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation -XX:-UseOnStackReplacement -XX:-BackgroundCompilation -XX:+UnlockExperimentalVMOptions -XX:+UseTypeSpeculation -XX:TypeProfileLevel=222 -XX:CompileCommand=exclude,java.lang.reflect.Method::invoke -XX:CompileCommand=exclude,sun.reflect.DelegatingMethodAccessorImpl::invoke -Xmx1M TestSpecTrapClassUnloading
*
*/