changeset 14671:77ca9a58fbe8

Merge
author anoll
date Tue, 04 Mar 2014 21:15:33 -0800
parents 27689a7550a8 (current diff) 81ccf2c854c7 (diff)
children 08adf1b5f2b6 53ed0f89f44e
files
diffstat 30 files changed, 5973 insertions(+), 81 deletions(-) [+]
line wrap: on
line diff
--- a/make/aix/makefiles/adjust-mflags.sh	Wed Mar 05 06:08:19 2014 +0100
+++ b/make/aix/makefiles/adjust-mflags.sh	Tue Mar 04 21:15:33 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/make/linux/makefiles/zeroshark.make	Wed Mar 05 06:08:19 2014 +0100
+++ b/make/linux/makefiles/zeroshark.make	Tue Mar 04 21:15:33 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/src/share/vm/c1/c1_GraphBuilder.cpp	Wed Mar 05 06:08:19 2014 +0100
+++ b/src/share/vm/c1/c1_GraphBuilder.cpp	Tue Mar 04 21:15:33 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/src/share/vm/c1/c1_IR.cpp	Wed Mar 05 06:08:19 2014 +0100
+++ b/src/share/vm/c1/c1_IR.cpp	Tue Mar 04 21:15:33 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/src/share/vm/c1/c1_IR.hpp	Wed Mar 05 06:08:19 2014 +0100
+++ b/src/share/vm/c1/c1_IR.hpp	Tue Mar 04 21:15:33 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/src/share/vm/c1/c1_LIRGenerator.cpp	Wed Mar 05 06:08:19 2014 +0100
+++ b/src/share/vm/c1/c1_LIRGenerator.cpp	Tue Mar 04 21:15:33 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/src/share/vm/c1/c1_Runtime1.cpp	Wed Mar 05 06:08:19 2014 +0100
+++ b/src/share/vm/c1/c1_Runtime1.cpp	Tue Mar 04 21:15:33 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/src/share/vm/ci/ciMethod.cpp	Wed Mar 05 06:08:19 2014 +0100
+++ b/src/share/vm/ci/ciMethod.cpp	Tue Mar 04 21:15:33 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/src/share/vm/opto/c2_globals.hpp	Wed Mar 05 06:08:19 2014 +0100
+++ b/src/share/vm/opto/c2_globals.hpp	Tue Mar 04 21:15:33 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/src/share/vm/opto/parse.hpp	Wed Mar 05 06:08:19 2014 +0100
+++ b/src/share/vm/opto/parse.hpp	Tue Mar 04 21:15:33 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/src/share/vm/opto/parse1.cpp	Wed Mar 05 06:08:19 2014 +0100
+++ b/src/share/vm/opto/parse1.cpp	Tue Mar 04 21:15:33 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/src/share/vm/opto/parse3.cpp	Wed Mar 05 06:08:19 2014 +0100
+++ b/src/share/vm/opto/parse3.cpp	Tue Mar 04 21:15:33 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/src/share/vm/runtime/globals.hpp	Wed Mar 05 06:08:19 2014 +0100
+++ b/src/share/vm/runtime/globals.hpp	Tue Mar 04 21:15:33 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/src/share/vm/runtime/thread.cpp	Wed Mar 05 06:08:19 2014 +0100
+++ b/src/share/vm/runtime/thread.cpp	Tue Mar 04 21:15:33 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/src/share/vm/shark/llvmHeaders.hpp	Wed Mar 05 06:08:19 2014 +0100
+++ b/src/share/vm/shark/llvmHeaders.hpp	Tue Mar 04 21:15:33 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/src/share/vm/shark/sharkCompiler.cpp	Wed Mar 05 06:08:19 2014 +0100
+++ b/src/share/vm/shark/sharkCompiler.cpp	Tue Mar 04 21:15:33 2014 -0800
@@ -364,3 +364,7 @@
   *(dst++) = '\0';
   return buf;
 }
+
+void SharkCompiler::print_timers() {
+  // do nothing
+}
--- a/src/share/vm/shark/sharkCompiler.hpp	Wed Mar 05 06:08:19 2014 +0100
+++ b/src/share/vm/shark/sharkCompiler.hpp	Tue Mar 04 21:15:33 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/src/share/vm/shark/sharkInliner.cpp	Wed Mar 05 06:08:19 2014 +0100
+++ b/src/share/vm/shark/sharkInliner.cpp	Tue Mar 04 21:15:33 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/src/share/vm/shark/sharkMemoryManager.cpp	Wed Mar 05 06:08:19 2014 +0100
+++ b/src/share/vm/shark/sharkMemoryManager.cpp	Tue Mar 04 21:15:33 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/src/share/vm/shark/sharkMemoryManager.hpp	Wed Mar 05 06:08:19 2014 +0100
+++ b/src/share/vm/shark/sharkMemoryManager.hpp	Tue Mar 04 21:15:33 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/test/compiler/inlining/InlineDefaultMethod1.java	Tue Mar 04 21:15:33 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/test/compiler/stable/TestStableBoolean.java	Tue Mar 04 21:15:33 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/test/compiler/stable/TestStableByte.java	Tue Mar 04 21:15:33 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/test/compiler/stable/TestStableChar.java	Tue Mar 04 21:15:33 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/test/compiler/stable/TestStableDouble.java	Tue Mar 04 21:15:33 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/test/compiler/stable/TestStableFloat.java	Tue Mar 04 21:15:33 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/test/compiler/stable/TestStableInt.java	Tue Mar 04 21:15:33 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/test/compiler/stable/TestStableLong.java	Tue Mar 04 21:15:33 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/test/compiler/stable/TestStableObject.java	Tue Mar 04 21:15:33 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/test/compiler/stable/TestStableShort.java	Tue Mar 04 21:15:33 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()));
+    }
+}