8146424: runtime/ReservedStack/ReservedStackTest.java triggers: assert(thread->deopt_mark() == __null) failed: no stack overflow from deopt blob/uncommon trap
Reviewed-by: twisti
--- 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");
+ }
+ }
+}