8146424: runtime/ReservedStack/ReservedStackTest.java triggers: assert(thread->deopt_mark() == __null) failed: no stack overflow from deopt blob/uncommon trap
authornever
Fri, 22 Jan 2016 11:11:06 -0800
changeset 35593 c733fd198e6e
parent 35592 5814f874d736
child 35594 cc13089c6327
8146424: runtime/ReservedStack/ReservedStackTest.java triggers: assert(thread->deopt_mark() == __null) failed: no stack overflow from deopt blob/uncommon trap Reviewed-by: twisti
hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java
hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCodeCacheProvider.java
hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java
hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp
hotspot/src/share/vm/jvmci/jvmciCompilerToVM.hpp
hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp
hotspot/test/compiler/jvmci/code/InterpreterFrameSizeTest.java
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java	Fri Jan 22 11:08:07 2016 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java	Fri Jan 22 11:11:06 2016 -0800
@@ -29,6 +29,7 @@
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Method;
 
+import jdk.vm.ci.code.BytecodeFrame;
 import jdk.vm.ci.code.InstalledCode;
 import jdk.vm.ci.code.InvalidInstalledCodeException;
 import jdk.vm.ci.code.TargetDescription;
@@ -589,4 +590,14 @@
      * @throws IllegalArgumentException if an out of range position is given
      */
     native int methodDataProfileDataSize(long metaspaceMethodData, int position);
+
+    /**
+     * Return the amount of native stack required for the interpreter frames represented by
+     * {@code frame}. This is used when emitting the stack banging code to ensure that there is
+     * enough space for the frames during deoptimization.
+     *
+     * @param frame
+     * @return the number of bytes required for deoptimization of this frame state
+     */
+    native int interpreterFrameSize(BytecodeFrame frame);
 }
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCodeCacheProvider.java	Fri Jan 22 11:08:07 2016 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCodeCacheProvider.java	Fri Jan 22 11:11:06 2016 -0800
@@ -25,6 +25,7 @@
 import java.lang.reflect.Field;
 
 import jdk.vm.ci.code.BailoutException;
+import jdk.vm.ci.code.BytecodeFrame;
 import jdk.vm.ci.code.CodeCacheProvider;
 import jdk.vm.ci.code.CompiledCode;
 import jdk.vm.ci.code.InstalledCode;
@@ -169,6 +170,10 @@
         return runtime.getCompilerToVM().shouldDebugNonSafepoints();
     }
 
+    public int interpreterFrameSize(BytecodeFrame pos) {
+        return runtime.getCompilerToVM().interpreterFrameSize(pos);
+    }
+
     /**
      * Resets all compilation statistics.
      */
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java	Fri Jan 22 11:08:07 2016 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java	Fri Jan 22 11:11:06 2016 -0800
@@ -973,11 +973,12 @@
     @HotSpotVMFlag(name = "UseBlockZeroing", archs = {"sparc"}) @Stable public boolean useBlockZeroing;
     @HotSpotVMFlag(name = "BlockZeroingLowLimit", archs = {"sparc"}) @Stable public int blockZeroingLowLimit;
 
-    // offsets, ...
     @HotSpotVMFlag(name = "StackShadowPages") @Stable public int stackShadowPages;
     @HotSpotVMFlag(name = "UseStackBanging") @Stable public boolean useStackBanging;
     @HotSpotVMConstant(name = "STACK_BIAS") @Stable public int stackBias;
+    @HotSpotVMField(name = "CompilerToVM::Data::vm_page_size", type = "int", get = HotSpotVMField.Type.VALUE) @Stable public int vmPageSize;
 
+    // offsets, ...
     @HotSpotVMField(name = "oopDesc::_mark", type = "markOop", get = HotSpotVMField.Type.OFFSET) @Stable public int markOffset;
     @HotSpotVMField(name = "oopDesc::_metadata._klass", type = "Klass*", get = HotSpotVMField.Type.OFFSET) @Stable public int hubOffset;
 
--- a/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp	Fri Jan 22 11:08:07 2016 -0800
+++ b/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp	Fri Jan 22 11:11:06 2016 -0800
@@ -149,6 +149,8 @@
 jbyte* CompilerToVM::Data::cardtable_start_address;
 int CompilerToVM::Data::cardtable_shift;
 
+int CompilerToVM::Data::vm_page_size;
+
 void CompilerToVM::Data::initialize() {
   InstanceKlass_vtable_start_offset = InstanceKlass::vtable_start_offset();
   InstanceKlass_vtable_length_offset = InstanceKlass::vtable_length_offset() * HeapWordSize;
@@ -198,6 +200,8 @@
     ShouldNotReachHere();
     break;
   }
