Merge
authorjwilhelm
Mon, 11 Apr 2016 20:16:34 +0200
changeset 37527 6080acc2c3aa
parent 37336 75e0bcdcc5bc (current diff)
parent 37526 dc4669f222ab (diff)
child 37528 caaadf14458c
Merge
--- a/jdk/make/Import.gmk	Fri Apr 08 12:36:27 2016 -0400
+++ b/jdk/make/Import.gmk	Mon Apr 11 20:16:34 2016 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2012, 2016, 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
@@ -83,20 +83,20 @@
   endif
 
   ifneq ($(OPENJDK_TARGET_OS), windows)
-    ifeq ($(JVM_VARIANT_SERVER), true)
+    ifeq ($(call check-jvm-variant, server), true)
       BASE_TARGETS += $(BASE_INSTALL_LIBRARIES_HERE)/server/$(LIBRARY_PREFIX)jsig$(SHARED_LIBRARY_SUFFIX)
       ifneq (, $(JSIG_DEBUGINFO))
         BASE_TARGETS += $(BASE_INSTALL_LIBRARIES_HERE)/server/$(foreach I,$(JSIG_DEBUGINFO),$(notdir $I))
       endif
     endif
-    ifeq ($(JVM_VARIANT_CLIENT), true)
+    ifeq ($(call check-jvm-variant, client), true)
       BASE_TARGETS += $(BASE_INSTALL_LIBRARIES_HERE)/client/$(LIBRARY_PREFIX)jsig$(SHARED_LIBRARY_SUFFIX)
       ifneq (, $(JSIG_DEBUGINFO))
         BASE_TARGETS += $(BASE_INSTALL_LIBRARIES_HERE)/client/$(foreach I,$(JSIG_DEBUGINFO),$(notdir $I))
       endif
     endif
     ifneq ($(OPENJDK_TARGET_OS), macosx)
-      ifeq ($(JVM_VARIANT_MINIMAL1), true)
+      ifeq ($(call check-jvm-variant, minimal), true)
         BASE_TARGETS += $(BASE_INSTALL_LIBRARIES_HERE)/minimal/$(LIBRARY_PREFIX)jsig$(SHARED_LIBRARY_SUFFIX)
         ifneq (,$(JSIG_DEBUGINFO))
           BASE_TARGETS += $(BASE_INSTALL_LIBRARIES_HERE)/minimal/$(foreach I,$(JSIG_DEBUGINFO),$(notdir $I))
--- a/jdk/make/copy/Copy-java.base.gmk	Fri Apr 08 12:36:27 2016 -0400
+++ b/jdk/make/copy/Copy-java.base.gmk	Mon Apr 11 20:16:34 2016 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2014, 2016, 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
@@ -88,7 +88,7 @@
 #
 # How to install jvm.cfg.
 #
-ifeq ($(JVM_VARIANT_ZERO), true)
+ifeq ($(call check-jvm-variant, zero zeroshark), true)
   JVMCFG_ARCH := zero
 else
   JVMCFG_ARCH := $(OPENJDK_TARGET_CPU_LEGACY)