+
+  vm_page_size = os::vm_page_size();
 }
 
 /**
@@ -1364,6 +1368,42 @@
   THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), err_msg("Invalid profile data position %d", position));
 C2V_END
 
+C2V_VMENTRY(int, interpreterFrameSize, (JNIEnv*, jobject, jobject bytecode_frame_handle))
+  if (bytecode_frame_handle == NULL) {
+    THROW_0(vmSymbols::java_lang_NullPointerException());
+  }
+
+  oop top_bytecode_frame = JNIHandles::resolve_non_null(bytecode_frame_handle);
+  oop bytecode_frame = top_bytecode_frame;
+  int size = 0;
+  int callee_parameters = 0;
+  int callee_locals = 0;
+  Method* method = getMethodFromHotSpotMethod(BytecodePosition::method(bytecode_frame));
+  int extra_args = method->max_stack() - BytecodeFrame::numStack(bytecode_frame);
+
+  while (bytecode_frame != NULL) {
+    int locks = BytecodeFrame::numLocks(bytecode_frame);
+    int temps = BytecodeFrame::numStack(bytecode_frame);
+    bool is_top_frame = (bytecode_frame == top_bytecode_frame);
+    Method* method = getMethodFromHotSpotMethod(BytecodePosition::method(bytecode_frame));
+
+    int frame_size = BytesPerWord * Interpreter::size_activation(method->max_stack(),
+                                                                 temps + callee_parameters,
+                                                                 extra_args,
+                                                                 locks,
+                                                                 callee_parameters,
+                                                                 callee_locals,
+                                                                 is_top_frame);
+    size += frame_size;
+
+    callee_parameters = method->size_of_parameters();
+    callee_locals = method->max_locals();
+    extra_args = 0;
+    bytecode_frame = BytecodePosition::caller(bytecode_frame);
+  }
+  return size + Deoptimization::last_frame_adjust(0, callee_locals) * BytesPerWord;
+C2V_END
+
 
 #define CC (char*)  /*cast a literal from (const char*)*/
 #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &(c2v_ ## f))
@@ -1374,6 +1414,7 @@
 #define STACK_TRACE_ELEMENT   "Ljava/lang/StackTraceElement;"
 #define INSTALLED_CODE        "Ljdk/vm/ci/code/InstalledCode;"
 #define TARGET_DESCRIPTION    "Ljdk/vm/ci/code/TargetDescription;"
+#define BYTECODE_FRAME        "Ljdk/vm/ci/code/BytecodeFrame;"
 #define RESOLVED_METHOD       "Ljdk/vm/ci/meta/ResolvedJavaMethod;"
 #define HS_RESOLVED_METHOD    "Ljdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl;"
 #define HS_RESOLVED_KLASS     "Ljdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl;"
@@ -1443,6 +1484,7 @@
   {CC"writeDebugOutput",                             CC"([BII)V",                                                                      FN_PTR(writeDebugOutput)},
   {CC"flushDebugOutput",                             CC"()V",                                                                          FN_PTR(flushDebugOutput)},
   {CC"methodDataProfileDataSize",                    CC"(JI)I",                                                                        FN_PTR(methodDataProfileDataSize)},
+  {CC"interpreterFrameSize",                         CC"("BYTECODE_FRAME")I",                                                          FN_PTR(interpreterFrameSize)},
 };
 
 int CompilerToVM::methods_count() {
--- a/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.hpp	Fri Jan 22 11:08:07 2016 -0800
+++ b/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.hpp	Fri Jan 22 11:11:06 2016 -0800
@@ -63,6 +63,8 @@
     static jbyte* cardtable_start_address;
     static int cardtable_shift;
 
+    static int vm_page_size;
+
    public:
     static void initialize();
   };
--- a/hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp	Fri Jan 22 11:08:07 2016 -0800
+++ b/hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp	Fri Jan 22 11:11:06 2016 -0800
@@ -74,6 +74,8 @@
   static_field(CompilerToVM::Data,             cardtable_start_address,                jbyte*)                                       \
   static_field(CompilerToVM::Data,             cardtable_shift,                        int)                                          \
                                                                                                                                      \
+  static_field(CompilerToVM::Data,             vm_page_size,                           int)                                          \
+                                                                                                                                     \
   static_field(Abstract_VM_Version,            _features,                              uint64_t)                                     \
                                                                                                                                      \
   nonstatic_field(Array<int>,                  _length,                                int)                                          \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/code/InterpreterFrameSizeTest.java	Fri Jan 22 11:11:06 2016 -0800
@@ -0,0 +1,78 @@
+/*
+ * 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.
+ */
+
+/**
+ * @test
+ * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64"
+ * @compile CodeInstallationTest.java DebugInfoTest.java TestAssembler.java amd64/AMD64TestAssembler.java sparc/SPARCTestAssembler.java
+ * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI compiler.jvmci.code.InterpreterFrameSizeTest
+ */
+
+package compiler.jvmci.code;
+
+import java.lang.reflect.Method;
+
+import jdk.vm.ci.code.BytecodeFrame;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.JavaValue;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+
+import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class InterpreterFrameSizeTest extends CodeInstallationTest {
+
+    HotSpotCodeCacheProvider hotspotCodeCache() {
+        return (HotSpotCodeCacheProvider) codeCache;
+    }
+
+    @Test
+    public void testNull() {
+        try {
+            hotspotCodeCache().interpreterFrameSize(null);
+        } catch (NullPointerException npe) {
+            System.out.println("threw NPE as expected");
+            return;
+        }
+        Assert.fail("expected NullPointerException");
+    }
+
+    @Test
+    public void test() {
+        ResolvedJavaMethod resolvedMethod = metaAccess.lookupJavaMethod(getMethod("testNull"));
+
+        int bci = 0;
+        int numLocals = resolvedMethod.getMaxLocals();
+        int numStack = 0;
+        JavaValue[] values = new JavaValue[numLocals];
+        JavaKind[] slotKinds = new JavaKind[numLocals];
+        BytecodeFrame frame = new BytecodeFrame(null, resolvedMethod, bci, false, false, values, slotKinds, numLocals, numStack, 0);
+        int size = hotspotCodeCache().interpreterFrameSize(frame);
+        System.out.println("Frame size is " + size + " bytes");
+        if (size <= 0) {
+            Assert.fail("expected non-zero result");
+        }
+    }
+}