@@ -99,7 +99,7 @@
 else
   JVMCFG_SRC := $(JDK_TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/conf/$(JVMCFG_ARCH)/jvm.cfg
   # Allow override by ALT_JVMCFG_SRC if it exists
-  JVMCFG_SRC := $(if $(wildcard $(ALT_JVMCFG_SRC)),$(ALT_JVMCFG_SRC),$(JVMCFG_SRC)) 
+  JVMCFG_SRC := $(if $(wildcard $(ALT_JVMCFG_SRC)),$(ALT_JVMCFG_SRC),$(JVMCFG_SRC))
 endif
 JVMCFG_DIR := $(LIB_DST_DIR)$(OPENJDK_TARGET_CPU_LIBDIR)
 JVMCFG := $(JVMCFG_DIR)/jvm.cfg
@@ -117,12 +117,12 @@
   # The main problem is deciding whether to use aliases for the VMs that are not
   # present and the current position is that we add aliases for client and server, but
   # not for minimal.
-  CLIENT_AND_SERVER := $(and $(findstring true, $(JVM_VARIANT_SERVER)), $(findstring true, $(JVM_VARIANT_CLIENT)))
-  ifeq ($(CLIENT_AND_SERVER), true)
+  CLIENT_AND_SERVER := $(call check-jvm-variant, client)+$(call check-jvm-variant, server)
+  ifeq ($(CLIENT_AND_SERVER), true+true)
     COPY_JVM_CFG_FILE := true
   else
     # For zero, the default jvm.cfg file is sufficient
-    ifeq ($(JVM_VARIANT_ZERO), true)
+    ifeq ($(call check-jvm-variant, zero zeroshark), true)
       COPY_JVM_CFG_FILE := true
     endif
   endif
@@ -136,21 +136,21 @@
 	$(MKDIR) -p $(@D)
 	$(RM) $(@)
         # Now check for other permutations
-        ifeq ($(JVM_VARIANT_SERVER), true)
+        ifeq ($(call check-jvm-variant, server), true)
 	  $(PRINTF) "-server KNOWN\n">>$(@)
 	  $(PRINTF) "-client ALIASED_TO -server\n">>$(@)
-          ifeq ($(JVM_VARIANT_MINIMAL1), true)
+          ifeq ($(call check-jvm-variant, minimal), true)
 	    $(PRINTF) "-minimal KNOWN\n">>$(@)
           endif
         else
-          ifeq ($(JVM_VARIANT_CLIENT), true)
+          ifeq ($(call check-jvm-variant, client), true)
 	    $(PRINTF) "-client KNOWN\n">>$(@)
 	    $(PRINTF) "-server ALIASED_TO -client\n">>$(@)
-            ifeq ($(JVM_VARIANT_MINIMAL1), true)
+            ifeq ($(call check-jvm-variant, minimal), true)
 	      $(PRINTF) "-minimal KNOWN\n">>$(@)
             endif
           else
-            ifeq ($(JVM_VARIANT_MINIMAL1), true)
+            ifeq ($(call check-jvm-variant, minimal), true)
 	      $(PRINTF) "-minimal KNOWN\n">>$(@)
 	      $(PRINTF) "-server ALIASED_TO -minimal\n">>$(@)
 	      $(PRINTF) "-client ALIASED_TO -minimal\n">>$(@)
--- a/jdk/make/lib/CoreLibraries.gmk	Fri Apr 08 12:36:27 2016 -0400
+++ b/jdk/make/lib/CoreLibraries.gmk	Mon Apr 11 20:16:34 2016 +0200
@@ -289,7 +289,7 @@
 
 LIBJLI_CFLAGS := $(CFLAGS_JDKLIB)
 
-ifeq ($(JVM_VARIANT_ZERO), true)
+ifeq ($(call check-jvm-variant, zero zeroshark), true)
   ERGO_FAMILY := zero
 else
   ifeq ($(OPENJDK_TARGET_CPU_ARCH), x86)
--- a/jdk/make/mapfiles/libjava/mapfile-vers	Fri Apr 08 12:36:27 2016 -0400
+++ b/jdk/make/mapfiles/libjava/mapfile-vers	Mon Apr 11 20:16:34 2016 +0200
@@ -139,8 +139,7 @@
 		Java_java_lang_Double_doubleToRawLongBits;
 		Java_java_lang_Float_intBitsToFloat;
 		Java_java_lang_Float_floatToRawIntBits;
-                Java_java_lang_StackFrameInfo_fillInStackFrames;
-                Java_java_lang_StackFrameInfo_setMethodInfo;
+                Java_java_lang_StackFrameInfo_toStackTraceElement0;
                 Java_java_lang_StackStreamFactory_checkStackWalkModes;
                 Java_java_lang_StackStreamFactory_00024AbstractStackWalker_callStackWalk;
                 Java_java_lang_StackStreamFactory_00024AbstractStackWalker_fetchStackFrames;
--- a/jdk/src/java.base/share/classes/java/lang/StackFrameInfo.java	Fri Apr 08 12:36:27 2016 -0400
+++ b/jdk/src/java.base/share/classes/java/lang/StackFrameInfo.java	Mon Apr 11 20:16:34 2016 +0200
@@ -37,24 +37,14 @@
     private final static JavaLangInvokeAccess jlInvokeAccess =
         SharedSecrets.getJavaLangInvokeAccess();
 
-    // -XX:+MemberNameInStackFrame will initialize MemberName and all other fields;
-    // otherwise, VM will set the hidden fields (injected by the VM).
-    // -XX:+MemberNameInStackFrame is temporary to enable performance measurement
-    //
-    // Footprint improvement: MemberName::clazz and MemberName::name
-    // can replace StackFrameInfo::declaringClass and StackFrameInfo::methodName
-    // Currently VM sets StackFrameInfo::methodName instead of expanding MemberName::name
+    // Footprint improvement: MemberName::clazz can replace
+    // StackFrameInfo::declaringClass.
 
     final StackWalker walker;
     final Class<?> declaringClass;
     final Object memberName;
-    final int bci;
-
-    // methodName, fileName, and lineNumber will be lazily set by the VM
-    // when first requested.
-    private String methodName;
-    private String fileName = null;     // default for unavailable filename
-    private int    lineNumber = -1;     // default for unavailable lineNumber
+    final short bci;
+    private volatile StackTraceElement ste;
 
     /*
      * Create StackFrameInfo for StackFrameTraverser and LiveStackFrameTraverser
@@ -78,77 +68,53 @@
         return declaringClass;
     }
 
-    // Call the VM to set methodName, lineNumber, and fileName
-    private synchronized void ensureMethodInfoInitialized() {
-        if (methodName == null) {
-            setMethodInfo();
-        }
-    }
-
     @Override
     public String getMethodName() {
-        ensureMethodInfoInitialized();
-        return methodName;
+        return jlInvokeAccess.getName(memberName);
     }
 
     @Override
-    public Optional<String> getFileName() {
-        ensureMethodInfoInitialized();
-        return fileName != null ? Optional.of(fileName) : Optional.empty();
+    public final Optional<String> getFileName() {
+        StackTraceElement ste = toStackTraceElement();
+        return ste.getFileName() != null ? Optional.of(ste.getFileName()) : Optional.empty();
     }
 
     @Override
-    public OptionalInt getLineNumber() {
-        ensureMethodInfoInitialized();
-        return lineNumber > 0 ? OptionalInt.of(lineNumber) : OptionalInt.empty();
+    public final OptionalInt getLineNumber() {
+        StackTraceElement ste = toStackTraceElement();
+        return ste.getLineNumber() > 0 ? OptionalInt.of(ste.getLineNumber()) : OptionalInt.empty();
     }
 
     @Override
-    public boolean isNativeMethod() {
-        ensureMethodInfoInitialized();
-        return lineNumber == -2;
+    public final boolean isNativeMethod() {
+        StackTraceElement ste = toStackTraceElement();
+        return ste.isNativeMethod();
     }
 
     @Override
     public String toString() {
-        ensureMethodInfoInitialized();
-        // similar format as StackTraceElement::toString
-        if (isNativeMethod()) {
-            return getClassName() + "." + getMethodName() + "(Native Method)";
-        } else {
-            // avoid allocating Optional objects
-            return getClassName() + "." + getMethodName() +
-                "(" + (fileName != null ? fileName : "Unknown Source") +
-                      (lineNumber > 0 ? ":" + lineNumber : " bci:" + bci) + ")";
-        }
+        StackTraceElement ste = toStackTraceElement();
+        return ste.toString();
     }
 
     /**
-     * Lazily initialize method name, file name, line number
+     * Fill in the fields of the given StackTraceElement
      */
-    private native void setMethodInfo();
-
-    /**
-     * Fill in source file name and line number of the given StackFrame array.
-     */
-    static native void fillInStackFrames(int startIndex,
-                                         Object[] stackframes,
-                                         int fromIndex, int toIndex);
+    private native void toStackTraceElement0(StackTraceElement ste);
 
     @Override
     public StackTraceElement toStackTraceElement() {
-        ensureMethodInfoInitialized();
-
-        Module module = declaringClass.getModule();
-        String moduleName = module.isNamed() ? module.getName() : null;
-        String moduleVersion = null;
-        if (module.isNamed() && module.getDescriptor().version().isPresent()) {
-            moduleVersion = module.getDescriptor().version().get().toString();
+        StackTraceElement s = ste;
+        if (s == null) {
+            synchronized (this) {
+                s = ste;
+                if (s == null) {
+                    s = new StackTraceElement();
+                    toStackTraceElement0(s);
+                    ste = s;
+                }
+            }
         }
-        return new StackTraceElement(moduleName, moduleVersion,
-                                     getClassName(), getMethodName(),
-                                     fileName,
-                                     lineNumber);
+        return s;
     }
-
 }
--- a/jdk/src/java.base/share/classes/java/lang/StackStreamFactory.java	Fri Apr 08 12:36:27 2016 -0400
+++ b/jdk/src/java.base/share/classes/java/lang/StackStreamFactory.java	Mon Apr 11 20:16:34 2016 +0200
@@ -24,9 +24,6 @@
  */
 package java.lang;
 
-import jdk.internal.misc.VM;
-
-import java.io.PrintStream;
 import java.lang.StackWalker.Option;
 import java.lang.StackWalker.StackFrame;
 
@@ -34,12 +31,9 @@
 import java.lang.reflect.Method;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
-import java.util.Arrays;
-import java.util.EnumSet;
 import java.util.HashSet;
 import java.util.NoSuchElementException;
 import java.util.Objects;
-import java.util.Optional;
 import java.util.Set;
 import java.util.Spliterator;
 import java.util.function.Consumer;
@@ -60,8 +54,7 @@
  * to avoid overhead of Stream/Lambda
  * 1. Support traversing Stream<StackFrame>
  * 2. StackWalker::getCallerClass
- * 3. Throwable::init and Throwable::getStackTrace
- * 4. AccessControlContext getting ProtectionDomain
+ * 3. AccessControlContext getting ProtectionDomain
  */
 final class StackStreamFactory {
     private StackStreamFactory() {}
@@ -78,25 +71,22 @@
     // These flags must match the values maintained in the VM
     @Native private static final int DEFAULT_MODE              = 0x0;
     @Native private static final int FILL_CLASS_REFS_ONLY      = 0x2;
-    @Native private static final int FILTER_FILL_IN_STACKTRACE = 0x10;
     @Native private static final int SHOW_HIDDEN_FRAMES        = 0x20;  // LambdaForms are hidden by the VM
     @Native private static final int FILL_LIVE_STACK_FRAMES    = 0x100;
-
     /*
      * For Throwable to use StackWalker, set useNewThrowable to true.
      * Performance work and extensive testing is needed to replace the
      * VM built-in backtrace filled in Throwable with the StackWalker.
      */
-    final static boolean useNewThrowable = getProperty("stackwalk.newThrowable", false);
     final static boolean isDebug = getProperty("stackwalk.debug", false);
 
     static <T> StackFrameTraverser<T>
         makeStackTraverser(StackWalker walker, Function<? super Stream<StackFrame>, ? extends T> function)
     {
         if (walker.hasLocalsOperandsOption())
-            return new LiveStackInfoTraverser<T>(walker, function);
+            return new LiveStackInfoTraverser<>(walker, function);
         else
-            return new StackFrameTraverser<T>(walker, function);
+            return new StackFrameTraverser<>(walker, function);
     }
 
     /**
@@ -106,40 +96,31 @@
         return new CallerClassFinder(walker);
     }
 
-    static boolean useStackTrace(Throwable t) {
-        if (t instanceof VirtualMachineError)
-            return false;
-
-        return VM.isBooted() && StackStreamFactory.useNewThrowable;
-    }
-
-    /*
-     * This should only be used by Throwable::<init>.
-     */
-    static StackTrace makeStackTrace(Throwable ex) {
-        return StackTrace.dump(ex);
-    }
-
-    /*
-     * This creates StackTrace for Thread::dumpThread to use.
-     */
-    static StackTrace makeStackTrace() {
-        return StackTrace.dump();
-    }
-
     enum WalkerState {
         NEW,     // the stream is new and stack walking has not started
         OPEN,    // the stream is open when it is being traversed.
         CLOSED;  // the stream is closed when the stack walking is done
     }
 
-    static abstract class AbstractStackWalker<T> {
+    /**
+     * Subclass of AbstractStackWalker implements a specific stack walking logic.
+     * It needs to set up the frame buffer and stack walking mode.
+     *
+     * It initiates the VM stack walking via the callStackWalk method that serves
+     * as the anchored frame and VM will call up to AbstractStackWalker::doStackWalk.
+     *
+     * @param <R> the type of the result returned from stack walking
+     * @param <T> the type of the data gathered for each frame.
+     *            For example, StackFrameInfo for StackWalker::walk or
+     *            Class<?> for StackWalker::getCallerClass
+     */
+    static abstract class AbstractStackWalker<R, T> {
         protected final StackWalker walker;
         protected final Thread thread;
         protected final int maxDepth;
         protected final long mode;
-        protected int depth;                 // traversed stack depth
-        protected FrameBuffer frameBuffer;   // buffer for VM to fill in
+        protected int depth;    // traversed stack depth
+        protected FrameBuffer<? extends T> frameBuffer;
         protected long anchor;
 
         // buffers to fill in stack frame information
@@ -157,16 +138,13 @@
         private int toStackWalkMode(StackWalker walker, int mode) {
             int newMode = mode;
             if (walker.hasOption(Option.SHOW_HIDDEN_FRAMES) &&
-                    !fillCallerClassOnly(newMode) /* don't show hidden frames for getCallerClass */)
+                    (mode & FILL_CLASS_REFS_ONLY) != FILL_CLASS_REFS_ONLY)
                 newMode |= SHOW_HIDDEN_FRAMES;
             if (walker.hasLocalsOperandsOption())
                 newMode |= FILL_LIVE_STACK_FRAMES;
             return newMode;
         }
 
-        private boolean fillCallerClassOnly(int mode) {
-            return (mode|FILL_CLASS_REFS_ONLY) != FILL_CLASS_REFS_ONLY;
-        }
         /**
          * A callback method to consume the stack frames.  This method is invoked
          * once stack walking begins (i.e. it is only invoked when walkFrames is called).
@@ -179,7 +157,7 @@
          *
          * @return the number of consumed frames
          */
-         protected abstract T consumeFrames();
+         protected abstract R consumeFrames();
 
         /**
          * Initialize FrameBuffer.  Subclass should implement this method to
@@ -252,7 +230,7 @@
          * Walks stack frames until {@link #consumeFrames} is done consuming
          * the frames it is interested in.
          */
-        final T walk() {
+        final R walk() {
             checkState(NEW);
             try {
                 // VM will need to stablize the stack before walking.  It will invoke
@@ -318,7 +296,7 @@
             }
 
             this.anchor = anchor;  // set anchor for this bulk stack frame traversal
-            frameBuffer.setBatch(bufStartIndex, bufEndIndex);
+            frameBuffer.setBatch(depth, bufStartIndex, bufEndIndex);
 
             // traverse all frames and perform the action on the stack frames, if specified
             return consumeFrames();
@@ -381,15 +359,14 @@
          * If all fetched stack frames are traversed, AbstractStackWalker::fetchStackFrames will
          * fetch the next batch of stack frames to continue.
          */
-        private T beginStackWalk() {
+        private R beginStackWalk() {
             // initialize buffers for VM to fill the stack frame info
             initFrameBuffer();
 
             return callStackWalk(mode, 0,
                                  frameBuffer.curBatchFrameCount(),
                                  frameBuffer.startIndex(),
-                                 frameBuffer.classes,
-                                 frameBuffer.stackFrames);
+                                 frameBuffer.frames());
         }
 
         /*
@@ -404,8 +381,7 @@
 
             int endIndex = fetchStackFrames(mode, anchor, batchSize,
                                             startIndex,
-                                            frameBuffer.classes,
-                                            frameBuffer.stackFrames);
+                                            frameBuffer.frames());
             if (isDebug) {
                 System.out.format("  more stack walk requesting %d got %d to %d frames%n",
                                   batchSize, frameBuffer.startIndex(), endIndex);
@@ -414,27 +390,26 @@
             if (numFrames == 0) {
                 frameBuffer.freeze(); // done stack walking
             } else {
-                frameBuffer.setBatch(startIndex, endIndex);
+                frameBuffer.setBatch(depth, startIndex, endIndex);
             }
             return numFrames;
         }
 
         /**
          * Begins stack walking.  This method anchors this frame and invokes
-         * AbstractStackWalker::doStackWalk after fetching the firt batch of stack frames.
+         * AbstractStackWalker::doStackWalk after fetching the first batch of stack frames.
          *
          * @param mode        mode of stack walking
          * @param skipframes  number of frames to be skipped before filling the frame buffer.
          * @param batchSize   the batch size, max. number of elements to be filled in the frame buffers.
          * @param startIndex  start index of the frame buffers to be filled.
-         * @param classes     Classes buffer of the stack frames
-         * @param frames      StackFrame buffer, or null
+         * @param frames      Either a Class<?> array, if mode is {@link #FILL_CLASS_REFS_ONLY}
+         *                    or a {@link StackFrameInfo} (or derivative) array otherwise.
          * @return            Result of AbstractStackWalker::doStackWalk
          */
-        private native T callStackWalk(long mode, int skipframes,
+        private native R callStackWalk(long mode, int skipframes,
                                        int batchSize, int startIndex,
-                                       Class<?>[] classes,
-                                       StackFrame[] frames);
+                                       T[] frames);
 
         /**
          * Fetch the next batch of stack frames.
@@ -443,185 +418,14 @@
          * @param anchor
          * @param batchSize   the batch size, max. number of elements to be filled in the frame buffers.
          * @param startIndex  start index of the frame buffers to be filled.
-         * @param classes     Classes buffer of the stack frames
-         * @param frames      StackFrame buffer, or null
+         * @param frames      Either a Class<?> array, if mode is {@link #FILL_CLASS_REFS_ONLY}
+         *                    or a {@link StackFrameInfo} (or derivative) array otherwise.
          *
          * @return the end index to the frame buffers
          */
         private native int fetchStackFrames(long mode, long anchor,
                                             int batchSize, int startIndex,
-                                            Class<?>[] classes,
-                                            StackFrame[] frames);
-
-
-        /*
-         * Frame buffer
-         *
-         * Each specialized AbstractStackWalker subclass may subclass the FrameBuffer.
-         */
-        class FrameBuffer {
-            static final int START_POS = 2;     // 0th and 1st elements are reserved
-
-            // buffers for VM to fill stack frame info
-            int currentBatchSize;    // current batch size
-            Class<?>[] classes;      // caller class for fast path
-
-            StackFrame[] stackFrames;
-
-            int origin;         // index to the current traversed stack frame
-            int fence;          // index to the last frame in the current batch
-
-            FrameBuffer(int initialBatchSize) {
-                if (initialBatchSize < MIN_BATCH_SIZE) {
-                    throw new IllegalArgumentException(initialBatchSize + " < minimum batch size: " + MIN_BATCH_SIZE);
-                }
-                this.origin = START_POS;
-                this.fence = 0;
-                this.currentBatchSize = initialBatchSize;
-                this.classes = new Class<?>[currentBatchSize];
-            }
-
-            int curBatchFrameCount() {
-                return currentBatchSize-START_POS;
-            }
-
-            /*
-             * Tests if this frame buffer is empty.  All frames are fetched.
-             */
-            final boolean isEmpty() {
-                return origin >= fence || (origin == START_POS && fence == 0);
-            }
-
-            /*
-             * Freezes this frame buffer.  The stack stream source is done fetching.
-             */
-            final void freeze() {
-                origin = 0;
-                fence = 0;
-            }
-
-            /*
-             * Tests if this frame buffer is active.  It is inactive when
-             * it is done for traversal.  All stack frames have been traversed.
-             */
-            final boolean isActive() {
-                return origin > 0 && (fence == 0 || origin < fence || fence == currentBatchSize);
-            }
-
-            /**
-             * Gets the class at the current frame and move to the next frame.
-             */
-            final Class<?> next() {
-                if (isEmpty()) {
-                    throw new NoSuchElementException("origin=" + origin + " fence=" + fence);
-                }
-                Class<?> c = classes[origin++];
-                if (isDebug) {
-                    int index = origin-1;
-                    System.out.format("  next frame at %d: %s (origin %d fence %d)%n", index,
-                                      Objects.toString(c), index, fence);
-                }
-                return c;
-            }
-
-            /**
-             * Gets the class at the current frame.
-             */
-            final Class<?> get() {
-                if (isEmpty()) {
-                    throw new NoSuchElementException("origin=" + origin + " fence=" + fence);
-                }
-                return classes[origin];
-            }
-
-            /*
-             * Returns the index of the current frame.
-             */
-            final int getIndex() {
-                return origin;
-            }
-
-            /*
-             * Set the start and end index of a new batch of stack frames that have
-             * been filled in this frame buffer.
-             */
-            final void setBatch(int startIndex, int endIndex) {
-                if (startIndex <= 0 || endIndex <= 0)
-                    throw new IllegalArgumentException("startIndex=" + startIndex + " endIndex=" + endIndex);
-
-                this.origin = startIndex;
-                this.fence = endIndex;
-                if (depth == 0 && fence > 0) {
-                    // filter the frames due to the stack stream implementation
-                    for (int i = START_POS; i < fence; i++) {
-                        Class<?> c = classes[i];
-                        if (isDebug) System.err.format("  frame %d: %s%n", i, c);
-                        if (filterStackWalkImpl(c)) {
-                            origin++;
-                        } else {
-                            break;
-                        }
-                    }
-                }
-            }
-
-            /*
-             * Checks if the origin is the expected start index.
-             */
-            final void check(int skipFrames) {
-                int index = skipFrames + START_POS;
-                if (origin != index) {
-                    // stack walk must continue with the previous frame depth
-                    throw new IllegalStateException("origin " + origin + " != " + index);
-                }
-            }
-
-            // ------ subclass may override the following methods -------
-            /**
-             * Resizes the buffers for VM to fill in the next batch of stack frames.
-             * The next batch will start at the given startIndex with the maximum number
-             * of elements.
-             *
-             * <p> Subclass may override this method to manage the allocated buffers.
-             *
-             * @param startIndex the start index for the first frame of the next batch to fill in.
-             * @param elements the number of elements for the next batch to fill in.
-             *
-             */
-            void resize(int startIndex, int elements) {
-                if (!isActive())
-                    throw new IllegalStateException("inactive frame buffer can't be resized");
-
-                int size = startIndex+elements;
-                if (classes.length < size) {
-                    // copy the elements in classes array to the newly allocated one.
-                    // classes[0] is a Thread object
-                    Class<?>[] prev = classes;
-                    classes = new Class<?>[size];
-                    System.arraycopy(prev, 0, classes, 0, START_POS);
-                }
-                currentBatchSize = size;
-            }
-
-            /*
-             * Returns the start index for this frame buffer is refilled.
-             *
-             * This implementation reuses the allocated buffer for the next batch
-             * of stack frames.  For subclass to retain the fetched stack frames,
-             * it should override this method to return the index at which the frame
-             * should be filled in for the next batch.
-             */
-            int startIndex() {
-                return START_POS;
-            }
-
-            /**
-             * Returns next StackFrame object in the current batch of stack frames
-             */
-            StackFrame nextStackFrame() {
-                throw new InternalError("should not reach here");
-            }
-        }
+                                            T[] frames);
     }
 
     /*
@@ -629,46 +433,66 @@
      *
      * This class implements Spliterator::forEachRemaining and Spliterator::tryAdvance.
      */
-    static class StackFrameTraverser<T> extends AbstractStackWalker<T>
+    static class StackFrameTraverser<T> extends AbstractStackWalker<T, StackFrameInfo>
             implements Spliterator<StackFrame>
     {
         static {
             stackWalkImplClasses.add(StackFrameTraverser.class);
         }
         private static final int CHARACTERISTICS = Spliterator.ORDERED | Spliterator.IMMUTABLE;
-        class Buffer extends FrameBuffer {
-            Buffer(int initialBatchSize) {
+
+        final class StackFrameBuffer extends FrameBuffer<StackFrameInfo> {
+            private StackFrameInfo[] stackFrames;
+            StackFrameBuffer(int initialBatchSize) {
                 super(initialBatchSize);
 
-                this.stackFrames = new StackFrame[initialBatchSize];
+                this.stackFrames = new StackFrameInfo[initialBatchSize];
                 for (int i = START_POS; i < initialBatchSize; i++) {
                     stackFrames[i] = new StackFrameInfo(walker);
                 }
             }
 
             @Override
+            StackFrameInfo[] frames() {
+                return stackFrames;
+            }
+
+            @Override
             void resize(int startIndex, int elements) {
-                super.resize(startIndex, elements);
+                if (!isActive())
+                    throw new IllegalStateException("inactive frame buffer can't be resized");
+
+                assert startIndex == START_POS :
+                       "bad start index " + startIndex + " expected " + START_POS;
 
                 int size = startIndex+elements;
                 if (stackFrames.length < size) {
-                    stackFrames = new StackFrame[size];
+                    StackFrameInfo[] newFrames = new StackFrameInfo[size];
+                    // copy initial magic...
+                    System.arraycopy(stackFrames, 0, newFrames, 0, startIndex);
+                    stackFrames = newFrames;
                 }
-                for (int i = startIndex(); i < size; i++) {
+                for (int i = startIndex; i < size; i++) {
                     stackFrames[i] = new StackFrameInfo(walker);
                 }
+                currentBatchSize = size;
             }
 
             @Override
-            StackFrame nextStackFrame() {
+            StackFrameInfo nextStackFrame() {
                 if (isEmpty()) {
                     throw new NoSuchElementException("origin=" + origin + " fence=" + fence);
                 }
 
-                StackFrame frame = stackFrames[origin];
+                StackFrameInfo frame = stackFrames[origin];
                 origin++;
                 return frame;
             }
+
+            @Override
+            final Class<?> at(int index) {
+                return stackFrames[index].declaringClass;
+            }
         }
 
         final Function<? super Stream<StackFrame>, ? extends T> function;  // callback
@@ -693,7 +517,7 @@
                 return null;
             }
 
-            StackFrame frame = frameBuffer.nextStackFrame();
+            StackFrameInfo frame = frameBuffer.nextStackFrame();
             depth++;
             return frame;
         }
@@ -710,7 +534,7 @@
 
         @Override
         protected void initFrameBuffer() {
-            this.frameBuffer = new Buffer(getNextBatchSize());
+            this.frameBuffer = new StackFrameBuffer(getNextBatchSize());
         }
 
         @Override
@@ -781,7 +605,7 @@
      * CallerClassFinder is specialized to return Class<?> for each stack frame.
      * StackFrame is not requested.
      */
-    static class CallerClassFinder extends AbstractStackWalker<Integer> {
+    static final class CallerClassFinder extends AbstractStackWalker<Integer, Class<?>> {
         static {
             stackWalkImplClasses.add(CallerClassFinder.class);
         }
@@ -790,6 +614,54 @@
 
         CallerClassFinder(StackWalker walker) {
             super(walker, FILL_CLASS_REFS_ONLY);
+            assert (mode & FILL_CLASS_REFS_ONLY) == FILL_CLASS_REFS_ONLY
+                   : "mode should contain FILL_CLASS_REFS_ONLY";
+        }
+
+        final class ClassBuffer extends FrameBuffer<Class<?>> {
+            Class<?>[] classes;      // caller class for fast path
+            ClassBuffer(int batchSize) {
+                super(batchSize);
+                classes = new Class<?>[batchSize];
+            }
+
+            @Override
+            Class<?>[] frames() { return classes;}
+
+            @Override
+            final Class<?> at(int index) { return classes[index];}
+
+
+            // ------ subclass may override the following methods -------
+            /**
+             * Resizes the buffers for VM to fill in the next batch of stack frames.
+             * The next batch will start at the given startIndex with the maximum number
+             * of elements.
+             *
+             * <p> Subclass may override this method to manage the allocated buffers.
+             *
+             * @param startIndex the start index for the first frame of the next batch to fill in.
+             * @param elements the number of elements for the next batch to fill in.
+             *
+             */
+            @Override
+            void resize(int startIndex, int elements) {
+                if (!isActive())
+                    throw new IllegalStateException("inactive frame buffer can't be resized");
+
+                assert startIndex == START_POS :
+                       "bad start index " + startIndex + " expected " + START_POS;
+
+                int size = startIndex+elements;
+                if (classes.length < size) {
+                    // copy the elements in classes array to the newly allocated one.
+                    // classes[0] is a Thread object
+                    Class<?>[] prev = classes;
+                    classes = new Class<?>[size];
+                    System.arraycopy(prev, 0, classes, 0, startIndex);
+                }
+                currentBatchSize = size;
+            }
         }
 
         Class<?> findCaller() {
@@ -810,15 +682,15 @@
                 if (isMethodHandleFrame(caller)) continue;
                 frames[n++] = caller;
             }
-
-            if (frames[1] == null)
+            if (frames[1] == null) {
                 throw new IllegalStateException("no caller frame");
+            }
             return n;
         }
 
         @Override
         protected void initFrameBuffer() {
-            this.frameBuffer = new FrameBuffer(getNextBatchSize());
+            this.frameBuffer = new ClassBuffer(getNextBatchSize());
         }
 
         @Override
@@ -832,215 +704,64 @@
         }
     }
 
-    /*
-     * StackTrace caches all frames in the buffer.  StackTraceElements are
-     * created lazily when Throwable::getStackTrace is called.
-     */
-    static class StackTrace extends AbstractStackWalker<Integer> {
-        static {
-            stackWalkImplClasses.add(StackTrace.class);
-        }
-
-        class GrowableBuffer extends FrameBuffer {
-            GrowableBuffer(int initialBatchSize) {
-                super(initialBatchSize);
-
-                this.stackFrames = new StackFrame[initialBatchSize];
-                for (int i = START_POS; i < initialBatchSize; i++) {
-                    stackFrames[i] = new StackFrameInfo(walker);
-                }
-            }
-
-            /*
-             * Returns the next index to fill
-             */
-            @Override
-            int startIndex() {
-                return origin;
-            }
-
-            /**
-             * Initialize the buffers for VM to fill in the stack frame information.
-             * The next batch will start at the given startIndex to
-             * the length of the buffer.
-             */
-            @Override
-            void resize(int startIndex, int elements) {
-                // Expand the frame buffer.
-                // Do not call super.resize that will reuse the filled elements
-                // in this frame buffer
-                int size = startIndex+elements;
-                if (classes.length < size) {
-                    // resize the frame buffer
-                    classes = Arrays.copyOf(classes, size);
-                    stackFrames = Arrays.copyOf(stackFrames, size);
-                }
-                for (int i = startIndex; i < size; i++) {
-                    stackFrames[i] = new StackFrameInfo(walker);
-                }
-                currentBatchSize = size;
-            }
-
-            StackTraceElement get(int index) {
-                return new StackTraceElement(classes[index].getName(), "unknown", null, -1);
-            }
-
-            /**
-             * Returns an array of StackTraceElement for all stack frames cached in
-             * this StackTrace object.
-             * <p>
-             * This method is intended for Throwable::getOurStackTrace use only.
-             */
-            StackTraceElement[] toStackTraceElements() {
-                int startIndex = START_POS;
-                for (int i = startIndex; i < classes.length; i++) {
-                    if (classes[i] != null && filterStackWalkImpl(classes[i])) {
-                        startIndex++;
-                    } else {
-                        break;
-                    }
-                }
-
-                // VM fills in the method name, filename, line number info
-                StackFrameInfo.fillInStackFrames(0, stackFrames, startIndex, startIndex + depth);
-
-                StackTraceElement[] stes = new StackTraceElement[depth];
-                for (int i = startIndex, j = 0; i < classes.length && j < depth; i++, j++) {
-                    if (isDebug) {
-                        System.err.println("StackFrame: " + i + " " + stackFrames[i]);
-                    }
-                    stes[j] = stackFrames[i].toStackTraceElement();
-                }
-                return stes;
-            }
-        }
-
-        private static final int MAX_STACK_FRAMES = 1024;
-        private static final StackWalker STACKTRACE_WALKER =
-            StackWalker.newInstanceNoCheck(EnumSet.of(Option.SHOW_REFLECT_FRAMES));
-
-        private StackTraceElement[] stes;
-        static StackTrace dump() {
-            return new StackTrace();
-        }
-
-        static StackTrace dump(Throwable ex) {
-            return new StackTrace(ex);
-        }
-
-        private StackTrace() {
-            this(STACKTRACE_WALKER, DEFAULT_MODE);
-        }
-
-        /*
-         * Throwable::fillInStackTrace and <init> of Throwable and subclasses
-         * are filtered in the VM.
-         */
-        private StackTrace(Throwable ex) {
-            this(STACKTRACE_WALKER, FILTER_FILL_IN_STACKTRACE);  // skip Throwable::init frames
-            if (isDebug) {
-                System.err.println("dump stack for " + ex.getClass().getName());
-            }
-        }
-
-        StackTrace(StackWalker walker, int mode) {
-            super(walker, mode, MAX_STACK_FRAMES);
-
-            // snapshot the stack trace
-            walk();
-        }
-
-        @Override
-        protected Integer consumeFrames() {
-            // traverse all frames and perform the action on the stack frames, if specified
-            int n = 0;
-            while (n < maxDepth && nextFrame() != null) {
-                n++;
-            }
-            return n;
-        }
-
-        @Override
-        protected void initFrameBuffer() {
-            this.frameBuffer = new GrowableBuffer(getNextBatchSize());
-        }
-
-        // TODO: implement better heuristic
-        @Override
-        protected int batchSize(int lastBatchFrameCount) {
-            // chunk size of VM backtrace is 32
-            return lastBatchFrameCount == 0 ? 32 : 32;
-        }
-
-        /**
-         * Returns an array of StackTraceElement for all stack frames cached in
-         * this StackTrace object.
-         * <p>
-         * This method is intended for Throwable::getOurStackTrace use only.
-         */
-        synchronized StackTraceElement[] getStackTraceElements() {
-            if (stes == null) {
-                stes = ((GrowableBuffer) frameBuffer).toStackTraceElements();
-                // release the frameBuffer memory
-                frameBuffer = null;
-            }
-            return stes;
-        }
-
-        /*
-         * Prints stack trace to the given PrintStream.
-         *
-         * Further implementation could skip creating StackTraceElement objects
-         * print directly to the PrintStream.
-         */
-        void printStackTrace(PrintStream s) {
-            StackTraceElement[] stes = getStackTraceElements();
-            synchronized (s) {
-                s.println("Stack trace");
-                for (StackTraceElement traceElement : stes)
-                    s.println("\tat " + traceElement);
-            }
-        }
-    }
-
-    static class LiveStackInfoTraverser<T> extends StackFrameTraverser<T> {
+    static final class LiveStackInfoTraverser<T> extends StackFrameTraverser<T> {
         static {
             stackWalkImplClasses.add(LiveStackInfoTraverser.class);
         }
         // VM will fill in all method info and live stack info directly in StackFrameInfo
-        class Buffer extends FrameBuffer {
-            Buffer(int initialBatchSize) {
+        final class LiveStackFrameBuffer extends FrameBuffer<LiveStackFrameInfo> {
+            private LiveStackFrameInfo[] stackFrames;
+            LiveStackFrameBuffer(int initialBatchSize) {
                 super(initialBatchSize);
-                this.stackFrames = new StackFrame[initialBatchSize];
+                this.stackFrames = new LiveStackFrameInfo[initialBatchSize];
                 for (int i = START_POS; i < initialBatchSize; i++) {
                     stackFrames[i] = new LiveStackFrameInfo(walker);
                 }
             }
 
             @Override
+            LiveStackFrameInfo[] frames() {
+                return stackFrames;
+            }
+
+            @Override
             void resize(int startIndex, int elements) {
-                super.resize(startIndex, elements);
+                if (!isActive()) {
+                    throw new IllegalStateException("inactive frame buffer can't be resized");
+                }
+                assert startIndex == START_POS :
+                       "bad start index " + startIndex + " expected " + START_POS;
+
                 int size = startIndex + elements;
-
                 if (stackFrames.length < size) {
-                    this.stackFrames = new StackFrame[size];
+                    LiveStackFrameInfo[] newFrames = new LiveStackFrameInfo[size];
+                    // copy initial magic...
+                    System.arraycopy(stackFrames, 0, newFrames, 0, startIndex);
+                    stackFrames = newFrames;
                 }
 
                 for (int i = startIndex(); i < size; i++) {
                     stackFrames[i] = new LiveStackFrameInfo(walker);
                 }
+
+                currentBatchSize = size;
             }
 
             @Override
-            StackFrame nextStackFrame() {
+            LiveStackFrameInfo nextStackFrame() {
                 if (isEmpty()) {
                     throw new NoSuchElementException("origin=" + origin + " fence=" + fence);
                 }
 
-                StackFrame frame = stackFrames[origin];
+                LiveStackFrameInfo frame = stackFrames[origin];
                 origin++;
                 return frame;
             }
+
+            @Override
+            final Class<?> at(int index) {
+                return stackFrames[index].declaringClass;
+            }
         }
 
         LiveStackInfoTraverser(StackWalker walker,
@@ -1050,7 +771,183 @@
 
         @Override
         protected void initFrameBuffer() {
-            this.frameBuffer = new Buffer(getNextBatchSize());
+            this.frameBuffer = new LiveStackFrameBuffer(getNextBatchSize());
+        }
+    }
+
+    /*
+     * Frame buffer
+     *
+     * Each specialized AbstractStackWalker subclass may subclass the FrameBuffer.
+     */
+    static abstract class FrameBuffer<F> {
+        static final int START_POS = 2;     // 0th and 1st elements are reserved
+
+        // buffers for VM to fill stack frame info
+        int currentBatchSize;    // current batch size
+        int origin;         // index to the current traversed stack frame
+        int fence;          // index to the last frame in the current batch
+
+        FrameBuffer(int initialBatchSize) {
+            if (initialBatchSize < MIN_BATCH_SIZE) {
+                throw new IllegalArgumentException(initialBatchSize +
+                        " < minimum batch size: " + MIN_BATCH_SIZE);
+            }
+            this.origin = START_POS;
+            this.fence = 0;
+            this.currentBatchSize = initialBatchSize;
+        }
+
+        /**
+         * Returns an array of frames that may be used to store frame objects
+         * when walking the stack.
+         *
+         * May be an array of {@code Class<?>} if the {@code AbstractStackWalker}
+         * mode is {@link #FILL_CLASS_REFS_ONLY}, or an array of
+         * {@link StackFrameInfo} (or derivative) array otherwise.
+         *
+         * @return An array of frames that may be used to store frame objects
+         * when walking the stack. Must not be null.
+         */
+        abstract F[] frames(); // must not return null
+
+        /**
+         * Resizes the buffers for VM to fill in the next batch of stack frames.
+         * The next batch will start at the given startIndex with the maximum number
+         * of elements.
+         *
+         * <p> Subclass may override this method to manage the allocated buffers.
+         *
+         * @param startIndex the start index for the first frame of the next batch to fill in.
+         * @param elements the number of elements for the next batch to fill in.
+         *
+         */
+        abstract void resize(int startIndex, int elements);
+
+        /**
+         * Return the class at the given position in the current batch.
+         * @param index the position of the frame.
+         * @return the class at the given position in the current batch.
+         */
+        abstract Class<?> at(int index);
+
+        // ------ subclass may override the following methods -------
+
+        /*
+         * Returns the start index for this frame buffer is refilled.
+         *
+         * This implementation reuses the allocated buffer for the next batch
+         * of stack frames.  For subclass to retain the fetched stack frames,
+         * it should override this method to return the index at which the frame
+         * should be filled in for the next batch.
+         */
+        int startIndex() {
+            return START_POS;
+        }
+
+        /**
+         * Returns next StackFrame object in the current batch of stack frames
+         */
+        F nextStackFrame() {
+            throw new InternalError("should not reach here");
+        }
+
+        // ------ FrameBuffer implementation ------
+
+        final int curBatchFrameCount() {
+            return currentBatchSize-START_POS;
+        }
+
+        /*
+         * Tests if this frame buffer is empty.  All frames are fetched.
+         */
+        final boolean isEmpty() {
+            return origin >= fence || (origin == START_POS && fence == 0);
+        }
+
+        /*
+         * Freezes this frame buffer.  The stack stream source is done fetching.
+         */
+        final void freeze() {
+            origin = 0;
+            fence = 0;
+        }
+
+        /*
+         * Tests if this frame buffer is active.  It is inactive when
+         * it is done for traversal.  All stack frames have been traversed.
+         */
+        final boolean isActive() {
+            return origin > 0 && (fence == 0 || origin < fence || fence == currentBatchSize);
+        }
+
+        /**
+         * Gets the class at the current frame and move to the next frame.
+         */
+        final Class<?> next() {
+            if (isEmpty()) {
+                throw new NoSuchElementException("origin=" + origin + " fence=" + fence);
+            }
+            Class<?> c = at(origin);
+            origin++;
+            if (isDebug) {
+                int index = origin-1;
+                System.out.format("  next frame at %d: %s (origin %d fence %d)%n", index,
+                        Objects.toString(c), index, fence);
+            }
+            return c;
+        }
+
+        /**
+         * Gets the class at the current frame.
+         */
+        final Class<?> get() {
+            if (isEmpty()) {
+                throw new NoSuchElementException("origin=" + origin + " fence=" + fence);
+            }
+            return at(origin);
+        }
+
+        /*
+         * Returns the index of the current frame.
+         */
+        final int getIndex() {
+            return origin;
+        }
+
+        /*
+         * Set the start and end index of a new batch of stack frames that have
+         * been filled in this frame buffer.
+         */
+        final void setBatch(int depth, int startIndex, int endIndex) {
+            if (startIndex <= 0 || endIndex <= 0)
+                throw new IllegalArgumentException("startIndex=" + startIndex + " endIndex=" + endIndex);
+
+            this.origin = startIndex;
+            this.fence = endIndex;
+            if (depth == 0 && fence > 0) {
+                // filter the frames due to the stack stream implementation
+                for (int i = START_POS; i < fence; i++) {
+                    Class<?> c = at(i);
+                    if (isDebug) System.err.format("  frame %d: %s%n", i, c);
+                    if (filterStackWalkImpl(c)) {
+                        origin++;
+                    } else {
+                        break;
+                    }
+                }
+            }
+        }
+
+        /*
+         * Checks if the origin is the expected start index.
+         */
+        final void check(int skipFrames) {
+            int index = skipFrames + START_POS;
+            if (origin != index) {
+                // stack walk must continue with the previous frame depth
+                throw new IllegalStateException("origin " + origin + " != " + index);
+            }
         }
     }
 
--- a/jdk/src/java.base/share/classes/java/lang/Thread.java	Fri Apr 08 12:36:27 2016 -0400
+++ b/jdk/src/java.base/share/classes/java/lang/Thread.java	Mon Apr 11 20:16:34 2016 +0200
@@ -1388,7 +1388,7 @@
      * This method is used only for debugging.
      */
     public static void dumpStack() {
-        StackStreamFactory.makeStackTrace().printStackTrace(System.err);
+        new Exception("Stack trace").printStackTrace();
     }
 
     /**
@@ -1610,8 +1610,7 @@
             }
             return stackTrace;
         } else {
-            // Don't need JVM help for current thread
-            return StackStreamFactory.makeStackTrace().getStackTraceElements();
+            return (new Exception()).getStackTrace();
         }
     }
 
--- a/jdk/src/java.base/share/classes/java/lang/Throwable.java	Fri Apr 08 12:36:27 2016 -0400
+++ b/jdk/src/java.base/share/classes/java/lang/Throwable.java	Mon Apr 11 20:16:34 2016 +0200
@@ -785,11 +785,7 @@
     public synchronized Throwable fillInStackTrace() {
         if (stackTrace != null ||
             backtrace != null /* Out of protocol state */ ) {
-            if (backtrace == null && StackStreamFactory.useStackTrace(this)) {
-                backtrace = StackStreamFactory.makeStackTrace(this);
-            } else {
-                fillInStackTrace(0);
-            }
+            fillInStackTrace(0);
             stackTrace = UNASSIGNED_STACK;
         }
         return this;
@@ -830,15 +826,11 @@
         // backtrace if this is the first call to this method
         if (stackTrace == UNASSIGNED_STACK ||
             (stackTrace == null && backtrace != null) /* Out of protocol state */) {
-            if (backtrace instanceof StackStreamFactory.StackTrace) {
-                stackTrace = ((StackStreamFactory.StackTrace)backtrace).getStackTraceElements();
-            } else {
-                stackTrace = new StackTraceElement[depth];
-                for (int i = 0; i < depth; i++) {
-                    stackTrace[i] = new StackTraceElement();
-                }
-                getStackTraceElements(stackTrace);
+            stackTrace = new StackTraceElement[depth];
+            for (int i = 0; i < depth; i++) {
+                stackTrace[i] = new StackTraceElement();
             }
+            getStackTraceElements(stackTrace);
         } else if (stackTrace == null) {
             return UNASSIGNED_STACK;
         }
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MemberName.java	Fri Apr 08 12:36:27 2016 -0400
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MemberName.java	Mon Apr 11 20:16:34 2016 +0200
@@ -1132,6 +1132,10 @@
             public Object newMemberName() {
                 return new MemberName();
             }
+            public String getName(Object mname) {
+                MemberName memberName = (MemberName)mname;
+                return memberName.getName();
+            }
         });
     }
 }
--- a/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangInvokeAccess.java	Fri Apr 08 12:36:27 2016 -0400
+++ b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangInvokeAccess.java	Mon Apr 11 20:16:34 2016 +0200
@@ -30,4 +30,9 @@
      * Create a new MemberName instance
      */
     Object newMemberName();
+
+    /**
+     * Returns the name for the given MemberName
+     */
+    String getName(Object mname);
 }
--- a/jdk/src/java.base/share/native/include/jvm.h	Fri Apr 08 12:36:27 2016 -0400
+++ b/jdk/src/java.base/share/native/include/jvm.h	Mon Apr 11 20:16:34 2016 +0200
@@ -179,7 +179,6 @@
  */
 enum {
   JVM_STACKWALK_FILL_CLASS_REFS_ONLY       = 0x2,
-  JVM_STACKWALK_FILTER_FILL_IN_STACK_TRACE = 0x10,
   JVM_STACKWALK_SHOW_HIDDEN_FRAMES         = 0x20,
   JVM_STACKWALK_FILL_LIVE_STACK_FRAMES     = 0x100
 };
@@ -187,23 +186,15 @@
 JNIEXPORT jobject JNICALL
 JVM_CallStackWalk(JNIEnv *env, jobject stackStream, jlong mode,
                   jint skip_frames, jint frame_count, jint start_index,
-                  jobjectArray classes,
                   jobjectArray frames);
 
 JNIEXPORT jint JNICALL
 JVM_MoreStackWalk(JNIEnv *env, jobject stackStream, jlong mode, jlong anchor,
                   jint frame_count, jint start_index,
-                  jobjectArray classes,
                   jobjectArray frames);
 
 JNIEXPORT void JNICALL
-JVM_FillStackFrames(JNIEnv* env, jclass cls,
-                    jint start_index,
-                    jobjectArray stackFrames,
-                    jint from_index, jint toIndex);
-
-JNIEXPORT void JNICALL
-JVM_SetMethodInfo(JNIEnv* env, jobject frame);
+JVM_ToStackTraceElement(JNIEnv* env, jobject frame, jobject stackElement);
 
 JNIEXPORT jobjectArray JNICALL
 JVM_GetVmArguments(JNIEnv *env);
--- a/jdk/src/java.base/share/native/libjava/StackFrameInfo.c	Fri Apr 08 12:36:27 2016 -0400
+++ b/jdk/src/java.base/share/native/libjava/StackFrameInfo.c	Mon Apr 11 20:16:34 2016 +0200
@@ -38,22 +38,10 @@
 
 /*
  * Class:     java_lang_StackFrameInfo
- * Method:    fillInStackFrames
- * Signature: (I[Ljava/lang/Object;[Ljava/lang/Object;II)V
+ * Method:    toStackTraceElement0
+ * Signature: (Ljava/lang/StackTraceElement;)V
  */
-JNIEXPORT void JNICALL Java_java_lang_StackFrameInfo_fillInStackFrames
-  (JNIEnv *env, jclass dummy, jint startIndex,
-   jobjectArray stackFrames, jint fromIndex, jint toIndex) {
-    JVM_FillStackFrames(env, dummy, startIndex,
-                        stackFrames, fromIndex, toIndex);
+JNIEXPORT void JNICALL Java_java_lang_StackFrameInfo_toStackTraceElement0
+  (JNIEnv *env, jobject stackframeinfo, jobject stacktraceinfo) {
+     JVM_ToStackTraceElement(env, stackframeinfo, stacktraceinfo);
 }
-
-/*
- * Class:     java_lang_StackFrameInfo
- * Method:    setMethodInfo
- * Signature: (Ljava/lang/Class;)V
- */
-JNIEXPORT void JNICALL Java_java_lang_StackFrameInfo_setMethodInfo
-  (JNIEnv *env, jobject stackframeinfo) {
-     JVM_SetMethodInfo(env, stackframeinfo);
-}
--- a/jdk/src/java.base/share/native/libjava/StackStreamFactory.c	Fri Apr 08 12:36:27 2016 -0400
+++ b/jdk/src/java.base/share/native/libjava/StackStreamFactory.c	Mon Apr 11 20:16:34 2016 +0200
@@ -45,7 +45,6 @@
   (JNIEnv *env, jclass dummy)
 {
    return JVM_STACKWALK_FILL_CLASS_REFS_ONLY == java_lang_StackStreamFactory_FILL_CLASS_REFS_ONLY &&
-          JVM_STACKWALK_FILTER_FILL_IN_STACK_TRACE == java_lang_StackStreamFactory_FILTER_FILL_IN_STACKTRACE &&
           JVM_STACKWALK_SHOW_HIDDEN_FRAMES == java_lang_StackStreamFactory_SHOW_HIDDEN_FRAMES &&
           JVM_STACKWALK_FILL_LIVE_STACK_FRAMES == java_lang_StackStreamFactory_FILL_LIVE_STACK_FRAMES;
 }
@@ -53,26 +52,26 @@
 /*
  * Class:     java_lang_StackStreamFactory_AbstractStackWalker
  * Method:    callStackWalk
- * Signature: (JIII[Ljava/lang/Class;[Ljava/lang/StackWalker/StackFrame;)Ljava/lang/Object;
+ * Signature: (JIII[Ljava/lang/Object;)Ljava/lang/Object;
  */
 JNIEXPORT jobject JNICALL Java_java_lang_StackStreamFactory_00024AbstractStackWalker_callStackWalk
   (JNIEnv *env, jobject stackstream, jlong mode, jint skipFrames, jint batchSize, jint startIndex,
-   jobjectArray classes, jobjectArray frames)
+   jobjectArray frames)
 {
     return JVM_CallStackWalk(env, stackstream, mode, skipFrames, batchSize,
-                             startIndex, classes, frames);
+                             startIndex, frames);
 }
 
 /*
  * Class:     java_lang_StackStreamFactory_AbstractStackWalker
  * Method:    fetchStackFrames
- * Signature: (JJII[Ljava/lang/Class;[Ljava/lang/StackWalker/StackFrame;)I
+ * Signature: (JJII[Ljava/lang/Object;)I
  */
 JNIEXPORT jint JNICALL Java_java_lang_StackStreamFactory_00024AbstractStackWalker_fetchStackFrames
   (JNIEnv *env, jobject stackstream, jlong mode, jlong anchor,
    jint batchSize, jint startIndex,
-   jobjectArray classes, jobjectArray frames)
+   jobjectArray frames)
 {
     return JVM_MoreStackWalk(env, stackstream, mode, anchor, batchSize,
-                             startIndex, classes, frames);
+                             startIndex, frames);
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/jdi/SunBootClassPathEmptyTest.java	Mon Apr 11 20:16:34 2016 +0200
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+import com.sun.jdi.connect.*;
+import com.sun.jdi.*;
+import java.util.Map;
+import java.util.List;
+import jdk.test.lib.Asserts;
+
+/*
+ * @test
+ * @summary Verifies that PathSearchingVirtualMachine.bootClassPath()
+ *          returns an empty list in case no bootclass path specified
+ *          regardless of sun.boot.class.path option, which is now obsolete
+ * @library /test/lib/share/classes
+ * @compile TestClass.java
+ * @compile SunBootClassPathEmptyTest.java
+ * @run main/othervm SunBootClassPathEmptyTest
+ */
+public class SunBootClassPathEmptyTest {
+
+    /**
+     * Helper class to facilitate the debuggee VM launching
+     */
+    private static class VmConnector {
+
+        LaunchingConnector lc;
+        VirtualMachine vm;
+
+        VmConnector() {
+            for (LaunchingConnector c : Bootstrap.virtualMachineManager().launchingConnectors()) {
+                System.out.println("name: " + c.name());
+                if (c.name().equals("com.sun.jdi.CommandLineLaunch")) {
+                    lc = c;
+                    break;
+                }
+            }
+            if (lc == null) {
+                throw new RuntimeException("Connector not found");
+            }
+        }
+
+        PathSearchingVirtualMachine launchVm(String cmdLine, String options) throws Exception {
+            Map<String, Connector.Argument> vmArgs = lc.defaultArguments();
+            vmArgs.get("main").setValue(cmdLine);
+            if (options != null) {
+                vmArgs.get("options").setValue(options);
+            }
+            System.out.println("Debugger is launching vm ...");
+            vm = lc.launch(vmArgs);
+            if (!(vm instanceof PathSearchingVirtualMachine)) {
+                throw new RuntimeException("VM is not a PathSearchingVirtualMachine");
+            }
+            return (PathSearchingVirtualMachine) vm;
+        }
+
+    }
+
+    private static VmConnector connector = new VmConnector();
+
+    public static void main(String[] args) throws Exception {
+        testWithObsoleteClassPathOption(null);
+        testWithObsoleteClassPathOption("someclasspath");
+    }
+
+    private static void testWithObsoleteClassPathOption(String obsoleteClassPath) throws Exception {
+        PathSearchingVirtualMachine vm = connector.launchVm("TestClass", makeClassPathOptions(obsoleteClassPath));
+        List<String> bootClassPath = vm.bootClassPath();
+        Asserts.assertNotNull(bootClassPath, "Expected bootClassPath to be empty but was null");
+        Asserts.assertEquals(0, bootClassPath.size(), "Expected bootClassPath.size() 0 but was: " + bootClassPath.size());
+    }
+
+    private static String makeClassPathOptions(String obsoleteClassPath) {
+        return obsoleteClassPath == null ? null : "-Dsun.boot.class.path=" + obsoleteClassPath;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/jdi/TestClass.java	Mon Apr 11 20:16:34 2016 +0200
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+public class TestClass {
+
+    public static void main(String[] args) {
+        System.out.println("This is a test");
+    }
+
+}
--- a/jdk/test/java/lang/StackWalker/DumpStackTest.java	Fri Apr 08 12:36:27 2016 -0400
+++ b/jdk/test/java/lang/StackWalker/DumpStackTest.java	Mon Apr 11 20:16:34 2016 +0200
@@ -28,9 +28,6 @@
  *          This test should also been run against jdk9 successfully except of
  *          VM option MemberNameInStackFrame.
  * @run main/othervm DumpStackTest
- * @run main/othervm -Dstackwalk.newThrowable=false DumpStackTest
- * @run main/othervm -Dstackwalk.newThrowable=true -XX:-MemberNameInStackFrame DumpStackTest
- * @run main/othervm -Dstackwalk.newThrowable=true -XX:+MemberNameInStackFrame DumpStackTest
  */
 
 import java.lang.invoke.MethodHandle;
--- a/jdk/test/java/lang/StackWalker/GetCallerClassTest.java	Fri Apr 08 12:36:27 2016 -0400
+++ b/jdk/test/java/lang/StackWalker/GetCallerClassTest.java	Mon Apr 11 20:16:34 2016 +0200
@@ -25,8 +25,7 @@
  * @test
  * @bug 8140450
  * @summary Basic test for StackWalker.getCallerClass()
- * @run main/othervm -XX:-MemberNameInStackFrame GetCallerClassTest
- * @run main/othervm -XX:+MemberNameInStackFrame GetCallerClassTest
+ * @run main/othervm GetCallerClassTest
  * @run main/othervm GetCallerClassTest sm
  */
 
--- a/jdk/test/java/lang/StackWalker/StackWalkTest.java	Fri Apr 08 12:36:27 2016 -0400
+++ b/jdk/test/java/lang/StackWalker/StackWalkTest.java	Mon Apr 11 20:16:34 2016 +0200
@@ -44,10 +44,6 @@
  * @run main/othervm/java.security.policy=stackwalktest.policy StackWalkTest
  * @run main/othervm StackWalkTest -random:50
  * @run main/othervm/java.security.policy=stackwalktest.policy StackWalkTest -random:50
- * @run main/othervm -XX:-MemberNameInStackFrame -Dstackwalk.newThrowable=false StackWalkTest -random:50
- * @run main/othervm -XX:-MemberNameInStackFrame -Dstackwalk.newThrowable=true  StackWalkTest -random:50
- * @run main/othervm -XX:+MemberNameInStackFrame -Dstackwalk.newThrowable=false StackWalkTest -random:50
- * @run main/othervm -XX:+MemberNameInStackFrame -Dstackwalk.newThrowable=true  StackWalkTest -random:50
  * @author danielfuchs, bchristi
  * @key randomness
  */
--- a/jdk/test/java/lang/StackWalker/VerifyStackTrace.java	Fri Apr 08 12:36:27 2016 -0400
+++ b/jdk/test/java/lang/StackWalker/VerifyStackTrace.java	Mon Apr 11 20:16:34 2016 +0200
@@ -40,8 +40,7 @@
  * @summary Verify stack trace information obtained with respect to StackWalker
  *          options, when the stack contains lambdas, method handle invoke
  *          virtual calls, and reflection.
- * @run main/othervm -XX:-MemberNameInStackFrame VerifyStackTrace
- * @run main/othervm -XX:+MemberNameInStackFrame VerifyStackTrace
+ * @run main/othervm VerifyStackTrace
  * @run main/othervm/java.security.policy=stackwalk.policy VerifyStackTrace
  * @author danielfuchs
  */